@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
@@ -35,7 +35,7 @@ function HeroInner({
35
35
  <Stack align={contentAlign} gap={compact ? 's' : 'm'}>
36
36
  <Stack align={contentAlign} gap="xs">
37
37
  {eyebrow !== undefined ? (
38
- <Text align={textAlign} tone="primary" variant="eyebrow">
38
+ <Text align={textAlign} color="primary" variant="eyebrow">
39
39
  {eyebrow}
40
40
  </Text>
41
41
  ) : null}
@@ -49,7 +49,7 @@ function HeroInner({
49
49
  {description !== undefined ? (
50
50
  <Text
51
51
  align={textAlign}
52
- tone="muted"
52
+ emphasis="muted"
53
53
  variant={{ base: 'body', md: compact ? 'body' : 'lead' }}
54
54
  >
55
55
  {description}
@@ -100,9 +100,9 @@ function renderAction(action: HeroAction, role: 'primary' | 'secondary') {
100
100
  return (
101
101
  <Button
102
102
  disabled={action.disabled}
103
- emphasis={action.emphasis ?? (role === 'primary' ? 'solid' : 'soft')}
103
+ variant={action.variant ?? (role === 'primary' ? 'solid' : 'soft')}
104
104
  onPress={action.onPress}
105
- tone={action.tone ?? (role === 'primary' ? 'primary' : 'neutral')}
105
+ color={action.color ?? (role === 'primary' ? 'primary' : 'neutral')}
106
106
  >
107
107
  {action.label}
108
108
  </Button>
@@ -1,6 +1,6 @@
1
1
  import type React from 'react';
2
2
 
3
- import type { ZoraEmphasis, ZoraTone } from '../../internal/recipes';
3
+ import type { ZoraButtonVariant, ZoraColor } from '../../internal/recipes';
4
4
  import type { ZoraBaseProps } from '../../theme/ZoraBaseProps';
5
5
 
6
6
  export type HeroAlign = 'start' | 'center';
@@ -10,8 +10,8 @@ export type HeroTone = 'default' | 'subtle' | 'outline';
10
10
  export interface HeroAction {
11
11
  label: React.ReactNode;
12
12
  onPress: () => void;
13
- tone?: ZoraTone;
14
- emphasis?: ZoraEmphasis;
13
+ color?: ZoraColor;
14
+ variant?: ZoraButtonVariant;
15
15
  disabled?: boolean;
16
16
  }
17
17
 
@@ -63,7 +63,7 @@ function ImagePreviewInner({
63
63
  <Text variant="label" weight="semiBold">
64
64
  {emptyTitle}
65
65
  </Text>
66
- <Text tone="muted" variant="bodySmall">
66
+ <Text emphasis="muted" variant="bodySmall">
67
67
  {emptyDescription}
68
68
  </Text>
69
69
  </Stack>
@@ -206,12 +206,12 @@ function ImageUploadFieldInner({
206
206
  {acceptHint || maxSizeHint ? (
207
207
  <Stack gap="xs">
208
208
  {acceptHint ? (
209
- <Text tone="muted" variant="caption">
209
+ <Text emphasis="muted" variant="caption">
210
210
  {acceptHint}
211
211
  </Text>
212
212
  ) : null}
213
213
  {maxSizeHint ? (
214
- <Text tone="muted" variant="caption">
214
+ <Text emphasis="muted" variant="caption">
215
215
  {maxSizeHint}
216
216
  </Text>
217
217
  ) : null}
@@ -220,7 +220,7 @@ function ImageUploadFieldInner({
220
220
 
221
221
  {uploading ? (
222
222
  <Stack gap="xs">
223
- <Text tone="muted" variant="caption">
223
+ <Text emphasis="muted" variant="caption">
224
224
  Uploading…
225
225
  </Text>
226
226
  {progress !== null ? <Progress max={1} value={progress} /> : null}
@@ -240,9 +240,9 @@ function ImageUploadFieldInner({
240
240
  {value ? (
241
241
  <Button
242
242
  disabled={actionsDisabled || uploading || removing}
243
- emphasis="outline"
243
+ variant="outline"
244
244
  loading={removing}
245
- tone="danger"
245
+ color="danger"
246
246
  onPress={() => {
247
247
  void handleRemove();
248
248
  }}
@@ -252,7 +252,7 @@ function ImageUploadFieldInner({
252
252
  ) : null}
253
253
 
254
254
  {isRenderable ? (
255
- <Button disabled={false} emphasis="soft" tone="neutral" onPress={handlePreview}>
255
+ <Button disabled={false} variant="soft" color="neutral" onPress={handlePreview}>
256
256
  Preview
257
257
  </Button>
258
258
  ) : null}
@@ -260,7 +260,7 @@ function ImageUploadFieldInner({
260
260
 
261
261
  {!isRenderable && value?.kind === 'storage' && value.publicUrl === undefined ? (
262
262
  <Box>
263
- <Text tone="muted" variant="caption">
263
+ <Text emphasis="muted" variant="caption">
264
264
  This image is stored, but no preview URL is available yet.
265
265
  </Text>
266
266
  </Box>
@@ -279,7 +279,7 @@ function ImageUploadFieldInner({
279
279
  <Stack gap="m">
280
280
  <ImagePreview asset={value} aspectRatio={aspectRatio} />
281
281
  <Stack direction="row" justify="flex-end">
282
- <Button emphasis="soft" tone="neutral" onPress={closePreview}>
282
+ <Button variant="soft" color="neutral" onPress={closePreview}>
283
283
  Close
284
284
  </Button>
285
285
  </Stack>
@@ -99,12 +99,12 @@ function ListRowInner({
99
99
  {title}
100
100
  </Text>
101
101
  {description ? (
102
- <Text tone="muted" variant="bodySmall">
102
+ <Text emphasis="muted" variant="bodySmall">
103
103
  {description}
104
104
  </Text>
105
105
  ) : null}
106
106
  {meta ? (
107
- <Text tone="subtle" variant="caption">
107
+ <Text emphasis="subtle" variant="caption">
108
108
  {meta}
109
109
  </Text>
110
110
  ) : null}
@@ -123,7 +123,7 @@ function MessageAvatar({
123
123
  shape={avatar.shape}
124
124
  size={avatar.size ?? (compact ? 'xs' : 's')}
125
125
  source={avatar.source}
126
- tone={avatar.tone}
126
+ color={avatar.color}
127
127
  />
128
128
  );
129
129
  }
@@ -175,12 +175,12 @@ function MessageBubbleInner({
175
175
  >
176
176
  <Stack align={isSystem ? 'center' : 'flex-start'} gap={compact ? 'xxs' : 'xs'}>
177
177
  {hasAuthorName ? (
178
- <Text tone="muted" variant="caption" weight="semiBold">
178
+ <Text emphasis="muted" variant="caption" weight="semiBold">
179
179
  {authorName}
180
180
  </Text>
181
181
  ) : null}
182
182
  {text != null ? (
183
- <Text align={isSystem ? 'center' : undefined} tone={disabled ? 'muted' : 'default'}>
183
+ <Text align={isSystem ? 'center' : undefined} emphasis={disabled ? 'muted' : 'default'}>
184
184
  {text}
185
185
  </Text>
186
186
  ) : null}
@@ -193,17 +193,21 @@ function MessageBubbleInner({
193
193
  wrap="wrap"
194
194
  >
195
195
  {timestamp != null ? (
196
- <Text tone="subtle" variant="caption">
196
+ <Text emphasis="subtle" variant="caption">
197
197
  {timestamp}
198
198
  </Text>
199
199
  ) : null}
200
200
  {meta != null ? (
201
- <Text tone="subtle" variant="caption">
201
+ <Text emphasis="subtle" variant="caption">
202
202
  {meta}
203
203
  </Text>
204
204
  ) : null}
205
205
  {renderedStatus != null ? (
206
- <Text tone={status === 'failed' ? 'danger' : 'subtle'} variant="caption">
206
+ <Text
207
+ color={status === 'failed' ? 'danger' : undefined}
208
+ emphasis={status === 'failed' ? 'default' : 'subtle'}
209
+ variant="caption"
210
+ >
207
211
  {renderedStatus}
208
212
  </Text>
209
213
  ) : null}
@@ -2,7 +2,7 @@ import type React from 'react';
2
2
  import type { ImageSourcePropType } from 'react-native';
3
3
 
4
4
  import type { AvatarShape, AvatarSize } from '../../components/avatar';
5
- import type { ZoraTone } from '../../internal/recipes';
5
+ import type { ZoraColor } from '../../internal/recipes';
6
6
  import type { ZoraBaseProps } from '../../theme/ZoraBaseProps';
7
7
 
8
8
  export type MessageBubbleDirection = 'incoming' | 'outgoing' | 'system';
@@ -16,7 +16,7 @@ export interface MessageBubbleAvatar {
16
16
  label?: string;
17
17
  size?: AvatarSize;
18
18
  shape?: AvatarShape;
19
- tone?: ZoraTone;
19
+ color?: ZoraColor;
20
20
  }
21
21
 
22
22
  export interface MessageBubbleAuthor {
@@ -13,13 +13,13 @@ function NoticeInner({
13
13
  description,
14
14
  children,
15
15
  actions,
16
- tone = 'primary',
16
+ color = 'primary',
17
17
  testID,
18
18
  }: NoticeProps) {
19
19
  return (
20
20
  <Card
21
21
  description={description}
22
- eyebrow={<Badge tone={tone}>{String(tone).toUpperCase()}</Badge>}
22
+ eyebrow={<Badge color={color}>{String(color).toUpperCase()}</Badge>}
23
23
  testID={testID}
24
24
  title={title}
25
25
  tone="subtle"
@@ -1,6 +1,6 @@
1
1
  import type React from 'react';
2
2
 
3
- import type { ZoraTone } from '../../internal/recipes';
3
+ import type { ZoraColor } from '../../internal/recipes';
4
4
  import type { ZoraBaseProps } from '../../theme/ZoraBaseProps';
5
5
 
6
6
  export interface NoticeProps extends ZoraBaseProps {
@@ -8,5 +8,5 @@ export interface NoticeProps extends ZoraBaseProps {
8
8
  description?: React.ReactNode;
9
9
  children?: React.ReactNode;
10
10
  actions?: React.ReactNode;
11
- tone?: ZoraTone;
11
+ color?: ZoraColor;
12
12
  }
@@ -59,7 +59,7 @@ function PostCardAuthor({ author, compact = false }: { author: PostAuthor; compa
59
59
  shape={avatar?.shape}
60
60
  size={avatar?.size ?? (compact ? 's' : 'm')}
61
61
  source={avatar?.source}
62
- tone={avatar?.tone}
62
+ color={avatar?.color}
63
63
  />
64
64
  <Box flex={1}>
65
65
  <Stack gap="xxs">
@@ -67,7 +67,7 @@ function PostCardAuthor({ author, compact = false }: { author: PostAuthor; compa
67
67
  {author.name}
68
68
  </Text>
69
69
  {author.subtitle ? (
70
- <Text tone="muted" variant="caption">
70
+ <Text emphasis="muted" variant="caption">
71
71
  {author.subtitle}
72
72
  </Text>
73
73
  ) : null}
@@ -125,11 +125,11 @@ function PostCardActions({ actions }: { actions: readonly PostAction[] }) {
125
125
  <Button
126
126
  key={action.id}
127
127
  disabled={action.disabled}
128
- emphasis={action.selected ? 'soft' : 'ghost'}
128
+ variant={action.selected ? 'soft' : 'ghost'}
129
129
  leadingIcon={action.icon}
130
130
  onPress={action.onPress}
131
131
  size="s"
132
- tone={action.selected ? 'primary' : 'neutral'}
132
+ color={action.selected ? 'primary' : 'neutral'}
133
133
  >
134
134
  <PostActionLabel action={action} />
135
135
  </Button>
@@ -146,7 +146,7 @@ function PostCommentPreviewItem({ comment }: { comment: PostCommentPreview }) {
146
146
  <Stack gap="xxs">
147
147
  <Text variant="bodySmall">{comment.text}</Text>
148
148
  {comment.meta ? (
149
- <Text tone="subtle" variant="caption">
149
+ <Text emphasis="subtle" variant="caption">
150
150
  {comment.meta}
151
151
  </Text>
152
152
  ) : null}
@@ -3,7 +3,7 @@ import type React from 'react';
3
3
  import type { ImageSourcePropType } from 'react-native';
4
4
 
5
5
  import type { AvatarShape, AvatarSize } from '../../components/avatar';
6
- import type { ZoraCardTone, ZoraTone } from '../../internal/recipes';
6
+ import type { ZoraCardTone, ZoraColor } from '../../internal/recipes';
7
7
  import type { ZoraBaseProps } from '../../theme/ZoraBaseProps';
8
8
 
9
9
  export interface PostAuthorAvatar {
@@ -13,7 +13,7 @@ export interface PostAuthorAvatar {
13
13
  label?: string;
14
14
  size?: AvatarSize;
15
15
  shape?: AvatarShape;
16
- tone?: ZoraTone;
16
+ color?: ZoraColor;
17
17
  }
18
18
 
19
19
  export interface PostAuthor {
@@ -26,13 +26,13 @@ function SectionHeaderInner({
26
26
  <Box flex={{ md: 1 }} width={{ base: '100%', md: 'auto' }}>
27
27
  <Stack gap="xs">
28
28
  {eyebrow ? (
29
- <Text tone="muted" variant="caption" weight="semiBold">
29
+ <Text emphasis="muted" variant="caption" weight="semiBold">
30
30
  {eyebrow}
31
31
  </Text>
32
32
  ) : null}
33
33
  <Heading level={3}>{title}</Heading>
34
34
  {description ? (
35
- <Text tone="muted" variant="bodySmall">
35
+ <Text emphasis="muted" variant="bodySmall">
36
36
  {description}
37
37
  </Text>
38
38
  ) : null}
@@ -34,7 +34,7 @@ function SettingsRowInner({
34
34
  >
35
35
  {meta ? (
36
36
  <Box pt="xs">
37
- <Text tone="muted" variant="caption">
37
+ <Text emphasis="muted" variant="caption">
38
38
  {meta}
39
39
  </Text>
40
40
  </Box>
@@ -144,7 +144,7 @@ function ThemeComposerInner({
144
144
  testID={testID ? `${testID}-name-input` : undefined}
145
145
  />
146
146
  {nameError ? (
147
- <Text tone="danger" variant="bodySmall">
147
+ <Text color="danger" variant="bodySmall">
148
148
  {nameError}
149
149
  </Text>
150
150
  ) : null}
@@ -152,7 +152,7 @@ function ThemeComposerInner({
152
152
  <Stack gap="xs">
153
153
  <Text variant="label">ID</Text>
154
154
  <Text
155
- tone="muted"
155
+ emphasis="muted"
156
156
  variant="bodySmall"
157
157
  testID={testID ? `${testID}-id-display` : undefined}
158
158
  >
@@ -201,7 +201,7 @@ function ThemeComposerInner({
201
201
  />
202
202
  </Stack>
203
203
  {hexError ? (
204
- <Text tone="danger" variant="bodySmall">
204
+ <Text color="danger" variant="bodySmall">
205
205
  {hexError}
206
206
  </Text>
207
207
  ) : null}
@@ -245,41 +245,41 @@ function ThemeComposerInner({
245
245
  </Stack>
246
246
  <Stack gap="xs">
247
247
  <Text variant="label">Primary color</Text>
248
- <Text tone="muted" variant="bodySmall">
248
+ <Text emphasis="muted" variant="bodySmall">
249
249
  {value.primaryColor}
250
250
  </Text>
251
251
  </Stack>
252
252
  <Stack gap="xs">
253
253
  <Text variant="label">Harmony</Text>
254
- <Text tone="muted" variant="bodySmall">
254
+ <Text emphasis="muted" variant="bodySmall">
255
255
  {value.harmony}
256
256
  </Text>
257
257
  </Stack>
258
258
  <Heading level={4}>Heading</Heading>
259
259
  <Text>Body text — this shows default text color and weight.</Text>
260
- <Text tone="muted" variant="bodySmall">
260
+ <Text emphasis="muted" variant="bodySmall">
261
261
  Muted caption text.
262
262
  </Text>
263
263
  <Stack direction="row" gap="s" align="center">
264
- <Button tone="primary" emphasis="solid" size="m">
264
+ <Button color="primary" variant="solid" size="m">
265
265
  Primary
266
266
  </Button>
267
- <Button tone="neutral" emphasis="soft" size="m">
267
+ <Button color="neutral" variant="soft" size="m">
268
268
  Neutral
269
269
  </Button>
270
- <Button tone="danger" emphasis="ghost" size="m">
270
+ <Button color="danger" variant="ghost" size="m">
271
271
  Danger
272
272
  </Button>
273
273
  </Stack>
274
274
  <Stack direction="row" gap="s" align="center">
275
- <Badge tone="primary">Primary</Badge>
276
- <Badge tone="success" emphasis="soft">
275
+ <Badge color="primary">Primary</Badge>
276
+ <Badge color="success" variant="soft">
277
277
  Success
278
278
  </Badge>
279
- <Badge tone="warning" emphasis="soft">
279
+ <Badge color="warning" variant="soft">
280
280
  Warning
281
281
  </Badge>
282
- <Badge tone="danger" emphasis="soft">
282
+ <Badge color="danger" variant="soft">
283
283
  Danger
284
284
  </Badge>
285
285
  </Stack>
@@ -295,8 +295,8 @@ function ThemeComposerInner({
295
295
  {/* Submit */}
296
296
  {onSubmit ? (
297
297
  <Button
298
- tone="primary"
299
- emphasis="solid"
298
+ color="primary"
299
+ variant="solid"
300
300
  onPress={handleSubmit}
301
301
  testID={testID ? `${testID}-submit` : undefined}
302
302
  >
@@ -44,7 +44,7 @@ function PaletteItemInner({
44
44
  {title}
45
45
  </Heading>
46
46
  {description ? (
47
- <Text align="center" tone="muted" variant="caption">
47
+ <Text align="center" emphasis="muted" variant="caption">
48
48
  {description}
49
49
  </Text>
50
50
  ) : null}
@@ -5,14 +5,24 @@ import { Heading } from '../../components/heading';
5
5
  import { Icon } from '../../components/icon';
6
6
  import { Text } from '../../components/text';
7
7
  import { Box, Inline, Stack } from '../../foundation';
8
- import type { ZoraTone } from '../../internal/recipes';
8
+ import type { ZoraColor } from '../../internal/recipes';
9
9
  import { resolveIconSize } from '../../internal/recipes';
10
10
  import { useZoraTheme } from '../../theme/useZoraTheme';
11
11
  import { withZoraThemeScope } from '../../theme/withZoraThemeScope';
12
12
  import type { TimelineItem, TimelineProps } from './types';
13
13
 
14
- function resolveRoleSemantics(theme: SurfaceTheme, tone: ZoraTone): RoleSemantics {
15
- switch (tone) {
14
+ function resolveRoleSemantics(theme: SurfaceTheme, color: ZoraColor): RoleSemantics {
15
+ switch (color) {
16
+ case 'secondary':
17
+ return theme.semantics.secondary;
18
+ case 'tertiary':
19
+ return theme.semantics.accent;
20
+ case 'quaternary':
21
+ return theme.semantics.highlight;
22
+ case 'error':
23
+ return theme.semantics.error;
24
+ case 'info':
25
+ return theme.semantics.info;
16
26
  case 'primary':
17
27
  return theme.semantics.action.primary;
18
28
  case 'danger':
@@ -80,13 +90,13 @@ function TimelineInner({
80
90
  <Inline align="flex-start" gap="s" justify="space-between" wrap="wrap">
81
91
  <Heading level={compact ? 4 : 3}>{item.title}</Heading>
82
92
  {item.meta ? (
83
- <Text tone="muted" variant="caption">
93
+ <Text emphasis="muted" variant="caption">
84
94
  {item.meta}
85
95
  </Text>
86
96
  ) : null}
87
97
  </Inline>
88
98
  {item.description ? (
89
- <Text tone="muted" variant="bodySmall">
99
+ <Text emphasis="muted" variant="bodySmall">
90
100
  {item.description}
91
101
  </Text>
92
102
  ) : 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 { ZoraTone } from '../../internal/recipes';
4
+ import type { ZoraColor } from '../../internal/recipes';
5
5
  import type { ZoraBaseProps } from '../../theme/ZoraBaseProps';
6
6
 
7
7
  export interface TimelineItem {
@@ -9,7 +9,7 @@ export interface TimelineItem {
9
9
  title: React.ReactNode;
10
10
  description?: React.ReactNode;
11
11
  meta?: React.ReactNode;
12
- status?: ZoraTone;
12
+ status?: ZoraColor;
13
13
  icon?: ButtonIconSpec;
14
14
  testID?: string;
15
15
  }
@@ -56,7 +56,7 @@ function TreeItemInner<TId extends string = string>({
56
56
  label={isExpanded ? 'Collapse' : 'Expand'}
57
57
  onPress={() => onToggleExpand(node.id)}
58
58
  size="s"
59
- emphasis="ghost"
59
+ variant="ghost"
60
60
  />
61
61
  ) : null}
62
62
  </Stack>
@@ -1,25 +1,48 @@
1
- import { TabBar as SurfaceTabBar } from '@ankhorage/surface';
2
1
  import React from 'react';
2
+ import { Pressable, Text as ReactNativeText } from 'react-native';
3
3
 
4
- import { Surface } from '../../foundation';
4
+ import { Icon } from '../../components/icon';
5
+ import { Box, Surface } from '../../foundation';
5
6
  import {
6
7
  createTabBarItemPressHandler,
7
8
  resolveNavigationItems,
8
9
  } from '../../internal/resolveZoraNavigationItems';
10
+ import { useZoraTheme } from '../../theme/useZoraTheme';
9
11
  import { withZoraThemeScope } from '../../theme/withZoraThemeScope';
10
12
  import type { ZoraTabBarProps } from './types';
11
13
 
14
+ function resolveAccessibilityLabel(
15
+ label: React.ReactNode,
16
+ explicitLabel?: string,
17
+ ): string | undefined {
18
+ if (explicitLabel !== undefined) {
19
+ return explicitLabel;
20
+ }
21
+
22
+ if (typeof label === 'string') {
23
+ return label;
24
+ }
25
+
26
+ if (typeof label === 'number') {
27
+ return String(label);
28
+ }
29
+
30
+ return undefined;
31
+ }
32
+
12
33
  function ZoraTabBarInner({
13
34
  themeId: _themeId,
14
35
  mode: _mode,
15
36
  state,
16
37
  navigation,
17
38
  descriptors,
39
+ insets,
18
40
  routeMap,
19
41
  compact = false,
20
42
  chrome = 'raised',
21
43
  testID,
22
44
  }: ZoraTabBarProps) {
45
+ const { theme } = useZoraTheme();
23
46
  const resolved = resolveNavigationItems({
24
47
  state,
25
48
  descriptors,
@@ -27,19 +50,85 @@ function ZoraTabBarInner({
27
50
  kind: 'tab',
28
51
  });
29
52
 
30
- const items = resolved.map((item) => ({
31
- id: item.route.key,
32
- label: item.label,
33
- icon: item.metadata?.icon,
34
- badge: item.metadata?.badge,
35
- active: item.active,
36
- disabled: item.disabled,
37
- onPress: createTabBarItemPressHandler({ item, navigation }),
38
- accessibilityLabel: item.metadata?.accessibilityLabel,
39
- testID: item.metadata?.testID,
40
- }));
41
-
42
- const content = <SurfaceTabBar compact={compact} items={items} testID={testID} />;
53
+ const bottomInset = insets?.bottom ?? 0;
54
+ const minHeight = compact ? 56 : 64;
55
+ const labelSize = compact ? theme.typography.sizes.xs : theme.typography.sizes.s;
56
+ const labelWeight = theme.typography.weights.medium;
57
+ const content = (
58
+ <Box
59
+ bg="surface"
60
+ style={{
61
+ borderTopColor: theme.semantics.border.default,
62
+ borderTopWidth: 1,
63
+ flexDirection: 'row',
64
+ minHeight: minHeight + bottomInset,
65
+ paddingBottom: bottomInset,
66
+ }}
67
+ testID={testID}
68
+ >
69
+ {resolved.map((item) => {
70
+ const { active } = item;
71
+ const { disabled } = item;
72
+ const contentColor = disabled
73
+ ? theme.semantics.content.subtle
74
+ : active
75
+ ? theme.semantics.action.primary.base
76
+ : theme.semantics.content.muted;
77
+ const backgroundColor = active
78
+ ? theme.semantics.action.primary.softBg
79
+ : theme.semantics.surface.default;
80
+
81
+ return (
82
+ <Pressable
83
+ accessibilityLabel={resolveAccessibilityLabel(
84
+ item.label,
85
+ item.metadata?.accessibilityLabel,
86
+ )}
87
+ accessibilityRole="tab"
88
+ accessibilityState={{ selected: active, disabled }}
89
+ disabled={disabled}
90
+ key={item.route.key}
91
+ onPress={createTabBarItemPressHandler({ item, navigation })}
92
+ style={{
93
+ alignItems: 'center',
94
+ backgroundColor,
95
+ flex: 1,
96
+ justifyContent: 'center',
97
+ minHeight,
98
+ opacity: disabled ? 0.48 : 1,
99
+ paddingHorizontal: theme.spacing.s,
100
+ paddingVertical: compact ? theme.spacing.xs : theme.spacing.s,
101
+ }}
102
+ testID={
103
+ item.metadata?.testID ?? (testID ? `${testID}-item-${item.route.key}` : undefined)
104
+ }
105
+ >
106
+ {item.metadata?.icon ? (
107
+ <Icon
108
+ color={contentColor}
109
+ name={item.metadata.icon.name}
110
+ provider={item.metadata.icon.provider}
111
+ size={compact ? theme.spacing.m : theme.spacing.l}
112
+ />
113
+ ) : null}
114
+ <ReactNativeText
115
+ numberOfLines={1}
116
+ style={{
117
+ color: contentColor,
118
+ fontSize: labelSize,
119
+ fontWeight: labelWeight,
120
+ lineHeight: compact ? 16 : 20,
121
+ marginTop: item.metadata?.icon ? theme.spacing.xs : 0,
122
+ textAlign: 'center',
123
+ }}
124
+ >
125
+ {item.label}
126
+ </ReactNativeText>
127
+ </Pressable>
128
+ );
129
+ })}
130
+ </Box>
131
+ );
43
132
 
44
133
  if (chrome === 'none') {
45
134
  return content;