@bubble-design-system/ui 1.0.1 → 1.1.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.
package/README.md CHANGED
@@ -54,16 +54,16 @@ The five rules every decision in Bubble traces back to:
54
54
 
55
55
  ## Tech stack
56
56
 
57
- | Concern | Tool |
58
- |---|---|
59
- | Framework | React 19 (works with ≥ 18.2) |
60
- | Primitives | `@base-ui/react` ≥ 1.0 (the post-rename successor to `@base-ui-components/react`) |
61
- | Styling | Plain CSS — one shipped stylesheet, hand-authored per component |
62
- | Class composition | `clsx` (re-exported as `cn()`) |
63
- | Build tool | `tsup` (ESM + CJS + dual `.d.ts`) + a 50-line Node script for CSS bundling |
64
- | Language | TypeScript 6 |
65
- | Package manager | `pnpm@10.33.0` |
66
- | Node | ≥ 20 |
57
+ | Concern | Tool |
58
+ | ----------------- | --------------------------------------------------------------------------------- |
59
+ | Framework | React 19 (works with ≥ 18.2) |
60
+ | Primitives | `@base-ui/react` ≥ 1.0 (the post-rename successor to `@base-ui-components/react`) |
61
+ | Styling | Plain CSS — one shipped stylesheet, hand-authored per component |
62
+ | Class composition | `clsx` (re-exported as `cn()`) |
63
+ | Build tool | `tsup` (ESM + CJS + dual `.d.ts`) + a 50-line Node script for CSS bundling |
64
+ | Language | TypeScript 6 |
65
+ | Package manager | `pnpm@10.33.0` |
66
+ | Node | ≥ 20 |
67
67
 
68
68
  ---
69
69
 
@@ -86,11 +86,11 @@ Then install the peer dependencies your app must have:
86
86
  npm install react react-dom @base-ui/react
87
87
  ```
88
88
 
89
- | Peer dependency | Required version |
90
- |---|---|
91
- | `react` | ≥ 18.2 |
92
- | `react-dom` | ≥ 18.2 |
93
- | `@base-ui/react` | ≥ 1.0.0 |
89
+ | Peer dependency | Required version |
90
+ | ---------------- | ---------------- |
91
+ | `react` | ≥ 18.2 |
92
+ | `react-dom` | ≥ 18.2 |
93
+ | `@base-ui/react` | ≥ 1.0.0 |
94
94
 
95
95
  ---
96
96
 
@@ -121,7 +121,11 @@ If you only want the raw CSS custom properties (no component rules), import the
121
121
 
122
122
  ```tsx
123
123
  // app/layout.tsx (Next.js App Router example)
124
- export default function RootLayout({ children }: { children: React.ReactNode }) {
124
+ export default function RootLayout({
125
+ children,
126
+ }: {
127
+ children: React.ReactNode;
128
+ }) {
125
129
  return (
126
130
  <html
127
131
  lang="en"
@@ -152,7 +156,9 @@ export function Example() {
152
156
  <Button variant="primary">Save</Button>
153
157
  <Divider />
154
158
  <Modal.Root>
155
- <Modal.Trigger render={<Button variant="secondary" />}>Open</Modal.Trigger>
159
+ <Modal.Trigger render={<Button variant="secondary" />}>
160
+ Open
161
+ </Modal.Trigger>
156
162
  <Modal.Content>
157
163
  <Modal.Title>Confirm</Modal.Title>
158
164
  <Modal.Description>Are you sure?</Modal.Description>
@@ -169,15 +175,15 @@ export function Example() {
169
175
 
170
176
  Seven `data-*` attributes on any ancestor element (typically `<html>` or `<body>`) re-skin every descendant at runtime, with no rebuild.
171
177
 
172
- | Attribute | Values | Default | What it controls |
173
- |---|---|---|---|
174
- | `data-theme` | `light` · `dark` | `light` | Semantic color mapping (background, text, border, shadow). |
175
- | `data-tone` | `vivid` · `pastel` · `soft` | `soft` | Surface model, palette saturation, control radius. `soft` is the signature look. |
176
- | `data-gray` | `slate` · `neutral` · `stone` | `slate` | The gray family used for surfaces and text. |
177
- | `data-brand` | `blue` · `violet` · `emerald` · `orange` · `mono` · `teal` | `teal` | The brand palette (`--brand-50` through `--brand-950`). |
178
- | `data-radius` | `default` · `sharp` · `soft` · `pill` | `default` | The corner radius scale (`--radius-xs` through `--radius-2xl`). |
179
- | `data-density` | `default` · `compact` · `comfortable` | `default` | Control heights and padding (`--control-h-*`, `--control-px-*`). |
180
- | `data-font` | `roboto` · `system` | `roboto` | The font pair (`--font-sans` / `--font-mono`). |
178
+ | Attribute | Values | Default | What it controls |
179
+ | -------------- | ---------------------------------------------------------- | --------- | -------------------------------------------------------------------------------- |
180
+ | `data-theme` | `light` · `dark` | `light` | Semantic color mapping (background, text, border, shadow). |
181
+ | `data-tone` | `vivid` · `pastel` · `soft` | `soft` | Surface model, palette saturation, control radius. `soft` is the signature look. |
182
+ | `data-gray` | `slate` · `neutral` · `stone` | `slate` | The gray family used for surfaces and text. |
183
+ | `data-brand` | `blue` · `violet` · `emerald` · `orange` · `mono` · `teal` | `teal` | The brand palette (`--brand-50` through `--brand-950`). |
184
+ | `data-radius` | `default` · `sharp` · `soft` · `pill` | `default` | The corner radius scale (`--radius-xs` through `--radius-2xl`). |
185
+ | `data-density` | `default` · `compact` · `comfortable` | `default` | Control heights and padding (`--control-h-*`, `--control-px-*`). |
186
+ | `data-font` | `roboto` · `system` | `roboto` | The font pair (`--font-sans` / `--font-mono`). |
181
187
 
182
188
  Toggle them with any approach you like — `setAttribute`, React state, a media-query listener, a server cookie:
183
189
 
@@ -196,10 +202,31 @@ Every component is exported from the package root:
196
202
 
197
203
  ```tsx
198
204
  import {
199
- Alert, Avatar, Badge, Button, Card, Checkbox, Container, Divider,
200
- DropdownMenu, Grid, Input, Modal, Radio, RadioGroup, Segmented,
201
- Select, Skeleton, StatusPill, Switch, Tabs, Textarea, Toast, Tooltip,
202
- useToast, cn,
205
+ Alert,
206
+ Avatar,
207
+ Badge,
208
+ Button,
209
+ Card,
210
+ Checkbox,
211
+ Container,
212
+ Divider,
213
+ DropdownMenu,
214
+ Grid,
215
+ Input,
216
+ Modal,
217
+ Radio,
218
+ RadioGroup,
219
+ Segmented,
220
+ Select,
221
+ Skeleton,
222
+ StatusPill,
223
+ Switch,
224
+ Tabs,
225
+ Textarea,
226
+ Toast,
227
+ Tooltip,
228
+ useToast,
229
+ cn,
203
230
  } from "@bubble-design-system/ui";
204
231
  ```
205
232
 
@@ -217,14 +244,14 @@ Conventions shared by all components:
217
244
 
218
245
  A static informational banner with a variant-specific icon, title, and body.
219
246
 
220
- | Prop | Type | Default | Description |
221
- |---|---|---|---|
222
- | `variant` | `"info" \| "success" \| "warning" \| "danger"` | `"info"` | Visual tone and default icon. |
223
- | `icon` | `ReactNode \| false` | variant-specific | Override the default icon, or pass `false` to hide it. |
224
- | `title` | `ReactNode` | — | Optional bold header line. |
225
- | `children` | `ReactNode` | — | The body copy, rendered in the secondary text color. |
226
- | `className` | `string` | — | Extra classes (appended after the library's). |
227
- | `...props` | `HTMLAttributes<HTMLDivElement>` (minus `title`) | — | All native div attributes. |
247
+ | Prop | Type | Default | Description |
248
+ | ----------- | ------------------------------------------------ | ---------------- | ------------------------------------------------------ |
249
+ | `variant` | `"info" \| "success" \| "warning" \| "danger"` | `"info"` | Visual tone and default icon. |
250
+ | `icon` | `ReactNode \| false` | variant-specific | Override the default icon, or pass `false` to hide it. |
251
+ | `title` | `ReactNode` | — | Optional bold header line. |
252
+ | `children` | `ReactNode` | — | The body copy, rendered in the secondary text color. |
253
+ | `className` | `string` | — | Extra classes (appended after the library's). |
254
+ | `...props` | `HTMLAttributes<HTMLDivElement>` (minus `title`) | — | All native div attributes. |
228
255
 
229
256
  ```tsx
230
257
  <Alert variant="success" title="Saved">Your changes are live.</Alert>
@@ -239,19 +266,19 @@ A static informational banner with a variant-specific icon, title, and body.
239
266
 
240
267
  Compound component built on `@base-ui/react/avatar` — handles image load failure with a fallback.
241
268
 
242
- | Sub-component | Description |
243
- |---|---|
244
- | `Avatar` (root) | Sized circular surface. |
245
- | `Avatar.Image` | The image element. |
269
+ | Sub-component | Description |
270
+ | ----------------- | --------------------------------------------------- |
271
+ | `Avatar` (root) | Sized circular surface. |
272
+ | `Avatar.Image` | The image element. |
246
273
  | `Avatar.Fallback` | Shown while the image is loading or after it fails. |
247
274
 
248
275
  **`Avatar` props:**
249
276
 
250
- | Prop | Type | Default | Description |
251
- |---|---|---|---|
252
- | `size` | `"sm" \| "md" \| "lg" \| "xl"` | `"md"` | 24 / 32 / 40 / 48 px. |
253
- | `className` | `string` | — | Extra classes. |
254
- | `...props` | Base UI `Avatar.Root` props | — | Spread to the root. |
277
+ | Prop | Type | Default | Description |
278
+ | ----------- | ------------------------------ | ------- | --------------------- |
279
+ | `size` | `"sm" \| "md" \| "lg" \| "xl"` | `"md"` | 24 / 32 / 40 / 48 px. |
280
+ | `className` | `string` | — | Extra classes. |
281
+ | `...props` | Base UI `Avatar.Root` props | — | Spread to the root. |
255
282
 
256
283
  `Avatar.Image` and `Avatar.Fallback` accept their Base UI props plus `className`.
257
284
 
@@ -268,12 +295,12 @@ Compound component built on `@base-ui/react/avatar` — handles image load failu
268
295
 
269
296
  Small inline pill for status, counts, or labels.
270
297
 
271
- | Prop | Type | Default | Description |
272
- |---|---|---|---|
273
- | `variant` | `"neutral" \| "brand" \| "success" \| "warning" \| "danger"` | `"neutral"` | Background and text color. |
274
- | `size` | `"sm" \| "md" \| "lg"` | `"md"` | Pill height and padding. |
275
- | `className` | `string` | — | Extra classes. |
276
- | `...props` | `HTMLAttributes<HTMLSpanElement>` | — | Native span attributes. |
298
+ | Prop | Type | Default | Description |
299
+ | ----------- | ------------------------------------------------------------ | ----------- | -------------------------- |
300
+ | `variant` | `"neutral" \| "brand" \| "success" \| "warning" \| "danger"` | `"neutral"` | Background and text color. |
301
+ | `size` | `"sm" \| "md" \| "lg"` | `"md"` | Pill height and padding. |
302
+ | `className` | `string` | — | Extra classes. |
303
+ | `...props` | `HTMLAttributes<HTMLSpanElement>` | — | Native span attributes. |
277
304
 
278
305
  ```tsx
279
306
  <Badge variant="success">Active</Badge>
@@ -286,12 +313,12 @@ Small inline pill for status, counts, or labels.
286
313
 
287
314
  Wraps `@base-ui/react/button`.
288
315
 
289
- | Prop | Type | Default | Description |
290
- |---|---|---|---|
291
- | `variant` | `"primary" \| "secondary" \| "destructive" \| "ghost"` | `"primary"` | Visual style. |
292
- | `size` | `"sm" \| "md" \| "lg"` | `"md"` | Maps to `--control-h-*` / `--control-px-*` so density attribute affects it. |
293
- | `className` | `string` | — | Extra classes. |
294
- | `...props` | Base UI `Button` props | — | Includes `disabled`, `type`, `onClick`, etc. |
316
+ | Prop | Type | Default | Description |
317
+ | ----------- | ------------------------------------------------------ | ----------- | --------------------------------------------------------------------------- |
318
+ | `variant` | `"primary" \| "secondary" \| "destructive" \| "ghost"` | `"primary"` | Visual style. |
319
+ | `size` | `"sm" \| "md" \| "lg"` | `"md"` | Maps to `--control-h-*` / `--control-px-*` so density attribute affects it. |
320
+ | `className` | `string` | — | Extra classes. |
321
+ | `...props` | Base UI `Button` props | — | Includes `disabled`, `type`, `onClick`, etc. |
295
322
 
296
323
  ```tsx
297
324
  <Button variant="primary" size="lg" onClick={save}>Save</Button>
@@ -305,22 +332,22 @@ Wraps `@base-ui/react/button`.
305
332
 
306
333
  Compound component for floating-pill surface content.
307
334
 
308
- | Sub-component | Description |
309
- |---|---|
310
- | `Card` (root) | The floating surface. Variant controls fill + shadow. |
311
- | `Card.Header` | Row with title + optional action. |
312
- | `Card.Title` | `<h3>` heading. |
313
- | `Card.Description` | Supporting paragraph. |
314
- | `Card.Action` | Right-aligned controls inside the header. |
315
- | `Card.Body` | Main content area. |
316
- | `Card.Footer` | Bordered footer row with right-aligned controls. |
335
+ | Sub-component | Description |
336
+ | ------------------ | ----------------------------------------------------- |
337
+ | `Card` (root) | The floating surface. Variant controls fill + shadow. |
338
+ | `Card.Header` | Row with title + optional action. |
339
+ | `Card.Title` | `<h3>` heading. |
340
+ | `Card.Description` | Supporting paragraph. |
341
+ | `Card.Action` | Right-aligned controls inside the header. |
342
+ | `Card.Body` | Main content area. |
343
+ | `Card.Footer` | Bordered footer row with right-aligned controls. |
317
344
 
318
345
  **`Card` props:**
319
346
 
320
- | Prop | Type | Default | Description |
321
- |---|---|---|---|
322
- | `variant` | `"elevated" \| "muted"` | `"elevated"` | `elevated` = white surface with shadow. `muted` = `bg-secondary`, no shadow. |
323
- | `className` | `string` | — | Extra classes. |
347
+ | Prop | Type | Default | Description |
348
+ | ----------- | ----------------------- | ------------ | ---------------------------------------------------------------------------- |
349
+ | `variant` | `"elevated" \| "muted"` | `"elevated"` | `elevated` = white surface with shadow. `muted` = `bg-secondary`, no shadow. |
350
+ | `className` | `string` | — | Extra classes. |
324
351
 
325
352
  ```tsx
326
353
  <Card>
@@ -330,12 +357,16 @@ Compound component for floating-pill surface content.
330
357
  <Card.Description>White card floating on a gray page.</Card.Description>
331
358
  </div>
332
359
  <Card.Action>
333
- <Button size="sm" variant="ghost">Manage</Button>
360
+ <Button size="sm" variant="ghost">
361
+ Manage
362
+ </Button>
334
363
  </Card.Action>
335
364
  </Card.Header>
336
365
  <Card.Body>…</Card.Body>
337
366
  <Card.Footer>
338
- <Button size="sm" variant="ghost">Cancel</Button>
367
+ <Button size="sm" variant="ghost">
368
+ Cancel
369
+ </Button>
339
370
  <Button size="sm">Save</Button>
340
371
  </Card.Footer>
341
372
  </Card>
@@ -347,11 +378,11 @@ Compound component for floating-pill surface content.
347
378
 
348
379
  Wraps `@base-ui/react/checkbox`. Supports checked, unchecked, and indeterminate states with built-in SVG indicators.
349
380
 
350
- | Prop | Type | Default | Description |
351
- |---|---|---|---|
352
- | `size` | `"sm" \| "md" \| "lg"` | `"md"` | 16 / 18 / 20 px. |
353
- | `className` | `string` | — | Extra classes on the root button. |
354
- | `...props` | Base UI `Checkbox.Root` props | — | `checked`, `defaultChecked`, `indeterminate`, `onCheckedChange`, etc. |
381
+ | Prop | Type | Default | Description |
382
+ | ----------- | ----------------------------- | ------- | --------------------------------------------------------------------- |
383
+ | `size` | `"sm" \| "md" \| "lg"` | `"md"` | 16 / 18 / 20 px. |
384
+ | `className` | `string` | — | Extra classes on the root button. |
385
+ | `...props` | Base UI `Checkbox.Root` props | — | `checked`, `defaultChecked`, `indeterminate`, `onCheckedChange`, etc. |
355
386
 
356
387
  ```tsx
357
388
  <Checkbox defaultChecked />
@@ -369,9 +400,15 @@ Layout primitives. `Container` centers content and applies page margins. `Grid`
369
400
  <Container size="lg">
370
401
  <Grid>
371
402
  <Grid.Col span={12}>full row</Grid.Col>
372
- <Grid.Col span={6} lgSpan={4}>half on mobile, third on lg</Grid.Col>
373
- <Grid.Col span={6} lgSpan={4}>…</Grid.Col>
374
- <Grid.Col span={12} lgSpan={4}>…</Grid.Col>
403
+ <Grid.Col span={6} lgSpan={4}>
404
+ half on mobile, third on lg
405
+ </Grid.Col>
406
+ <Grid.Col span={6} lgSpan={4}>
407
+
408
+ </Grid.Col>
409
+ <Grid.Col span={12} lgSpan={4}>
410
+
411
+ </Grid.Col>
375
412
  </Grid>
376
413
  </Container>
377
414
  ```
@@ -388,11 +425,11 @@ Layout primitives. `Container` centers content and applies page margins. `Grid`
388
425
 
389
426
  Horizontal or vertical separator with a semantic role from `@base-ui/react/separator`.
390
427
 
391
- | Prop | Type | Default | Description |
392
- |---|---|---|---|
393
- | `orientation` | `"horizontal" \| "vertical"` | `"horizontal"` | Layout direction. |
394
- | `className` | `string` | — | Extra classes. |
395
- | `...props` | Base UI `Separator` props | — | Spread to the underlying element. |
428
+ | Prop | Type | Default | Description |
429
+ | ------------- | ---------------------------- | -------------- | --------------------------------- |
430
+ | `orientation` | `"horizontal" \| "vertical"` | `"horizontal"` | Layout direction. |
431
+ | `className` | `string` | — | Extra classes. |
432
+ | `...props` | Base UI `Separator` props | — | Spread to the underlying element. |
396
433
 
397
434
  ```tsx
398
435
  <Divider />
@@ -407,27 +444,27 @@ Horizontal or vertical separator with a semantic role from `@base-ui/react/separ
407
444
 
408
445
  Compound component built on `@base-ui/react/menu`. Supports items, checkbox items, radio groups, labels, and separators.
409
446
 
410
- | Sub-component | Description |
411
- |---|---|
412
- | `DropdownMenu.Root` | The state container. |
413
- | `DropdownMenu.Trigger` | The element that opens the menu. |
414
- | `DropdownMenu.Content` | The portalled popup. |
415
- | `DropdownMenu.Item` | A selectable row. |
447
+ | Sub-component | Description |
448
+ | --------------------------- | ---------------------------------------- |
449
+ | `DropdownMenu.Root` | The state container. |
450
+ | `DropdownMenu.Trigger` | The element that opens the menu. |
451
+ | `DropdownMenu.Content` | The portalled popup. |
452
+ | `DropdownMenu.Item` | A selectable row. |
416
453
  | `DropdownMenu.CheckboxItem` | A toggleable row with a check indicator. |
417
- | `DropdownMenu.RadioGroup` | Wrapper for radio items. |
418
- | `DropdownMenu.RadioItem` | A single radio choice. |
419
- | `DropdownMenu.Group` | Logical group of items. |
420
- | `DropdownMenu.Label` | Uppercase group label. |
421
- | `DropdownMenu.Separator` | Thin horizontal divider. |
454
+ | `DropdownMenu.RadioGroup` | Wrapper for radio items. |
455
+ | `DropdownMenu.RadioItem` | A single radio choice. |
456
+ | `DropdownMenu.Group` | Logical group of items. |
457
+ | `DropdownMenu.Label` | Uppercase group label. |
458
+ | `DropdownMenu.Separator` | Thin horizontal divider. |
422
459
 
423
460
  **`DropdownMenu.Content` props:**
424
461
 
425
- | Prop | Type | Default | Description |
426
- |---|---|---|---|
427
- | `sideOffset` | `number` | `6` | Distance in px from the trigger. |
428
- | `align` | `"start" \| "center" \| "end"` | `"start"` | Alignment relative to the trigger. |
429
- | `className` | `string` | — | Extra classes on the popup. |
430
- | `...props` | Base UI `Menu.Popup` props | — | Spread to the popup. |
462
+ | Prop | Type | Default | Description |
463
+ | ------------ | ------------------------------ | --------- | ---------------------------------- |
464
+ | `sideOffset` | `number` | `6` | Distance in px from the trigger. |
465
+ | `align` | `"start" \| "center" \| "end"` | `"start"` | Alignment relative to the trigger. |
466
+ | `className` | `string` | — | Extra classes on the popup. |
467
+ | `...props` | Base UI `Menu.Popup` props | — | Spread to the popup. |
431
468
 
432
469
  ```tsx
433
470
  <DropdownMenu.Root>
@@ -448,12 +485,12 @@ Compound component built on `@base-ui/react/menu`. Supports items, checkbox item
448
485
 
449
486
  Wraps `@base-ui/react/input`. Includes built-in invalid styling via `aria-invalid`.
450
487
 
451
- | Prop | Type | Default | Description |
452
- |---|---|---|---|
453
- | `size` | `"sm" \| "md" \| "lg"` | `"md"` | Density-aware control height. |
454
- | `invalid` | `boolean` | — | Sets `aria-invalid` and applies the danger border + focus ring. |
455
- | `className` | `string` | — | Extra classes. |
456
- | `...props` | Base UI `Input` props (minus `size`) | — | All native input attributes: `value`, `placeholder`, `type`, `onChange`, `disabled`, etc. |
488
+ | Prop | Type | Default | Description |
489
+ | ----------- | ------------------------------------ | ------- | ----------------------------------------------------------------------------------------- |
490
+ | `size` | `"sm" \| "md" \| "lg"` | `"md"` | Density-aware control height. |
491
+ | `invalid` | `boolean` | — | Sets `aria-invalid` and applies the danger border + focus ring. |
492
+ | `className` | `string` | — | Extra classes. |
493
+ | `...props` | Base UI `Input` props (minus `size`) | — | All native input attributes: `value`, `placeholder`, `type`, `onChange`, `disabled`, etc. |
457
494
 
458
495
  ```tsx
459
496
  <Input placeholder="Email" />
@@ -466,22 +503,22 @@ Wraps `@base-ui/react/input`. Includes built-in invalid styling via `aria-invali
466
503
 
467
504
  Compound component built on `@base-ui/react/dialog`. Renders into a portal, with backdrop blur and scale-in animation.
468
505
 
469
- | Sub-component | Description |
470
- |---|---|
471
- | `Modal.Root` | Open-state container. |
472
- | `Modal.Trigger` | Element that opens the modal. |
473
- | `Modal.Close` | Element that closes the modal. |
474
- | `Modal.Content` | The portalled popup with backdrop. |
475
- | `Modal.Title` | Heading text. |
476
- | `Modal.Description` | Sub-text under the title. |
506
+ | Sub-component | Description |
507
+ | ------------------- | ---------------------------------- |
508
+ | `Modal.Root` | Open-state container. |
509
+ | `Modal.Trigger` | Element that opens the modal. |
510
+ | `Modal.Close` | Element that closes the modal. |
511
+ | `Modal.Content` | The portalled popup with backdrop. |
512
+ | `Modal.Title` | Heading text. |
513
+ | `Modal.Description` | Sub-text under the title. |
477
514
 
478
515
  **`Modal.Content` props:**
479
516
 
480
- | Prop | Type | Default | Description |
481
- |---|---|---|---|
482
- | `className` | `string` | — | Extra classes on the popup. |
483
- | `backdropClassName` | `string` | — | Extra classes on the backdrop. |
484
- | `...props` | Base UI `Dialog.Popup` props | — | Spread to the popup. |
517
+ | Prop | Type | Default | Description |
518
+ | ------------------- | ---------------------------- | ------- | ------------------------------ |
519
+ | `className` | `string` | — | Extra classes on the popup. |
520
+ | `backdropClassName` | `string` | — | Extra classes on the backdrop. |
521
+ | `...props` | Base UI `Dialog.Popup` props | — | Spread to the popup. |
485
522
 
486
523
  `Modal.Title` and `Modal.Description` accept their Base UI props plus `className`.
487
524
 
@@ -491,7 +528,14 @@ Compound component built on `@base-ui/react/dialog`. Renders into a portal, with
491
528
  <Modal.Content>
492
529
  <Modal.Title>Delete project?</Modal.Title>
493
530
  <Modal.Description>This action cannot be undone.</Modal.Description>
494
- <div style={{ marginTop: "1rem", display: "flex", justifyContent: "flex-end", gap: "0.5rem" }}>
531
+ <div
532
+ style={{
533
+ marginTop: "1rem",
534
+ display: "flex",
535
+ justifyContent: "flex-end",
536
+ gap: "0.5rem",
537
+ }}
538
+ >
495
539
  <Modal.Close render={<Button variant="secondary">Cancel</Button>} />
496
540
  <Button variant="destructive">Delete</Button>
497
541
  </div>
@@ -507,23 +551,27 @@ Wraps `@base-ui/react/radio` and `@base-ui/react/radio-group`.
507
551
 
508
552
  **`Radio` props:**
509
553
 
510
- | Prop | Type | Default | Description |
511
- |---|---|---|---|
512
- | `size` | `"sm" \| "md" \| "lg"` | `"md"` | 16 / 18 / 20 px. |
513
- | `className` | `string` | — | Extra classes. |
514
- | `...props` | Base UI `Radio.Root` props | — | `value`, `disabled`, etc. |
554
+ | Prop | Type | Default | Description |
555
+ | ----------- | -------------------------- | ------- | ------------------------- |
556
+ | `size` | `"sm" \| "md" \| "lg"` | `"md"` | 16 / 18 / 20 px. |
557
+ | `className` | `string` | — | Extra classes. |
558
+ | `...props` | Base UI `Radio.Root` props | — | `value`, `disabled`, etc. |
515
559
 
516
560
  **`RadioGroup` props:**
517
561
 
518
- | Prop | Type | Default | Description |
519
- |---|---|---|---|
520
- | `className` | `string` | — | Override the default vertical stack. |
521
- | `...props` | Base UI `RadioGroup` props | — | `value`, `defaultValue`, `onValueChange`. |
562
+ | Prop | Type | Default | Description |
563
+ | ----------- | -------------------------- | ------- | ----------------------------------------- |
564
+ | `className` | `string` | — | Override the default vertical stack. |
565
+ | `...props` | Base UI `RadioGroup` props | — | `value`, `defaultValue`, `onValueChange`. |
522
566
 
523
567
  ```tsx
524
568
  <RadioGroup defaultValue="email">
525
- <label><Radio value="email" /> Email</label>
526
- <label><Radio value="sms" /> SMS</label>
569
+ <label>
570
+ <Radio value="email" /> Email
571
+ </label>
572
+ <label>
573
+ <Radio value="sms" /> SMS
574
+ </label>
527
575
  </RadioGroup>
528
576
  ```
529
577
 
@@ -533,19 +581,19 @@ Wraps `@base-ui/react/radio` and `@base-ui/react/radio-group`.
533
581
 
534
582
  Compound component built on `@base-ui/react/toggle-group` (single-select). The selected item rises as a white floating pill.
535
583
 
536
- | Sub-component | Description |
537
- |---|---|
584
+ | Sub-component | Description |
585
+ | ------------------ | ----------------- |
538
586
  | `Segmented` (root) | The toggle group. |
539
- | `Segmented.Item` | A single segment. |
587
+ | `Segmented.Item` | A single segment. |
540
588
 
541
589
  **`Segmented` props:**
542
590
 
543
- | Prop | Type | Default | Description |
544
- |---|---|---|---|
545
- | `value` | `string` | — | Controlled selected value. |
546
- | `defaultValue` | `string` | — | Uncontrolled initial value. |
547
- | `onValueChange` | `(value: string) => void` | — | Fired with the new value. |
548
- | `size` | `"sm" \| "md" \| "lg"` | `"md"` | 24 / 28 / 32 px. |
591
+ | Prop | Type | Default | Description |
592
+ | --------------- | ------------------------- | ------- | --------------------------- |
593
+ | `value` | `string` | — | Controlled selected value. |
594
+ | `defaultValue` | `string` | — | Uncontrolled initial value. |
595
+ | `onValueChange` | `(value: string) => void` | — | Fired with the new value. |
596
+ | `size` | `"sm" \| "md" \| "lg"` | `"md"` | 24 / 28 / 32 px. |
549
597
 
550
598
  ```tsx
551
599
  <Segmented value={range} onValueChange={setRange}>
@@ -561,13 +609,13 @@ Compound component built on `@base-ui/react/toggle-group` (single-select). The s
561
609
 
562
610
  Compound component built on `@base-ui/react/select`.
563
611
 
564
- | Sub-component | Description |
565
- |---|---|
566
- | `Select.Root` | State container (`value`, `onValueChange`). |
567
- | `Select.Trigger` | The clickable trigger; renders a chevron icon. |
568
- | `Select.Value` | The selected value's display. |
569
- | `Select.Content` | The portalled popup. |
570
- | `Select.Item` | A selectable row with a check indicator when selected. |
612
+ | Sub-component | Description |
613
+ | ---------------- | ------------------------------------------------------ |
614
+ | `Select.Root` | State container (`value`, `onValueChange`). |
615
+ | `Select.Trigger` | The clickable trigger; renders a chevron icon. |
616
+ | `Select.Value` | The selected value's display. |
617
+ | `Select.Content` | The portalled popup. |
618
+ | `Select.Item` | A selectable row with a check indicator when selected. |
571
619
 
572
620
  **`Select.Trigger` props:** `size` = `"sm" | "md" | "lg"` (default `"md"`), plus `className`.
573
621
 
@@ -594,11 +642,11 @@ Compound component built on `@base-ui/react/select`.
594
642
 
595
643
  Loading placeholder with a pulse animation.
596
644
 
597
- | Prop | Type | Default | Description |
598
- |---|---|---|---|
599
- | `shape` | `"line" \| "circle" \| "block"` | `"line"` | Default dimensions and radius. |
600
- | `className` | `string` | — | Override width/height/radius via your own CSS. |
601
- | `...props` | `HTMLAttributes<HTMLDivElement>` | — | Native div attributes. |
645
+ | Prop | Type | Default | Description |
646
+ | ----------- | -------------------------------- | -------- | ---------------------------------------------- |
647
+ | `shape` | `"line" \| "circle" \| "block"` | `"line"` | Default dimensions and radius. |
648
+ | `className` | `string` | — | Override width/height/radius via your own CSS. |
649
+ | `...props` | `HTMLAttributes<HTMLDivElement>` | — | Native div attributes. |
602
650
 
603
651
  ```tsx
604
652
  <Skeleton />
@@ -612,11 +660,11 @@ Loading placeholder with a pulse animation.
612
660
 
613
661
  Compound floating-pill component for status indicators. Intent drives chip + label color via CSS custom properties.
614
662
 
615
- | Sub-component | Description |
616
- |---|---|
617
- | `StatusPill` (root) | The pill surface. |
663
+ | Sub-component | Description |
664
+ | ---------------------- | ----------------------------------------------------------- |
665
+ | `StatusPill` (root) | The pill surface. |
618
666
  | `StatusPill.Indicator` | The leading colored chip. Children render an optional icon. |
619
- | `StatusPill.Label` | The colored text label. |
667
+ | `StatusPill.Label` | The colored text label. |
620
668
 
621
669
  **`StatusPill` props:** `intent` = `"neutral" | "success" | "warning" | "danger" | "info"` (default `"neutral"`).
622
670
 
@@ -633,11 +681,11 @@ Compound floating-pill component for status indicators. Intent drives chip + lab
633
681
 
634
682
  Wraps `@base-ui/react/switch` — a thumb that slides on `data-[checked]`.
635
683
 
636
- | Prop | Type | Default | Description |
637
- |---|---|---|---|
638
- | `size` | `"sm" \| "md" \| "lg"` | `"md"` | 16 / 20 / 24 px tall. |
639
- | `className` | `string` | — | Extra classes on the root. |
640
- | `...props` | Base UI `Switch.Root` props | — | `checked`, `defaultChecked`, `onCheckedChange`, `disabled`. |
684
+ | Prop | Type | Default | Description |
685
+ | ----------- | --------------------------- | ------- | ----------------------------------------------------------- |
686
+ | `size` | `"sm" \| "md" \| "lg"` | `"md"` | 16 / 20 / 24 px tall. |
687
+ | `className` | `string` | — | Extra classes on the root. |
688
+ | `...props` | Base UI `Switch.Root` props | — | `checked`, `defaultChecked`, `onCheckedChange`, `disabled`. |
641
689
 
642
690
  ```tsx
643
691
  <Switch defaultChecked />
@@ -650,12 +698,12 @@ Wraps `@base-ui/react/switch` — a thumb that slides on `data-[checked]`.
650
698
 
651
699
  Compound component built on `@base-ui/react/tabs`. The list renders an animated indicator that slides between active tabs.
652
700
 
653
- | Sub-component | Description |
654
- |---|---|
701
+ | Sub-component | Description |
702
+ | ------------- | --------------------------------------------------------------- |
655
703
  | `Tabs` (root) | State container; pass `value`, `defaultValue`, `onValueChange`. |
656
- | `Tabs.List` | Horizontal tab strip with a sliding indicator. |
657
- | `Tabs.Tab` | A single tab button. |
658
- | `Tabs.Panel` | The panel paired with a tab `value`. |
704
+ | `Tabs.List` | Horizontal tab strip with a sliding indicator. |
705
+ | `Tabs.Tab` | A single tab button. |
706
+ | `Tabs.Panel` | The panel paired with a tab `value`. |
659
707
 
660
708
  All sub-components accept their Base UI props plus `className`.
661
709
 
@@ -678,12 +726,12 @@ All sub-components accept their Base UI props plus `className`.
678
726
 
679
727
  A thin styled `<textarea>` mirroring Input's API.
680
728
 
681
- | Prop | Type | Default | Description |
682
- |---|---|---|---|
683
- | `size` | `"sm" \| "md" \| "lg"` | `"md"` | Density-aware control padding. |
684
- | `invalid` | `boolean` | — | Sets `aria-invalid` and applies the danger border + focus ring. |
685
- | `className` | `string` | — | Extra classes. |
686
- | `...props` | `TextareaHTMLAttributes` (minus `size`) | — | All native textarea attributes. |
729
+ | Prop | Type | Default | Description |
730
+ | ----------- | --------------------------------------- | ------- | --------------------------------------------------------------- |
731
+ | `size` | `"sm" \| "md" \| "lg"` | `"md"` | Density-aware control padding. |
732
+ | `invalid` | `boolean` | — | Sets `aria-invalid` and applies the danger border + focus ring. |
733
+ | `className` | `string` | — | Extra classes. |
734
+ | `...props` | `TextareaHTMLAttributes` (minus `size`) | — | All native textarea attributes. |
687
735
 
688
736
  ```tsx
689
737
  <Textarea placeholder="Notes" rows={4} />
@@ -696,12 +744,12 @@ A thin styled `<textarea>` mirroring Input's API.
696
744
 
697
745
  Built on `@base-ui/react/toast`. Provides a `<Toast.Provider>` boundary, a `<Toast.Viewport>` for positioning, a pre-built `<Toast.Toaster>` that renders the queue, and the `useToast()` hook to push toasts.
698
746
 
699
- | Sub-component | Description |
700
- |---|---|
701
- | `Toast.Provider` | Wrap your app to enable toasts. |
702
- | `Toast.Viewport` | Positioned region where toasts mount (bottom-right by default). |
703
- | `Toast.Toaster` | Pre-styled queue renderer — drop this inside `Provider`. |
704
- | `useToast()` | Hook returning Base UI's toast manager (`.add({ title, description })`). |
747
+ | Sub-component | Description |
748
+ | ---------------- | ------------------------------------------------------------------------ |
749
+ | `Toast.Provider` | Wrap your app to enable toasts. |
750
+ | `Toast.Viewport` | Positioned region where toasts mount (bottom-right by default). |
751
+ | `Toast.Toaster` | Pre-styled queue renderer — drop this inside `Provider`. |
752
+ | `useToast()` | Hook returning Base UI's toast manager (`.add({ title, description })`). |
705
753
 
706
754
  ```tsx
707
755
  import { Toast, useToast, Button } from "@bubble-design-system/ui";
@@ -718,7 +766,11 @@ function Root({ children }) {
718
766
  function SaveButton() {
719
767
  const toast = useToast();
720
768
  return (
721
- <Button onClick={() => toast.add({ title: "Saved", description: "Changes are live." })}>
769
+ <Button
770
+ onClick={() =>
771
+ toast.add({ title: "Saved", description: "Changes are live." })
772
+ }
773
+ >
722
774
  Save
723
775
  </Button>
724
776
  );
@@ -731,21 +783,21 @@ function SaveButton() {
731
783
 
732
784
  Compound component built on `@base-ui/react/tooltip`. Requires a `Tooltip.Provider` ancestor (typically once at the app root).
733
785
 
734
- | Sub-component | Description |
735
- |---|---|
736
- | `Tooltip.Provider` | App-level provider. |
737
- | `Tooltip.Root` | Single tooltip state container. |
738
- | `Tooltip.Trigger` | The hovered/focused element. |
739
- | `Tooltip.Content` | The portalled popup. |
786
+ | Sub-component | Description |
787
+ | ------------------ | ------------------------------- |
788
+ | `Tooltip.Provider` | App-level provider. |
789
+ | `Tooltip.Root` | Single tooltip state container. |
790
+ | `Tooltip.Trigger` | The hovered/focused element. |
791
+ | `Tooltip.Content` | The portalled popup. |
740
792
 
741
793
  **`Tooltip.Content` props:**
742
794
 
743
- | Prop | Type | Default | Description |
744
- |---|---|---|---|
745
- | `side` | `"top" \| "bottom" \| "left" \| "right"` | `"top"` | Preferred side. |
746
- | `align` | `"start" \| "center" \| "end"` | `"center"` | Alignment along the side. |
747
- | `sideOffset` | `number` | `6` | Distance from the trigger. |
748
- | `className` | `string` | — | Extra classes on the popup. |
795
+ | Prop | Type | Default | Description |
796
+ | ------------ | ---------------------------------------- | ---------- | --------------------------- |
797
+ | `side` | `"top" \| "bottom" \| "left" \| "right"` | `"top"` | Preferred side. |
798
+ | `align` | `"start" \| "center" \| "end"` | `"center"` | Alignment along the side. |
799
+ | `sideOffset` | `number` | `6` | Distance from the trigger. |
800
+ | `className` | `string` | — | Extra classes on the popup. |
749
801
 
750
802
  ```tsx
751
803
  <Tooltip.Provider>
@@ -779,65 +831,65 @@ All tokens are CSS custom properties defined in `src/tokens.css`. Reference them
779
831
 
780
832
  Semantic colors map to primitive palettes and are remapped by `[data-theme]`, `[data-gray]`, and `[data-brand]`.
781
833
 
782
- | Token | Purpose |
783
- |---|---|
784
- | `--color-bg-primary` | Page background. |
785
- | `--color-bg-secondary` | Secondary surface (cards on page). |
786
- | `--color-bg-tertiary` | Tertiary surface (inset wells). |
787
- | `--color-bg-inverse` | Inverted surface (tooltip, toast). |
788
- | `--color-bg-brand` | Brand primary fill. |
789
- | `--color-bg-brand-hover` | Brand hover state. |
790
- | `--color-bg-brand-active` | Brand pressed state. |
791
- | `--color-bg-brand-subtle` | Tinted brand surface (info backgrounds, badges). |
792
- | `--color-bg-success` | Soft success surface. |
793
- | `--color-bg-success-strong` | Solid success fill. |
794
- | `--color-bg-warning` | Soft warning surface. |
795
- | `--color-bg-warning-strong` | Solid warning fill. |
796
- | `--color-bg-danger` | Soft danger surface. |
797
- | `--color-bg-danger-strong` | Solid danger fill (destructive buttons). |
798
- | `--color-bg-danger-hover` | Danger hover state. |
799
- | `--color-bg-info` | Info alert surface. |
800
- | `--color-bg-hover` | Neutral hover. |
801
- | `--color-bg-pressed` | Neutral pressed. |
802
- | `--color-bg-disabled` | Disabled surface. |
803
- | `--color-text-primary` | Body text. |
804
- | `--color-text-secondary` | Supporting text. |
805
- | `--color-text-tertiary` | Placeholder, hints. |
806
- | `--color-text-disabled` | Disabled text. |
807
- | `--color-text-inverse` | Text on `bg-inverse`. |
808
- | `--color-text-brand` | Brand-colored text (links). |
809
- | `--color-text-success` | Success copy. |
810
- | `--color-text-warning` | Warning copy. |
811
- | `--color-text-danger` | Error copy. |
812
- | `--color-text-on-brand` | Text on `bg-brand`. |
813
- | `--color-text-on-danger` | Text on `bg-danger-strong`. |
814
- | `--color-text-on-success` | Text on `bg-success-strong`. |
815
- | `--color-border-primary` | Default form/control border. |
816
- | `--color-border-secondary` | Section dividers, cards. |
817
- | `--color-border-tertiary` | Subtle inner dividers. |
818
- | `--color-border-brand` | Selected/active accent. |
819
- | `--color-border-success` | Success accent. |
820
- | `--color-border-warning` | Warning accent. |
821
- | `--color-border-danger` | Error accent (invalid inputs). |
822
- | `--color-border-focus` | Focus ring color. |
834
+ | Token | Purpose |
835
+ | --------------------------- | ------------------------------------------------ |
836
+ | `--color-bg-primary` | Page background. |
837
+ | `--color-bg-secondary` | Secondary surface (cards on page). |
838
+ | `--color-bg-tertiary` | Tertiary surface (inset wells). |
839
+ | `--color-bg-inverse` | Inverted surface (tooltip, toast). |
840
+ | `--color-bg-brand` | Brand primary fill. |
841
+ | `--color-bg-brand-hover` | Brand hover state. |
842
+ | `--color-bg-brand-active` | Brand pressed state. |
843
+ | `--color-bg-brand-subtle` | Tinted brand surface (info backgrounds, badges). |
844
+ | `--color-bg-success` | Soft success surface. |
845
+ | `--color-bg-success-strong` | Solid success fill. |
846
+ | `--color-bg-warning` | Soft warning surface. |
847
+ | `--color-bg-warning-strong` | Solid warning fill. |
848
+ | `--color-bg-danger` | Soft danger surface. |
849
+ | `--color-bg-danger-strong` | Solid danger fill (destructive buttons). |
850
+ | `--color-bg-danger-hover` | Danger hover state. |
851
+ | `--color-bg-info` | Info alert surface. |
852
+ | `--color-bg-hover` | Neutral hover. |
853
+ | `--color-bg-pressed` | Neutral pressed. |
854
+ | `--color-bg-disabled` | Disabled surface. |
855
+ | `--color-text-primary` | Body text. |
856
+ | `--color-text-secondary` | Supporting text. |
857
+ | `--color-text-tertiary` | Placeholder, hints. |
858
+ | `--color-text-disabled` | Disabled text. |
859
+ | `--color-text-inverse` | Text on `bg-inverse`. |
860
+ | `--color-text-brand` | Brand-colored text (links). |
861
+ | `--color-text-success` | Success copy. |
862
+ | `--color-text-warning` | Warning copy. |
863
+ | `--color-text-danger` | Error copy. |
864
+ | `--color-text-on-brand` | Text on `bg-brand`. |
865
+ | `--color-text-on-danger` | Text on `bg-danger-strong`. |
866
+ | `--color-text-on-success` | Text on `bg-success-strong`. |
867
+ | `--color-border-primary` | Default form/control border. |
868
+ | `--color-border-secondary` | Section dividers, cards. |
869
+ | `--color-border-tertiary` | Subtle inner dividers. |
870
+ | `--color-border-brand` | Selected/active accent. |
871
+ | `--color-border-success` | Success accent. |
872
+ | `--color-border-warning` | Warning accent. |
873
+ | `--color-border-danger` | Error accent (invalid inputs). |
874
+ | `--color-border-focus` | Focus ring color. |
823
875
 
824
876
  ### Primitive palettes
825
877
 
826
878
  These are the raw color swatches that the semantic tokens reference. You usually shouldn't touch them directly, but they're exposed if you need to.
827
879
 
828
- | Family | Stops | Notes |
829
- |---|---|---|
830
- | `--slate-*` | 50–950 | Default gray family. |
831
- | `--neutral-*` | 50–950 | True neutral (no temperature). |
832
- | `--stone-*` | 50–950 | Warm gray. |
833
- | `--blue-*` | 50–950 | Brand option. |
834
- | `--violet-*` | 50–950 | Brand option. |
835
- | `--emerald-*` | 50–950 | Brand option. |
836
- | `--orange-*` | 50–950 | Brand option. |
837
- | `--green-*` | 50–950 | Success palette. |
838
- | `--amber-*` | 50–950 | Warning palette. |
839
- | `--red-*` | 50–950 | Danger palette. |
840
- | `--white`, `--black` | — | Pure values. |
880
+ | Family | Stops | Notes |
881
+ | -------------------- | ------ | ------------------------------ |
882
+ | `--slate-*` | 50–950 | Default gray family. |
883
+ | `--neutral-*` | 50–950 | True neutral (no temperature). |
884
+ | `--stone-*` | 50–950 | Warm gray. |
885
+ | `--blue-*` | 50–950 | Brand option. |
886
+ | `--violet-*` | 50–950 | Brand option. |
887
+ | `--emerald-*` | 50–950 | Brand option. |
888
+ | `--orange-*` | 50–950 | Brand option. |
889
+ | `--green-*` | 50–950 | Success palette. |
890
+ | `--amber-*` | 50–950 | Warning palette. |
891
+ | `--red-*` | 50–950 | Danger palette. |
892
+ | `--white`, `--black` | — | Pure values. |
841
893
 
842
894
  Aliases follow the active `data-*` attribute: `--gray-*` resolves to whichever gray family is selected, `--brand-*` to whichever brand. The `mono` and `teal` brands have special-case treatment for contrast on light/dark themes.
843
895
 
@@ -845,15 +897,15 @@ Aliases follow the active `data-*` attribute: `--gray-*` resolves to whichever g
845
897
 
846
898
  Selected by `[data-radius]`. Each scale rewrites the same custom properties.
847
899
 
848
- | Token | default | sharp | soft | pill |
849
- |---|---|---|---|---|
850
- | `--radius-xs` | 2px | 0px | 4px | 4px |
851
- | `--radius-sm` | 4px | 1px | 8px | 9999px |
852
- | `--radius-md` | 6px | 2px | 12px | 9999px |
853
- | `--radius-lg` | 8px | 3px | 14px | 9999px |
854
- | `--radius-xl` | 12px | 4px | 18px | 18px |
855
- | `--radius-2xl` | 16px | 6px | 24px | 22px |
856
- | `--radius-full` | 9999px | 9999px | 9999px | 9999px |
900
+ | Token | default | sharp | soft | pill |
901
+ | --------------- | ------- | ------ | ------ | ------ |
902
+ | `--radius-xs` | 2px | 0px | 4px | 4px |
903
+ | `--radius-sm` | 4px | 1px | 8px | 9999px |
904
+ | `--radius-md` | 6px | 2px | 12px | 9999px |
905
+ | `--radius-lg` | 8px | 3px | 14px | 9999px |
906
+ | `--radius-xl` | 12px | 4px | 18px | 18px |
907
+ | `--radius-2xl` | 16px | 6px | 24px | 22px |
908
+ | `--radius-full` | 9999px | 9999px | 9999px | 9999px |
857
909
 
858
910
  Plus `--ctrl-radius` — the control radius used by Button/Input/Select. Pills under `[data-tone="soft"]`, `--radius-md` elsewhere.
859
911
 
@@ -861,33 +913,33 @@ Plus `--ctrl-radius` — the control radius used by Button/Input/Select. Pills u
861
913
 
862
914
  Light theme uses cool slate tints; dark theme uses opaque black. The `soft` tone adds an inset white top-highlight on md/lg/xl. The focus ring tracks the brand color.
863
915
 
864
- | Token | Purpose |
865
- |---|---|
866
- | `--shadow-xs` | Hairline lift. |
867
- | `--shadow-sm` | Subtle card. |
868
- | `--shadow-md` | Standard card. |
869
- | `--shadow-lg` | Popover, dropdown. |
870
- | `--shadow-xl` | Modal. |
916
+ | Token | Purpose |
917
+ | ---------------- | -------------------------------- |
918
+ | `--shadow-xs` | Hairline lift. |
919
+ | `--shadow-sm` | Subtle card. |
920
+ | `--shadow-md` | Standard card. |
921
+ | `--shadow-lg` | Popover, dropdown. |
922
+ | `--shadow-xl` | Modal. |
871
923
  | `--shadow-focus` | Focus ring (3–4px brand-tinted). |
872
924
 
873
925
  ### Typography
874
926
 
875
- | Token | Value |
876
- |---|---|
877
- | `--font-size-xs` | 0.75rem |
878
- | `--font-size-sm` | 0.875rem |
879
- | `--font-size-md` | 1rem |
880
- | `--font-size-lg` | 1.125rem |
881
- | `--font-size-xl` | 1.25rem |
882
- | `--font-size-2xl` | 1.5rem |
883
- | `--font-size-3xl` | 1.875rem |
884
- | `--font-size-4xl` | 2.25rem |
885
- | `--font-size-5xl` | 3rem |
886
- | `--font-size-6xl` | 3.75rem |
887
- | `--line-height-tight` / `snug` / `normal` / `relaxed` | 1.15 / 1.3 / 1.5 / 1.65 |
888
- | `--letter-tight` / `snug` / `normal` / `wide` | -0.022em / -0.012em / 0 / 0.04em |
889
- | `--font-weight-regular` / `medium` / `semibold` / `bold` | 400 / 500 / 600 / 700 |
890
- | `--font-sans` / `--font-mono` | Set by `[data-font]` |
927
+ | Token | Value |
928
+ | -------------------------------------------------------- | -------------------------------- |
929
+ | `--font-size-xs` | 0.75rem |
930
+ | `--font-size-sm` | 0.875rem |
931
+ | `--font-size-md` | 1rem |
932
+ | `--font-size-lg` | 1.125rem |
933
+ | `--font-size-xl` | 1.25rem |
934
+ | `--font-size-2xl` | 1.5rem |
935
+ | `--font-size-3xl` | 1.875rem |
936
+ | `--font-size-4xl` | 2.25rem |
937
+ | `--font-size-5xl` | 3rem |
938
+ | `--font-size-6xl` | 3.75rem |
939
+ | `--line-height-tight` / `snug` / `normal` / `relaxed` | 1.15 / 1.3 / 1.5 / 1.65 |
940
+ | `--letter-tight` / `snug` / `normal` / `wide` | -0.022em / -0.012em / 0 / 0.04em |
941
+ | `--font-weight-regular` / `medium` / `semibold` / `bold` | 400 / 500 / 600 / 700 |
942
+ | `--font-sans` / `--font-mono` | Set by `[data-font]` |
891
943
 
892
944
  ### Spacing
893
945
 
@@ -897,30 +949,30 @@ Light theme uses cool slate tints; dark theme uses opaque black. The `soft` tone
897
949
 
898
950
  Selected by `[data-density]`.
899
951
 
900
- | Token | default | compact | comfortable |
901
- |---|---|---|---|
902
- | `--control-h-sm` | 28px | 24px | 32px |
903
- | `--control-h-md` | 36px | 30px | 42px |
904
- | `--control-h-lg` | 44px | 38px | 52px |
905
- | `--control-px-sm` | 10px | 8px | 12px |
906
- | `--control-px-md` | 14px | 12px | 18px |
907
- | `--control-px-lg` | 18px | 16px | 22px |
908
- | `--card-p` | 24px | 16px | 32px |
909
- | `--row-gap` | 16px | 12px | 20px |
952
+ | Token | default | compact | comfortable |
953
+ | ----------------- | ------- | ------- | ----------- |
954
+ | `--control-h-sm` | 28px | 24px | 32px |
955
+ | `--control-h-md` | 36px | 30px | 42px |
956
+ | `--control-h-lg` | 44px | 38px | 52px |
957
+ | `--control-px-sm` | 10px | 8px | 12px |
958
+ | `--control-px-md` | 14px | 12px | 18px |
959
+ | `--control-px-lg` | 18px | 16px | 22px |
960
+ | `--card-p` | 24px | 16px | 32px |
961
+ | `--row-gap` | 16px | 12px | 20px |
910
962
 
911
963
  ### Motion
912
964
 
913
- | Token | Value |
914
- |---|---|
915
- | `--duration-instant` | 50ms |
916
- | `--duration-fast` | 120ms |
917
- | `--duration-normal` | 200ms |
918
- | `--duration-slow` | 320ms |
919
- | `--duration-slower` | 500ms |
920
- | `--ease-linear` | `linear` |
921
- | `--ease-out` | `cubic-bezier(0.16, 1, 0.3, 1)` |
922
- | `--ease-in-out` | `cubic-bezier(0.65, 0, 0.35, 1)` |
923
- | `--ease-spring` | `cubic-bezier(0.34, 1.56, 0.64, 1)` |
965
+ | Token | Value |
966
+ | -------------------- | ----------------------------------- |
967
+ | `--duration-instant` | 50ms |
968
+ | `--duration-fast` | 120ms |
969
+ | `--duration-normal` | 200ms |
970
+ | `--duration-slow` | 320ms |
971
+ | `--duration-slower` | 500ms |
972
+ | `--ease-linear` | `linear` |
973
+ | `--ease-out` | `cubic-bezier(0.16, 1, 0.3, 1)` |
974
+ | `--ease-in-out` | `cubic-bezier(0.65, 0, 0.35, 1)` |
975
+ | `--ease-spring` | `cubic-bezier(0.34, 1.56, 0.64, 1)` |
924
976
 
925
977
  ### Browsing tokens visually
926
978