@ankhorage/zora 1.5.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (306) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/README.md +125 -123
  3. package/dist/components/app-bar/AppBar.js +4 -4
  4. package/dist/components/app-bar/AppBar.js.map +1 -1
  5. package/dist/components/avatar/Avatar.d.ts.map +1 -1
  6. package/dist/components/avatar/Avatar.js +19 -9
  7. package/dist/components/avatar/Avatar.js.map +1 -1
  8. package/dist/components/avatar/types.d.ts +2 -2
  9. package/dist/components/avatar/types.d.ts.map +1 -1
  10. package/dist/components/avatar/types.js.map +1 -1
  11. package/dist/components/avatar-group/AvatarGroup.js +2 -2
  12. package/dist/components/avatar-group/AvatarGroup.js.map +1 -1
  13. package/dist/components/avatar-group/types.d.ts +2 -2
  14. package/dist/components/avatar-group/types.d.ts.map +1 -1
  15. package/dist/components/avatar-group/types.js.map +1 -1
  16. package/dist/components/badge/Badge.js +3 -3
  17. package/dist/components/badge/Badge.js.map +1 -1
  18. package/dist/components/badge/types.d.ts +4 -4
  19. package/dist/components/badge/types.d.ts.map +1 -1
  20. package/dist/components/badge/types.js.map +1 -1
  21. package/dist/components/button/Button.js +3 -3
  22. package/dist/components/button/Button.js.map +1 -1
  23. package/dist/components/button/meta.d.ts +7 -7
  24. package/dist/components/button/meta.d.ts.map +1 -1
  25. package/dist/components/button/meta.js +8 -7
  26. package/dist/components/button/meta.js.map +1 -1
  27. package/dist/components/button/types.d.ts +4 -4
  28. package/dist/components/button/types.d.ts.map +1 -1
  29. package/dist/components/button/types.js.map +1 -1
  30. package/dist/components/card/Card.js +2 -2
  31. package/dist/components/card/Card.js.map +1 -1
  32. package/dist/components/checkbox/CheckboxGroup.js +5 -5
  33. package/dist/components/checkbox/CheckboxGroup.js.map +1 -1
  34. package/dist/components/checkbox/types.d.ts +1 -1
  35. package/dist/components/checkbox/types.d.ts.map +1 -1
  36. package/dist/components/checkbox/types.js.map +1 -1
  37. package/dist/components/chip/Chip.d.ts.map +1 -1
  38. package/dist/components/chip/Chip.js +9 -10
  39. package/dist/components/chip/Chip.js.map +1 -1
  40. package/dist/components/chip/resolveChipColors.d.ts +3 -3
  41. package/dist/components/chip/resolveChipColors.d.ts.map +1 -1
  42. package/dist/components/chip/resolveChipColors.js +14 -4
  43. package/dist/components/chip/resolveChipColors.js.map +1 -1
  44. package/dist/components/chip/types.d.ts +2 -2
  45. package/dist/components/chip/types.d.ts.map +1 -1
  46. package/dist/components/chip/types.js.map +1 -1
  47. package/dist/components/chip-group/ChipGroup.js +2 -2
  48. package/dist/components/chip-group/ChipGroup.js.map +1 -1
  49. package/dist/components/chip-group/types.d.ts +2 -2
  50. package/dist/components/chip-group/types.d.ts.map +1 -1
  51. package/dist/components/chip-group/types.js.map +1 -1
  52. package/dist/components/drawer/Drawer.js +1 -1
  53. package/dist/components/drawer/Drawer.js.map +1 -1
  54. package/dist/components/form/FormError.js +1 -1
  55. package/dist/components/form/FormError.js.map +1 -1
  56. package/dist/components/form/FormField.js +1 -1
  57. package/dist/components/form/FormField.js.map +1 -1
  58. package/dist/components/heading/Heading.d.ts.map +1 -1
  59. package/dist/components/heading/Heading.js +5 -3
  60. package/dist/components/heading/Heading.js.map +1 -1
  61. package/dist/components/heading/index.d.ts +1 -1
  62. package/dist/components/heading/index.d.ts.map +1 -1
  63. package/dist/components/heading/index.js.map +1 -1
  64. package/dist/components/heading/meta.d.ts +9 -3
  65. package/dist/components/heading/meta.d.ts.map +1 -1
  66. package/dist/components/heading/meta.js +10 -3
  67. package/dist/components/heading/meta.js.map +1 -1
  68. package/dist/components/heading/resolveHeadingRecipe.d.ts +4 -3
  69. package/dist/components/heading/resolveHeadingRecipe.d.ts.map +1 -1
  70. package/dist/components/heading/resolveHeadingRecipe.js +33 -12
  71. package/dist/components/heading/resolveHeadingRecipe.js.map +1 -1
  72. package/dist/components/heading/types.d.ts +5 -2
  73. package/dist/components/heading/types.d.ts.map +1 -1
  74. package/dist/components/heading/types.js.map +1 -1
  75. package/dist/components/icon-button/IconButton.js +3 -3
  76. package/dist/components/icon-button/IconButton.js.map +1 -1
  77. package/dist/components/icon-button/types.d.ts +3 -3
  78. package/dist/components/icon-button/types.d.ts.map +1 -1
  79. package/dist/components/icon-button/types.js.map +1 -1
  80. package/dist/components/input/Input.js +1 -1
  81. package/dist/components/input/Input.js.map +1 -1
  82. package/dist/components/media-card/MediaCard.js +2 -2
  83. package/dist/components/media-card/MediaCard.js.map +1 -1
  84. package/dist/components/metric-card/MetricCard.js +5 -5
  85. package/dist/components/metric-card/MetricCard.js.map +1 -1
  86. package/dist/components/metric-card/types.d.ts +2 -2
  87. package/dist/components/metric-card/types.d.ts.map +1 -1
  88. package/dist/components/metric-card/types.js.map +1 -1
  89. package/dist/components/modal/Modal.js +1 -1
  90. package/dist/components/modal/Modal.js.map +1 -1
  91. package/dist/components/progress/Progress.js +2 -2
  92. package/dist/components/progress/Progress.js.map +1 -1
  93. package/dist/components/progress/types.d.ts +3 -3
  94. package/dist/components/progress/types.d.ts.map +1 -1
  95. package/dist/components/progress/types.js +12 -2
  96. package/dist/components/progress/types.js.map +1 -1
  97. package/dist/components/radio/RadioGroup.js +5 -5
  98. package/dist/components/radio/RadioGroup.js.map +1 -1
  99. package/dist/components/radio/types.d.ts +1 -1
  100. package/dist/components/radio/types.d.ts.map +1 -1
  101. package/dist/components/radio/types.js.map +1 -1
  102. package/dist/components/rating/Rating.js +2 -2
  103. package/dist/components/rating/Rating.js.map +1 -1
  104. package/dist/components/rating/types.d.ts +3 -3
  105. package/dist/components/rating/types.d.ts.map +1 -1
  106. package/dist/components/rating/types.js +12 -2
  107. package/dist/components/rating/types.js.map +1 -1
  108. package/dist/components/tabs/Tabs.d.ts.map +1 -1
  109. package/dist/components/tabs/Tabs.js +4 -4
  110. package/dist/components/tabs/Tabs.js.map +1 -1
  111. package/dist/components/text/Text.d.ts.map +1 -1
  112. package/dist/components/text/Text.js +3 -2
  113. package/dist/components/text/Text.js.map +1 -1
  114. package/dist/components/text/index.d.ts +1 -1
  115. package/dist/components/text/index.d.ts.map +1 -1
  116. package/dist/components/text/index.js.map +1 -1
  117. package/dist/components/text/meta.d.ts +10 -4
  118. package/dist/components/text/meta.d.ts.map +1 -1
  119. package/dist/components/text/meta.js +11 -4
  120. package/dist/components/text/meta.js.map +1 -1
  121. package/dist/components/text/resolveTextRecipe.d.ts +4 -3
  122. package/dist/components/text/resolveTextRecipe.d.ts.map +1 -1
  123. package/dist/components/text/resolveTextRecipe.js +35 -13
  124. package/dist/components/text/resolveTextRecipe.js.map +1 -1
  125. package/dist/components/text/types.d.ts +5 -2
  126. package/dist/components/text/types.d.ts.map +1 -1
  127. package/dist/components/text/types.js.map +1 -1
  128. package/dist/components/toolbar/ToolbarAction.js +1 -1
  129. package/dist/components/toolbar/ToolbarAction.js.map +1 -1
  130. package/dist/index.d.ts +4 -2
  131. package/dist/index.d.ts.map +1 -1
  132. package/dist/index.js +1 -0
  133. package/dist/index.js.map +1 -1
  134. package/dist/internal/colorModel.d.ts +10 -0
  135. package/dist/internal/colorModel.d.ts.map +1 -0
  136. package/dist/internal/colorModel.js +25 -0
  137. package/dist/internal/colorModel.js.map +1 -0
  138. package/dist/internal/recipes.d.ts +12 -11
  139. package/dist/internal/recipes.d.ts.map +1 -1
  140. package/dist/internal/recipes.js +6 -6
  141. package/dist/internal/recipes.js.map +1 -1
  142. package/dist/layout/screen/Screen.d.ts.map +1 -1
  143. package/dist/layout/screen/Screen.js +7 -3
  144. package/dist/layout/screen/Screen.js.map +1 -1
  145. package/dist/patterns/auth/ForgotPasswordForm.js +2 -2
  146. package/dist/patterns/auth/ForgotPasswordForm.js.map +1 -1
  147. package/dist/patterns/auth/OtpForm.js +2 -2
  148. package/dist/patterns/auth/OtpForm.js.map +1 -1
  149. package/dist/patterns/auth/SignInForm.js +4 -4
  150. package/dist/patterns/auth/SignInForm.js.map +1 -1
  151. package/dist/patterns/auth/SignUpForm.js +2 -2
  152. package/dist/patterns/auth/SignUpForm.js.map +1 -1
  153. package/dist/patterns/chat-list-item/ChatListItem.d.ts.map +1 -1
  154. package/dist/patterns/chat-list-item/ChatListItem.js +6 -6
  155. package/dist/patterns/chat-list-item/ChatListItem.js.map +1 -1
  156. package/dist/patterns/chat-list-item/types.d.ts +2 -2
  157. package/dist/patterns/chat-list-item/types.d.ts.map +1 -1
  158. package/dist/patterns/chat-list-item/types.js.map +1 -1
  159. package/dist/patterns/collection-editor/CollectionEditor.js +5 -5
  160. package/dist/patterns/collection-editor/CollectionEditor.js.map +1 -1
  161. package/dist/patterns/confirm-dialog/ConfirmDialog.js +3 -3
  162. package/dist/patterns/confirm-dialog/ConfirmDialog.js.map +1 -1
  163. package/dist/patterns/confirm-dialog/types.d.ts +3 -3
  164. package/dist/patterns/confirm-dialog/types.d.ts.map +1 -1
  165. package/dist/patterns/confirm-dialog/types.js.map +1 -1
  166. package/dist/patterns/disclosure-section/DisclosureSection.js +1 -1
  167. package/dist/patterns/disclosure-section/DisclosureSection.js.map +1 -1
  168. package/dist/patterns/empty-state/EmptyState.js +2 -2
  169. package/dist/patterns/empty-state/EmptyState.js.map +1 -1
  170. package/dist/patterns/empty-state/types.d.ts +3 -3
  171. package/dist/patterns/empty-state/types.d.ts.map +1 -1
  172. package/dist/patterns/empty-state/types.js.map +1 -1
  173. package/dist/patterns/form-field/FormField.js +1 -1
  174. package/dist/patterns/form-field/FormField.js.map +1 -1
  175. package/dist/patterns/hero/Hero.js +3 -3
  176. package/dist/patterns/hero/Hero.js.map +1 -1
  177. package/dist/patterns/hero/types.d.ts +3 -3
  178. package/dist/patterns/hero/types.d.ts.map +1 -1
  179. package/dist/patterns/hero/types.js.map +1 -1
  180. package/dist/patterns/image-preview/ImagePreview.js +1 -1
  181. package/dist/patterns/image-preview/ImagePreview.js.map +1 -1
  182. package/dist/patterns/image-upload-field/ImageUploadField.js +7 -7
  183. package/dist/patterns/image-upload-field/ImageUploadField.js.map +1 -1
  184. package/dist/patterns/list/ListRow.js +2 -2
  185. package/dist/patterns/list/ListRow.js.map +1 -1
  186. package/dist/patterns/message-bubble/MessageBubble.d.ts.map +1 -1
  187. package/dist/patterns/message-bubble/MessageBubble.js +6 -6
  188. package/dist/patterns/message-bubble/MessageBubble.js.map +1 -1
  189. package/dist/patterns/message-bubble/types.d.ts +2 -2
  190. package/dist/patterns/message-bubble/types.d.ts.map +1 -1
  191. package/dist/patterns/message-bubble/types.js.map +1 -1
  192. package/dist/patterns/notice/Notice.js +2 -2
  193. package/dist/patterns/notice/Notice.js.map +1 -1
  194. package/dist/patterns/notice/types.d.ts +2 -2
  195. package/dist/patterns/notice/types.d.ts.map +1 -1
  196. package/dist/patterns/notice/types.js.map +1 -1
  197. package/dist/patterns/post-card/PostCard.js +4 -4
  198. package/dist/patterns/post-card/PostCard.js.map +1 -1
  199. package/dist/patterns/post-card/types.d.ts +2 -2
  200. package/dist/patterns/post-card/types.d.ts.map +1 -1
  201. package/dist/patterns/post-card/types.js.map +1 -1
  202. package/dist/patterns/section-header/SectionHeader.js +2 -2
  203. package/dist/patterns/section-header/SectionHeader.js.map +1 -1
  204. package/dist/patterns/settings-row/SettingsRow.js +1 -1
  205. package/dist/patterns/settings-row/SettingsRow.js.map +1 -1
  206. package/dist/patterns/theme-composer/ThemeComposer.js +14 -14
  207. package/dist/patterns/theme-composer/ThemeComposer.js.map +1 -1
  208. package/dist/patterns/tile-grid/PaletteItem.js +1 -1
  209. package/dist/patterns/tile-grid/PaletteItem.js.map +1 -1
  210. package/dist/patterns/timeline/Timeline.d.ts.map +1 -1
  211. package/dist/patterns/timeline/Timeline.js +14 -4
  212. package/dist/patterns/timeline/Timeline.js.map +1 -1
  213. package/dist/patterns/timeline/types.d.ts +2 -2
  214. package/dist/patterns/timeline/types.d.ts.map +1 -1
  215. package/dist/patterns/timeline/types.js.map +1 -1
  216. package/dist/patterns/tree-view/TreeItem.js +1 -1
  217. package/dist/patterns/tree-view/TreeItem.js.map +1 -1
  218. package/dist/patterns/zora-tab-bar/ZoraTabBar.d.ts.map +1 -1
  219. package/dist/patterns/zora-tab-bar/ZoraTabBar.js +64 -15
  220. package/dist/patterns/zora-tab-bar/ZoraTabBar.js.map +1 -1
  221. package/package.json +2 -2
  222. package/src/components/app-bar/AppBar.tsx +6 -6
  223. package/src/components/avatar/Avatar.tsx +21 -11
  224. package/src/components/avatar/types.ts +2 -2
  225. package/src/components/avatar-group/AvatarGroup.tsx +2 -2
  226. package/src/components/avatar-group/types.ts +2 -2
  227. package/src/components/badge/Badge.tsx +4 -4
  228. package/src/components/badge/types.ts +4 -4
  229. package/src/components/button/Button.tsx +4 -4
  230. package/src/components/button/meta.ts +8 -7
  231. package/src/components/button/types.ts +4 -4
  232. package/src/components/card/Card.tsx +2 -2
  233. package/src/components/checkbox/CheckboxGroup.tsx +6 -6
  234. package/src/components/checkbox/types.ts +1 -1
  235. package/src/components/chip/Chip.tsx +9 -10
  236. package/src/components/chip/resolveChipColors.ts +16 -6
  237. package/src/components/chip/types.ts +2 -2
  238. package/src/components/chip-group/ChipGroup.tsx +2 -2
  239. package/src/components/chip-group/types.ts +2 -2
  240. package/src/components/drawer/Drawer.tsx +1 -1
  241. package/src/components/form/FormError.tsx +1 -1
  242. package/src/components/form/FormField.tsx +1 -1
  243. package/src/components/heading/Heading.tsx +6 -3
  244. package/src/components/heading/index.ts +2 -1
  245. package/src/components/heading/meta.ts +10 -3
  246. package/src/components/heading/resolveHeadingRecipe.test.ts +13 -10
  247. package/src/components/heading/resolveHeadingRecipe.ts +58 -15
  248. package/src/components/heading/types.ts +5 -10
  249. package/src/components/icon-button/IconButton.tsx +4 -4
  250. package/src/components/icon-button/types.ts +3 -3
  251. package/src/components/input/Input.tsx +2 -2
  252. package/src/components/media-card/MediaCard.tsx +2 -2
  253. package/src/components/metric-card/MetricCard.tsx +6 -6
  254. package/src/components/metric-card/types.ts +2 -2
  255. package/src/components/modal/Modal.tsx +1 -1
  256. package/src/components/progress/Progress.tsx +2 -2
  257. package/src/components/progress/types.ts +14 -4
  258. package/src/components/radio/RadioGroup.tsx +6 -6
  259. package/src/components/radio/types.ts +1 -1
  260. package/src/components/rating/Rating.tsx +2 -2
  261. package/src/components/rating/types.ts +14 -4
  262. package/src/components/tabs/Tabs.tsx +11 -7
  263. package/src/components/text/Text.tsx +4 -2
  264. package/src/components/text/index.ts +8 -1
  265. package/src/components/text/meta.ts +11 -4
  266. package/src/components/text/resolveTextRecipe.test.ts +18 -14
  267. package/src/components/text/resolveTextRecipe.ts +42 -15
  268. package/src/components/text/types.ts +5 -10
  269. package/src/components/toolbar/ToolbarAction.tsx +2 -2
  270. package/src/index.ts +22 -2
  271. package/src/internal/colorModel.ts +39 -0
  272. package/src/internal/recipes.test.ts +2 -2
  273. package/src/internal/recipes.ts +18 -18
  274. package/src/layout/screen/Screen.tsx +11 -3
  275. package/src/patterns/auth/ForgotPasswordForm.tsx +2 -2
  276. package/src/patterns/auth/OtpForm.tsx +2 -2
  277. package/src/patterns/auth/SignInForm.tsx +4 -4
  278. package/src/patterns/auth/SignUpForm.tsx +2 -2
  279. package/src/patterns/chat-list-item/ChatListItem.tsx +7 -6
  280. package/src/patterns/chat-list-item/types.ts +2 -2
  281. package/src/patterns/collection-editor/CollectionEditor.tsx +6 -6
  282. package/src/patterns/confirm-dialog/ConfirmDialog.tsx +4 -4
  283. package/src/patterns/confirm-dialog/types.ts +3 -3
  284. package/src/patterns/disclosure-section/DisclosureSection.tsx +2 -2
  285. package/src/patterns/empty-state/EmptyState.tsx +4 -4
  286. package/src/patterns/empty-state/types.ts +3 -3
  287. package/src/patterns/form-field/FormField.tsx +1 -1
  288. package/src/patterns/hero/Hero.tsx +4 -4
  289. package/src/patterns/hero/types.ts +3 -3
  290. package/src/patterns/image-preview/ImagePreview.tsx +1 -1
  291. package/src/patterns/image-upload-field/ImageUploadField.tsx +8 -8
  292. package/src/patterns/list/ListRow.tsx +2 -2
  293. package/src/patterns/message-bubble/MessageBubble.tsx +10 -6
  294. package/src/patterns/message-bubble/types.ts +2 -2
  295. package/src/patterns/notice/Notice.tsx +2 -2
  296. package/src/patterns/notice/types.ts +2 -2
  297. package/src/patterns/post-card/PostCard.tsx +5 -5
  298. package/src/patterns/post-card/types.ts +2 -2
  299. package/src/patterns/section-header/SectionHeader.tsx +2 -2
  300. package/src/patterns/settings-row/SettingsRow.tsx +1 -1
  301. package/src/patterns/theme-composer/ThemeComposer.tsx +15 -15
  302. package/src/patterns/tile-grid/PaletteItem.tsx +1 -1
  303. package/src/patterns/timeline/Timeline.tsx +15 -5
  304. package/src/patterns/timeline/types.ts +2 -2
  305. package/src/patterns/tree-view/TreeItem.tsx +1 -1
  306. package/src/patterns/zora-tab-bar/ZoraTabBar.tsx +104 -15
@@ -1,12 +1,20 @@
1
- import type { FontWeight, SurfaceTheme } from '@ankhorage/surface';
1
+ import type { FontWeight, RoleSemantics, SurfaceTheme } from '@ankhorage/surface';
2
2
  import type { TextStyle } from 'react-native';
3
3
 
4
- import type { HeadingAlign, HeadingLevel, HeadingSize, HeadingTone, HeadingWeight } from './types';
4
+ import type {
5
+ HeadingAlign,
6
+ HeadingColor,
7
+ HeadingEmphasis,
8
+ HeadingLevel,
9
+ HeadingSize,
10
+ HeadingWeight,
11
+ } from './types';
5
12
 
6
13
  interface ResolveHeadingRecipeOptions {
7
14
  level: HeadingLevel;
8
15
  size?: HeadingSize;
9
- tone?: HeadingTone;
16
+ color?: HeadingColor;
17
+ emphasis?: HeadingEmphasis;
10
18
  align?: HeadingAlign;
11
19
  weight?: HeadingWeight;
12
20
  italic?: boolean;
@@ -72,22 +80,49 @@ function resolveSizeRecipe(theme: SurfaceTheme, size: HeadingSize): HeadingRecip
72
80
  };
73
81
  }
74
82
 
75
- function resolveToneColor(theme: SurfaceTheme, tone: HeadingTone): string {
76
- switch (tone) {
83
+ function resolveRoleSemantics(theme: SurfaceTheme, color: HeadingColor): RoleSemantics {
84
+ switch (color) {
85
+ case 'secondary':
86
+ return theme.semantics.secondary;
87
+ case 'tertiary':
88
+ return theme.semantics.accent;
89
+ case 'quaternary':
90
+ return theme.semantics.highlight;
91
+ case 'neutral':
92
+ return theme.semantics.action.neutral;
93
+ case 'error':
94
+ return theme.semantics.error;
95
+ case 'info':
96
+ return theme.semantics.info;
97
+ case 'danger':
98
+ return theme.semantics.action.danger;
99
+ case 'success':
100
+ return theme.semantics.success;
101
+ case 'warning':
102
+ return theme.semantics.warning;
103
+ case 'primary':
104
+ default:
105
+ return theme.semantics.action.primary;
106
+ }
107
+ }
108
+
109
+ function resolveHeadingColor(
110
+ theme: SurfaceTheme,
111
+ emphasis: HeadingEmphasis,
112
+ color?: HeadingColor,
113
+ ): string {
114
+ if (color) {
115
+ const role = resolveRoleSemantics(theme, color);
116
+ return emphasis === 'inverse' ? role.onSolidText : role.base;
117
+ }
118
+
119
+ switch (emphasis) {
77
120
  case 'muted':
78
121
  return theme.semantics.content.muted;
79
122
  case 'subtle':
80
123
  return theme.semantics.content.subtle;
81
124
  case 'inverse':
82
125
  return theme.semantics.content.inverse;
83
- case 'primary':
84
- return theme.semantics.brand.base;
85
- case 'danger':
86
- return theme.semantics.danger.base;
87
- case 'success':
88
- return theme.semantics.success.base;
89
- case 'warning':
90
- return theme.semantics.warning.base;
91
126
  case 'default':
92
127
  default:
93
128
  return theme.semantics.content.default;
@@ -112,13 +147,21 @@ function resolveFontFamily({
112
147
 
113
148
  export function resolveHeadingRecipe(
114
149
  theme: SurfaceTheme,
115
- { align, italic = false, level, size, tone = 'default', weight }: ResolveHeadingRecipeOptions,
150
+ {
151
+ align,
152
+ color,
153
+ emphasis = 'default',
154
+ italic = false,
155
+ level,
156
+ size,
157
+ weight,
158
+ }: ResolveHeadingRecipeOptions,
116
159
  ): TextStyle {
117
160
  const recipe = resolveSizeRecipe(theme, size ?? resolveHeadingSizeFromLevel(level));
118
161
  const resolvedWeight = resolveWeight(theme, weight ?? recipe.weight);
119
162
 
120
163
  return {
121
- color: resolveToneColor(theme, tone),
164
+ color: resolveHeadingColor(theme, emphasis, color),
122
165
  elevation: 0,
123
166
  fontFamily: resolveFontFamily({ theme, weight: resolvedWeight, italic }),
124
167
  fontSize: recipe.fontSize,
@@ -2,21 +2,15 @@ import type { Responsive } from '@ankhorage/surface';
2
2
  import type React from 'react';
3
3
  import type { AccessibilityRole, TextStyle } from 'react-native';
4
4
 
5
+ import type { ZoraColor, ZoraEmphasis } from '../../internal/recipes';
5
6
  import type { ZoraBaseProps } from '../../theme/ZoraBaseProps';
6
7
 
7
8
  export type HeadingLevel = 1 | 2 | 3 | 4 | 5 | 6;
8
9
 
9
10
  export type HeadingSize = 'display' | 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';
10
11
 
11
- export type HeadingTone =
12
- | 'default'
13
- | 'muted'
14
- | 'subtle'
15
- | 'inverse'
16
- | 'primary'
17
- | 'danger'
18
- | 'success'
19
- | 'warning';
12
+ export type HeadingColor = ZoraColor;
13
+ export type HeadingEmphasis = ZoraEmphasis;
20
14
 
21
15
  export type HeadingAlign = NonNullable<TextStyle['textAlign']>;
22
16
 
@@ -28,7 +22,8 @@ export interface HeadingProps extends ZoraBaseProps {
28
22
  i18nKey?: string;
29
23
  level?: HeadingLevel;
30
24
  size?: Responsive<HeadingSize>;
31
- tone?: Responsive<HeadingTone>;
25
+ color?: Responsive<HeadingColor>;
26
+ emphasis?: Responsive<HeadingEmphasis>;
32
27
  align?: Responsive<HeadingAlign>;
33
28
  weight?: Responsive<HeadingWeight>;
34
29
  italic?: boolean;
@@ -10,20 +10,20 @@ function IconButtonInner({
10
10
  mode: _mode,
11
11
  icon,
12
12
  label,
13
- emphasis = 'ghost',
14
- tone = 'neutral',
13
+ variant = 'ghost',
14
+ color = 'neutral',
15
15
  size = 'm',
16
16
  ...props
17
17
  }: IconButtonProps) {
18
- const recipe = resolveButtonRecipe({ emphasis, tone, size });
18
+ const recipe = resolveButtonRecipe({ color, variant, size });
19
19
 
20
20
  return (
21
21
  <SurfaceIconButton
22
22
  {...props}
23
23
  icon={icon}
24
24
  accessibilityLabel={label}
25
+ color={recipe.color}
25
26
  size={recipe.size}
26
- tone={recipe.tone}
27
27
  variant={recipe.variant}
28
28
  />
29
29
  );
@@ -1,13 +1,13 @@
1
1
  import type { ButtonIconSpec } from '@ankhorage/surface';
2
2
 
3
- import type { ZoraControlSize, ZoraEmphasis, ZoraTone } from '../../internal/recipes';
3
+ import type { ZoraButtonVariant, ZoraColor, ZoraControlSize } from '../../internal/recipes';
4
4
  import type { ZoraBaseProps } from '../../theme/ZoraBaseProps';
5
5
 
6
6
  export interface IconButtonProps extends ZoraBaseProps {
7
7
  icon: ButtonIconSpec;
8
8
  label: string;
9
- emphasis?: ZoraEmphasis;
10
- tone?: ZoraTone;
9
+ variant?: ZoraButtonVariant;
10
+ color?: ZoraColor;
11
11
  size?: ZoraControlSize;
12
12
  disabled?: boolean;
13
13
  loading?: boolean;
@@ -44,9 +44,9 @@ function InputInner({
44
44
  icon={trailingAction.icon}
45
45
  label={trailingAction.label}
46
46
  disabled={disabled ?? readOnly}
47
- emphasis="ghost"
47
+ variant="ghost"
48
48
  size={size === 'l' ? 'm' : size}
49
- tone="neutral"
49
+ color="neutral"
50
50
  onPress={trailingAction.onPress}
51
51
  />
52
52
  ) : trailingIcon ? (
@@ -91,7 +91,7 @@ function MediaCardInner({
91
91
  <Box flex={{ md: 1 }} width={{ base: '100%', md: 'auto' }}>
92
92
  <Stack gap="xs">
93
93
  {eyebrow ? (
94
- <Text tone="muted" variant="caption" weight="semiBold">
94
+ <Text emphasis="muted" variant="caption" weight="semiBold">
95
95
  {eyebrow}
96
96
  </Text>
97
97
  ) : null}
@@ -100,7 +100,7 @@ function MediaCardInner({
100
100
  {badges ? <Box>{badges}</Box> : null}
101
101
  </Stack>
102
102
  {description ? (
103
- <Text tone="muted" variant="bodySmall">
103
+ <Text emphasis="muted" variant="bodySmall">
104
104
  {description}
105
105
  </Text>
106
106
  ) : null}
@@ -20,7 +20,7 @@ function MetricCardInner({
20
20
  description,
21
21
  icon,
22
22
  delta,
23
- deltaTone = 'neutral',
23
+ deltaColor = 'neutral',
24
24
  actions,
25
25
  tone = 'default',
26
26
  compact = false,
@@ -29,7 +29,7 @@ function MetricCardInner({
29
29
  const { theme } = useZoraTheme();
30
30
  const isInteractive = Boolean(onPress) && !actions;
31
31
 
32
- const badgeRecipe = resolveBadgeRecipe({ tone: deltaTone, emphasis: 'soft', size: 's' });
32
+ const badgeRecipe = resolveBadgeRecipe({ color: deltaColor, variant: 'soft', size: 's' });
33
33
  const iconColor = theme.semantics.content.muted;
34
34
 
35
35
  return (
@@ -51,14 +51,14 @@ function MetricCardInner({
51
51
  size={resolveIconSize('s')}
52
52
  />
53
53
  ) : null}
54
- <Text tone="muted" variant="caption" weight="semiBold">
54
+ <Text emphasis="muted" variant="caption" weight="semiBold">
55
55
  {label}
56
56
  </Text>
57
57
  {delta != null ? (
58
58
  <Badge
59
- emphasis={badgeRecipe.variant}
59
+ variant={badgeRecipe.variant}
60
60
  size={badgeRecipe.size}
61
- tone={badgeRecipe.tone}
61
+ color={badgeRecipe.color}
62
62
  >
63
63
  {delta}
64
64
  </Badge>
@@ -68,7 +68,7 @@ function MetricCardInner({
68
68
  <Heading level={compact ? 3 : 2}>{value}</Heading>
69
69
 
70
70
  {description ? (
71
- <Text tone="muted" variant="bodySmall">
71
+ <Text emphasis="muted" variant="bodySmall">
72
72
  {description}
73
73
  </Text>
74
74
  ) : null}
@@ -1,7 +1,7 @@
1
1
  import type { ButtonIconSpec } from '@ankhorage/surface';
2
2
  import type React from 'react';
3
3
 
4
- import type { ZoraCardTone, ZoraTone } from '../../internal/recipes';
4
+ import type { ZoraCardTone, ZoraColor } from '../../internal/recipes';
5
5
  import type { ZoraBaseProps } from '../../theme/ZoraBaseProps';
6
6
 
7
7
  export interface MetricCardProps extends ZoraBaseProps {
@@ -10,7 +10,7 @@ export interface MetricCardProps extends ZoraBaseProps {
10
10
  description?: React.ReactNode;
11
11
  icon?: ButtonIconSpec;
12
12
  delta?: React.ReactNode;
13
- deltaTone?: ZoraTone;
13
+ deltaColor?: ZoraColor;
14
14
  actions?: React.ReactNode;
15
15
  tone?: ZoraCardTone;
16
16
  compact?: boolean;
@@ -42,7 +42,7 @@ function ModalInner({
42
42
  <Stack gap="xs">
43
43
  {title ? <Heading level={3}>{title}</Heading> : null}
44
44
  {description ? (
45
- <Text tone="muted" variant="bodySmall">
45
+ <Text emphasis="muted" variant="bodySmall">
46
46
  {description}
47
47
  </Text>
48
48
  ) : null}
@@ -24,13 +24,13 @@ function ProgressInner({
24
24
  testID,
25
25
  value,
26
26
  max = 100,
27
- tone = 'primary',
27
+ color = 'primary',
28
28
  size = 'm',
29
29
  }: ProgressProps) {
30
30
  const { theme } = useZoraTheme();
31
31
  const fraction = resolveProgressFraction({ value, max });
32
32
  const height = resolveProgressHeight(size);
33
- const role = resolveProgressRole(theme, tone);
33
+ const role = resolveProgressRole(theme, color);
34
34
 
35
35
  return (
36
36
  <Box
@@ -1,17 +1,27 @@
1
1
  import type { RoleSemantics, SurfaceTheme } from '@ankhorage/surface';
2
2
 
3
- import type { ZoraControlSize, ZoraTone } from '../../internal/recipes';
3
+ import type { ZoraColor, ZoraControlSize } from '../../internal/recipes';
4
4
  import type { ZoraBaseProps } from '../../theme/ZoraBaseProps';
5
5
 
6
6
  export interface ProgressProps extends ZoraBaseProps {
7
7
  value: number;
8
8
  max?: number;
9
- tone?: ZoraTone;
9
+ color?: ZoraColor;
10
10
  size?: ZoraControlSize;
11
11
  }
12
12
 
13
- export function resolveProgressRole(theme: SurfaceTheme, tone: ZoraTone): RoleSemantics {
14
- switch (tone) {
13
+ export function resolveProgressRole(theme: SurfaceTheme, color: ZoraColor): RoleSemantics {
14
+ switch (color) {
15
+ case 'secondary':
16
+ return theme.semantics.secondary;
17
+ case 'tertiary':
18
+ return theme.semantics.accent;
19
+ case 'quaternary':
20
+ return theme.semantics.highlight;
21
+ case 'error':
22
+ return theme.semantics.error;
23
+ case 'info':
24
+ return theme.semantics.info;
15
25
  case 'primary':
16
26
  return theme.semantics.action.primary;
17
27
  case 'danger':
@@ -15,7 +15,7 @@ function RadioGroupInner<TValue extends string>({
15
15
  options,
16
16
  orientation = 'vertical',
17
17
  gap = 's',
18
- tone = 'primary',
18
+ color = 'primary',
19
19
  size = 'm',
20
20
  invalid = false,
21
21
  readOnly = false,
@@ -47,7 +47,7 @@ function RadioGroupInner<TValue extends string>({
47
47
  invalid={invalid}
48
48
  readOnly={readOnly}
49
49
  size={size}
50
- tone={tone}
50
+ color={color}
51
51
  onSelect={onValueChange}
52
52
  />
53
53
  ))}
@@ -65,7 +65,7 @@ function RadioGroupItem<TValue extends string>({
65
65
  invalid,
66
66
  readOnly,
67
67
  size,
68
- tone,
68
+ color,
69
69
  onSelect,
70
70
  }: {
71
71
  option: RadioGroupOption<TValue>;
@@ -74,7 +74,7 @@ function RadioGroupItem<TValue extends string>({
74
74
  invalid: boolean;
75
75
  readOnly: boolean;
76
76
  size: NonNullable<RadioGroupProps<TValue>['size']>;
77
- tone: NonNullable<RadioGroupProps<TValue>['tone']>;
77
+ color: NonNullable<RadioGroupProps<TValue>['color']>;
78
78
  onSelect: (value: TValue) => void;
79
79
  }) {
80
80
  return (
@@ -84,7 +84,7 @@ function RadioGroupItem<TValue extends string>({
84
84
  invalid={invalid}
85
85
  readOnly={readOnly}
86
86
  size={size}
87
- tone={tone}
87
+ color={color}
88
88
  testID={option.testID}
89
89
  onCheckedChange={(nextChecked) => {
90
90
  if (nextChecked) onSelect(option.value);
@@ -93,7 +93,7 @@ function RadioGroupItem<TValue extends string>({
93
93
  <Stack gap="xs">
94
94
  <Text>{option.label}</Text>
95
95
  {option.description ? (
96
- <Text variant="caption" tone="muted">
96
+ <Text emphasis="muted" variant="caption">
97
97
  {option.description}
98
98
  </Text>
99
99
  ) : null}
@@ -18,7 +18,7 @@ export interface RadioGroupProps<TValue extends string>
18
18
  ZoraBaseProps,
19
19
  Pick<
20
20
  Omit<SurfaceRadioProps, 'mode' | 'themeId'>,
21
- 'tone' | 'size' | 'invalid' | 'readOnly' | 'disabled'
21
+ 'color' | 'size' | 'invalid' | 'readOnly' | 'disabled'
22
22
  > {
23
23
  value: TValue;
24
24
  onValueChange: (value: TValue) => void;
@@ -14,11 +14,11 @@ function RatingInner({
14
14
  testID,
15
15
  value,
16
16
  max = 5,
17
- tone = 'warning',
17
+ color = 'warning',
18
18
  size = 'm',
19
19
  }: RatingProps) {
20
20
  const { theme } = useZoraTheme();
21
- const role = resolveRatingRole(theme, tone);
21
+ const role = resolveRatingRole(theme, color);
22
22
  const segments = resolveRatingSegments({ value, max });
23
23
  const iconSize = resolveIconSize(size);
24
24
 
@@ -1,17 +1,27 @@
1
1
  import type { RoleSemantics, SurfaceTheme } from '@ankhorage/surface';
2
2
 
3
- import type { ZoraControlSize, ZoraTone } from '../../internal/recipes';
3
+ import type { ZoraColor, ZoraControlSize } from '../../internal/recipes';
4
4
  import type { ZoraBaseProps } from '../../theme/ZoraBaseProps';
5
5
 
6
6
  export interface RatingProps extends ZoraBaseProps {
7
7
  value: number;
8
8
  max?: number;
9
- tone?: ZoraTone;
9
+ color?: ZoraColor;
10
10
  size?: ZoraControlSize;
11
11
  }
12
12
 
13
- export function resolveRatingRole(theme: SurfaceTheme, tone: ZoraTone): RoleSemantics {
14
- switch (tone) {
13
+ export function resolveRatingRole(theme: SurfaceTheme, color: ZoraColor): RoleSemantics {
14
+ switch (color) {
15
+ case 'secondary':
16
+ return theme.semantics.secondary;
17
+ case 'tertiary':
18
+ return theme.semantics.accent;
19
+ case 'quaternary':
20
+ return theme.semantics.highlight;
21
+ case 'error':
22
+ return theme.semantics.error;
23
+ case 'info':
24
+ return theme.semantics.info;
15
25
  case 'primary':
16
26
  return theme.semantics.action.primary;
17
27
  case 'danger':
@@ -28,8 +28,8 @@ function TabsInner<TValue extends string = string>({
28
28
  return (
29
29
  <Button
30
30
  key={item.value}
31
- emphasis={isActive ? 'solid' : 'ghost'}
32
- tone="neutral"
31
+ variant={isActive ? 'solid' : 'ghost'}
32
+ color="neutral"
33
33
  size={size}
34
34
  disabled={isDisabled}
35
35
  onPress={() => onValueChange(item.value)}
@@ -46,8 +46,8 @@ function TabsInner<TValue extends string = string>({
46
46
  return (
47
47
  <Button
48
48
  key={item.value}
49
- emphasis={isActive ? 'soft' : 'ghost'}
50
- tone={isActive ? 'primary' : 'neutral'}
49
+ variant={isActive ? 'soft' : 'ghost'}
50
+ color={isActive ? 'primary' : 'neutral'}
51
51
  size={size}
52
52
  disabled={isDisabled}
53
53
  onPress={() => onValueChange(item.value)}
@@ -71,15 +71,19 @@ function TabsInner<TValue extends string = string>({
71
71
  }}
72
72
  >
73
73
  <Button
74
- emphasis="ghost"
75
- tone="neutral"
74
+ variant="ghost"
75
+ color="neutral"
76
76
  size={size}
77
77
  disabled={isDisabled}
78
78
  onPress={() => onValueChange(item.value)}
79
79
  leadingIcon={item.icon}
80
80
  testID={item.testID}
81
81
  >
82
- <Text tone={isActive ? 'primary' : 'muted'} weight={isActive ? 'semiBold' : 'regular'}>
82
+ <Text
83
+ color={isActive ? 'primary' : undefined}
84
+ emphasis={isActive ? 'default' : 'muted'}
85
+ weight={isActive ? 'semiBold' : 'regular'}
86
+ >
83
87
  {item.label}
84
88
  </Text>
85
89
  {item.badge}
@@ -38,7 +38,8 @@ function TextInner({
38
38
  text,
39
39
  i18nKey,
40
40
  variant = 'body',
41
- tone = 'default',
41
+ color,
42
+ emphasis = 'default',
42
43
  align,
43
44
  weight,
44
45
  italic = false,
@@ -59,7 +60,8 @@ function TextInner({
59
60
  theme,
60
61
  breakpoint,
61
62
  variant: resolvedVariant,
62
- tone,
63
+ color,
64
+ emphasis,
63
65
  align,
64
66
  weight,
65
67
  italic,
@@ -1,2 +1,9 @@
1
1
  export { Text } from './Text';
2
- export type { TextAlign, TextProps, TextTone, TextVariant, TextWeight } from './types';
2
+ export type {
3
+ TextAlign,
4
+ TextColor,
5
+ TextEmphasis,
6
+ TextProps,
7
+ TextVariant,
8
+ TextWeight,
9
+ } from './types';
@@ -1,3 +1,4 @@
1
+ import { ZORA_COLORS, ZORA_EMPHASES } from '../../internal/colorModel';
1
2
  import type { ZoraComponentMeta } from '../../metadata';
2
3
 
3
4
  export const textMeta = {
@@ -9,7 +10,7 @@ export const textMeta = {
9
10
  label: 'Text',
10
11
  defaultProps: {
11
12
  text: 'Text',
12
- tone: 'default',
13
+ emphasis: 'default',
13
14
  variant: 'body',
14
15
  },
15
16
  },
@@ -35,11 +36,17 @@ export const textMeta = {
35
36
  enum: ['body', 'lead', 'bodySmall', 'caption', 'label', 'eyebrow', 'code'],
36
37
  default: 'body',
37
38
  },
38
- tone: {
39
+ color: {
39
40
  type: 'enum',
40
41
  category: 'Style',
41
- label: 'Tone',
42
- enum: ['default', 'muted', 'subtle', 'inverse', 'primary', 'danger', 'success', 'warning'],
42
+ label: 'Color',
43
+ enum: ZORA_COLORS,
44
+ },
45
+ emphasis: {
46
+ type: 'enum',
47
+ category: 'Style',
48
+ label: 'Emphasis',
49
+ enum: ZORA_EMPHASES,
43
50
  default: 'default',
44
51
  },
45
52
  align: {
@@ -286,31 +286,34 @@ describe('resolveTextStyle', () => {
286
286
  );
287
287
  });
288
288
 
289
- test('maps tones to semantic colors', () => {
290
- expect(resolveTextStyle({ theme, breakpoint: 'base', tone: 'default' }).color).toBe(
289
+ test('maps emphasis and color to semantic colors', () => {
290
+ expect(resolveTextStyle({ theme, breakpoint: 'base', emphasis: 'default' }).color).toBe(
291
291
  theme.semantics.content.default,
292
292
  );
293
- expect(resolveTextStyle({ theme, breakpoint: 'base', tone: 'muted' }).color).toBe(
293
+ expect(resolveTextStyle({ theme, breakpoint: 'base', emphasis: 'muted' }).color).toBe(
294
294
  theme.semantics.content.muted,
295
295
  );
296
- expect(resolveTextStyle({ theme, breakpoint: 'base', tone: 'subtle' }).color).toBe(
296
+ expect(resolveTextStyle({ theme, breakpoint: 'base', emphasis: 'subtle' }).color).toBe(
297
297
  theme.semantics.content.subtle,
298
298
  );
299
- expect(resolveTextStyle({ theme, breakpoint: 'base', tone: 'inverse' }).color).toBe(
299
+ expect(resolveTextStyle({ theme, breakpoint: 'base', emphasis: 'inverse' }).color).toBe(
300
300
  theme.semantics.content.inverse,
301
301
  );
302
- expect(resolveTextStyle({ theme, breakpoint: 'base', tone: 'primary' }).color).toBe(
303
- theme.semantics.brand.base,
302
+ expect(resolveTextStyle({ theme, breakpoint: 'base', color: 'primary' }).color).toBe(
303
+ theme.semantics.action.primary.base,
304
304
  );
305
- expect(resolveTextStyle({ theme, breakpoint: 'base', tone: 'danger' }).color).toBe(
306
- theme.semantics.danger.base,
305
+ expect(resolveTextStyle({ theme, breakpoint: 'base', color: 'danger' }).color).toBe(
306
+ theme.semantics.action.danger.base,
307
307
  );
308
- expect(resolveTextStyle({ theme, breakpoint: 'base', tone: 'success' }).color).toBe(
308
+ expect(resolveTextStyle({ theme, breakpoint: 'base', color: 'success' }).color).toBe(
309
309
  theme.semantics.success.base,
310
310
  );
311
- expect(resolveTextStyle({ theme, breakpoint: 'base', tone: 'warning' }).color).toBe(
311
+ expect(resolveTextStyle({ theme, breakpoint: 'base', color: 'warning' }).color).toBe(
312
312
  theme.semantics.warning.base,
313
313
  );
314
+ expect(
315
+ resolveTextStyle({ theme, breakpoint: 'base', color: 'primary', emphasis: 'inverse' }).color,
316
+ ).toBe(theme.semantics.action.primary.onSolidText);
314
317
  });
315
318
 
316
319
  test('allows explicit weight to override the recipe weight', () => {
@@ -339,19 +342,20 @@ describe('resolveTextStyle', () => {
339
342
  expect(style.fontFamily).toBe('ZoraMediumItalic');
340
343
  });
341
344
 
342
- test('resolves responsive variant, tone, align, and weight values', () => {
345
+ test('resolves responsive variant, color, emphasis, align, and weight values', () => {
343
346
  const style = resolveTextStyle({
344
347
  theme,
345
348
  breakpoint: 'md',
346
349
  variant: { base: 'bodySmall', md: 'lead' },
347
- tone: { base: 'muted', md: 'primary' },
350
+ emphasis: { base: 'muted', md: 'default' },
351
+ color: { base: 'neutral', md: 'primary' },
348
352
  align: { base: 'center', md: 'left' },
349
353
  weight: { base: 'regular', md: 'semiBold' },
350
354
  });
351
355
 
352
356
  expect(style.fontSize).toBe(theme.typography.sizes.l);
353
357
  expect(style.lineHeight).toBe(28);
354
- expect(style.color).toBe(theme.semantics.brand.base);
358
+ expect(style.color).toBe(theme.semantics.action.primary.base);
355
359
  expect(style.textAlign).toBe('left');
356
360
  expect(style.fontWeight).toBe(theme.typography.weights.semiBold);
357
361
  });