@adea-ai/ui 0.100.2 → 0.101.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 (116) hide show
  1. package/dist/components/composites/about-dialog/about-dialog.d.ts.map +1 -1
  2. package/dist/components/composites/about-dialog/about-dialog.js +2 -1
  3. package/dist/components/composites/about-dialog/about-dialog.js.map +1 -1
  4. package/dist/components/composites/account-menu/account-menu.d.ts +7 -0
  5. package/dist/components/composites/account-menu/account-menu.d.ts.map +1 -1
  6. package/dist/components/composites/account-menu/account-menu.js +116 -89
  7. package/dist/components/composites/account-menu/account-menu.js.map +1 -1
  8. package/dist/components/composites/help-center/help-center.d.ts.map +1 -1
  9. package/dist/components/composites/help-center/help-center.js +26 -21
  10. package/dist/components/composites/help-center/help-center.js.map +1 -1
  11. package/dist/components/composites/settings/settings.d.ts.map +1 -1
  12. package/dist/components/composites/settings/settings.js +43 -36
  13. package/dist/components/composites/settings/settings.js.map +1 -1
  14. package/dist/components/composites/stat/stat.d.ts.map +1 -1
  15. package/dist/components/composites/stat/stat.js +46 -35
  16. package/dist/components/composites/stat/stat.js.map +1 -1
  17. package/dist/components/composites/update-dialog/update-dialog.d.ts.map +1 -1
  18. package/dist/components/composites/update-dialog/update-dialog.js +73 -58
  19. package/dist/components/composites/update-dialog/update-dialog.js.map +1 -1
  20. package/dist/components/layout/page/page.d.ts.map +1 -1
  21. package/dist/components/layout/page/page.js +19 -13
  22. package/dist/components/layout/page/page.js.map +1 -1
  23. package/dist/components/theme/appearance-panel.d.ts.map +1 -1
  24. package/dist/components/theme/appearance-panel.js +37 -18
  25. package/dist/components/theme/appearance-panel.js.map +1 -1
  26. package/dist/components/ui/alert-dialog/alert-dialog.d.ts.map +1 -1
  27. package/dist/components/ui/alert-dialog/alert-dialog.js +5 -1
  28. package/dist/components/ui/alert-dialog/alert-dialog.js.map +1 -1
  29. package/dist/components/ui/card/card.d.ts.map +1 -1
  30. package/dist/components/ui/card/card.js +5 -1
  31. package/dist/components/ui/card/card.js.map +1 -1
  32. package/dist/components/ui/chart/chart-options.d.ts +3 -2
  33. package/dist/components/ui/chart/chart-options.d.ts.map +1 -1
  34. package/dist/components/ui/chart/chart-options.js +30 -9
  35. package/dist/components/ui/chart/chart-options.js.map +1 -1
  36. package/dist/components/ui/chart/chart.d.ts +4 -9
  37. package/dist/components/ui/chart/chart.d.ts.map +1 -1
  38. package/dist/components/ui/chart/chart.js +65 -10
  39. package/dist/components/ui/chart/chart.js.map +1 -1
  40. package/dist/components/ui/dialog/dialog.d.ts.map +1 -1
  41. package/dist/components/ui/dialog/dialog.js +5 -1
  42. package/dist/components/ui/dialog/dialog.js.map +1 -1
  43. package/dist/components/ui/drawer/drawer.d.ts.map +1 -1
  44. package/dist/components/ui/drawer/drawer.js +5 -1
  45. package/dist/components/ui/drawer/drawer.js.map +1 -1
  46. package/dist/components/ui/field/field.d.ts.map +1 -1
  47. package/dist/components/ui/field/field.js +2 -1
  48. package/dist/components/ui/field/field.js.map +1 -1
  49. package/dist/components/ui/item/item.d.ts +1 -1
  50. package/dist/components/ui/sheet/sheet.d.ts.map +1 -1
  51. package/dist/components/ui/sheet/sheet.js +5 -1
  52. package/dist/components/ui/sheet/sheet.js.map +1 -1
  53. package/dist/components/ui/typography/index.d.ts +3 -0
  54. package/dist/components/ui/typography/index.d.ts.map +1 -0
  55. package/dist/components/ui/typography/index.js +2 -0
  56. package/dist/components/ui/typography/typography.d.ts +84 -0
  57. package/dist/components/ui/typography/typography.d.ts.map +1 -0
  58. package/dist/components/ui/typography/typography.js +179 -0
  59. package/dist/components/ui/typography/typography.js.map +1 -0
  60. package/dist/index.d.ts +1 -0
  61. package/dist/index.d.ts.map +1 -1
  62. package/dist/index.js +2 -1
  63. package/dist/r/account-menu.json +1 -0
  64. package/dist/r/alert-dialog.json +1 -0
  65. package/dist/r/card.json +1 -0
  66. package/dist/r/dialog.json +1 -0
  67. package/dist/r/drawer.json +1 -0
  68. package/dist/r/field.json +1 -0
  69. package/dist/r/help-center.json +1 -0
  70. package/dist/r/page.json +1 -0
  71. package/dist/r/registry.json +37 -0
  72. package/dist/r/settings.json +1 -0
  73. package/dist/r/sheet.json +1 -0
  74. package/dist/r/src/components/composites/about-dialog/about-dialog.tsx +3 -2
  75. package/dist/r/src/components/composites/account-menu/account-menu.tsx +105 -66
  76. package/dist/r/src/components/composites/help-center/help-center.tsx +2 -1
  77. package/dist/r/src/components/composites/settings/settings.tsx +4 -1
  78. package/dist/r/src/components/composites/stat/stat.tsx +7 -2
  79. package/dist/r/src/components/composites/update-dialog/update-dialog.tsx +36 -24
  80. package/dist/r/src/components/layout/page/page.tsx +3 -2
  81. package/dist/r/src/components/theme/appearance-panel.tsx +13 -4
  82. package/dist/r/src/components/ui/alert-dialog/alert-dialog.tsx +2 -1
  83. package/dist/r/src/components/ui/card/card.tsx +2 -1
  84. package/dist/r/src/components/ui/chart/chart-options.ts +35 -7
  85. package/dist/r/src/components/ui/chart/chart.tsx +65 -12
  86. package/dist/r/src/components/ui/dialog/dialog.tsx +2 -1
  87. package/dist/r/src/components/ui/drawer/drawer.tsx +2 -1
  88. package/dist/r/src/components/ui/field/field.tsx +2 -3
  89. package/dist/r/src/components/ui/sheet/sheet.tsx +5 -1
  90. package/dist/r/src/components/ui/typography/index.ts +9 -0
  91. package/dist/r/src/components/ui/typography/typography.tsx +205 -0
  92. package/dist/r/stat.json +1 -0
  93. package/dist/r/theming.json +1 -0
  94. package/dist/r/typography.json +24 -0
  95. package/dist/r/update-dialog.json +1 -0
  96. package/package.json +1 -1
  97. package/registry.json +37 -0
  98. package/src/components/composites/about-dialog/about-dialog.tsx +3 -2
  99. package/src/components/composites/account-menu/account-menu.tsx +105 -66
  100. package/src/components/composites/help-center/help-center.tsx +2 -1
  101. package/src/components/composites/settings/settings.tsx +4 -1
  102. package/src/components/composites/stat/stat.tsx +7 -2
  103. package/src/components/composites/update-dialog/update-dialog.tsx +36 -24
  104. package/src/components/layout/page/page.tsx +3 -2
  105. package/src/components/theme/appearance-panel.tsx +13 -4
  106. package/src/components/ui/alert-dialog/alert-dialog.tsx +2 -1
  107. package/src/components/ui/card/card.tsx +2 -1
  108. package/src/components/ui/chart/chart-options.ts +35 -7
  109. package/src/components/ui/chart/chart.tsx +65 -12
  110. package/src/components/ui/dialog/dialog.tsx +2 -1
  111. package/src/components/ui/drawer/drawer.tsx +2 -1
  112. package/src/components/ui/field/field.tsx +2 -3
  113. package/src/components/ui/sheet/sheet.tsx +5 -1
  114. package/src/components/ui/typography/index.ts +9 -0
  115. package/src/components/ui/typography/typography.tsx +205 -0
  116. package/src/index.ts +1 -0
@@ -61,6 +61,7 @@
61
61
  "@kobalte/core@^0.13.14"
62
62
  ],
63
63
  "registryDependencies": [
64
+ "@adea-ai/ui/typography",
64
65
  "lib"
65
66
  ],
66
67
  "files": [
@@ -270,6 +271,7 @@
270
271
  "description": "",
271
272
  "dependencies": [],
272
273
  "registryDependencies": [
274
+ "@adea-ai/ui/typography",
273
275
  "lib"
274
276
  ],
275
277
  "files": [
@@ -533,6 +535,7 @@
533
535
  "lucide-solid@^1.48.0"
534
536
  ],
535
537
  "registryDependencies": [
538
+ "@adea-ai/ui/typography",
536
539
  "lib"
537
540
  ],
538
541
  "files": [
@@ -579,6 +582,7 @@
579
582
  "@corvu/drawer@^0.2.4"
580
583
  ],
581
584
  "registryDependencies": [
585
+ "@adea-ai/ui/typography",
582
586
  "lib"
583
587
  ],
584
588
  "files": [
@@ -683,6 +687,7 @@
683
687
  "registryDependencies": [
684
688
  "@adea-ai/ui/input",
685
689
  "@adea-ai/ui/label",
690
+ "@adea-ai/ui/typography",
686
691
  "lib"
687
692
  ],
688
693
  "files": [
@@ -1174,6 +1179,7 @@
1174
1179
  ],
1175
1180
  "registryDependencies": [
1176
1181
  "@adea-ai/ui/dialog",
1182
+ "@adea-ai/ui/typography",
1177
1183
  "lib"
1178
1184
  ],
1179
1185
  "files": [
@@ -1496,6 +1502,30 @@
1496
1502
  }
1497
1503
  ]
1498
1504
  },
1505
+ {
1506
+ "name": "typography",
1507
+ "type": "registry:ui",
1508
+ "title": "Typography",
1509
+ "description": "",
1510
+ "dependencies": [
1511
+ "@kobalte/core@^0.13.14"
1512
+ ],
1513
+ "registryDependencies": [
1514
+ "lib"
1515
+ ],
1516
+ "files": [
1517
+ {
1518
+ "path": "src/components/ui/typography/index.ts",
1519
+ "type": "registry:ui",
1520
+ "target": "components/ui/typography/index.ts"
1521
+ },
1522
+ {
1523
+ "path": "src/components/ui/typography/typography.tsx",
1524
+ "type": "registry:ui",
1525
+ "target": "components/ui/typography/typography.tsx"
1526
+ }
1527
+ ]
1528
+ },
1499
1529
  {
1500
1530
  "name": "app-shell",
1501
1531
  "type": "registry:ui",
@@ -1582,6 +1612,7 @@
1582
1612
  "description": "",
1583
1613
  "dependencies": [],
1584
1614
  "registryDependencies": [
1615
+ "@adea-ai/ui/typography",
1585
1616
  "lib"
1586
1617
  ],
1587
1618
  "files": [
@@ -1825,6 +1856,7 @@
1825
1856
  "registryDependencies": [
1826
1857
  "@adea-ai/ui/button",
1827
1858
  "@adea-ai/ui/dropdown-menu",
1859
+ "@adea-ai/ui/side-rail",
1828
1860
  "@adea-ai/ui/tooltip",
1829
1861
  "lib"
1830
1862
  ],
@@ -1975,6 +2007,7 @@
1975
2007
  "@adea-ai/ui/alert",
1976
2008
  "@adea-ai/ui/card",
1977
2009
  "@adea-ai/ui/kbd",
2010
+ "@adea-ai/ui/typography",
1978
2011
  "lib"
1979
2012
  ],
1980
2013
  "files": [
@@ -2053,6 +2086,7 @@
2053
2086
  "registryDependencies": [
2054
2087
  "@adea-ai/ui/sidebar-nav",
2055
2088
  "@adea-ai/ui/tabs",
2089
+ "@adea-ai/ui/typography",
2056
2090
  "lib"
2057
2091
  ],
2058
2092
  "files": [
@@ -2087,6 +2121,7 @@
2087
2121
  "lucide-solid@^1.48.0"
2088
2122
  ],
2089
2123
  "registryDependencies": [
2124
+ "@adea-ai/ui/typography",
2090
2125
  "lib"
2091
2126
  ],
2092
2127
  "files": [
@@ -2145,6 +2180,7 @@
2145
2180
  "@adea-ai/ui/button",
2146
2181
  "@adea-ai/ui/dialog",
2147
2182
  "@adea-ai/ui/progress",
2183
+ "@adea-ai/ui/typography",
2148
2184
  "lib"
2149
2185
  ],
2150
2186
  "files": [
@@ -2320,6 +2356,7 @@
2320
2356
  "@adea-ai/ui/radio-group",
2321
2357
  "@adea-ai/ui/toggle-group",
2322
2358
  "@adea-ai/ui/tooltip",
2359
+ "@adea-ai/ui/typography",
2323
2360
  "lib"
2324
2361
  ],
2325
2362
  "files": [
@@ -7,6 +7,7 @@
7
7
  "registryDependencies": [
8
8
  "@adea-ai/ui/sidebar-nav",
9
9
  "@adea-ai/ui/tabs",
10
+ "@adea-ai/ui/typography",
10
11
  "lib"
11
12
  ],
12
13
  "files": [
package/dist/r/sheet.json CHANGED
@@ -9,6 +9,7 @@
9
9
  ],
10
10
  "registryDependencies": [
11
11
  "@adea-ai/ui/dialog",
12
+ "@adea-ai/ui/typography",
12
13
  "lib"
13
14
  ],
14
15
  "files": [
@@ -94,6 +94,7 @@ export function AboutDialog(props: AboutDialogProps) {
94
94
  return (
95
95
  <Dialog open={props.open} onOpenChange={props.onOpenChange}>
96
96
  <DialogContent
97
+ class="w-96"
97
98
  onKeyDown={(event: KeyboardEvent) => {
98
99
  // Tooltip help on the identity actions cannot trap Escape in this popup.
99
100
  if (event.key === 'Escape' && !event.defaultPrevented) {
@@ -114,8 +115,8 @@ export function AboutDialog(props: AboutDialogProps) {
114
115
  }}
115
116
  onCloseAutoFocus={focus.onCloseAutoFocus}
116
117
  >
117
- <div class="flex flex-col items-center gap-3 px-6 py-8 text-center">
118
- <img src={props.appIcon} alt="" class="size-16" aria-hidden="true" />
118
+ <div class="flex flex-col items-center gap-2 text-center">
119
+ <img src={props.appIcon} alt="" class="size-14" aria-hidden="true" />
119
120
  <DialogTitle>{props.appName}</DialogTitle>
120
121
  {/* Body text on the dialog's themed surface: primary ink measures
121
122
  below AA against the lighter dialog backgrounds across schemes,
@@ -13,6 +13,7 @@ import type { ComponentProps, JSX } from 'solid-js'
13
13
  import { For, Show, createSignal, onCleanup, splitProps } from 'solid-js'
14
14
  import { cn } from '../../../lib/utils'
15
15
  import { Button, type ButtonProps } from '../../ui/button/button'
16
+ import { SideRailButton } from '../../layout/side-rail/side-rail'
16
17
  import {
17
18
  DropdownMenu,
18
19
  DropdownMenuContent,
@@ -70,6 +71,13 @@ export type AccountMenuProps = {
70
71
  hideArrow?: boolean
71
72
  /** The trigger size. Icon-only menus default to the standard icon size. */
72
73
  size?: ButtonProps['size']
74
+ /**
75
+ * Render the trigger as a `SideRailButton` row instead of a bare icon
76
+ * button: same geometry, hover treatment, and flush collapsed-rail tip as
77
+ * every other entry in the surrounding rail. The component's own tooltip
78
+ * is skipped — the rail row owns its help.
79
+ */
80
+ railTrigger?: boolean
73
81
  /** The entries above the separator. */
74
82
  items: readonly AccountMenuItem[]
75
83
  /** Which platform this is rendered on, for items that declare one. */
@@ -104,6 +112,7 @@ export function AccountMenu(props: AccountMenuProps) {
104
112
  'gutter',
105
113
  'hideArrow',
106
114
  'size',
115
+ 'railTrigger',
107
116
  'items',
108
117
  'platform',
109
118
  'authenticated',
@@ -133,83 +142,113 @@ export function AccountMenu(props: AccountMenuProps) {
133
142
  const visible = () =>
134
143
  local.items.filter((item) => !item.platform || item.platform === (local.platform ?? 'desktop'))
135
144
 
136
- return (
137
- <Tooltip open={tooltipOpen()} onOpenChange={(open) => setTooltipOpen(open && !menuOpen())}>
138
- <DropdownMenu
139
- modal={false}
140
- placement={local.placement ?? 'top-start'}
141
- gutter={local.gutter}
142
- onOpenChange={(open) => {
143
- setMenuOpen(open)
144
- if (open) setTooltipOpen(false)
145
- }}
145
+ // Built by reference at each return, not once up front: Solid fixes a node's
146
+ // owner chain when the JSX expression runs, and an eagerly created tree would
147
+ // never see the Tooltip provider below — Kobalte's TooltipTrigger then throws
148
+ // `useTooltipContext must be used within a Tooltip component`.
149
+ const menu = () => (
150
+ <DropdownMenu
151
+ modal={false}
152
+ placement={local.placement ?? 'top-start'}
153
+ gutter={local.gutter}
154
+ onOpenChange={(open) => {
155
+ setMenuOpen(open)
156
+ if (open) setTooltipOpen(false)
157
+ }}
158
+ >
159
+ <Show
160
+ when={local.railTrigger}
161
+ fallback={
162
+ <TooltipTrigger
163
+ as={AccountMenuButton}
164
+ ref={(element: HTMLButtonElement) => (trigger = element)}
165
+ variant="ghost"
166
+ size={local.size ?? 'icon-md'}
167
+ class={cn('text-muted-foreground', local.class)}
168
+ aria-label={local.label ?? 'Account and settings'}
169
+ onFocus={() => local.onIntent?.()}
170
+ onPointerEnter={() => local.onIntent?.()}
171
+ {...rest}
172
+ >
173
+ <UserRound aria-hidden="true" />
174
+ </TooltipTrigger>
175
+ }
146
176
  >
147
- <TooltipTrigger
148
- as={AccountMenuButton}
177
+ {/* Rail parity: the trigger is a SideRailButton row — the same
178
+ geometry and flush collapsed-rail tip as every other rail entry —
179
+ so the composite's own tooltip stays out of the way. */}
180
+ <DropdownMenuTrigger
181
+ as={SideRailButton}
149
182
  ref={(element: HTMLButtonElement) => (trigger = element)}
150
- variant="ghost"
151
- size={local.size ?? 'icon-md'}
152
- class={cn('text-muted-foreground', local.class)}
153
- aria-label={local.label ?? 'Account and settings'}
183
+ label={local.label ?? 'Account and settings'}
184
+ class={local.class}
154
185
  onFocus={() => local.onIntent?.()}
155
186
  onPointerEnter={() => local.onIntent?.()}
156
187
  {...rest}
157
188
  >
158
189
  <UserRound aria-hidden="true" />
159
- </TooltipTrigger>
160
- <DropdownMenuContent
161
- hideArrow={local.hideArrow}
162
- class="min-w-56 max-h-(--kb-popper-available-height) overflow-x-hidden overflow-y-auto"
163
- onCloseAutoFocus={(event) => {
164
- const selection = pendingAfterClose
165
- pendingAfterClose = undefined
166
- if (!selection) return
190
+ </DropdownMenuTrigger>
191
+ </Show>
192
+ <DropdownMenuContent
193
+ hideArrow={local.hideArrow}
194
+ class="min-w-56 max-h-(--kb-popper-available-height) overflow-x-hidden overflow-y-auto"
195
+ onCloseAutoFocus={(event) => {
196
+ const selection = pendingAfterClose
197
+ pendingAfterClose = undefined
198
+ if (!selection) return
167
199
 
168
- event.preventDefault()
169
- scheduledAfterClose = selection
170
- queueMicrotask(() => {
171
- if (scheduledAfterClose !== selection) return
172
- scheduledAfterClose = undefined
173
- selection.callback(trigger)
174
- })
175
- }}
176
- >
177
- <DropdownMenuGroup>
178
- <For each={visible()}>
179
- {(item) => (
180
- <DropdownMenuItem
181
- disabled={item.disabled}
182
- onSelect={() => {
183
- pendingAfterClose = item.onSelectAfterClose
184
- ? { callback: item.onSelectAfterClose }
185
- : undefined
186
- item.onSelect?.()
187
- }}
188
- shortcut={item.shortcut}
189
- keyshortcuts={item.keyshortcuts}
190
- >
191
- {item.icon ?? renderFallbackIcon(item.id)}
192
- <span>{item.label}</span>
193
- </DropdownMenuItem>
194
- )}
195
- </For>
196
- </DropdownMenuGroup>
197
- <Show when={local.showSession !== false}>
198
- <DropdownMenuSeparator />
199
- <DropdownMenuGroup>
200
+ event.preventDefault()
201
+ scheduledAfterClose = selection
202
+ queueMicrotask(() => {
203
+ if (scheduledAfterClose !== selection) return
204
+ scheduledAfterClose = undefined
205
+ selection.callback(trigger)
206
+ })
207
+ }}
208
+ >
209
+ <DropdownMenuGroup>
210
+ <For each={visible()}>
211
+ {(item) => (
200
212
  <DropdownMenuItem
201
- disabled={local.busy}
202
- onSelect={() => (local.authenticated ? local.onSignOut?.() : local.onSignIn?.())}
213
+ disabled={item.disabled}
214
+ onSelect={() => {
215
+ pendingAfterClose = item.onSelectAfterClose
216
+ ? { callback: item.onSelectAfterClose }
217
+ : undefined
218
+ item.onSelect?.()
219
+ }}
220
+ shortcut={item.shortcut}
221
+ keyshortcuts={item.keyshortcuts}
203
222
  >
204
- <Show when={local.authenticated} fallback={<LogIn aria-hidden="true" />}>
205
- <LogOut aria-hidden="true" />
206
- </Show>
207
- <span>{local.authenticated ? 'Sign out' : 'Sign in'}</span>
223
+ {item.icon ?? renderFallbackIcon(item.id)}
224
+ <span>{item.label}</span>
208
225
  </DropdownMenuItem>
209
- </DropdownMenuGroup>
210
- </Show>
211
- </DropdownMenuContent>
212
- </DropdownMenu>
226
+ )}
227
+ </For>
228
+ </DropdownMenuGroup>
229
+ <Show when={local.showSession !== false}>
230
+ <DropdownMenuSeparator />
231
+ <DropdownMenuGroup>
232
+ <DropdownMenuItem
233
+ disabled={local.busy}
234
+ onSelect={() => (local.authenticated ? local.onSignOut?.() : local.onSignIn?.())}
235
+ >
236
+ <Show when={local.authenticated} fallback={<LogIn aria-hidden="true" />}>
237
+ <LogOut aria-hidden="true" />
238
+ </Show>
239
+ <span>{local.authenticated ? 'Sign out' : 'Sign in'}</span>
240
+ </DropdownMenuItem>
241
+ </DropdownMenuGroup>
242
+ </Show>
243
+ </DropdownMenuContent>
244
+ </DropdownMenu>
245
+ )
246
+
247
+ if (local.railTrigger) return menu()
248
+
249
+ return (
250
+ <Tooltip open={tooltipOpen()} onOpenChange={(open) => setTooltipOpen(open && !menuOpen())}>
251
+ {menu()}
213
252
  {/* Both overlays own a Popper context; the tooltip must stay outside the menu root. */}
214
253
  <TooltipContent placement="top">{local.label ?? 'Account and settings'}</TooltipContent>
215
254
  </Tooltip>
@@ -5,6 +5,7 @@ import { ActionButton } from '../action-button'
5
5
  import { Alert, AlertDescription } from '../../ui/alert'
6
6
  import { Card, CardContent, CardHeader } from '../../ui/card'
7
7
  import { Kbd, KbdGroup } from '../../ui/kbd'
8
+ import { Heading } from '../../ui/typography'
8
9
 
9
10
  export type HelpShortcut = { label: string; keys: readonly string[] }
10
11
  export type HelpLink = { label: string; description?: string; url: string }
@@ -37,7 +38,7 @@ export function HelpCenter(props: HelpCenterProps) {
37
38
  <div class={cn('flex min-w-0 flex-col gap-5', props.class)}>
38
39
  <Show when={props.showHeader !== false}>
39
40
  <div class="flex flex-col gap-2">
40
- <h1 class="text-xl font-semibold tracking-tight">Help Center</h1>
41
+ <Heading size="page">Help Center</Heading>
41
42
  <p class="text-sm text-muted-foreground">
42
43
  Keyboard shortcuts and resources for {props.appName}.
43
44
  </p>
@@ -2,6 +2,7 @@ import type { ComponentProps, JSX } from 'solid-js'
2
2
  import { createUniqueId, Show, splitProps } from 'solid-js'
3
3
  import { createFormFieldContext, FormFieldContext } from '../../../lib/form-field'
4
4
  import { cn } from '../../../lib/utils'
5
+ import { Heading } from '../../ui/typography'
5
6
 
6
7
  /**
7
8
  * SettingsSection and SettingsRow.
@@ -43,7 +44,9 @@ export function SettingsSection(
43
44
  >
44
45
  <div class="flex items-start justify-between gap-4">
45
46
  <div class="flex min-w-0 flex-col gap-0.5">
46
- <h2 class="text-base font-semibold tracking-tight">{local.title}</h2>
47
+ <Heading as="h2" size="card">
48
+ {local.title}
49
+ </Heading>
47
50
  <Show when={local.description}>
48
51
  <p class="max-w-prose text-sm text-muted-foreground text-pretty">{local.description}</p>
49
52
  </Show>
@@ -3,6 +3,7 @@ import type { ComponentProps, JSX } from 'solid-js'
3
3
  import { Show, splitProps } from 'solid-js'
4
4
  import { Dynamic } from 'solid-js/web'
5
5
  import { cn } from '../../../lib/utils'
6
+ import { Heading, Text } from '../../ui/typography'
6
7
 
7
8
  /**
8
9
  * Stat.
@@ -53,9 +54,13 @@ export function Stat(props: StatProps) {
53
54
  >
54
55
  <div class="text-muted-foreground truncate text-xs font-medium">{local.label}</div>
55
56
  <div class="flex items-baseline gap-1">
56
- <span class="text-xl font-semibold tabular-nums tracking-tight">{local.value}</span>
57
+ <Heading as="span" size="page" numeric>
58
+ {local.value}
59
+ </Heading>
57
60
  <Show when={local.unit}>
58
- <span class="text-muted-foreground text-xs">{local.unit}</span>
61
+ <Text variant="caption" tone="muted">
62
+ {local.unit}
63
+ </Text>
59
64
  </Show>
60
65
  </div>
61
66
  <Show when={local.delta}>
@@ -33,6 +33,7 @@ import {
33
33
  } from '../../ui/dialog'
34
34
  import { createDialogFocusRestoration } from '../../ui/dialog/dialog'
35
35
  import { Progress } from '../../ui/progress'
36
+ import { Heading } from '../../ui/typography'
36
37
  import { cn } from '../../../lib/utils'
37
38
  import { formatBytes, formatReleaseDate, plainTextFromMarkdown } from '../../../lib/version-notes'
38
39
 
@@ -590,9 +591,9 @@ export function UpdateDialog(props: UpdateDialogProps) {
590
591
  <p class="text-2xs font-semibold tracking-widest text-muted-foreground uppercase">
591
592
  Installed version
592
593
  </p>
593
- <p class="text-xl font-semibold tracking-tight text-foreground">
594
+ <Heading as="p" size="page" tone="foreground">
594
595
  v{state()?.currentVersion || local.fallbackVersion || '0.1.0'}
595
- </p>
596
+ </Heading>
596
597
  <p class="text-sm text-muted-foreground">
597
598
  <Show
598
599
  when={isCurrent()}
@@ -618,19 +619,30 @@ export function UpdateDialog(props: UpdateDialogProps) {
618
619
  </Show>
619
620
  </p>
620
621
  </div>
621
- <ActionButton
622
- type="button"
623
- variant="outline"
624
- size="sm"
625
- tooltip="Check the release channel for the latest signed app version."
626
- disabled={!desktop() || working()}
627
- onClick={() => void check()}
628
- >
629
- <Show when={working()} fallback={<RefreshCw aria-hidden="true" />}>
630
- <LoaderCircle class="animate-spin" aria-hidden="true" />
622
+ <div class="flex flex-col items-end gap-2">
623
+ <ActionButton
624
+ type="button"
625
+ variant="outline"
626
+ size="sm"
627
+ tooltip="Check the release channel for the latest signed app version."
628
+ disabled={!desktop() || working()}
629
+ onClick={() => void check()}
630
+ >
631
+ <Show when={working()} fallback={<RefreshCw aria-hidden="true" />}>
632
+ <LoaderCircle class="animate-spin" aria-hidden="true" />
633
+ </Show>
634
+ {checkFailed() ? 'Retry update check' : 'Check latest version'}
635
+ </ActionButton>
636
+ {/* The up-to-date confirmation reads as the button's outcome,
637
+ so it sits directly beneath it rather than floating as a
638
+ full-width row between sections. */}
639
+ <Show when={isCurrent()}>
640
+ <p class="text-foreground flex items-center gap-2 text-sm" role="status">
641
+ <Check class="size-4 text-success" aria-hidden="true" />
642
+ {appName()} is up to date.
643
+ </p>
631
644
  </Show>
632
- {checkFailed() ? 'Retry update check' : 'Check latest version'}
633
- </ActionButton>
645
+ </div>
634
646
  </div>
635
647
  </section>
636
648
 
@@ -729,13 +741,6 @@ export function UpdateDialog(props: UpdateDialogProps) {
729
741
  </section>
730
742
  </Show>
731
743
 
732
- <Show when={isCurrent()}>
733
- <p class="text-foreground flex items-center gap-2 text-sm" role="status">
734
- <Check class="size-4 text-success" aria-hidden="true" />
735
- {appName()} is up to date.
736
- </p>
737
- </Show>
738
-
739
744
  <Show when={state()?.phase === 'installed'}>
740
745
  <p class="text-foreground flex items-center gap-2 text-sm" role="status">
741
746
  <Check class="size-4 text-success" aria-hidden="true" />
@@ -780,9 +785,16 @@ export function UpdateDialog(props: UpdateDialogProps) {
780
785
 
781
786
  <Show when={changelog()}>
782
787
  <div class="flex flex-col gap-2">
783
- <h2 id="update-changelog" class="text-sm font-semibold text-foreground">
784
- Installed changelog
785
- </h2>
788
+ <div class="flex items-center gap-2">
789
+ <h2 id="update-changelog" class="text-sm font-semibold text-foreground">
790
+ Installed changelog
791
+ </h2>
792
+ {/* The version pill identifies which build's history this is —
793
+ the same treatment the available-update heading carries. */}
794
+ <Badge variant="subtle" size="sm">
795
+ v{state()?.currentVersion || local.fallbackVersion || '0.1.0'}
796
+ </Badge>
797
+ </div>
786
798
  <p class="text-xs text-muted-foreground">
787
799
  All versions and updates included with this installation.
788
800
  </p>
@@ -1,6 +1,7 @@
1
1
  import type { ComponentProps, JSX } from 'solid-js'
2
2
  import { Show, splitProps } from 'solid-js'
3
3
  import { cn } from '../../../lib/utils'
4
+ import { Heading, headingVariants } from '../../ui/typography'
4
5
 
5
6
  /**
6
7
  * PageHeader.
@@ -44,7 +45,7 @@ export function PageHeaderTitle(props: ComponentProps<'h1'>) {
44
45
  return (
45
46
  <h1
46
47
  data-slot="page-header-title"
47
- class={cn('text-xl font-semibold tracking-tight', local.class)}
48
+ class={cn(headingVariants({ size: 'page' }), local.class)}
48
49
  {...rest}
49
50
  />
50
51
  )
@@ -92,7 +93,7 @@ export function PageSection(
92
93
  <Show when={local.title}>
93
94
  <div class="flex items-baseline justify-between gap-3">
94
95
  <div class="flex min-w-0 flex-col gap-0.5">
95
- <h2 class="text-base font-semibold tracking-tight">{local.title}</h2>
96
+ <Heading size="section">{local.title}</Heading>
96
97
  <Show when={local.description}>
97
98
  <p class="max-w-prose text-sm text-muted-foreground text-pretty">
98
99
  {local.description}
@@ -7,6 +7,7 @@ import { Button } from '../ui/button/button'
7
7
  import { RadioGroup, RadioGroupItem } from '../ui/radio-group/radio-group'
8
8
  import { ThemePicker } from './theme-picker'
9
9
  import { useTheme } from './theme-provider'
10
+ import { Heading } from '../ui/typography'
10
11
 
11
12
  /**
12
13
  * AppearancePanel.
@@ -43,7 +44,9 @@ export function AppearancePanel(props: AppearancePanelProps) {
43
44
  {/* --- 1. Appearance ------------------------------------------------- */}
44
45
  <section class="flex flex-col gap-3">
45
46
  <header class="flex flex-col gap-0.5">
46
- <h2 class="text-base font-semibold tracking-tight">Appearance</h2>
47
+ <Heading as="h2" size="card">
48
+ Appearance
49
+ </Heading>
47
50
  <p class="max-w-prose text-sm text-muted-foreground">
48
51
  Follow the system, or pin one. The theme below is chosen per appearance, so switching at
49
52
  sunset does not make you choose again.
@@ -87,7 +90,9 @@ export function AppearancePanel(props: AppearancePanelProps) {
87
90
  {/* --- 3. Accent ------------------------------------------------------ */}
88
91
  <section class="flex flex-col gap-3">
89
92
  <header class="flex flex-col gap-0.5">
90
- <h2 class="text-base font-semibold tracking-tight">Accent</h2>
93
+ <Heading as="h2" size="card">
94
+ Accent
95
+ </Heading>
91
96
  <p class="max-w-prose text-sm text-muted-foreground">
92
97
  Colours the interactive roles — the primary button, the focus ring, a selected row — on
93
98
  top of the theme above. Every preset is measured against the surface it lands on, so
@@ -130,7 +135,9 @@ export function AppearancePanel(props: AppearancePanelProps) {
130
135
  {/* --- 4. Font -------------------------------------------------------- */}
131
136
  <section class="flex flex-col gap-3">
132
137
  <header class="flex flex-col gap-0.5">
133
- <h2 class="text-base font-semibold tracking-tight">Typeface</h2>
138
+ <Heading as="h2" size="card">
139
+ Typeface
140
+ </Heading>
134
141
  <p class="max-w-prose text-sm text-muted-foreground">
135
142
  The interface face. Every option is self-hosted, so nothing is fetched at runtime and
136
143
  the choice survives going offline.
@@ -166,7 +173,9 @@ function ThemeSection(props: {
166
173
  return (
167
174
  <section class="flex flex-col gap-3">
168
175
  <header class="flex flex-col gap-0.5">
169
- <h2 class="text-base font-semibold tracking-tight">{props.title}</h2>
176
+ <Heading as="h2" size="card">
177
+ {props.title}
178
+ </Heading>
170
179
  <p class="max-w-prose text-sm text-muted-foreground">{props.description}</p>
171
180
  </header>
172
181
  <ThemePicker
@@ -7,6 +7,7 @@ import type { ComponentProps } from 'solid-js'
7
7
  import { createEffect, createSignal, splitProps } from 'solid-js'
8
8
  import { overlayMotion, overlayPositioner, overlayScrim, overlaySurface } from '../../../lib/overlay'
9
9
  import { cn } from '../../../lib/utils'
10
+ import { headingVariants } from '../typography'
10
11
 
11
12
  /**
12
13
  * AlertDialog.
@@ -117,7 +118,7 @@ export function AlertDialogTitle(props: ComponentProps<typeof KobalteAlertDialog
117
118
  const [local, rest] = splitProps(props, ['class'])
118
119
  return (
119
120
  <KobalteAlertDialog.Title
120
- class={cn('text-base leading-none font-semibold tracking-tight', local.class)}
121
+ class={cn(headingVariants({ size: 'card', leading: 'none' }), local.class)}
121
122
  {...rest}
122
123
  />
123
124
  )
@@ -1,6 +1,7 @@
1
1
  import type { ComponentProps, JSX } from 'solid-js'
2
2
  import { splitProps } from 'solid-js'
3
3
  import { cn } from '../../../lib/utils'
4
+ import { headingVariants } from '../typography'
4
5
 
5
6
  /**
6
7
  * Card.
@@ -41,7 +42,7 @@ export function CardTitle(props: ComponentProps<'div'>) {
41
42
  return (
42
43
  <div
43
44
  data-slot="card-title"
44
- class={cn('text-base leading-none font-semibold tracking-tight', local.class)}
45
+ class={cn(headingVariants({ size: 'card', leading: 'none' }), local.class)}
45
46
  {...rest}
46
47
  />
47
48
  )