@tempoxyz/ds 0.3.6 → 0.3.9

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 (219) hide show
  1. package/dist/web/components/Accordion.js.zyzz.json +1 -1
  2. package/dist/web/components/AddressCard.css +1 -1
  3. package/dist/web/components/AddressCard.js.zyzz.json +1 -1
  4. package/dist/web/components/AgentLogo.css +1 -1
  5. package/dist/web/components/AgentLogo.js.zyzz.json +1 -1
  6. package/dist/web/components/Alert.js.zyzz.json +1 -1
  7. package/dist/web/components/AlertDialog.js.zyzz.json +1 -1
  8. package/dist/web/components/Amount.js.zyzz.json +1 -1
  9. package/dist/web/components/AmountInput.css +1 -1
  10. package/dist/web/components/AmountInput.js +1 -1
  11. package/dist/web/components/AmountInput.js.map +1 -1
  12. package/dist/web/components/AmountInput.js.zyzz.json +1 -1
  13. package/dist/web/components/AppShell.css +1 -1
  14. package/dist/web/components/AppShell.d.ts +31 -110
  15. package/dist/web/components/AppShell.d.ts.map +1 -1
  16. package/dist/web/components/AppShell.js +40 -44
  17. package/dist/web/components/AppShell.js.map +1 -1
  18. package/dist/web/components/AppShell.js.zyzz.json +1 -1
  19. package/dist/web/components/AssetChip.css +1 -1
  20. package/dist/web/components/AssetChip.js.zyzz.json +1 -1
  21. package/dist/web/components/Autocomplete.js.zyzz.json +1 -1
  22. package/dist/web/components/Avatar.js.zyzz.json +1 -1
  23. package/dist/web/components/Badge.css +1 -1
  24. package/dist/web/components/Badge.d.ts +1 -1
  25. package/dist/web/components/Badge.js.map +1 -1
  26. package/dist/web/components/Badge.js.zyzz.json +1 -1
  27. package/dist/web/components/BadgedLogo.css +1 -0
  28. package/dist/web/components/BadgedLogo.d.ts +44 -0
  29. package/dist/web/components/BadgedLogo.d.ts.map +1 -0
  30. package/dist/web/components/BadgedLogo.js +59 -0
  31. package/dist/web/components/BadgedLogo.js.map +1 -0
  32. package/dist/web/components/BadgedLogo.js.zyzz.json +1 -0
  33. package/dist/web/components/Banner.js.zyzz.json +1 -1
  34. package/dist/web/components/BarChart.css +1 -1
  35. package/dist/web/components/BarChart.d.ts +1 -1
  36. package/dist/web/components/BarChart.js.map +1 -1
  37. package/dist/web/components/BarChart.js.zyzz.json +1 -1
  38. package/dist/web/components/Breadcrumbs.js.zyzz.json +1 -1
  39. package/dist/web/components/Button.css +1 -1
  40. package/dist/web/components/Button.d.ts +40 -31
  41. package/dist/web/components/Button.d.ts.map +1 -1
  42. package/dist/web/components/Button.js +25 -8
  43. package/dist/web/components/Button.js.map +1 -1
  44. package/dist/web/components/Button.js.zyzz.json +1 -1
  45. package/dist/web/components/ButtonGroup.js.zyzz.json +1 -1
  46. package/dist/web/components/Calendar.css +1 -1
  47. package/dist/web/components/Calendar.js.zyzz.json +1 -1
  48. package/dist/web/components/Callout.js.zyzz.json +1 -1
  49. package/dist/web/components/Checkbox.css +1 -1
  50. package/dist/web/components/Checkbox.js.zyzz.json +1 -1
  51. package/dist/web/components/CheckboxGroup.js.zyzz.json +1 -1
  52. package/dist/web/components/ChoiceGroup.css +1 -1
  53. package/dist/web/components/ChoiceGroup.js.zyzz.json +1 -1
  54. package/dist/web/components/Choicebox.css +1 -1
  55. package/dist/web/components/Choicebox.js.zyzz.json +1 -1
  56. package/dist/web/components/Code.js.zyzz.json +1 -1
  57. package/dist/web/components/Combobox.css +1 -1
  58. package/dist/web/components/Combobox.js.zyzz.json +1 -1
  59. package/dist/web/components/Container.js.zyzz.json +1 -1
  60. package/dist/web/components/CopyButton.js.zyzz.json +1 -1
  61. package/dist/web/components/DatePicker.css +1 -1
  62. package/dist/web/components/DatePicker.js.zyzz.json +1 -1
  63. package/dist/web/components/Dialog.css +1 -1
  64. package/dist/web/components/Dialog.d.ts +14 -0
  65. package/dist/web/components/Dialog.d.ts.map +1 -1
  66. package/dist/web/components/Dialog.js +7 -5
  67. package/dist/web/components/Dialog.js.map +1 -1
  68. package/dist/web/components/Dialog.js.zyzz.json +1 -1
  69. package/dist/web/components/Drawer.css +1 -1
  70. package/dist/web/components/Drawer.js.zyzz.json +1 -1
  71. package/dist/web/components/Empty.js.zyzz.json +1 -1
  72. package/dist/web/components/Field.js.zyzz.json +1 -1
  73. package/dist/web/components/Fieldset.js.zyzz.json +1 -1
  74. package/dist/web/components/Frame.js.zyzz.json +1 -1
  75. package/dist/web/components/Gauge.js.zyzz.json +1 -1
  76. package/dist/web/components/GetStartedVisual.js.zyzz.json +1 -1
  77. package/dist/web/components/Grid.js.zyzz.json +1 -1
  78. package/dist/web/components/HeroVisual.js.zyzz.json +1 -1
  79. package/dist/web/components/Hex.js.zyzz.json +1 -1
  80. package/dist/web/components/IconTile.js.zyzz.json +1 -1
  81. package/dist/web/components/Identicon.js.zyzz.json +1 -1
  82. package/dist/web/components/Inline.js.zyzz.json +1 -1
  83. package/dist/web/components/Inset.js.zyzz.json +1 -1
  84. package/dist/web/components/Kbd.js.zyzz.json +1 -1
  85. package/dist/web/components/ListGroup.css +1 -1
  86. package/dist/web/components/ListGroup.d.ts +46 -4
  87. package/dist/web/components/ListGroup.d.ts.map +1 -1
  88. package/dist/web/components/ListGroup.js +11 -9
  89. package/dist/web/components/ListGroup.js.map +1 -1
  90. package/dist/web/components/ListGroup.js.zyzz.json +1 -1
  91. package/dist/web/components/LoadingDots.js.zyzz.json +1 -1
  92. package/dist/web/components/Menu.css +1 -1
  93. package/dist/web/components/Menu.js.zyzz.json +1 -1
  94. package/dist/web/components/NativeSelect.css +1 -1
  95. package/dist/web/components/NativeSelect.js.zyzz.json +1 -1
  96. package/dist/web/components/NetworkLogo.js.zyzz.json +1 -1
  97. package/dist/web/components/NumberField.js.zyzz.json +1 -1
  98. package/dist/web/components/OtpField.css +1 -1
  99. package/dist/web/components/OtpField.js.zyzz.json +1 -1
  100. package/dist/web/components/Pagination.css +1 -1
  101. package/dist/web/components/Pagination.js.zyzz.json +1 -1
  102. package/dist/web/components/Popover.css +1 -1
  103. package/dist/web/components/Popover.js.zyzz.json +1 -1
  104. package/dist/web/components/Progress.js.zyzz.json +1 -1
  105. package/dist/web/components/Qr.js.zyzz.json +1 -1
  106. package/dist/web/components/RadioGroup.css +1 -1
  107. package/dist/web/components/RadioGroup.js.zyzz.json +1 -1
  108. package/dist/web/components/SecretValue.js.zyzz.json +1 -1
  109. package/dist/web/components/Select.css +1 -1
  110. package/dist/web/components/Select.d.ts +14 -7
  111. package/dist/web/components/Select.d.ts.map +1 -1
  112. package/dist/web/components/Select.js +8 -6
  113. package/dist/web/components/Select.js.map +1 -1
  114. package/dist/web/components/Select.js.zyzz.json +1 -1
  115. package/dist/web/components/Separator.js.zyzz.json +1 -1
  116. package/dist/web/components/SidebarMenu.css +1 -1
  117. package/dist/web/components/SidebarMenu.d.ts +102 -11
  118. package/dist/web/components/SidebarMenu.d.ts.map +1 -1
  119. package/dist/web/components/SidebarMenu.js +58 -4
  120. package/dist/web/components/SidebarMenu.js.map +1 -1
  121. package/dist/web/components/SidebarMenu.js.zyzz.json +1 -1
  122. package/dist/web/components/Skeleton.js.zyzz.json +1 -1
  123. package/dist/web/components/Slider.js.zyzz.json +1 -1
  124. package/dist/web/components/Snippet.css +1 -1
  125. package/dist/web/components/Snippet.js.zyzz.json +1 -1
  126. package/dist/web/components/Spinner.css +1 -1
  127. package/dist/web/components/Spinner.d.ts +40 -12
  128. package/dist/web/components/Spinner.d.ts.map +1 -1
  129. package/dist/web/components/Spinner.js +8 -7
  130. package/dist/web/components/Spinner.js.map +1 -1
  131. package/dist/web/components/Spinner.js.zyzz.json +1 -1
  132. package/dist/web/components/SplitBar.js.zyzz.json +1 -1
  133. package/dist/web/components/SplitButton.js.zyzz.json +1 -1
  134. package/dist/web/components/Stack.js.zyzz.json +1 -1
  135. package/dist/web/components/StatusChip.js.zyzz.json +1 -1
  136. package/dist/web/components/StatusIndicator.js.zyzz.json +1 -1
  137. package/dist/web/components/StatusRow.js.zyzz.json +1 -1
  138. package/dist/web/components/Stepper.js.zyzz.json +1 -1
  139. package/dist/web/components/SuccessHero.css +1 -1
  140. package/dist/web/components/SuccessHero.d.ts.map +1 -1
  141. package/dist/web/components/SuccessHero.js +0 -2
  142. package/dist/web/components/SuccessHero.js.map +1 -1
  143. package/dist/web/components/SuccessHero.js.zyzz.json +1 -1
  144. package/dist/web/components/Surface.css +1 -1
  145. package/dist/web/components/Surface.d.ts +1 -1
  146. package/dist/web/components/Surface.js.map +1 -1
  147. package/dist/web/components/Surface.js.zyzz.json +1 -1
  148. package/dist/web/components/Switch.css +1 -1
  149. package/dist/web/components/Switch.d.ts +1 -1
  150. package/dist/web/components/Switch.js.map +1 -1
  151. package/dist/web/components/Switch.js.zyzz.json +1 -1
  152. package/dist/web/components/Table.css +1 -1
  153. package/dist/web/components/Table.js.zyzz.json +1 -1
  154. package/dist/web/components/Tabs.css +1 -1
  155. package/dist/web/components/Tabs.d.ts +9 -18
  156. package/dist/web/components/Tabs.d.ts.map +1 -1
  157. package/dist/web/components/Tabs.js.map +1 -1
  158. package/dist/web/components/Tabs.js.zyzz.json +1 -1
  159. package/dist/web/components/TempoLogo.js.zyzz.json +1 -1
  160. package/dist/web/components/TextInput.js.zyzz.json +1 -1
  161. package/dist/web/components/Textarea.css +1 -1
  162. package/dist/web/components/Textarea.js.zyzz.json +1 -1
  163. package/dist/web/components/Toast.css +1 -1
  164. package/dist/web/components/Toast.d.ts.map +1 -1
  165. package/dist/web/components/Toast.js +6 -7
  166. package/dist/web/components/Toast.js.map +1 -1
  167. package/dist/web/components/Toast.js.zyzz.json +1 -1
  168. package/dist/web/components/Token.css +1 -1
  169. package/dist/web/components/Token.d.ts.map +1 -1
  170. package/dist/web/components/Token.js +1 -1
  171. package/dist/web/components/Token.js.map +1 -1
  172. package/dist/web/components/Token.js.zyzz.json +1 -1
  173. package/dist/web/components/TokenLogo.js.zyzz.json +1 -1
  174. package/dist/web/components/Tooltip.css +1 -1
  175. package/dist/web/components/Tooltip.js.zyzz.json +1 -1
  176. package/dist/web/components/VerificationCode.js.zyzz.json +1 -1
  177. package/dist/web/components/Visual.css +1 -1
  178. package/dist/web/components/Visual.js.zyzz.json +1 -1
  179. package/dist/web/components/internal/Field.css +1 -1
  180. package/dist/web/components/internal/Field.js.zyzz.json +1 -1
  181. package/dist/web/components/internal/InputGroup.css +1 -1
  182. package/dist/web/components/internal/InputGroup.js.zyzz.json +1 -1
  183. package/dist/web/components/internal/Listbox.css +1 -1
  184. package/dist/web/components/internal/Listbox.js.zyzz.json +1 -1
  185. package/dist/web/components/internal/Streaks.js.zyzz.json +1 -1
  186. package/dist/web/components/internal/TabBar.d.ts +1 -1
  187. package/dist/web/index.d.ts +1 -0
  188. package/dist/web/index.d.ts.map +1 -1
  189. package/dist/web/index.js +1 -0
  190. package/dist/web/index.js.map +1 -1
  191. package/dist/web/index.js.zyzz.json +1 -1
  192. package/dist/web/vars.d.ts +50 -4
  193. package/dist/web/vars.d.ts.map +1 -1
  194. package/dist/web/vars.js.map +1 -1
  195. package/dist/web/vars.js.zyzz.json +1 -1
  196. package/dist/web/zyzz.config.d.ts +250 -20
  197. package/dist/web/zyzz.config.d.ts.map +1 -1
  198. package/dist/web/zyzz.config.js.zyzz.json +1 -1
  199. package/package.json +1 -1
  200. package/src/web/components/AmountInput.tsx +6 -1
  201. package/src/web/components/AppShell.tsx +64 -125
  202. package/src/web/components/Badge.tsx +1 -1
  203. package/src/web/components/BadgedLogo.tsx +125 -0
  204. package/src/web/components/BarChart.tsx +1 -1
  205. package/src/web/components/Button.tsx +66 -36
  206. package/src/web/components/Dialog.tsx +11 -0
  207. package/src/web/components/ListGroup.tsx +53 -7
  208. package/src/web/components/Select.tsx +15 -8
  209. package/src/web/components/SidebarMenu.tsx +165 -11
  210. package/src/web/components/Spinner.tsx +34 -11
  211. package/src/web/components/SuccessHero.tsx +2 -4
  212. package/src/web/components/Surface.tsx +1 -1
  213. package/src/web/components/Switch.tsx +1 -1
  214. package/src/web/components/Tabs.tsx +10 -20
  215. package/src/web/components/Toast.tsx +17 -5
  216. package/src/web/components/Token.tsx +2 -4
  217. package/src/web/components/internal/TabBar.ts +1 -1
  218. package/src/web/index.ts +1 -0
  219. package/src/web/vars.ts +43 -5
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tempoxyz/ds",
3
3
  "type": "module",
4
- "version": "0.3.6",
4
+ "version": "0.3.9",
5
5
  "license": "MIT",
6
6
  "files": [
7
7
  "DESIGN.md",
@@ -204,8 +204,13 @@ namespace styles {
204
204
  typography: 'body.b3',
205
205
  },
206
206
  '& > :is(p, [data-field-error])': { flexBasis: '100% !custom' },
207
- // A `Field.Description`, such as the balance, takes the tertiary color.
207
+ // A `Field.Description`, such as the balance, takes the tertiary color, and the negative
208
+ // color while the amount is invalid.
208
209
  '& > p': { color: 'content.tertiary' },
210
+ '&[data-invalid] > p, [data-invalid] & > p': { color: 'content.negative' },
211
+ // Focus keeps the fill at rest beside the inset focus border of the field. `:where` keeps the
212
+ // invalid and disabled fills above it.
213
+ '&:where(:has(input:focus-visible))': { backgroundColor: 'container.regular' },
209
214
  },
210
215
  },
211
216
  { id: 'tds/web/amount-input' },
@@ -54,7 +54,7 @@ function useShell() {
54
54
  * Application frame with a sticky sidebar beside a content column. `align="center"` centers both
55
55
  * on wide viewports, with the sidebar fill to the start edge and the header bar to the end edge.
56
56
  * `align="start"` pins the sidebar left with content filling the rest.
57
- * Below 1024px the sidebar moves into a drawer that `AppShell.Trigger` opens from the right edge.
57
+ * Below 1024px the sidebar moves into a drawer that `AppShell.Trigger` opens from the bottom bar.
58
58
  *
59
59
  * - Name the `Sidebar` with `aria-label`. It labels the `aside` on wide viewports and the drawer
60
60
  * dialog below 1024px.
@@ -68,9 +68,9 @@ function useShell() {
68
68
  * <AppShell.Main>
69
69
  * <AppShell.Header>
70
70
  * <AppShell.Title>API Keys</AppShell.Title>
71
- * <AppShell.Trigger />
72
71
  * </AppShell.Header>
73
72
  * </AppShell.Main>
73
+ * <AppShell.Trigger />
74
74
  * </AppShell.Root>
75
75
  *
76
76
  * @see {@link https://base-ui.com/react/components/drawer | Base UI Drawer}
@@ -81,8 +81,8 @@ function useShell() {
81
81
  */
82
82
  export namespace AppShell {
83
83
  /**
84
- * Renders the transparent 56px page header at the top of `Main`, holding the title, actions and
85
- * the compact-viewport `Trigger`. It spans the full width of `Main`.
84
+ * Renders the transparent page header at the top of `Main`, holding the title and actions. It
85
+ * spans the full width of `Main` and is at least 76px tall, so a one-row header centers on the sidebar account row.
86
86
  */
87
87
  export function Header(props: Header.Props) {
88
88
  const { className, vars, ...attributes } = props
@@ -160,8 +160,9 @@ export namespace AppShell {
160
160
  }}
161
161
  >
162
162
  <TabBar.Context.Provider value={tabBar}>
163
- {children}
163
+ {/* The bar is fixed to the bottom, so leading the DOM puts its menu button early in the tab order. */}
164
164
  <BottomBar />
165
+ {children}
165
166
  </TabBar.Context.Provider>
166
167
  </div>
167
168
  </context.Provider>
@@ -174,7 +175,7 @@ export namespace AppShell {
174
175
  /**
175
176
  * Collapses the inline sidebar to a 64px column of icons from 768px to 1023px, and opens
176
177
  * the drawer only below 768px. Give every `SidebarMenu.Item` an icon as its first child.
177
- * Absent, the sidebar opens as a drawer below 1024px.
178
+ * Absent, the sidebar opens as a drawer below 1024px, and the bottom bar shows there too.
178
179
  * @default false
179
180
  */
180
181
  collapse?: boolean | undefined
@@ -293,32 +294,26 @@ export namespace AppShell {
293
294
  }
294
295
 
295
296
  /**
296
- * Toggles the sidebar drawer from a button fixed to the top-right corner, above the drawer, whose
297
- * two bars turn into a close mark while it is open. Hidden from 1024px, where the sidebar is
298
- * always visible. It is named `Open menu` or `Close menu` and exposes `aria-expanded`. Pass
299
- * `aria-label` to replace the name, or `children` to replace the bars. With `tabBar`, the bottom
300
- * bar renders it as its floating action button below 768px instead of the top-right button.
297
+ * Adds the button that toggles the sidebar drawer to the bottom bar, after the `action` items,
298
+ * wherever the drawer replaces the sidebar. Its two bars turn into a close mark while the drawer
299
+ * is open, and the other items of the bar fade out. It is named `Open menu` or `Close menu` and
300
+ * exposes `aria-expanded`. Pass `aria-label` to replace the name, or `children` to replace the bars.
301
301
  *
302
302
  * @example
303
- * <AppShell.Trigger tabBar />
303
+ * <AppShell.Trigger />
304
304
  */
305
305
  export function Trigger(props: Trigger.Props) {
306
- const { children, className, ref, tabBar = false, vars, ...attributes } = props
307
- const shell = useShell()
306
+ const { children, ref, ...attributes } = props
308
307
  const store = use(TabBar.Context)
309
308
  const id = useId()
310
- // The bottom bar shows below 768px, so the ref follows whichever of the two buttons shows.
311
- const bar = useQuery('(max-width: 767px)') && tabBar
309
+ // Throws outside `Root`, like every other part, though the bottom bar renders the button.
310
+ useShell()
312
311
 
313
312
  // Registers on every render, so the bottom bar repeats the current props of the trigger.
314
313
  useLayoutEffect(() => {
315
- if (!store) return
316
- if (!tabBar) return store.delete(id)
317
-
318
- const { style: _, ...rest } = attributes
319
- store.set(id, {
314
+ store?.set(id, {
320
315
  active: false,
321
- attributes: { ...rest, ref: bar ? ref : undefined },
316
+ attributes: { ...attributes, ref },
322
317
  children,
323
318
  variant: 'menu',
324
319
  })
@@ -329,31 +324,12 @@ export namespace AppShell {
329
324
  return () => store.delete(id)
330
325
  }, [id, store])
331
326
 
332
- return (
333
- <BaseUi.Drawer.Trigger
334
- aria-label={shell.open ? 'Close menu' : 'Open menu'}
335
- {...attributes}
336
- {...styles.trigger({ className, style: props.style, vars })}
337
- data-app-shell-tab-bar={tabBar ? '' : undefined}
338
- handle={shell.handle}
339
- ref={bar ? undefined : ref}
340
- >
341
- {children ?? <Bars />}
342
- </BaseUi.Drawer.Trigger>
343
- )
327
+ return null
344
328
  }
345
329
 
346
330
  export namespace Trigger {
347
331
  export type Props = ComponentPropsWithRef<'button'> &
348
- zyzz.Props.Variants<typeof styles.trigger> &
349
- Pick<BaseUi.Drawer.Trigger.Props, 'nativeButton' | 'render'> & {
350
- /**
351
- * Renders the trigger as the floating action button of the bottom bar below 768px, after
352
- * the `action` items, in place of the top-right button. While the drawer is open, the
353
- * button stays above it as a close mark, and the other items of the bar fade out.
354
- */
355
- tabBar?: boolean | undefined
356
- }
332
+ Pick<BaseUi.Drawer.Trigger.Props, 'nativeButton' | 'render'>
357
333
  }
358
334
  }
359
335
 
@@ -368,9 +344,10 @@ function Bars() {
368
344
  }
369
345
 
370
346
  /**
371
- * Repeats the `SidebarMenu.Item`s that set `tabBar` in a bar fixed to the bottom edge below 768px:
347
+ * Repeats the `SidebarMenu.Item`s that set `tabBar` in a bar fixed to the bottom edge wherever the
348
+ * drawer replaces the sidebar, below 1024px or below 768px with `collapse`:
372
349
  * `tab` items as icons in a pill `<nav>`, then each `action` item as a floating action button, then
373
- * the `AppShell.Trigger` that sets `tabBar`. Renders nothing while nothing registers.
350
+ * the `AppShell.Trigger`. Renders nothing while nothing registers.
374
351
  */
375
352
  function BottomBar() {
376
353
  const store = use(TabBar.Context)!
@@ -423,16 +400,17 @@ function BottomBarItem(props: { entry: TabBar.Entry }) {
423
400
  })
424
401
  }
425
402
 
426
- /** Renders the `AppShell.Trigger` that sets `tabBar` as a floating action button. */
403
+ /** Renders the `AppShell.Trigger` as a floating action button. */
427
404
  function BottomBarTrigger(props: { entry: TabBar.Entry }) {
428
405
  const { entry } = props
406
+ const { className, style, ...attributes } = entry.attributes as AppShell.Trigger.Props
429
407
  const shell = useShell()
430
408
 
431
409
  return (
432
410
  <BaseUi.Drawer.Trigger
433
411
  aria-label={shell.open ? 'Close menu' : 'Open menu'}
434
- {...(entry.attributes as BaseUi.Drawer.Trigger.Props)}
435
- {...styles.action()}
412
+ {...(attributes as BaseUi.Drawer.Trigger.Props)}
413
+ {...styles.action({ className, style })}
436
414
  data-app-shell-menu-trigger=""
437
415
  handle={shell.handle}
438
416
  >
@@ -557,9 +535,13 @@ namespace styles {
557
535
  columnGap: '12',
558
536
  display: 'none',
559
537
  insetInline: '24',
538
+ // Without tabs the buttons end at the right edge, and the empty bar lets clicks reach the page.
539
+ justifyContent: 'flex-end',
540
+ pointerEvents: 'none',
560
541
  position: 'fixed',
561
542
  zIndex: '39 !custom',
562
543
  selectors: {
544
+ '& > *': { pointerEvents: 'auto' },
563
545
  // A bar that holds the trigger rises above the open drawer, so the trigger closes it. The
564
546
  // other items fade out and leave the drawer uncovered.
565
547
  '[data-state="open"] > &[data-app-shell-menu]': { zIndex: 'modal' },
@@ -569,6 +551,10 @@ namespace styles {
569
551
  },
570
552
  },
571
553
  '@media (max-width: 767px)': { display: 'flex' },
554
+ // A sidebar that does not collapse opens as the drawer up to 1023px, so its bar shows too.
555
+ '@media (min-width: 768px) and (max-width: 1023px)': {
556
+ selectors: { ':not([data-app-shell-collapse]) > &': { display: 'flex' } },
557
+ },
572
558
  },
573
559
  { id: 'tds/web/app-shell/bottom-bar' },
574
560
  )
@@ -632,17 +618,14 @@ namespace styles {
632
618
  marginBottom: '24',
633
619
  marginInline: '-16',
634
620
  marginTop: '-20',
635
- minHeight: '56',
621
+ // A 44px row under the sidebar header's 20px inset, so a one-row header centers on the account row.
622
+ minHeight: '4.75rem !custom',
636
623
  minWidth: '0',
624
+ paddingBottom: '12',
625
+ paddingTop: '20',
637
626
  paddingInline: '16',
638
627
  // The title starts on the 28px edge of the content below it, as the Page Header pads it.
639
628
  '@media (min-width: 640px)': { marginInline: '-1.75rem !custom', paddingInline: '28' },
640
- // Below 1024px the fixed trigger covers the end of the bar, so header actions end 8px
641
- // before it: its 40px plus its 16px inset. A collapsed sidebar hides it from 768px.
642
- '@media (max-width: 1023px)': { paddingInlineEnd: '64' },
643
- '@media (min-width: 768px) and (max-width: 1023px)': {
644
- selectors: { '[data-app-shell-collapse] > main > &': { paddingInlineEnd: '24' } },
645
- },
646
629
  },
647
630
  },
648
631
  { id: 'tds/web/app-shell/header' },
@@ -693,6 +676,13 @@ namespace styles {
693
676
  },
694
677
  },
695
678
  },
679
+ '@media (min-width: 768px) and (max-width: 1023px)': {
680
+ selectors: {
681
+ '&:not([data-app-shell-collapse]):has(> [data-app-shell-bottom-bar]) > main': {
682
+ paddingBottom: 'calc(5.5rem + env(safe-area-inset-bottom)) !custom',
683
+ },
684
+ },
685
+ },
696
686
  },
697
687
  defaultVariants: { align: 'center' },
698
688
  variants: {
@@ -710,6 +700,8 @@ namespace styles {
710
700
  { id: 'tds/web/app-shell' },
711
701
  )
712
702
 
703
+ // The Platform Wallet Sidebar pads its content by 20px, and by 32px above the header, which
704
+ // sits 32px above the menu.
713
705
  export const sidebar = variants(
714
706
  {
715
707
  base: {
@@ -719,9 +711,9 @@ namespace styles {
719
711
  flexDirection: 'column',
720
712
  flexShrink: '0 !custom',
721
713
  minHeight: '0',
722
- paddingBottom: '16',
723
- paddingInline: '12',
724
- rowGap: '16',
714
+ paddingBottom: '20',
715
+ paddingInline: '20',
716
+ rowGap: '32',
725
717
  },
726
718
  },
727
719
  { id: 'tds/web/app-shell/sidebar' },
@@ -744,7 +736,7 @@ namespace styles {
744
736
  // server-rendered markup, which always emits the wide layout.
745
737
  export const inline = style(
746
738
  {
747
- borderInlineEndColor: 'line.secondary',
739
+ borderInlineEndColor: 'line.tertiary',
748
740
  borderInlineEndStyle: 'solid',
749
741
  borderInlineEndWidth: '1px !custom',
750
742
  height: '100dvh !custom',
@@ -753,10 +745,15 @@ namespace styles {
753
745
  position: 'sticky',
754
746
  width: 'var(--sidebar-width, 16rem) !custom',
755
747
  '@media (max-width: 1023px)': { display: 'none !custom' },
756
- // A collapsed sidebar stays inline as a column of icons, which `SidebarMenu` centers.
748
+ // A collapsed sidebar stays inline as a column of icons, which `SidebarMenu` centers in 12px
749
+ // of padding.
757
750
  '@media (min-width: 768px) and (max-width: 1023px)': {
758
751
  selectors: {
759
- '&[data-app-shell-rail]': { display: 'flex !custom', width: '4rem !custom' },
752
+ '&[data-app-shell-rail]': {
753
+ display: 'flex !custom',
754
+ paddingInline: '12',
755
+ width: '4rem !custom',
756
+ },
760
757
  },
761
758
  },
762
759
  },
@@ -770,11 +767,11 @@ namespace styles {
770
767
  '--tds-sidebar-scrollbar-thumb': `${vars.color.line.primary}`,
771
768
  flex: '1 !custom',
772
769
  // Bleeding into the sidebar's inline padding puts the scrollbar at the sidebar edge.
773
- marginInline: '-12',
770
+ marginInline: '-20',
774
771
  minHeight: '0',
775
772
  overflowY: 'auto',
776
773
  overscrollBehavior: 'contain',
777
- paddingInline: '12',
774
+ paddingInline: '20',
778
775
  // A transparent track leaves only the thin thumb over the sidebar fill.
779
776
  scrollbarColor: 'var(--tds-sidebar-scrollbar-thumb) transparent !custom',
780
777
  // Classic scrollbars keep their own lane instead of covering content at the edge.
@@ -784,6 +781,8 @@ namespace styles {
784
781
  '@media (min-width: 768px) and (max-width: 1023px)': {
785
782
  selectors: {
786
783
  '[data-app-shell-rail] &': {
784
+ marginInline: '-12',
785
+ paddingInline: '12',
787
786
  scrollbarGutter: 'auto !custom',
788
787
  scrollbarWidth: 'none !custom',
789
788
  },
@@ -838,14 +837,14 @@ namespace styles {
838
837
  flexDirection: 'column',
839
838
  flexShrink: '0 !custom',
840
839
  marginTop: 'auto !custom',
841
- rowGap: '8',
840
+ rowGap: '12',
842
841
  },
843
842
  },
844
843
  { id: 'tds/web/app-shell/sidebar-footer' },
845
844
  )
846
845
 
847
846
  export const sidebarHeader = variants(
848
- { base: { flexShrink: '0 !custom', paddingTop: '16' } },
847
+ { base: { flexShrink: '0 !custom', paddingTop: '20' } },
849
848
  { id: 'tds/web/app-shell/sidebar-header' },
850
849
  )
851
850
 
@@ -945,66 +944,6 @@ namespace styles {
945
944
  { id: 'tds/web/app-shell/title' },
946
945
  )
947
946
 
948
- export const trigger = variants(
949
- {
950
- base: {
951
- alignItems: 'center',
952
- backgroundColor: 'background.elevated',
953
- borderColor: 'line.secondary',
954
- borderRadius: 'full',
955
- borderStyle: 'solid',
956
- borderWidth: 'regular',
957
- boxSizing: 'border-box',
958
- color: 'content.primary',
959
- cornerShape: 'round',
960
- cursor: 'pointer',
961
- display: 'inline-flex',
962
- height: '40',
963
- // Centers the button on the 56px header bar.
964
- insetBlockStart: '8',
965
- insetInlineEnd: '16',
966
- justifyContent: 'center',
967
- outlineColor: 'transparent !custom',
968
- outlineOffset: '0',
969
- outlineStyle: 'solid !custom',
970
- outlineWidth: '2',
971
- padding: '0',
972
- // Fixed above the drawer and its backdrop, so the same button closes what it opened.
973
- position: 'fixed',
974
- transitionDuration: '160',
975
- transitionProperty: 'background-color, outline-color, outline-offset, transform !custom',
976
- transitionTimingFunction: 'snappy',
977
- width: '40',
978
- zIndex: 'modal',
979
- selectors: {
980
- '&:active': { transform: 'scale(0.96) !custom' },
981
- '&:focus-visible': { outlineColor: 'border.focus', outlineOffset: '2' },
982
- '&:hover': { backgroundColor: 'container.regular' },
983
- // While open, the button rides out with the drawer and rests 8px outside its left edge,
984
- // so the close mark never covers the sidebar. The width matches the drawer's.
985
- '&[data-popup-open]': {
986
- transform: 'translateX(calc(8px - min(18rem, 85vw))) !custom',
987
- transitionDuration: '280',
988
- transitionTimingFunction: 'spring',
989
- },
990
- },
991
- '@media (min-width: 1024px)': { display: 'none !custom' },
992
- '@media (min-width: 768px) and (max-width: 1023px)': {
993
- selectors: { '[data-app-shell-collapse] &': { display: 'none !custom' } },
994
- },
995
- // The bottom bar renders this trigger as its floating action button.
996
- '@media (max-width: 767px)': {
997
- selectors: { '&[data-app-shell-tab-bar]': { display: 'none !custom' } },
998
- },
999
- '@media (prefers-reduced-motion: reduce)': {
1000
- transitionProperty: 'background-color, outline-color, outline-offset !custom',
1001
- selectors: { '&:active': { transform: 'none !custom' } },
1002
- },
1003
- },
1004
- },
1005
- { id: 'tds/web/app-shell/trigger' },
1006
- )
1007
-
1008
947
  export const viewport = style(
1009
948
  {
1010
949
  display: 'flex',
@@ -139,7 +139,7 @@ namespace styles {
139
139
  variant: {
140
140
  // The accent text follows the inverse content color, which turns black in dark mode.
141
141
  accent: { backgroundColor: 'accent.blue.background', color: 'inverse.content.primary' },
142
- elevated: { backgroundColor: 'background.elevated', color: 'content.primary' },
142
+ elevated: { backgroundColor: 'background.secondary', color: 'content.primary' },
143
143
  inverse: {
144
144
  backgroundColor: 'inverse.background.secondary',
145
145
  color: 'inverse.content.primary',
@@ -0,0 +1,125 @@
1
+ /** The Badged Logo: a token or app logo with a small badge at its lower trailing corner. @module */
2
+ import type { ComponentPropsWithRef } from 'react'
3
+ import { style, vars } from '../zyzz.config.js'
4
+
5
+ /**
6
+ * A logo with a small round badge on its lower trailing corner, such as the arrow that marks a
7
+ * token or an app as the destination of a transfer. The root insets the logo 6px, so the badge and
8
+ * its ring stay inside its 56px box.
9
+ *
10
+ * - Put one logo first: a `TokenLogo`, or a `BadgedLogo.Tile` for an app without artwork. The root
11
+ * sizes it to 44px.
12
+ * - Put one `BadgedLogo.Badge` with one 12px icon last.
13
+ * - Name what the logo and the badge mean in text beside it. The parts add no semantics.
14
+ *
15
+ * @example
16
+ * <BadgedLogo.Root>
17
+ * <TokenLogo symbol="USDC" />
18
+ * <BadgedLogo.Badge>
19
+ * <ArrowRight />
20
+ * </BadgedLogo.Badge>
21
+ * </BadgedLogo.Root>
22
+ *
23
+ * @see {@link https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Elements/span | MDN span element}
24
+ * @see {@link https://www.w3.org/WAI/WCAG22/Understanding/non-text-content.html | WCAG 2.2 Non-text Content}
25
+ */
26
+ export namespace BadgedLogo {
27
+ /** Renders the 20px circle of the badge, which centers one 12px icon in the primary color. */
28
+ export function Badge(props: Badge.Props) {
29
+ const { className, ...attributes } = props
30
+
31
+ return (
32
+ <span
33
+ data-badged-logo-badge=""
34
+ {...attributes}
35
+ {...styles.badge({ className, style: props.style })}
36
+ />
37
+ )
38
+ }
39
+
40
+ export namespace Badge {
41
+ export type Props = ComponentPropsWithRef<'span'>
42
+ }
43
+
44
+ /** Renders the 56px `<span>` that holds the logo and its `BadgedLogo.Badge`. */
45
+ export function Root(props: Root.Props) {
46
+ const { className, ...attributes } = props
47
+
48
+ return <span {...attributes} {...styles.root({ className, style: props.style })} />
49
+ }
50
+
51
+ export namespace Root {
52
+ export type Props = ComponentPropsWithRef<'span'>
53
+ }
54
+
55
+ /**
56
+ * Renders a 44px rounded square that stands in for the logo of an app without artwork, such as
57
+ * the first letter of its name.
58
+ */
59
+ export function Tile(props: Tile.Props) {
60
+ const { className, ...attributes } = props
61
+
62
+ return <span {...attributes} {...styles.tile({ className, style: props.style })} />
63
+ }
64
+
65
+ export namespace Tile {
66
+ export type Props = ComponentPropsWithRef<'span'>
67
+ }
68
+ }
69
+
70
+ namespace styles {
71
+ // A 2px ring in the elevated background separates the badge from the logo below it.
72
+ export const badge = style(
73
+ {
74
+ alignItems: 'center',
75
+ backgroundColor: 'background.secondary',
76
+ borderRadius: 'full',
77
+ boxShadow: `0 0 0 2px ${vars.color.background.elevated} !custom`,
78
+ boxSizing: 'border-box',
79
+ color: 'content.primary',
80
+ cornerShape: 'round',
81
+ display: 'inline-flex',
82
+ height: '20',
83
+ insetBlockEnd: '4',
84
+ insetInlineEnd: '4',
85
+ justifyContent: 'center',
86
+ position: 'absolute',
87
+ width: '20',
88
+ selectors: { '& > svg': { flexShrink: '0 !custom', height: '12', width: '12' } },
89
+ },
90
+ { id: 'tds/web/badged-logo/badge' },
91
+ )
92
+
93
+ // The logo takes 44px whatever size it sets itself, such as the 32px of a large `TokenLogo`.
94
+ export const root = style(
95
+ {
96
+ alignItems: 'center',
97
+ display: 'inline-flex',
98
+ flexShrink: '0 !custom',
99
+ justifyContent: 'center',
100
+ padding: '6',
101
+ position: 'relative',
102
+ verticalAlign: 'middle',
103
+ selectors: {
104
+ '& > :not([data-badged-logo-badge])': { height: '44', width: '44' },
105
+ },
106
+ },
107
+ { id: 'tds/web/badged-logo' },
108
+ )
109
+
110
+ export const tile = style(
111
+ {
112
+ alignItems: 'center',
113
+ backgroundColor: 'container.regular',
114
+ borderRadius: 'xs',
115
+ boxSizing: 'border-box',
116
+ color: 'content.primary',
117
+ display: 'inline-flex',
118
+ height: '44',
119
+ justifyContent: 'center',
120
+ typography: 'heading.h3',
121
+ width: '44',
122
+ },
123
+ { id: 'tds/web/badged-logo/tile' },
124
+ )
125
+ }
@@ -406,7 +406,7 @@ namespace styles {
406
406
  export const tooltip = variants(
407
407
  {
408
408
  base: {
409
- backgroundColor: 'background.elevated',
409
+ backgroundColor: 'background.menu',
410
410
  borderRadius: 'sm',
411
411
  boxShadow: 'regular',
412
412
  boxSizing: 'border-box',