@platned/ui 0.3.0 → 0.5.1

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/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as react from 'react';
2
- import { ButtonHTMLAttributes, ReactNode, InputHTMLAttributes, TextareaHTMLAttributes, SelectHTMLAttributes, HTMLAttributes, RefObject, Key } from 'react';
2
+ import { ButtonHTMLAttributes, ReactNode, InputHTMLAttributes, HTMLAttributes, LabelHTMLAttributes, TextareaHTMLAttributes, ReactElement, RefObject, AnchorHTMLAttributes, TdHTMLAttributes, ThHTMLAttributes, Key } from 'react';
3
3
  import { ClassValue } from 'clsx';
4
4
 
5
5
  type ButtonVariant = 'primary' | 'neutral' | 'subtle' | 'danger' | 'danger-subtle';
@@ -9,8 +9,20 @@ interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
9
9
  size?: ButtonSize;
10
10
  leadingIcon?: ReactNode;
11
11
  trailingIcon?: ReactNode;
12
+ /**
13
+ * Render the single child element instead of a `<button>` — e.g. a router `Link`, so a
14
+ * navigation action can look like a button without nesting an anchor inside one.
15
+ */
16
+ asChild?: boolean;
17
+ /**
18
+ * Swaps the leading icon for a spinner and disables the button. `aria-busy` is set so
19
+ * assistive tech reports the pending state rather than only the disabled one.
20
+ */
21
+ loading?: boolean;
22
+ /** Announced while `loading`. Defaults to the button's own content. */
23
+ loadingLabel?: string;
12
24
  }
13
- declare function Button({ variant, size, leadingIcon, trailingIcon, children, className, ...props }: ButtonProps): react.JSX.Element;
25
+ declare const Button: react.ForwardRefExoticComponent<ButtonProps & react.RefAttributes<HTMLButtonElement>>;
14
26
 
15
27
  type IconButtonVariant = 'primary' | 'neutral' | 'subtle';
16
28
  interface IconButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
@@ -18,8 +30,11 @@ interface IconButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
18
30
  size?: ButtonSize;
19
31
  /** Required for accessibility — no visible text label */
20
32
  'aria-label': string;
33
+ /** Render the single child element instead of a `<button>` — e.g. a router `Link`. */
34
+ asChild?: boolean;
35
+ children?: ReactNode;
21
36
  }
22
- declare function IconButton({ variant, size, children, className, ...props }: IconButtonProps): react.JSX.Element;
37
+ declare const IconButton: react.ForwardRefExoticComponent<IconButtonProps & react.RefAttributes<HTMLButtonElement>>;
23
38
 
24
39
  type ButtonGroupVariant = 'primary' | 'neutral' | 'filter';
25
40
  type ButtonGroupAlign = 'justify' | 'start' | 'end' | 'center' | 'stack';
@@ -86,7 +101,7 @@ type InputSize = 'lg' | 'md' | 'sm';
86
101
  interface InputProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'size'> {
87
102
  label?: string;
88
103
  description?: string;
89
- /** Red border + message shown below the input */
104
+ /** Red border + message shown below the input. Also sets `aria-invalid`. */
90
105
  error?: string;
91
106
  /** Neutral helper text shown below the input (hidden when error is set) */
92
107
  hint?: string;
@@ -98,38 +113,238 @@ interface InputProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'size'>
98
113
  trailingAction?: ReactNode;
99
114
  }
100
115
  declare const Input: react.ForwardRefExoticComponent<InputProps & react.RefAttributes<HTMLInputElement>>;
116
+ /**
117
+ * The bare `<input>` with the field wiring applied and no label/message chrome — for
118
+ * `InputGroup` and any composition that supplies its own `Field`.
119
+ */
120
+ interface InputControlProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'size'> {
121
+ size?: InputSize;
122
+ invalid?: boolean;
123
+ }
124
+ declare const InputControl: react.ForwardRefExoticComponent<InputControlProps & react.RefAttributes<HTMLInputElement>>;
125
+
126
+ /**
127
+ * The label / description / error / control wiring, in one place.
128
+ *
129
+ * This exists because of the single largest defect the 0.3.0 audit found. `Input`,
130
+ * `Textarea`, `Select` and `DatePicker` all accepted `label`, `description`, `error` and
131
+ * `hint`, rendered them, and then connected **none** of them:
132
+ *
133
+ * - `<label htmlFor={id}>` used the caller's `id` with no fallback. Omit `id` — the
134
+ * common case — and `htmlFor` was `undefined`, so the label pointed at nothing.
135
+ * Clicking it did nothing and assistive tech announced an unlabelled field.
136
+ * - `description`, `error` and `hint` were bare `<p>` elements with no `id`, and no
137
+ * control ever referenced them. A consumer could not fix this from outside either:
138
+ * passing `aria-describedby` had nothing to point at.
139
+ * - `error` drove the border colour and nothing else. No `aria-invalid`, no `role`, no
140
+ * live region — so an async validation failure was completely silent.
141
+ *
142
+ * For scale: `aria-describedby`, `aria-invalid` and `aria-required` appeared nowhere in
143
+ * `src/`, and `useId` was used exactly once in the whole library — in `Sparkline`, for an
144
+ * SVG gradient.
145
+ *
146
+ * `Field` generates the ids and hands them down through context, so a control only has to
147
+ * spread `useFieldControl()` onto its input element. It is also usable directly for
148
+ * controls the library does not wrap, which is why the parts are exported.
149
+ */
150
+ interface FieldContextValue {
151
+ controlId: string;
152
+ /**
153
+ * Id of the `FieldLabel`, for controls whose accessible name cannot come from a
154
+ * `<label for>` association. A `<button>` is named by its own contents, so the Select
155
+ * trigger has to point `aria-labelledby` at the label explicitly or it announces only
156
+ * the chosen value.
157
+ */
158
+ labelId: string;
159
+ descriptionId: string;
160
+ errorId: string;
161
+ hintId: string;
162
+ hasDescription: boolean;
163
+ hasError: boolean;
164
+ hasHint: boolean;
165
+ invalid: boolean;
166
+ required: boolean;
167
+ disabled: boolean;
168
+ size: InputSize;
169
+ }
170
+ declare function useFieldContext(): FieldContextValue | null;
171
+ /**
172
+ * Props for the control itself. Spread onto the `<input>`/`<select>`/`<textarea>`.
173
+ *
174
+ * `aria-describedby` deliberately lists description *and* message: a field can carry
175
+ * both persistent guidance and a transient error, and a screen reader should read both
176
+ * rather than have the error replace the instruction that explains the format.
177
+ */
178
+ declare function useFieldControl(): {
179
+ id: string | undefined;
180
+ 'aria-describedby': string | undefined;
181
+ 'aria-invalid': true | undefined;
182
+ 'aria-required': true | undefined;
183
+ disabled: boolean | undefined;
184
+ };
185
+ type FieldOrientation = 'vertical' | 'horizontal';
186
+ interface FieldProps extends HTMLAttributes<HTMLDivElement> {
187
+ children: ReactNode;
188
+ /** Supply to control the id yourself; otherwise one is generated. */
189
+ id?: string;
190
+ size?: InputSize;
191
+ invalid?: boolean;
192
+ required?: boolean;
193
+ disabled?: boolean;
194
+ /** `horizontal` puts the label beside the control — for switches and checkboxes. */
195
+ orientation?: FieldOrientation;
196
+ /** Set when a `FieldDescription` is rendered. Inferred by the wrapped controls. */
197
+ hasDescription?: boolean;
198
+ hasError?: boolean;
199
+ hasHint?: boolean;
200
+ }
201
+ declare function Field({ children, id, size, invalid, required, disabled, orientation, hasDescription, hasError, hasHint, className, ...rest }: FieldProps): react.JSX.Element;
202
+ interface FieldLabelProps extends LabelHTMLAttributes<HTMLLabelElement> {
203
+ children: ReactNode;
204
+ }
205
+ declare function FieldLabel({ children, className, htmlFor, ...rest }: FieldLabelProps): react.JSX.Element;
206
+ interface FieldTextProps extends HTMLAttributes<HTMLParagraphElement> {
207
+ children: ReactNode;
208
+ }
209
+ /** Persistent guidance, shown above the control and announced with it. */
210
+ declare function FieldDescription({ children, className, ...rest }: FieldTextProps): react.JSX.Element;
211
+ /**
212
+ * Validation message. `role="alert"` because an error that appears after submit —
213
+ * asynchronously, without focus moving — is otherwise never announced at all.
214
+ */
215
+ declare function FieldError({ children, className, ...rest }: FieldTextProps): react.JSX.Element;
216
+ /** Neutral helper text. Suppressed while an error is showing, so the two never stack. */
217
+ declare function FieldHint({ children, className, ...rest }: FieldTextProps): react.JSX.Element;
218
+ interface FieldGroupProps extends HTMLAttributes<HTMLDivElement> {
219
+ children: ReactNode;
220
+ }
221
+ /** Stacks several `Field`s with consistent rhythm. */
222
+ declare function FieldGroup({ children, className, ...rest }: FieldGroupProps): react.JSX.Element;
223
+ interface FieldSetProps extends HTMLAttributes<HTMLFieldSetElement> {
224
+ children: ReactNode;
225
+ }
226
+ /**
227
+ * A real `<fieldset>`. Required for radio groups and checkbox groups: the group needs a
228
+ * name of its own, and only `<legend>` gives it one that is announced before each option.
229
+ */
230
+ declare function FieldSet({ children, className, ...rest }: FieldSetProps): react.JSX.Element;
231
+ interface FieldLegendProps extends HTMLAttributes<HTMLLegendElement> {
232
+ children: ReactNode;
233
+ /** `label` matches a field label's weight; `legend` is the larger section heading. */
234
+ variant?: 'legend' | 'label';
235
+ }
236
+ declare function FieldLegend({ children, variant, className, ...rest }: FieldLegendProps): react.JSX.Element;
237
+ interface FieldSeparatorProps extends HTMLAttributes<HTMLDivElement> {
238
+ }
239
+ declare function FieldSeparator({ className, ...rest }: FieldSeparatorProps): react.JSX.Element;
240
+
241
+ interface ControlSizeProviderProps {
242
+ size: InputSize;
243
+ children: ReactNode;
244
+ }
245
+ declare function ControlSizeProvider({ size, children }: ControlSizeProviderProps): react.JSX.Element;
246
+ /**
247
+ * Resolve a control's size: an explicit prop, else the enclosing container's default,
248
+ * else `md`.
249
+ *
250
+ * Call it unconditionally at the top of the component — it is a hook.
251
+ */
252
+ declare function useControlSize(explicit?: InputSize): InputSize;
101
253
 
102
254
  interface TextareaProps extends TextareaHTMLAttributes<HTMLTextAreaElement> {
103
255
  label?: string;
104
256
  description?: string;
257
+ /** Red border + message shown below the control. Also sets `aria-invalid`. */
105
258
  error?: string;
106
259
  hint?: string;
107
260
  size?: InputSize;
108
261
  }
109
262
  declare const Textarea: react.ForwardRefExoticComponent<TextareaProps & react.RefAttributes<HTMLTextAreaElement>>;
263
+ interface TextareaControlProps extends TextareaHTMLAttributes<HTMLTextAreaElement> {
264
+ size?: InputSize;
265
+ invalid?: boolean;
266
+ }
267
+ /** The bare `<textarea>` with field wiring, for compositions that supply their own `Field`. */
268
+ declare const TextareaControl: react.ForwardRefExoticComponent<TextareaControlProps & react.RefAttributes<HTMLTextAreaElement>>;
110
269
 
111
270
  interface SelectOption {
112
271
  value: string;
113
272
  label: string;
273
+ disabled?: boolean;
274
+ }
275
+ interface SelectOptionGroup {
276
+ label: string;
277
+ options: SelectOption[];
278
+ }
279
+ interface SelectControlProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'value' | 'defaultValue' | 'onChange' | 'children' | 'type'> {
280
+ /** Flat options, or groups which render as a labelled `role="group"`. */
281
+ options: (SelectOption | SelectOptionGroup)[];
282
+ value?: string | null;
283
+ defaultValue?: string | null;
284
+ onValueChange?: (value: string) => void;
285
+ /**
286
+ * Submits with a surrounding form, through a hidden input. Note that hidden inputs are
287
+ * exempt from constraint validation, so `required` no longer blocks submit — see the
288
+ * note on `Select`.
289
+ */
290
+ name?: string;
291
+ size?: InputSize;
292
+ invalid?: boolean;
293
+ placeholder?: string;
114
294
  }
115
- interface SelectProps extends Omit<SelectHTMLAttributes<HTMLSelectElement>, 'size'> {
295
+ /**
296
+ * The bare trigger and its listbox, with field wiring and no label/message chrome — for
297
+ * `Select` and any composition that supplies its own `Field`.
298
+ */
299
+ declare const SelectControl: react.ForwardRefExoticComponent<SelectControlProps & react.RefAttributes<HTMLButtonElement>>;
300
+ interface SelectProps extends SelectControlProps {
116
301
  label?: string;
117
302
  description?: string;
303
+ /** Red border + message shown below the control. Also sets `aria-invalid`. */
118
304
  error?: string;
119
305
  hint?: string;
120
- size?: InputSize;
121
- options: SelectOption[];
122
- placeholder?: string;
306
+ required?: boolean;
123
307
  }
124
- declare const Select: react.ForwardRefExoticComponent<SelectProps & react.RefAttributes<HTMLSelectElement>>;
308
+ /**
309
+ * Single-select dropdown: a trigger and a portalled listbox.
310
+ *
311
+ * Through 0.4.0 this wrapped a native `<select>`, which was the right call for its keyboard
312
+ * contract and the wrong one for everything visual: the option popup is drawn by the OS and
313
+ * cannot be styled at all, so a Select never matched the `DropdownMenu` and `Combobox`
314
+ * panels sitting beside it on the same filter row. It is now the same panel as those, and
315
+ * the keyboard contract it used to inherit is implemented rather than borrowed — arrows,
316
+ * Home/End, typeahead, Escape, and Tab that leaves without committing.
317
+ *
318
+ * Two consequences of dropping the native element, neither papered over:
319
+ *
320
+ * - **No OS picker on mobile.** The wheel/sheet a native select opens is gone.
321
+ * - **`required` no longer blocks submit.** The value posts through a hidden input, and
322
+ * hidden inputs are exempt from constraint validation. `required` remains semantic and
323
+ * visual — `aria-required` on the control and the `*` on its label — which is already
324
+ * true of `Combobox`, `RadioGroup` and `MultiSelectCard`. In react-hook-form, register
325
+ * it with `Controller` rather than `register`.
326
+ *
327
+ * For a list long enough to need filtering, use `Combobox`.
328
+ */
329
+ declare const Select: react.ForwardRefExoticComponent<SelectProps & react.RefAttributes<HTMLButtonElement>>;
125
330
 
126
331
  interface DatePickerProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'size' | 'type'> {
127
332
  label?: string;
128
333
  description?: string;
334
+ /** Red border + message shown below the control. Also sets `aria-invalid`. */
129
335
  error?: string;
130
336
  hint?: string;
131
337
  size?: InputSize;
132
338
  }
339
+ /**
340
+ * A native `<input type="date">`.
341
+ *
342
+ * The `::-webkit-calendar-picker-indicator` styling below is Chromium-only — on Firefox
343
+ * and Safari the native affordance differs, so the drawn `LuCalendar` sits alongside
344
+ * whatever the platform renders rather than replacing it. That is a known limitation of
345
+ * this component, not a bug to paper over: for a real month grid, range selection, locale
346
+ * control or min/max navigation, use `Calendar` and `DateField` instead.
347
+ */
133
348
  declare const DatePicker: react.ForwardRefExoticComponent<DatePickerProps & react.RefAttributes<HTMLInputElement>>;
134
349
 
135
350
  type StepStatus = 'complete' | 'active' | 'upcoming';
@@ -137,39 +352,162 @@ interface StepItem {
137
352
  label: string;
138
353
  status: StepStatus;
139
354
  }
355
+ type StepperSize = 'sm' | 'md';
140
356
  interface StepperProps {
141
357
  steps: StepItem[];
358
+ /** Matches Figma's `Size` axis on the `Stepper` component set. */
359
+ size?: StepperSize;
360
+ /** Names the list. Defaults to `Progress`. Override for a non-English UI. */
361
+ label?: string;
142
362
  className?: string;
143
363
  }
144
- declare function Stepper({ steps, className }: StepperProps): react.JSX.Element;
364
+ declare function Stepper({ steps, size, label, className }: StepperProps): react.JSX.Element;
145
365
 
366
+ /** Matches Figma's `Size` axis on `Multiselect Card` (`Default | Small`). */
367
+ type MultiSelectCardSize = 'default' | 'sm';
146
368
  interface MultiSelectCardProps {
147
369
  icon: ReactNode;
148
370
  title: string;
149
371
  description?: string;
150
372
  selected: boolean;
151
373
  onToggle: () => void;
374
+ /**
375
+ * Figma has had this axis since 0.2.0; the 0.3.0 CHANGELOG recorded it as "left alone
376
+ * pending a design decision". `Default` and `Small` differ only in padding, icon box and
377
+ * type step, so there was nothing to decide.
378
+ */
379
+ size?: MultiSelectCardSize;
380
+ disabled?: boolean;
152
381
  className?: string;
153
382
  }
154
- declare function MultiSelectCard({ icon, title, description, selected, onToggle, className, }: MultiSelectCardProps): react.JSX.Element;
383
+ declare function MultiSelectCard({ icon, title, description, selected, onToggle, size, disabled, className, }: MultiSelectCardProps): react.JSX.Element;
155
384
 
156
- type ToggleSize = 'sm' | 'md';
157
- interface ToggleProps {
158
- checked: boolean;
159
- onChange: (checked: boolean) => void;
385
+ type SwitchSize = 'sm' | 'md';
386
+ interface SwitchProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'onChange' | 'value' | 'type'> {
387
+ /** Controlled. Omit and pass `defaultChecked` for uncontrolled. */
388
+ checked?: boolean;
389
+ defaultChecked?: boolean;
390
+ onCheckedChange?: (checked: boolean) => void;
160
391
  /** Visible text beside the switch. Doubles as the accessible name. */
161
- label?: string;
392
+ label?: ReactNode;
393
+ /** Second line under the label. Matches Figma's `Supporting text` axis. */
394
+ description?: ReactNode;
162
395
  /** Track size. `sm` is 36×20, `md` is 44×24. */
396
+ size?: SwitchSize;
397
+ }
398
+ /**
399
+ * An on/off switch — a setting that takes effect immediately, with no save step.
400
+ *
401
+ * **Renamed from `Toggle` in 0.4.0.** It was always a switch: `role="switch"`,
402
+ * `aria-checked`, and the track/knob geometry taken from Figma. The name was blocking,
403
+ * because "Toggle" means something else in shadcn/ui and in most design systems — a
404
+ * pressed-state *button*, like a bold button in a text toolbar. That component now exists
405
+ * here under the name everyone expects, and the two are not interchangeable:
406
+ *
407
+ * - `Switch` — `role="switch"`, "on"/"off", applies immediately. A setting.
408
+ * - `Toggle` — `aria-pressed`, "pressed"/"not pressed". A button whose effect persists.
409
+ *
410
+ * Figma calls its set `Toggle` with a `Pressed` axis, but its geometry and `_Toggle base`
411
+ * match this component exactly, so Figma's `Toggle` **is** this switch. Figma has no
412
+ * pressed-button equivalent yet; that is a gap on the design side, recorded in the
413
+ * CHANGELOG rather than papered over here.
414
+ */
415
+ declare const Switch: react.ForwardRefExoticComponent<SwitchProps & react.RefAttributes<HTMLButtonElement>>;
416
+
417
+ type ToggleSize = 'sm' | 'md' | 'lg';
418
+ type ToggleVariant = 'ghost' | 'outline';
419
+ interface ToggleProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'onChange' | 'type'> {
420
+ /** Controlled pressed state. Omit and pass `defaultPressed` for uncontrolled. */
421
+ pressed?: boolean;
422
+ defaultPressed?: boolean;
423
+ onPressedChange?: (pressed: boolean) => void;
163
424
  size?: ToggleSize;
425
+ variant?: ToggleVariant;
426
+ children?: ReactNode;
427
+ }
428
+ /**
429
+ * A button with a sticky pressed state — bold in a text toolbar, a map layer on/off, a
430
+ * filter that stays applied.
431
+ *
432
+ * **New in 0.4.0, and not what `Toggle` used to be.** Through 0.3.0 this name belonged to
433
+ * the on/off switch, which is now `Switch`. The two look similar and mean different things:
434
+ *
435
+ * - `Toggle` — `aria-pressed`. A *button*. "Bold is pressed."
436
+ * - `Switch` — `role="switch"` + `aria-checked`. A *setting*. "Notifications are on."
437
+ *
438
+ * `aria-pressed` rather than `aria-checked` is the whole distinction as far as assistive
439
+ * tech is concerned, and it is why this is not just `Switch` with different styling.
440
+ *
441
+ * An icon-only toggle needs `aria-label`, exactly as `IconButton` does — there is no visible
442
+ * text to name it.
443
+ */
444
+ declare const Toggle: react.ForwardRefExoticComponent<ToggleProps & react.RefAttributes<HTMLButtonElement>>;
445
+ type ToggleGroupType = 'single' | 'multiple';
446
+ interface ToggleGroupProps extends Omit<HTMLAttributes<HTMLDivElement>, 'onChange'> {
447
+ children: ReactNode;
448
+ /** `single` behaves like a radio group; `multiple` like a set of checkboxes. */
449
+ type?: ToggleGroupType;
450
+ value?: string | string[];
451
+ defaultValue?: string | string[];
452
+ onValueChange?: (value: string | string[]) => void;
453
+ /** Names the group. Required by the APG for a toolbar-style group. */
454
+ label: string;
164
455
  disabled?: boolean;
165
- id?: string;
166
- /** Accessible name when there is no visible `label`. */
167
- 'aria-label'?: string;
168
- /** Points at the id of an existing visible label elsewhere on the page. */
169
- 'aria-labelledby'?: string;
456
+ orientation?: 'horizontal' | 'vertical';
457
+ }
458
+ /**
459
+ * A set of related toggles sharing one selection.
460
+ *
461
+ * `role="group"` with `aria-pressed` on each child, and a roving tabindex so the set is one
462
+ * tab stop with arrow keys inside — the same contract `SegmentedControl` was missing before
463
+ * 0.4.0.
464
+ *
465
+ * How this differs from the neighbours, since three components in this library now look
466
+ * similar: `SegmentedControl` is a `radiogroup` for choosing *one* of a small set of views,
467
+ * and always has exactly one selection. `ToggleGroup type="multiple"` allows none or many.
468
+ * `ToggleGroup type="single"` allows none or one — the deselectable case a radio group
469
+ * cannot express.
470
+ */
471
+ declare function ToggleGroup({ children, type, value: valueProp, defaultValue, onValueChange, label, disabled, orientation, className, ...rest }: ToggleGroupProps): react.JSX.Element;
472
+ interface ToggleGroupItemProps extends Omit<ToggleProps, 'pressed' | 'defaultPressed'> {
473
+ value: string;
474
+ }
475
+ /** A `Toggle` wired to its `ToggleGroup`, with the roving tabindex applied. */
476
+ declare const ToggleGroupItem: react.ForwardRefExoticComponent<ToggleGroupItemProps & react.RefAttributes<HTMLButtonElement>>;
477
+
478
+ type InputOTPMode = 'numeric' | 'alphanumeric';
479
+ interface InputOTPProps {
480
+ /** Number of characters. Default `6`. */
481
+ length?: number;
482
+ value?: string;
483
+ defaultValue?: string;
484
+ onValueChange?: (value: string) => void;
485
+ /** Fired once the last slot is filled. */
486
+ onComplete?: (value: string) => void;
487
+ mode?: InputOTPMode;
488
+ /** Draws a gap after this many slots — `3` for a `123 456` code. */
489
+ groupAfter?: number;
490
+ /** Accessible name. Default `Verification code`. */
491
+ label?: string;
492
+ disabled?: boolean;
493
+ invalid?: boolean;
494
+ autoFocus?: boolean;
170
495
  className?: string;
171
496
  }
172
- declare function Toggle({ checked, onChange, label, size, disabled, id, 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledBy, className, }: ToggleProps): react.JSX.Element;
497
+ /**
498
+ * A one-time-code field — the boxed digits from a 2FA or email-verification flow.
499
+ *
500
+ * **One real input, N drawn boxes.** The obvious implementation is N separate `<input>`s,
501
+ * and it is the wrong one: it makes the code N tab stops, breaks paste (the browser puts all
502
+ * six characters in the first box), fights password managers and SMS autofill, and announces
503
+ * "edit text, blank" six times. Instead there is a single input holding the whole value —
504
+ * with `autocomplete="one-time-code"`, so iOS and Android offer the code from the incoming
505
+ * message — rendered transparently over the boxes, which are decorative.
506
+ *
507
+ * That means paste, autofill, undo, selection and screen readers all get the real value, and
508
+ * the caret position simply drives which box is highlighted.
509
+ */
510
+ declare const InputOTP: react.ForwardRefExoticComponent<InputOTPProps & react.RefAttributes<HTMLInputElement>>;
173
511
 
174
512
  interface FileDropZoneProps {
175
513
  className?: string;
@@ -216,18 +554,28 @@ interface BadgeProps {
216
554
  }
217
555
  declare function Badge({ label, color, size, variant, indicator, onClose, className, }: BadgeProps): react.JSX.Element;
218
556
 
557
+ /**
558
+ * The nine-hue categorical palette from `badge.css`, which is what roles want: a role is a
559
+ * *category*, not a severity, so it must not borrow the semantic tones — a `danger`-coloured
560
+ * role badge would imply the role itself is a problem.
561
+ */
562
+ type RoleBadgeTone = 'slate' | 'blue' | 'green' | 'yellow' | 'red' | 'pink' | 'teal' | 'lime' | 'gray';
219
563
  interface RoleBadgeProps {
220
564
  role: string;
221
565
  size?: 'sm' | 'md';
222
566
  /**
223
- * Explicit role colour as a solid 6-digit hex (e.g. `#0c2d58`). When set it drives
224
- * the badge — text uses the hex and the background a light tint of it. Prefer this
225
- * over relying on the built-in name map, which only covers a fixed set of English
226
- * role names. Falls back to the name map, then grey.
567
+ * Override the name-map lookup. Use this for roles the map does not know, in preference to
568
+ * `color` — it stays on the token layer and re-themes with the rest of the badge palette.
569
+ */
570
+ tone?: RoleBadgeTone;
571
+ /**
572
+ * @deprecated Bypasses the design tokens — pass `tone` instead. Raw 6-digit hex; text uses
573
+ * the hex and the background a 12% tint of it. Kept for role colours that genuinely come
574
+ * from API data rather than from the design system.
227
575
  */
228
576
  color?: string | null;
229
577
  }
230
- declare function RoleBadge({ role, size, color }: RoleBadgeProps): react.JSX.Element;
578
+ declare function RoleBadge({ role, size, tone, color }: RoleBadgeProps): react.JSX.Element;
231
579
 
232
580
  interface RoleOption {
233
581
  role: string;
@@ -238,8 +586,130 @@ interface RoleComboBoxProps {
238
586
  value: string;
239
587
  onChange: (role: string) => void;
240
588
  options?: RoleOption[];
589
+ /** Accessible name. Defaults to `Role`. */
590
+ label?: string;
591
+ size?: InputSize;
592
+ disabled?: boolean;
593
+ className?: string;
594
+ }
595
+ /**
596
+ * Role picker.
597
+ *
598
+ * Rebuilt in 0.4.0 as a thin wrapper over `Combobox`, which is all it should ever have been.
599
+ * The version it replaces was the least correct component in the library and is worth
600
+ * recording, because every one of these was a category of bug rather than a detail:
601
+ *
602
+ * - `role="combobox"` sat on a `<div>` while the real `<input>` had no role and none of the
603
+ * state attributes. Under ARIA 1.2 the role belongs on the input.
604
+ * - The `role="listbox"` had no `id`, so `aria-controls` could not point at it, and there
605
+ * was no `aria-activedescendant` at all.
606
+ * - No arrow keys, no Home/End, no wrap. The **selected** option had no `tabIndex`, so it
607
+ * was mouse-only, while every *other* option was individually tabbable.
608
+ * - Escape worked on the trigger but not on the search input or the options, and closing
609
+ * never returned focus to the trigger.
610
+ * - The tick was a literal `✓` text node, announced as "check mark" mid-option.
611
+ * - It bypassed the token system entirely — `border-blue-500`, `bg-white`, `bg-blue-50`,
612
+ * `text-blue-600`, `text-sm` — and built its className with a template literal. Both are
613
+ * explicitly against the rules in CLAUDE.md, and the raw colours meant it would not theme.
614
+ *
615
+ * It stays a preset rather than becoming `Combobox` usage at every call site only because it
616
+ * renders a `RoleBadge` per option, which `renderOption` exists for.
617
+ */
618
+ declare function RoleComboBox({ value, onChange, options, label, size, disabled, className, }: RoleComboBoxProps): react.JSX.Element;
619
+
620
+ interface ComboboxOption<T = string> {
621
+ value: T;
622
+ label: string;
623
+ description?: string;
624
+ disabled?: boolean;
625
+ /** Optional group heading. Options sharing a group are rendered together. */
626
+ group?: string;
627
+ }
628
+ interface ComboboxProps<T extends string = string> {
629
+ options: ComboboxOption<T>[];
630
+ value?: T | null;
631
+ defaultValue?: T | null;
632
+ onValueChange?: (value: T | null) => void;
633
+ /** Accessible name. Required unless the combobox is inside a `Field` with a label. */
634
+ label?: string;
635
+ placeholder?: string;
636
+ size?: InputSize;
637
+ disabled?: boolean;
638
+ invalid?: boolean;
639
+ /** Allow clearing back to `null` by selecting the chosen option again. Default `true`. */
640
+ clearable?: boolean;
641
+ /** Override the filter. Default is a case-insensitive substring match on `label`. */
642
+ filter?: (option: ComboboxOption<T>, query: string) => boolean;
643
+ /** Shown when nothing matches. */
644
+ emptyMessage?: ReactNode;
645
+ /** Custom option rendering. Receives the option and whether it is selected. */
646
+ renderOption?: (option: ComboboxOption<T>, selected: boolean) => ReactNode;
647
+ className?: string;
648
+ }
649
+ /**
650
+ * Single-select combobox with a text filter — an autocomplete.
651
+ *
652
+ * Implements the ARIA 1.2 combobox pattern, which is specific about a few things that are
653
+ * easy to get wrong and were all wrong in the `RoleComboBox` this replaces:
654
+ *
655
+ * - **`role="combobox"` belongs on the text input**, not on a wrapping `<div>`. The div
656
+ * version means the state attributes sit on an element the user never focuses.
657
+ * - **`aria-activedescendant`, not focus, tracks the highlighted option.** Focus stays in
658
+ * the input the whole time — moving DOM focus into the list breaks typing. This is the
659
+ * one place a roving tabindex is the *wrong* answer, which is why this does not use
660
+ * `useRovingFocus`.
661
+ * - **`aria-controls` points at the listbox**, which therefore needs a stable id.
662
+ * - The listbox is portaled, so it is not clipped by a `Card` or a scrolling container.
663
+ *
664
+ * For a command palette — filter over *actions* rather than a value — use `Command`.
665
+ */
666
+ declare function Combobox<T extends string = string>({ options, value: valueProp, defaultValue, onValueChange, label, placeholder, size: sizeProp, disabled, invalid, clearable, filter, emptyMessage, renderOption, className, }: ComboboxProps<T>): react.JSX.Element;
667
+
668
+ interface CommandItem {
669
+ id: string;
670
+ label: string;
671
+ description?: string;
672
+ /** Group heading. Items sharing a group render together, in the order given. */
673
+ group?: string;
674
+ icon?: ReactNode;
675
+ /** Trailing hint — pass `<Kbd>` elements. */
676
+ shortcut?: ReactNode;
677
+ /** Extra words to match on that are not in the label — synonyms, the old name of a page. */
678
+ keywords?: string[];
679
+ disabled?: boolean;
680
+ onSelect: () => void;
681
+ }
682
+ interface CommandProps {
683
+ items: CommandItem[];
684
+ /** Accessible name. Default `Command palette`. */
685
+ label?: string;
686
+ placeholder?: string;
687
+ emptyMessage?: ReactNode;
688
+ /** Called after any item is chosen — usually closes the containing dialog. */
689
+ onAfterSelect?: () => void;
690
+ autoFocus?: boolean;
691
+ className?: string;
241
692
  }
242
- declare function RoleComboBox({ value, onChange, options }: RoleComboBoxProps): react.JSX.Element;
693
+ /**
694
+ * A ⌘K command palette — filter over *actions* and run one.
695
+ *
696
+ * The same ARIA combobox pattern as `Combobox`, and for the same reasons: `role="combobox"`
697
+ * on the input, focus never leaving it, and `aria-activedescendant` carrying the highlight.
698
+ * What differs is the intent, and it changes two behaviours:
699
+ *
700
+ * - Items are **commands, not values**. There is no selected state to display, no way to
701
+ * clear, and choosing one runs a callback rather than setting anything.
702
+ * - Matching includes `keywords`, so "logout" can find "Sign out" — a palette is useless if
703
+ * you have to already know the wording.
704
+ *
705
+ * This is the palette body only. Put it in a `Modal` for the usual ⌘K overlay; keeping the
706
+ * two separate means the palette can also be embedded in a page or a `Popover`, and the
707
+ * dialog semantics stay with the component that owns them.
708
+ *
709
+ * A live region reports the result count, because otherwise a screen reader user typing into
710
+ * the filter gets no feedback that the list changed underneath them.
711
+ */
712
+ declare function Command({ items, label, placeholder, emptyMessage, onAfterSelect, autoFocus, className, }: CommandProps): react.JSX.Element;
243
713
 
244
714
  /**
245
715
  * The six status tones from the Figma design system.
@@ -384,29 +854,264 @@ interface EntityIconBadgeProps {
384
854
  }
385
855
  declare function EntityIconBadge({ size, tone, shape, bg, iconColor, children, className }: EntityIconBadgeProps): react.JSX.Element;
386
856
 
387
- interface CheckboxProps {
388
- checked: boolean;
389
- onChange: (checked: boolean) => void;
857
+ type CheckControlSize = 'sm' | 'md';
858
+
859
+ type CheckboxSize = CheckControlSize;
860
+ interface CheckboxProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'size' | 'type' | 'onChange' | 'checked'> {
861
+ /** Controlled. Omit and pass `defaultChecked` for uncontrolled. */
862
+ checked?: boolean;
863
+ defaultChecked?: boolean;
864
+ onCheckedChange?: (checked: boolean) => void;
390
865
  label?: ReactNode;
391
- disabled?: boolean;
866
+ /** Second line under the label. Matches Figma's `Supporting text` axis. */
867
+ description?: ReactNode;
868
+ /** Matches Figma's `Size` axis. Default `md`, which is 0.3.0's fixed 18px. */
869
+ size?: CheckboxSize;
392
870
  indeterminate?: boolean;
871
+ invalid?: boolean;
872
+ className?: string;
873
+ }
874
+ /**
875
+ * Checkbox built on a real `<input type="checkbox">`.
876
+ *
877
+ * Widened in 0.4.0 to match Figma's `Checkbox` set, which has `Size: sm | md`,
878
+ * `Text` and `Supporting text` axes — none of which existed in code, where the control was
879
+ * a fixed 18px with an optional single-line label and no `id`, `name`, `value`, `required`
880
+ * or ref. It also had no uncontrolled mode: `checked` and `onChange` were both required, so
881
+ * the simplest possible use site needed a `useState` in the consumer.
882
+ *
883
+ * `onChange` became `onCheckedChange` and takes a boolean, matching the rest of 0.4.0.
884
+ * The native `onChange` event shape is still reachable — the ref is forwarded to the real
885
+ * input, so `react-hook-form`'s `register()` works.
886
+ */
887
+ declare const Checkbox: react.ForwardRefExoticComponent<CheckboxProps & react.RefAttributes<HTMLInputElement>>;
888
+
889
+ type RadioGroupOrientation = 'vertical' | 'horizontal';
890
+ interface RadioGroupProps extends Omit<HTMLAttributes<HTMLDivElement>, 'onChange'> {
891
+ children: ReactNode;
892
+ value?: string;
893
+ defaultValue?: string;
894
+ onValueChange?: (value: string) => void;
895
+ /** Shared `name` for the underlying inputs. Generated when omitted. */
896
+ name?: string;
897
+ /** Names the group. Prefer wrapping in `FieldSet` + `FieldLegend` for a visible label. */
898
+ label?: string;
899
+ size?: CheckControlSize;
900
+ orientation?: RadioGroupOrientation;
901
+ disabled?: boolean;
902
+ invalid?: boolean;
903
+ required?: boolean;
904
+ }
905
+ /**
906
+ * Radio group. Matches the `Type=Radio` half of Figma's `Checkbox` set, and shares its
907
+ * geometry through `CheckControl`.
908
+ *
909
+ * Built on real `<input type="radio">` elements sharing a `name`, which is what buys the
910
+ * whole keyboard contract for free: arrow keys move *and* select, only the checked radio is
911
+ * in the tab sequence, and the group is announced as "2 of 4". A `div`-based
912
+ * `role="radiogroup"` has to reimplement all of that, and the version of this pattern the
913
+ * library already had — `SegmentedControl` before 0.4.0 — shipped with none of it.
914
+ *
915
+ * `role="radiogroup"` is still set explicitly rather than relying on a `<fieldset>`, so the
916
+ * group works with or without a visible legend.
917
+ */
918
+ declare const RadioGroup: react.ForwardRefExoticComponent<RadioGroupProps & react.RefAttributes<HTMLDivElement>>;
919
+ interface RadioProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'size' | 'type' | 'onChange' | 'checked'> {
920
+ value: string;
921
+ label?: ReactNode;
922
+ /** Second line under the label. Matches Figma's `Supporting text` axis. */
923
+ description?: ReactNode;
393
924
  className?: string;
394
925
  }
395
- /** Checkbox built on a real `<input type="checkbox">` — the hand-rolled `<div onClick>` version
396
- * this replaces was not keyboard-reachable and exposed no checked state to assistive tech. */
397
- declare function Checkbox({ checked, onChange, label, disabled, indeterminate, className, }: CheckboxProps): react.JSX.Element;
926
+ declare const Radio: react.ForwardRefExoticComponent<RadioProps & react.RefAttributes<HTMLInputElement>>;
398
927
 
399
928
  interface SegmentedControlOption {
400
929
  value: string;
401
930
  label: string;
931
+ disabled?: boolean;
402
932
  }
403
933
  interface SegmentedControlProps {
404
934
  options: SegmentedControlOption[];
405
- value: string;
406
- onChange?: (value: string) => void;
935
+ /** Controlled selection. Omit and pass `defaultValue` for uncontrolled. */
936
+ value?: string;
937
+ defaultValue?: string;
938
+ onValueChange?: (value: string) => void;
939
+ /** Names the group. Required by the APG when the control has no visible label. */
940
+ label?: string;
941
+ className?: string;
942
+ }
943
+ /**
944
+ * Single-select segmented toggle.
945
+ *
946
+ * Through 0.3.0 this had **no ARIA whatsoever** — the selected segment was distinguished
947
+ * only by `bg-default shadow-panel`, so a screen reader user could not tell which of the
948
+ * segments was active. It is single-select, so `radiogroup`/`radio` is the correct pattern
949
+ * rather than a row of `aria-pressed` buttons: it announces "2 of 3" and lets the arrow
950
+ * keys move between options, which a toggle-button group does not.
951
+ *
952
+ * `onChange` was also optional, so `<SegmentedControl options value />` rendered a control
953
+ * that looked interactive and silently did nothing.
954
+ */
955
+ declare function SegmentedControl({ options, value: valueProp, defaultValue, onValueChange, label, className, }: SegmentedControlProps): react.JSX.Element;
956
+
957
+ interface SliderProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'type' | 'size' | 'onChange' | 'value'> {
958
+ value?: number;
959
+ defaultValue?: number;
960
+ onValueChange?: (value: number) => void;
961
+ min?: number;
962
+ max?: number;
963
+ step?: number;
964
+ /** Matches Figma's `Label` / `Has Label`. */
965
+ label?: ReactNode;
966
+ /** Matches Figma's `Description` / `Has Description`. */
967
+ description?: ReactNode;
968
+ /** Show the current value at the right of the label row. */
969
+ showValue?: boolean;
970
+ /** Formats the displayed and announced value — percentages, currency, durations. */
971
+ formatValue?: (value: number) => string;
972
+ className?: string;
973
+ }
974
+ /**
975
+ * Range slider. Matches Figma's `Slider Field` (`State: Default | Disabled`, with label and
976
+ * description slots).
977
+ *
978
+ * A native `<input type="range">`, deliberately. It arrives with the entire APG slider
979
+ * contract already implemented — arrow keys, Page Up/Down, Home/End, the correct
980
+ * `aria-valuenow`/`valuemin`/`valuemax`, touch and pointer dragging, and RTL handling — and
981
+ * a `div`-based slider has to rebuild all of it. The track and thumb are styled through the
982
+ * vendor pseudo-elements instead, which is the one place raw `[&::-webkit-…]` selectors are
983
+ * the right tool.
984
+ *
985
+ * `formatValue` feeds `aria-valuetext`, because "70" announced on a price slider is
986
+ * meaningless where "£70" is not.
987
+ */
988
+ declare const Slider: react.ForwardRefExoticComponent<SliderProps & react.RefAttributes<HTMLInputElement>>;
989
+
990
+ interface LabelProps extends LabelHTMLAttributes<HTMLLabelElement> {
991
+ children: ReactNode;
992
+ size?: InputSize;
993
+ }
994
+ /**
995
+ * A standalone `<label>`.
996
+ *
997
+ * `FieldLabel` is the one to reach for inside a `Field` — it picks up the generated id,
998
+ * the size and the disabled state from context automatically. This is for the cases that
999
+ * are not a field: naming a `SegmentedControl`, a group of buttons, or any control the
1000
+ * library does not wrap. It still reads `Field` context when it happens to be inside one,
1001
+ * so it degrades to `FieldLabel` behaviour rather than silently losing the association.
1002
+ */
1003
+ declare const Label: react.ForwardRefExoticComponent<LabelProps & react.RefAttributes<HTMLLabelElement>>;
1004
+
1005
+ type CalendarMode = 'single' | 'range';
1006
+ interface DateRange {
1007
+ from: Date | null;
1008
+ to: Date | null;
1009
+ }
1010
+ interface CalendarProps extends Omit<HTMLAttributes<HTMLDivElement>, 'onSelect'> {
1011
+ mode?: CalendarMode;
1012
+ /** Selected date in `single` mode. */
1013
+ value?: Date | null;
1014
+ /** Selected range in `range` mode. */
1015
+ range?: DateRange;
1016
+ onSelect?: (value: Date) => void;
1017
+ onRangeChange?: (range: DateRange) => void;
1018
+ /** Month shown on mount. Defaults to the selection's month, else today. */
1019
+ defaultMonth?: Date;
1020
+ min?: Date;
1021
+ max?: Date;
1022
+ /** Return `true` to disable a day. Combined with `min`/`max`. */
1023
+ isDateDisabled?: (date: Date) => boolean;
1024
+ /** 0 = Sunday, 1 = Monday. Default `1`. */
1025
+ weekStartsOn?: 0 | 1;
1026
+ /** BCP 47 tag for month, weekday and announced day names. Default: the browser's. */
1027
+ locale?: string;
1028
+ /** Names the grid. Default `Calendar`. */
1029
+ label?: string;
1030
+ }
1031
+ /**
1032
+ * Month grid. Matches Figma's `Calendar`, `Calendar Button`
1033
+ * (`State: Default | Hover | Active | Disabled | Range | Range Disabled | Hidden`),
1034
+ * `Calendar Select Group` and `Calendar Month/Year Field`.
1035
+ *
1036
+ * The code had no calendar at all — `DatePicker` was a bare `<input type="date">` with
1037
+ * Chromium-only indicator styling, so there was nothing to build a range picker on, no
1038
+ * locale control and no min/max navigation.
1039
+ *
1040
+ * The keyboard model is the APG date-grid pattern, and it is the whole reason this is not
1041
+ * just a table of buttons:
1042
+ *
1043
+ * - **One tab stop.** Tab enters the grid once and leaves it; arrows move within. A grid of
1044
+ * 42 individually tabbable buttons takes 42 presses to get past.
1045
+ * - **Arrows cross month boundaries.** Pressing Left on the 1st moves to the previous
1046
+ * month's last day and pages the view, rather than dead-ending.
1047
+ * - **PageUp/PageDown** move by month, **Home/End** to the start/end of the week.
1048
+ * - Each day's accessible name is the full date, not the number — "14" tells a screen
1049
+ * reader user nothing.
1050
+ */
1051
+ declare function Calendar({ mode, value, range, onSelect, onRangeChange, defaultMonth, min, max, isDateDisabled, weekStartsOn, locale, label, className, ...rest }: CalendarProps): react.JSX.Element;
1052
+
1053
+ type InputGroupAlign = 'inline-start' | 'inline-end' | 'block-start' | 'block-end';
1054
+ interface InputGroupProps extends HTMLAttributes<HTMLDivElement> {
1055
+ children: ReactNode;
1056
+ size?: InputSize;
1057
+ invalid?: boolean;
1058
+ disabled?: boolean;
1059
+ }
1060
+ /**
1061
+ * A bordered shell that holds an input alongside addons — a prefix, a unit suffix, a
1062
+ * search glyph, a clear button, a copy button.
1063
+ *
1064
+ * This generalises what `PasswordInput` did as a one-off. `Input` has `leadingIcon`,
1065
+ * `trailingIcon` and `trailingAction` props, which works for a single decoration but forces
1066
+ * absolute positioning and per-size padding maps to keep the text clear of it. Here the
1067
+ * addons are real flex siblings, so the input's text box simply ends where the addon
1068
+ * begins and nothing has to be measured.
1069
+ *
1070
+ * The border and focus ring live on the group, not the input — so focusing the input rings
1071
+ * the whole control, which is what a user perceives as "the field".
1072
+ */
1073
+ declare const InputGroup: react.ForwardRefExoticComponent<InputGroupProps & react.RefAttributes<HTMLDivElement>>;
1074
+ interface InputGroupInputProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'size'> {
1075
+ }
1076
+ /**
1077
+ * The input inside an `InputGroup`. Carries no border, background or ring of its own —
1078
+ * the group owns all three.
1079
+ */
1080
+ declare const InputGroupInput: react.ForwardRefExoticComponent<InputGroupInputProps & react.RefAttributes<HTMLInputElement>>;
1081
+ interface InputGroupAddonProps extends HTMLAttributes<HTMLSpanElement> {
1082
+ children: ReactNode;
1083
+ align?: InputGroupAlign;
1084
+ /**
1085
+ * `true` when the addon is decoration — an icon, a unit. Decorative addons are
1086
+ * `aria-hidden` and ignore pointer events, so they never steal a click meant for the
1087
+ * text box. Default `true`; set `false` for an addon containing a control.
1088
+ */
1089
+ decorative?: boolean;
1090
+ }
1091
+ declare const InputGroupAddon: react.ForwardRefExoticComponent<InputGroupAddonProps & react.RefAttributes<HTMLSpanElement>>;
1092
+ interface InputGroupTextProps extends HTMLAttributes<HTMLSpanElement> {
1093
+ children: ReactNode;
1094
+ }
1095
+ /** Static text inside the shell — a currency symbol, a domain suffix, a unit. */
1096
+ declare const InputGroupText: react.ForwardRefExoticComponent<InputGroupTextProps & react.RefAttributes<HTMLSpanElement>>;
1097
+ interface SearchInputProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'size' | 'type'> {
1098
+ size?: InputSize;
1099
+ /** Renders a clear button once there is a value. */
1100
+ onClear?: () => void;
1101
+ /** Accessible name. Default `Search`. */
1102
+ label?: string;
407
1103
  className?: string;
408
1104
  }
409
- declare function SegmentedControl({ options, value, onChange, className }: SegmentedControlProps): react.JSX.Element;
1105
+ /**
1106
+ * Search field. Matches Figma's `Search` set — `Size: Large | Medium | Small`,
1107
+ * `State: Default | Disabled`, `Value Type: Filled | Placeholder`.
1108
+ *
1109
+ * `type="search"` rather than `type="text"`: it gets the platform's search affordances and
1110
+ * is announced as a search field. The clear button is a real button so it is keyboard
1111
+ * reachable, unlike the UA-provided cancel widget which is pointer-only in most browsers
1112
+ * and is therefore suppressed.
1113
+ */
1114
+ declare const SearchInput: react.ForwardRefExoticComponent<SearchInputProps & react.RefAttributes<HTMLInputElement>>;
410
1115
 
411
1116
  type ModalSize = 'sm' | 'md' | 'lg' | 'xl';
412
1117
  /**
@@ -417,20 +1122,32 @@ type ModalSize = 'sm' | 'md' | 'lg' | 'xl';
417
1122
  type ModalTone = 'default' | 'info' | 'positive' | 'warning' | 'danger';
418
1123
  type ModalFooterAlign = 'start' | 'between' | 'end';
419
1124
  interface ModalProps {
420
- isOpen: boolean;
421
- onClose: () => void;
1125
+ open: boolean;
1126
+ /** Fired with `false` on Escape, an outside press, or the close button. */
1127
+ onOpenChange: (open: boolean) => void;
422
1128
  /**
423
- * Accessible name for the dialog. Required, so a slot-composed modal can never ship
424
- * unnamed. Was `title` in 0.2.0, renamed because `title` is also an HTML attribute
425
- * that renders a tooltip.
1129
+ * Accessible name. Only needed when the dialog renders no `ModalTitle` — with one, the
1130
+ * name comes from the heading itself via `aria-labelledby`, so it cannot drift.
426
1131
  */
427
- label: string;
1132
+ label?: string;
428
1133
  children: ReactNode;
429
1134
  size?: ModalSize;
1135
+ /**
1136
+ * `alertdialog` for a dialog that interrupts to confirm or warn — it makes assistive
1137
+ * tech announce the body immediately rather than waiting to be browsed. `ConfirmDialog`
1138
+ * passes it; plain content dialogs should stay `dialog`.
1139
+ */
1140
+ role?: 'dialog' | 'alertdialog';
430
1141
  /** Renders the top-right close button. */
431
1142
  showClose?: boolean;
432
1143
  /** Applied to the panel. With `cn`, `className="sm:max-w-[560px]"` beats `size`. */
433
1144
  className?: string;
1145
+ /** Call `preventDefault()` to keep the dialog open — e.g. unsaved input. */
1146
+ onEscapeKeyDown?: (event: KeyboardEvent) => void;
1147
+ /** Call `preventDefault()` to keep the dialog open. */
1148
+ onInteractOutside?: (event: PointerEvent) => void;
1149
+ /** Focus this on open instead of the first tabbable element. */
1150
+ initialFocus?: React.RefObject<HTMLElement | null>;
434
1151
  }
435
1152
  /**
436
1153
  * A centred dialog above `sm`, a bottom sheet below it.
@@ -451,11 +1168,11 @@ declare function ModalHeader({ children, tone, divider, className, ...rest }: Mo
451
1168
  interface ModalTitleProps extends HTMLAttributes<HTMLHeadingElement> {
452
1169
  children: ReactNode;
453
1170
  }
454
- declare function ModalTitle({ children, className, ...rest }: ModalTitleProps): react.JSX.Element;
1171
+ declare function ModalTitle({ children, className, id, ...rest }: ModalTitleProps): react.JSX.Element;
455
1172
  interface ModalDescriptionProps extends HTMLAttributes<HTMLParagraphElement> {
456
1173
  children: ReactNode;
457
1174
  }
458
- declare function ModalDescription({ children, className, ...rest }: ModalDescriptionProps): react.JSX.Element;
1175
+ declare function ModalDescription({ children, className, id, ...rest }: ModalDescriptionProps): react.JSX.Element;
459
1176
  interface ModalBodyProps extends HTMLAttributes<HTMLDivElement> {
460
1177
  children: ReactNode;
461
1178
  }
@@ -468,10 +1185,263 @@ interface ModalFooterProps extends HTMLAttributes<HTMLDivElement> {
468
1185
  }
469
1186
  declare function ModalFooter({ children, align, divider, className, ...rest }: ModalFooterProps): react.JSX.Element;
470
1187
 
1188
+ type FloatingSide = 'top' | 'right' | 'bottom' | 'left';
1189
+ type FloatingAlign = 'start' | 'center' | 'end';
1190
+
1191
+ interface TooltipProps {
1192
+ /**
1193
+ * The trigger. Must be a single focusable element — a tooltip that can only be reached
1194
+ * with a pointer is invisible to keyboard and touch users, so this deliberately does not
1195
+ * wrap its child in a span to make it hoverable.
1196
+ */
1197
+ children: ReactElement;
1198
+ /** Bold first line. Matches Figma's `Title` property. */
1199
+ title?: ReactNode;
1200
+ /** Supporting line. Matches Figma's `Body` / `Has Body`. */
1201
+ body?: ReactNode;
1202
+ side?: FloatingSide;
1203
+ align?: FloatingAlign;
1204
+ /** Delay before opening, in ms. Default `150`. */
1205
+ openDelay?: number;
1206
+ /** Delay before closing, in ms. Default `0`. */
1207
+ closeDelay?: number;
1208
+ open?: boolean;
1209
+ defaultOpen?: boolean;
1210
+ onOpenChange?: (open: boolean) => void;
1211
+ /**
1212
+ * `describedby` — the trigger keeps its own name and the tooltip adds detail. This is
1213
+ * almost always what you want. `labelledby` makes the tooltip *be* the trigger's name,
1214
+ * for an icon-only button with no other text. Default `describedby`.
1215
+ *
1216
+ * Deliberately not called `as`: everywhere else in this library `as` chooses the rendered
1217
+ * element, and reusing it for something else here would be a trap (it also makes
1218
+ * `jsx-a11y`'s polymorphic-component checking treat the value as a tag name).
1219
+ */
1220
+ association?: 'describedby' | 'labelledby';
1221
+ className?: string;
1222
+ }
1223
+ /**
1224
+ * Tooltip. Matches Figma's `Tooltip` set — `Placement: Top | Left | Right | Bottom`, with
1225
+ * a title and an optional body.
1226
+ *
1227
+ * Things this gets right that a naive tooltip does not:
1228
+ *
1229
+ * - **Keyboard and touch reachable.** Opens on `focus` as well as hover, and closes on
1230
+ * Escape. A hover-only tooltip is inaccessible to half the people using it.
1231
+ * - **Referenced, not floating text.** The panel is wired to the trigger with
1232
+ * `aria-describedby` (or `aria-labelledby`), so it is announced *with* the control
1233
+ * rather than being an orphan region a screen reader may never reach.
1234
+ * - **`role="tooltip"` and no interactive content.** A tooltip cannot be hovered into or
1235
+ * focused, so anything interactive inside it is unreachable — use `Popover` for that.
1236
+ * - Not modal: no focus trap, no scroll lock, no inert background.
1237
+ */
1238
+ declare function Tooltip({ children, title, body, side, align, openDelay, closeDelay, open: openProp, defaultOpen, onOpenChange, association, className, }: TooltipProps): react.JSX.Element | null;
1239
+
1240
+ interface PopoverProps {
1241
+ children: ReactNode;
1242
+ open?: boolean;
1243
+ defaultOpen?: boolean;
1244
+ onOpenChange?: (open: boolean) => void;
1245
+ /**
1246
+ * Trap focus, lock scroll and mark the rest of the page inert. Default `false`.
1247
+ *
1248
+ * A popover is normally non-modal: the page behind stays usable, and Tab moves out of the
1249
+ * panel and on through the document. Set `modal` when the panel is a small form whose
1250
+ * background must not be touched until it is dismissed.
1251
+ */
1252
+ modal?: boolean;
1253
+ }
1254
+ /**
1255
+ * A floating panel anchored to a trigger, for **interactive** content.
1256
+ *
1257
+ * The distinction from `Tooltip` is not visual and it matters: a tooltip cannot be hovered
1258
+ * into or focused, so anything interactive inside one is unreachable. If the panel holds a
1259
+ * link, a button or a field, it has to be a popover — which means a real trigger with
1260
+ * `aria-expanded`/`aria-controls`, focus moving into the panel on open, and focus returning
1261
+ * to the trigger on close. All of that is here; none of it is in `Tooltip`, by design.
1262
+ */
1263
+ declare function Popover({ children, open: openProp, defaultOpen, onOpenChange, modal, }: PopoverProps): react.JSX.Element;
1264
+ interface PopoverTriggerProps extends HTMLAttributes<HTMLElement> {
1265
+ children: ReactNode;
1266
+ asChild?: boolean;
1267
+ }
1268
+ declare function PopoverTrigger({ children, asChild, className, ...rest }: PopoverTriggerProps): react.JSX.Element;
1269
+ interface PopoverContentProps extends HTMLAttributes<HTMLDivElement> {
1270
+ children: ReactNode;
1271
+ side?: FloatingSide;
1272
+ align?: FloatingAlign;
1273
+ sideOffset?: number;
1274
+ /** Accessible name for the panel. Falls back to being labelled by the trigger. */
1275
+ label?: string;
1276
+ }
1277
+ declare function PopoverContent({ children, side, align, sideOffset, label, className, ...rest }: PopoverContentProps): react.JSX.Element | null;
1278
+
1279
+ interface HoverCardProps {
1280
+ /** The trigger. Must be a single focusable element — normally a link. */
1281
+ children: ReactElement;
1282
+ /** Panel content. May contain links and text; see the note on interactivity below. */
1283
+ content: ReactNode;
1284
+ side?: FloatingSide;
1285
+ align?: FloatingAlign;
1286
+ /** Delay before opening, in ms. Default `400`. */
1287
+ openDelay?: number;
1288
+ /** Delay before closing, in ms. Default `200`. */
1289
+ closeDelay?: number;
1290
+ open?: boolean;
1291
+ defaultOpen?: boolean;
1292
+ onOpenChange?: (open: boolean) => void;
1293
+ className?: string;
1294
+ }
1295
+ /**
1296
+ * A preview panel that appears on hover — a user card on an @mention, a page preview on a
1297
+ * link.
1298
+ *
1299
+ * Sits between `Tooltip` and `Popover`, and the difference is about intent rather than
1300
+ * looks:
1301
+ *
1302
+ * - `Tooltip` is a short label. It cannot be entered, so it must hold no controls.
1303
+ * - `HoverCard` is supplementary content that *can* be entered — the panel stays open while
1304
+ * the pointer is inside it, so a link in the preview is reachable. It is opened by hover
1305
+ * and focus, never by click.
1306
+ * - `Popover` is opened deliberately by click and is the only one of the three appropriate
1307
+ * for content the user must act on.
1308
+ *
1309
+ * **It is supplementary by contract.** Hover has no touch equivalent, so anything only
1310
+ * reachable here is unreachable on a phone. The panel is `aria-labelledby` the trigger and
1311
+ * exposed as a group; the trigger keeps its own name and destination.
1312
+ *
1313
+ * The close delay is what makes the panel usable: without it, moving the pointer from the
1314
+ * trigger to the panel crosses a gap and dismisses the thing you were reaching for.
1315
+ */
1316
+ declare function HoverCard({ children, content, side, align, openDelay, closeDelay, open: openProp, defaultOpen, onOpenChange, className, }: HoverCardProps): react.JSX.Element | null;
1317
+
1318
+ type OverlayItemTone = 'default' | 'danger';
1319
+
1320
+ type MenuItemTone = OverlayItemTone;
1321
+ interface MenuItemProps extends Omit<HTMLAttributes<HTMLDivElement>, 'onSelect'> {
1322
+ children: ReactNode;
1323
+ onSelect?: () => void;
1324
+ tone?: MenuItemTone;
1325
+ disabled?: boolean;
1326
+ /** Leading glyph. Marked decorative automatically. Matches Figma's `Icon` / `Has Icon`. */
1327
+ icon?: ReactNode;
1328
+ /** Second line. Matches Figma's `Description` / `Has Description`. */
1329
+ description?: ReactNode;
1330
+ /** Trailing shortcut hint. Matches Figma's `Shortcut` / `Has Shortcut`. */
1331
+ shortcut?: ReactNode;
1332
+ /** Typeahead match text, when `children` is not a plain string. */
1333
+ textValue?: string;
1334
+ }
1335
+ declare function MenuItem({ children, onSelect, tone, disabled, icon, description, shortcut, textValue, className, ...rest }: MenuItemProps): react.JSX.Element;
1336
+ interface MenuCheckboxItemProps extends Omit<MenuItemProps, 'onSelect' | 'icon'> {
1337
+ checked: boolean;
1338
+ onCheckedChange?: (checked: boolean) => void;
1339
+ }
1340
+ declare function MenuCheckboxItem({ children, checked, onCheckedChange, disabled, tone, shortcut, textValue, className, ...rest }: MenuCheckboxItemProps): react.JSX.Element;
1341
+ interface MenuRadioGroupProps {
1342
+ children: ReactNode;
1343
+ value?: string;
1344
+ onValueChange?: (value: string) => void;
1345
+ }
1346
+ declare function MenuRadioGroup({ children, value, onValueChange }: MenuRadioGroupProps): react.JSX.Element;
1347
+ interface MenuRadioItemProps extends Omit<MenuItemProps, 'onSelect' | 'icon'> {
1348
+ value: string;
1349
+ }
1350
+ declare function MenuRadioItem({ children, value, disabled, tone, textValue, className, ...rest }: MenuRadioItemProps): react.JSX.Element;
1351
+ interface MenuGroupProps extends HTMLAttributes<HTMLDivElement> {
1352
+ children: ReactNode;
1353
+ /** Names the group. Rendered as a heading when set. */
1354
+ label?: string;
1355
+ }
1356
+ declare function MenuGroup({ children, label, className, ...rest }: MenuGroupProps): react.JSX.Element;
1357
+ interface MenuLabelProps extends HTMLAttributes<HTMLDivElement> {
1358
+ children: ReactNode;
1359
+ }
1360
+ /** A non-interactive heading inside the menu. Matches Figma's `Menu Heading`. */
1361
+ declare function MenuLabel({ children, className, ...rest }: MenuLabelProps): react.JSX.Element;
1362
+ interface MenuSeparatorProps extends HTMLAttributes<HTMLDivElement> {
1363
+ }
1364
+ /** Matches Figma's `Menu Separator`. Was a bare unlabelled `div` before 0.4.0. */
1365
+ declare function MenuSeparator({ className, ...rest }: MenuSeparatorProps): react.JSX.Element;
1366
+ interface MenuShortcutProps extends HTMLAttributes<HTMLSpanElement> {
1367
+ children: ReactNode;
1368
+ }
1369
+ /** Trailing keyboard hint, for use outside an item's `shortcut` prop. */
1370
+ declare function MenuShortcut({ children, className, ...rest }: MenuShortcutProps): react.JSX.Element;
1371
+
1372
+ interface ContextMenuProps {
1373
+ children: ReactNode;
1374
+ open?: boolean;
1375
+ defaultOpen?: boolean;
1376
+ onOpenChange?: (open: boolean) => void;
1377
+ }
1378
+ /**
1379
+ * Right-click menu.
1380
+ *
1381
+ * Shares every item and the whole keyboard contract with `DropdownMenu` via `menu-core`;
1382
+ * the only difference is how it opens — at the pointer, with no trigger element to anchor
1383
+ * to, so it is positioned from coordinates rather than by Floating UI's reference/floating
1384
+ * pair.
1385
+ *
1386
+ * **A context menu must never be the only way to reach an action.** `contextmenu` fires on
1387
+ * right-click and on the Windows Menu / Shift+F10 keys, but not on touch, and plenty of
1388
+ * users never right-click at all. `ContextMenuTrigger` therefore also opens on Shift+F10 and
1389
+ * the ContextMenu key, and anything in here should have a visible equivalent elsewhere —
1390
+ * usually a `DropdownMenu` on the same row.
1391
+ */
1392
+ declare function ContextMenu({ children, open: openProp, defaultOpen, onOpenChange, }: ContextMenuProps): react.JSX.Element;
1393
+ interface ContextMenuTriggerProps extends HTMLAttributes<HTMLDivElement> {
1394
+ children: ReactNode;
1395
+ disabled?: boolean;
1396
+ }
1397
+ declare function ContextMenuTrigger({ children, disabled, className, ...rest }: ContextMenuTriggerProps): react.JSX.Element;
1398
+ interface ContextMenuContentProps extends HTMLAttributes<HTMLDivElement> {
1399
+ children: ReactNode;
1400
+ /** Minimum gap from the viewport edge, in px. Default `8`. */
1401
+ collisionPadding?: number;
1402
+ }
1403
+ declare function ContextMenuContent({ children, collisionPadding, className, ...rest }: ContextMenuContentProps): react.JSX.Element | null;
1404
+
1405
+ interface MenubarProps extends HTMLAttributes<HTMLDivElement> {
1406
+ children: ReactNode;
1407
+ /** Names the menubar. Required by the APG. */
1408
+ label: string;
1409
+ }
1410
+ /**
1411
+ * An application menu bar — a horizontal row of menus, as in a desktop app.
1412
+ *
1413
+ * Two things distinguish it from a row of `DropdownMenu`s, and both are in the APG:
1414
+ *
1415
+ * - **The bar is one tab stop.** Left/Right move between the top-level menus; Tab leaves the
1416
+ * bar entirely. A row of independent dropdowns is N tab stops.
1417
+ * - **Only one menu is open at a time**, and once any is open, moving along the bar switches
1418
+ * directly to the next menu rather than closing and reopening.
1419
+ *
1420
+ * Items and the vertical keyboard contract come from `menu-core`, shared with
1421
+ * `DropdownMenu` and `ContextMenu`.
1422
+ */
1423
+ declare function Menubar({ children, label, className, ...rest }: MenubarProps): react.JSX.Element;
1424
+ interface MenubarMenuProps {
1425
+ children: ReactNode;
1426
+ /** Identifies this menu within the bar. */
1427
+ value: string;
1428
+ }
1429
+ /** One menu in the bar. Wraps a `MenubarTrigger` and a `MenubarContent`. */
1430
+ declare function MenubarMenu({ children, value }: MenubarMenuProps): react.JSX.Element;
1431
+ interface MenubarTriggerProps extends HTMLAttributes<HTMLButtonElement> {
1432
+ children: ReactNode;
1433
+ }
1434
+ declare function MenubarTrigger({ children, className, ...rest }: MenubarTriggerProps): react.JSX.Element;
1435
+ interface MenubarContentProps extends HTMLAttributes<HTMLDivElement> {
1436
+ children: ReactNode;
1437
+ }
1438
+ declare function MenubarContent({ children, className, ...rest }: MenubarContentProps): react.JSX.Element | null;
1439
+
1440
+ type DrawerSide = 'right' | 'left';
471
1441
  interface DrawerProps {
472
- /** Required as of 0.3.0 — every overlay is now `isOpen` + `onClose`. */
473
- isOpen: boolean;
474
- onClose: () => void;
1442
+ open: boolean;
1443
+ /** Fired with `false` on Escape, an outside press, or the close button. */
1444
+ onOpenChange: (open: boolean) => void;
475
1445
  /** Header content (left side). The copies this replaces differ only here — a status badge +
476
1446
  * title in one, an avatar + title + category in another — so it is a slot, not props. */
477
1447
  header: ReactNode;
@@ -481,18 +1451,34 @@ interface DrawerProps {
481
1451
  footerAlign?: 'end' | 'between';
482
1452
  /** Panel width. Defaults to the `w-[440px] max-w-[90vw]` shared by every existing drawer. */
483
1453
  width?: string;
484
- /** Accessible name for the dialog. */
485
- label?: string;
1454
+ /** Which edge the panel slides in from. Default `right`. */
1455
+ side?: DrawerSide;
1456
+ /**
1457
+ * Accessible name for the dialog. **Required** as of 0.4.0.
1458
+ *
1459
+ * It was optional through 0.3.0 while `Modal.label` was required, which meant the
1460
+ * public API allowed a `role="dialog" aria-modal="true"` element with no accessible
1461
+ * name at all — a screen reader announced "dialog" and nothing else. Unlike `Modal`
1462
+ * there is no `DrawerTitle` part to infer a name from, because `header` is a free
1463
+ * slot, so the string is the only place it can come from.
1464
+ */
1465
+ label: string;
486
1466
  className?: string;
1467
+ /** Call `preventDefault()` to keep the drawer open — e.g. unsaved input. */
1468
+ onEscapeKeyDown?: (event: KeyboardEvent) => void;
1469
+ /** Call `preventDefault()` to keep the drawer open. */
1470
+ onInteractOutside?: (event: PointerEvent) => void;
1471
+ /** Focus this on open instead of the first tabbable element. */
1472
+ initialFocus?: RefObject<HTMLElement | null>;
487
1473
  }
488
1474
  /**
489
- * Right-hand side panel. Handles Esc, traps Tab focus, and restores focus to the
490
- * trigger on close.
1475
+ * Side panel. Handles Esc, traps Tab focus, locks background scroll, marks the rest of
1476
+ * the page inert, and restores focus to the trigger on close.
491
1477
  */
492
1478
  declare function Drawer(props: DrawerProps): react.JSX.Element | null;
493
1479
 
494
1480
  interface ConfirmDialogProps {
495
- isOpen: boolean;
1481
+ open: boolean;
496
1482
  title: string;
497
1483
  subtitle?: string;
498
1484
  /**
@@ -513,8 +1499,8 @@ interface ConfirmDialogProps {
513
1499
  children?: ReactNode;
514
1500
  className?: string;
515
1501
  onConfirm: () => void;
516
- /** Renamed from `onCancel` in 0.3.0 — every overlay now uses `isOpen` + `onClose`. */
517
- onClose: () => void;
1502
+ /** Fired with `false` on cancel, Escape, or an outside press. */
1503
+ onOpenChange: (open: boolean) => void;
518
1504
  }
519
1505
  /**
520
1506
  * The in-app replacement for `window.confirm`: a title, an optional body, and a
@@ -525,11 +1511,10 @@ interface ConfirmDialogProps {
525
1511
  * is the thing call sites get wrong when they hand-roll a confirm. For any other
526
1512
  * shape, compose `Modal` and its parts directly.
527
1513
  */
528
- declare function ConfirmDialog({ isOpen, title, subtitle, tone, size, confirmLabel, cancelLabel, confirmVariant, isConfirming, confirmingLabel, children, className, onConfirm, onClose, }: ConfirmDialogProps): react.JSX.Element;
1514
+ declare function ConfirmDialog({ open, title, subtitle, tone, size, confirmLabel, cancelLabel, confirmVariant, isConfirming, confirmingLabel, children, className, onConfirm, onOpenChange, }: ConfirmDialogProps): react.JSX.Element;
529
1515
 
530
1516
  interface NoteConfirmModalProps {
531
- /** Required as of 0.3.0 — this is now a controlled overlay like every other. */
532
- isOpen: boolean;
1517
+ open: boolean;
533
1518
  title: string;
534
1519
  subtitle?: string;
535
1520
  tone?: ModalTone;
@@ -543,8 +1528,14 @@ interface NoteConfirmModalProps {
543
1528
  submittingLabel?: string;
544
1529
  isSubmitting?: boolean;
545
1530
  className?: string;
546
- onClose: () => void;
1531
+ /** Fired with `false` on cancel, Escape, or an outside press. */
1532
+ onOpenChange: (open: boolean) => void;
547
1533
  onConfirm: (note: string) => void;
1534
+ /**
1535
+ * Asked before an Escape or outside press throws away a note that has content.
1536
+ * Return `false` to keep the dialog open. Defaults to `window.confirm`.
1537
+ */
1538
+ onDiscardNote?: (note: string) => boolean;
548
1539
  }
549
1540
  /**
550
1541
  * Confirm dialog that collects a free-text note — approvals, rejections, information
@@ -552,45 +1543,161 @@ interface NoteConfirmModalProps {
552
1543
  *
553
1544
  * Kept as a preset because it owns state, and a composition cannot.
554
1545
  */
555
- declare function NoteConfirmModal({ isOpen, ...rest }: NoteConfirmModalProps): react.JSX.Element | null;
1546
+ declare function NoteConfirmModal({ open, ...rest }: NoteConfirmModalProps): react.JSX.Element | null;
556
1547
 
557
- interface DropdownMenuItem {
558
- label: string;
559
- onSelect: () => void;
560
- tone?: 'default' | 'danger';
561
- disabled?: boolean;
562
- /** Draw a separator above this item. */
563
- separatorBefore?: boolean;
564
- }
1548
+ /**
1549
+ * Overflow / row-actions menu, rebuilt in 0.4.0.
1550
+ *
1551
+ * The previous version declared `role="menu"` and `role="menuitem"` and implemented none of
1552
+ * the WAI-ARIA menu contract. Announcing a pattern you do not implement is worse than
1553
+ * announcing nothing, because a screen reader tells the user which keys should work. Fixed:
1554
+ * arrow keys, Home/End and typeahead; a roving tabindex (every item used to be a natively
1555
+ * tabbable `<button>`, so Tab walked all of them); focus moving into the menu on open and
1556
+ * back to the trigger on close; a portal, so the panel is no longer clipped by `Card`'s
1557
+ * `overflow-hidden` or `DataTable`'s `overflow-x-auto` — both named in its own doc comment
1558
+ * as the reason it exists; collision handling instead of a static `left`/`right`; correct
1559
+ * ARIA ownership; and `open`/`onOpenChange`, where open state used to be unreachable.
1560
+ *
1561
+ * The items and keyboard model now live in `menu-core`, shared with `ContextMenu` and
1562
+ * `Menubar`.
1563
+ *
1564
+ * Not implemented: submenus. Doing them properly needs hover intent and a safe-travel
1565
+ * polygon between trigger and panel, and a half-built version is worse than none — nest a
1566
+ * second `DropdownMenu` in the meantime.
1567
+ */
565
1568
  interface DropdownMenuProps {
566
- items: DropdownMenuItem[];
567
- /** Custom trigger content. Defaults to a `⋯` overflow button. */
568
- trigger?: ReactNode;
569
- /** Accessible name for the trigger, e.g. `Open actions for Admin`. */
570
- label: string;
571
- align?: 'left' | 'right';
572
- className?: string;
1569
+ children: ReactNode;
1570
+ /** Controlled open state. Omit for uncontrolled. */
1571
+ open?: boolean;
1572
+ defaultOpen?: boolean;
1573
+ onOpenChange?: (open: boolean) => void;
573
1574
  }
574
- /** Overflow / row-actions menu.
575
- *
576
- * Keeps the outside-click dismissal and `aria-haspopup`/`aria-expanded` wiring from the
577
- * hand-rolled `RowMenu` it replaces, and adds Esc-to-close. `mousedown` is stopped at the
578
- * wrapper so the menu works inside clickable table rows. */
579
- declare function DropdownMenu({ items, trigger, label, align, className, }: DropdownMenuProps): react.JSX.Element;
1575
+ declare function DropdownMenu({ children, open: openProp, defaultOpen, onOpenChange, }: DropdownMenuProps): react.JSX.Element;
1576
+ interface DropdownMenuTriggerProps extends HTMLAttributes<HTMLElement> {
1577
+ children?: ReactNode;
1578
+ /** Render the child element instead of the default overflow button. */
1579
+ asChild?: boolean;
1580
+ /** Accessible name for the default `⋯` button. Ignored when `asChild` is set. */
1581
+ label?: string;
1582
+ }
1583
+ declare function DropdownMenuTrigger({ children, asChild, label, ...rest }: DropdownMenuTriggerProps): react.JSX.Element;
1584
+ interface DropdownMenuContentProps extends HTMLAttributes<HTMLDivElement> {
1585
+ children: ReactNode;
1586
+ side?: FloatingSide;
1587
+ align?: FloatingAlign;
1588
+ sideOffset?: number;
1589
+ }
1590
+ declare function DropdownMenuContent({ children, side, align, sideOffset, className, ...rest }: DropdownMenuContentProps): react.JSX.Element | null;
1591
+
1592
+ interface PortalProps {
1593
+ children: ReactNode;
1594
+ /**
1595
+ * Where to mount. Defaults to `document.body`.
1596
+ *
1597
+ * Pass a container when the app renders inside a shadow root or a scoped theme
1598
+ * wrapper — the portal must stay inside whatever element the design tokens are
1599
+ * declared on, or every `var(--color-*)` resolves to nothing.
1600
+ */
1601
+ container?: HTMLElement | null;
1602
+ }
1603
+ /**
1604
+ * Renders `children` outside the parent DOM hierarchy.
1605
+ *
1606
+ * Until 0.4.0 this library never called `createPortal` — `Modal`, `Drawer`,
1607
+ * `DropdownMenu`, `RoleComboBox` and the sidebar menu all rendered inline. Two concrete
1608
+ * failures came out of that:
1609
+ *
1610
+ * - `DropdownMenu` was positioned `absolute` inside a `relative` wrapper, so it was
1611
+ * clipped by `Card`'s `overflow-hidden` and by `DataTable`'s `overflow-x-auto` — the
1612
+ * two places its own doc comment said it was for.
1613
+ * - `position: fixed` resolves against the nearest ancestor with `transform`, `filter`,
1614
+ * `backdrop-filter`, `perspective`, `will-change` or `contain`, so a `Modal` opened
1615
+ * from inside any transformed ancestor was positioned against that ancestor rather
1616
+ * than the viewport, and `z-50` was scoped to a stacking context it did not control.
1617
+ *
1618
+ * Mounting is deferred to an effect so the server render and the first client render
1619
+ * agree — reaching for `document` during render breaks SSR and hydration.
1620
+ */
1621
+ declare function Portal({ children, container }: PortalProps): react.ReactPortal | null;
580
1622
 
581
1623
  /** The one scrim for every overlay primitive.
582
1624
  *
583
1625
  * Modal and Drawer both reference this constant, so there is a single place to change
584
1626
  * the dimming behind a dialog. Backed by `--color-background-utilities-overlay`. */
585
1627
  declare const OVERLAY_SCRIM = "bg-overlay";
586
- /** Esc-to-close, a Tab focus trap, and focus restore for a mounted overlay.
587
- *
588
- * None of the hand-rolled drawers/modals this replaces handled Esc or trapped focus —
589
- * they closed on scrim click only. Pass the ref of the panel element (not the scrim). */
590
- declare function useOverlayDismiss(onClose: () => void, panelRef: RefObject<HTMLElement | null>): void;
1628
+ interface UseOverlayDismissOptions {
1629
+ /** Called when the overlay should close. */
1630
+ onDismiss: () => void;
1631
+ /** The panel element — not the scrim. */
1632
+ panelRef: RefObject<HTMLElement | null>;
1633
+ /** Set `false` to suspend every behaviour without unmounting. Default `true`. */
1634
+ active?: boolean;
1635
+ /** Default `true`. */
1636
+ closeOnEscape?: boolean;
1637
+ /** Default `true`. */
1638
+ closeOnOutsidePress?: boolean;
1639
+ /** Keep Tab inside the panel. Default `true`. Turn off for non-modal surfaces. */
1640
+ trapFocus?: boolean;
1641
+ /** Default `true`. */
1642
+ lockScroll?: boolean;
1643
+ /** Mark sibling content `inert`. Default `true`. */
1644
+ inertBackground?: boolean;
1645
+ /**
1646
+ * Move focus into the panel on mount. Default `true`.
1647
+ *
1648
+ * Set `false` when the overlay manages its own entry point — a menu with a roving
1649
+ * tabindex exposes exactly one focusable item at a time, so a generic
1650
+ * "focus the first tabbable element" scan would fight it.
1651
+ */
1652
+ autoFocus?: boolean;
1653
+ /** Focus this instead of the first tabbable element. */
1654
+ initialFocus?: RefObject<HTMLElement | null>;
1655
+ /**
1656
+ * Restore focus here instead of wherever it was when the overlay opened.
1657
+ *
1658
+ * Passing the ref at all takes over the restore: a `current` of `null` means "leave
1659
+ * focus alone", not "fall back to the previously focused element". `Menubar` depends on
1660
+ * that — while it is switching from one menu to a sibling, focus already belongs to the
1661
+ * sibling and pulling it back to the closing menu's trigger reopens the menu.
1662
+ */
1663
+ returnFocus?: RefObject<HTMLElement | null>;
1664
+ /** Call `preventDefault()` to veto the close — e.g. a form with unsaved input. */
1665
+ onEscapeKeyDown?: (event: KeyboardEvent) => void;
1666
+ /** Call `preventDefault()` to veto the close. */
1667
+ onInteractOutside?: (event: PointerEvent) => void;
1668
+ }
1669
+ /** Esc-to-close, a Tab focus trap, scroll lock, an inert background, and focus restore
1670
+ * for a mounted overlay. Pass the ref of the panel element (not the scrim).
1671
+ *
1672
+ * Rewritten in 0.4.0. The previous version handled Esc, Tab and focus restore, and had
1673
+ * the following defects — each is now covered by a test:
1674
+ *
1675
+ * - **One Escape closed every open overlay.** Each overlay put its own listener on
1676
+ * `document` and called `stopPropagation`, which stops propagation to other *nodes*,
1677
+ * not to sibling listeners on the same node. Dismissal is now gated on `isTopmost`
1678
+ * from the shared layer stack.
1679
+ * - **A text-selection drag dismissed the dialog.** Outside-press used `click`, whose
1680
+ * target for a drag is the nearest common ancestor — the scrim. Now `pointerdown`.
1681
+ * - **Forward Tab could walk out of the panel.** The trap only compared against the
1682
+ * last tabbable element; once focus was outside by any other route, Tab roamed the
1683
+ * background freely. A `focusin` guard now pulls focus back.
1684
+ * - **Fixed-position elements were excluded from the trap.** The visibility filter was
1685
+ * `offsetParent !== null`, which is `null` for `position: fixed`. Element collection
1686
+ * is delegated to `tabbable`, which also honours real tab order (a positive
1687
+ * `tabindex` reorders the sequence, so DOM order was the wrong answer), `inert`,
1688
+ * `[aria-disabled]`, `contenteditable`, `<summary>`, media with controls, and
1689
+ * descendants of a disabled `<fieldset>`.
1690
+ * - **Initial focus was a silent no-op for a content-only dialog.** It fell back to
1691
+ * focusing the panel, which does nothing without `tabIndex="-1"`. The hook now sets
1692
+ * that itself, and retries once content arrives asynchronously.
1693
+ * - **Focus restore could land on a detached node**, resetting focus to `<body>`.
1694
+ * Now checked with `isConnected`.
1695
+ * - No opt-out existed for either dismissal route. Both are now vetoable.
1696
+ */
1697
+ declare function useOverlayDismiss({ onDismiss, panelRef, active, closeOnEscape, closeOnOutsidePress, trapFocus, lockScroll, inertBackground, autoFocus, initialFocus, returnFocus, onEscapeKeyDown, onInteractOutside, }: UseOverlayDismissOptions): void;
591
1698
 
592
1699
  /**
593
- * `clsx` + `tailwind-merge`.
1700
+ * `clsx` + `tailwind-merge`, taught this system's type scale.
594
1701
  *
595
1702
  * Use this instead of bare `clsx` in any component whose `className` prop is meant to
596
1703
  * *override* a base utility — the composable `Card*` and `Modal*` parts, and anything
@@ -617,76 +1724,313 @@ type CardTone = 'default' | 'brand' | 'positive' | 'warning' | 'danger';
617
1724
  type CardFooterAlign = 'start' | 'between' | 'end';
618
1725
  interface CardProps extends HTMLAttributes<HTMLDivElement> {
619
1726
  children: ReactNode;
620
- /** `2xl` suits detail pages, `xl` section panels, `lg` dense or nested cards. */
621
- radius?: CardRadius;
1727
+ /** `2xl` suits detail pages, `xl` section panels, `lg` dense or nested cards. */
1728
+ radius?: CardRadius;
1729
+ /**
1730
+ * Surface tint. This is a prop rather than a `className` because a tone has to
1731
+ * un-set the base `border-default bg-default` pair, not add to it.
1732
+ */
1733
+ tone?: CardTone;
1734
+ }
1735
+ /**
1736
+ * The card shell. Composed from `CardHeader`, `CardBody` and `CardFooter` — or from
1737
+ * nothing at all, if you want content to bleed to the edges (drop `CardBody` and put
1738
+ * a `DataTable` straight inside).
1739
+ *
1740
+ * Replaces `SectionCard` and the two monolithic cards that shipped beside it,
1741
+ * `AlertCard` and `BenchmarkCard`. Both of those are now documented compositions; see
1742
+ * the Cards page. The vocabulary follows shadcn/ui so it is already familiar, with
1743
+ * `CardBody` in place of its `CardContent`.
1744
+ */
1745
+ declare function Card({ children, radius, tone, className, ...rest }: CardProps): react.JSX.Element;
1746
+ interface CardHeaderProps extends HTMLAttributes<HTMLDivElement> {
1747
+ children: ReactNode;
1748
+ size?: CardSize;
1749
+ /** Bottom rule separating the header from the body. */
1750
+ divider?: boolean;
1751
+ }
1752
+ /**
1753
+ * Header row. Holds `CardTitle`, `CardDescription` and an optional `CardAction`.
1754
+ *
1755
+ * The `has-[…]` selector switches to a two-column grid only when a `CardAction` is
1756
+ * present, which is what lets title, description and action share a header with no
1757
+ * wrapper div and no stray gap when the action is absent.
1758
+ */
1759
+ declare function CardHeader({ children, size, divider, className, ...rest }: CardHeaderProps): react.JSX.Element;
1760
+ interface CardTitleProps extends HTMLAttributes<HTMLElement> {
1761
+ children: ReactNode;
1762
+ size?: CardSize;
1763
+ /** Heading level. Defaults to `p`; use h2/h3 where the page has a real hierarchy. */
1764
+ as?: 'h2' | 'h3' | 'h4' | 'p';
1765
+ }
1766
+ declare function CardTitle({ children, size, as: Tag, className, ...rest }: CardTitleProps): react.JSX.Element;
1767
+ interface CardDescriptionProps extends HTMLAttributes<HTMLParagraphElement> {
1768
+ children: ReactNode;
1769
+ /** Overrides the size inherited from the enclosing `CardHeader`. */
1770
+ size?: CardSize;
1771
+ }
1772
+ declare function CardDescription({ children, size, className, ...rest }: CardDescriptionProps): react.JSX.Element;
1773
+ interface CardActionProps extends HTMLAttributes<HTMLDivElement> {
1774
+ children: ReactNode;
1775
+ }
1776
+ /** Right-hand slot in a `CardHeader` — a button, a count, a status badge, a menu. */
1777
+ declare function CardAction({ children, className, ...rest }: CardActionProps): react.JSX.Element;
1778
+ interface CardBodyProps extends HTMLAttributes<HTMLDivElement> {
1779
+ children: ReactNode;
1780
+ size?: CardSize;
1781
+ }
1782
+ /**
1783
+ * The content region. A vertical stack by default.
1784
+ *
1785
+ * Because this file uses `cn`, `className` genuinely overrides the base — so
1786
+ * `className="flex-row items-center"` gives you a row, and
1787
+ * `className="grid grid-cols-3"` a grid. That is what makes the `AlertCard` and
1788
+ * `BenchmarkCard` rebuilds possible without a `layout` prop.
1789
+ */
1790
+ declare function CardBody({ children, size, className, ...rest }: CardBodyProps): react.JSX.Element;
1791
+ interface CardFooterProps extends HTMLAttributes<HTMLDivElement> {
1792
+ children: ReactNode;
1793
+ size?: CardSize;
1794
+ divider?: boolean;
1795
+ align?: CardFooterAlign;
1796
+ }
1797
+ /** Action row at the foot of a card. Mirrors `ModalFooter` and `Drawer`'s footer. */
1798
+ declare function CardFooter({ children, size, divider, align, className, ...rest }: CardFooterProps): react.JSX.Element;
1799
+
1800
+ type AccordionType = 'single' | 'multiple';
1801
+ interface AccordionProps extends Omit<HTMLAttributes<HTMLDivElement>, 'onChange'> {
1802
+ children: ReactNode;
1803
+ /** `single` closes the open item when another opens. Default `single`. */
1804
+ type?: AccordionType;
1805
+ /** Open item value(s) — a string for `single`, an array for `multiple`. */
1806
+ value?: string | string[];
1807
+ defaultValue?: string | string[];
1808
+ onValueChange?: (value: string | string[]) => void;
1809
+ /** Allow closing the open item in `single` mode. Default `true`. */
1810
+ collapsible?: boolean;
1811
+ /**
1812
+ * Heading level for each item's trigger. Default `3`.
1813
+ *
1814
+ * Each trigger is wrapped in a real heading, per the APG, so the accordion appears in
1815
+ * the document outline and a screen reader can jump between sections by heading. The
1816
+ * right level depends on what surrounds it, which only the caller knows.
1817
+ */
1818
+ headingLevel?: 2 | 3 | 4;
1819
+ }
1820
+ /**
1821
+ * Accordion. Matches Figma's `Accordion` / `Accordion Item` (`State: Closed | Open`).
1822
+ *
1823
+ * Width is deliberately not set — Figma's own note on `Accordion Item` says the 640px in
1824
+ * the component set is a container artefact and the parent should own width, so this is
1825
+ * `w-full` and nothing more.
1826
+ */
1827
+ declare function Accordion({ children, type, value: valueProp, defaultValue, onValueChange, collapsible, headingLevel, className, ...rest }: AccordionProps): react.JSX.Element;
1828
+ interface AccordionItemProps extends HTMLAttributes<HTMLDivElement> {
1829
+ children: ReactNode;
1830
+ value: string;
1831
+ disabled?: boolean;
1832
+ }
1833
+ declare function AccordionItem({ children, value, disabled, className, ...rest }: AccordionItemProps): react.JSX.Element;
1834
+ interface AccordionTriggerProps extends HTMLAttributes<HTMLButtonElement> {
1835
+ children: ReactNode;
1836
+ /** Hide the chevron — for a trigger that supplies its own affordance. */
1837
+ hideIndicator?: boolean;
1838
+ }
1839
+ declare function AccordionTrigger({ children, hideIndicator, className, ...rest }: AccordionTriggerProps): react.JSX.Element;
1840
+ interface AccordionContentProps extends HTMLAttributes<HTMLDivElement> {
1841
+ children: ReactNode;
1842
+ }
1843
+ declare function AccordionContent({ children, className, ...rest }: AccordionContentProps): react.JSX.Element | null;
1844
+
1845
+ interface CollapsibleProps extends HTMLAttributes<HTMLDivElement> {
1846
+ children: ReactNode;
1847
+ open?: boolean;
1848
+ defaultOpen?: boolean;
1849
+ onOpenChange?: (open: boolean) => void;
1850
+ disabled?: boolean;
1851
+ }
1852
+ /**
1853
+ * A show/hide region with a trigger. The single-item primitive behind `Accordion`.
1854
+ *
1855
+ * The whole point is the wiring, which is easy to get wrong by hand: the trigger needs
1856
+ * `aria-expanded` and `aria-controls`, the panel needs an id and a matching
1857
+ * `aria-labelledby`, and the panel must be genuinely removed from the accessibility tree
1858
+ * when closed — `height: 0` with `overflow: hidden` leaves its content focusable and
1859
+ * announceable, so a keyboard user tabs into a collapsed section.
1860
+ */
1861
+ declare function Collapsible({ children, open: openProp, defaultOpen, onOpenChange, disabled, className, ...rest }: CollapsibleProps): react.JSX.Element;
1862
+ interface CollapsibleTriggerProps extends HTMLAttributes<HTMLButtonElement> {
1863
+ children?: ReactNode;
1864
+ asChild?: boolean;
1865
+ }
1866
+ declare function CollapsibleTrigger({ children, asChild, className, ...rest }: CollapsibleTriggerProps): react.JSX.Element;
1867
+ interface CollapsibleContentProps extends HTMLAttributes<HTMLDivElement> {
1868
+ children: ReactNode;
1869
+ /**
1870
+ * Keep the content mounted while closed, hidden with `hidden`. Default `false`.
1871
+ *
1872
+ * `hidden` — not `height: 0` — is what keeps hidden content out of the tab sequence and
1873
+ * the accessibility tree, so this stays safe. Use it to preserve form state or scroll
1874
+ * position across collapses.
1875
+ */
1876
+ keepMounted?: boolean;
1877
+ }
1878
+ declare function CollapsibleContent({ children, keepMounted, className, ...rest }: CollapsibleContentProps): react.JSX.Element | null;
1879
+
1880
+ interface AspectRatioProps extends HTMLAttributes<HTMLDivElement> {
1881
+ children: ReactNode;
1882
+ /** Width ÷ height. `16 / 9` for video, `1` for a square, `4 / 3` for a photo. Default `1`. */
1883
+ ratio?: number;
1884
+ }
1885
+ /**
1886
+ * Holds a fixed width-to-height ratio for its content.
1887
+ *
1888
+ * Uses the CSS `aspect-ratio` property rather than the old padding-top percentage hack, so
1889
+ * the child is a normal in-flow element instead of being absolutely positioned inside a
1890
+ * zero-height box. The ratio is an inline style because it is a per-instance numeric value —
1891
+ * a Tailwind class cannot express `16 / 9` without an arbitrary-value escape at every call
1892
+ * site.
1893
+ */
1894
+ declare const AspectRatio: react.ForwardRefExoticComponent<AspectRatioProps & react.RefAttributes<HTMLDivElement>>;
1895
+
1896
+ /**
1897
+ * Styled native scrollbars, for the components that must own their own overflow and so
1898
+ * cannot delegate to `ScrollArea`.
1899
+ *
1900
+ * Two kinds qualify. A table wrapper, a tab strip or a stepper, where inserting another
1901
+ * element would break the layout or the `<table>` element relationship; and a floating panel
1902
+ * that is already its own scroll container. Both hold focusable children, so a keyboard user
1903
+ * can already reach and scroll them — which is the one thing `ScrollArea` adds beyond these
1904
+ * classes, and the one thing they do not need.
1905
+ *
1906
+ * Prefer `ScrollArea` for a scrolling *region* of content. Reach for this only when a wrapper
1907
+ * element is not an option, and say why at the call site.
1908
+ *
1909
+ * A plain string module rather than an export from `scroll-area.tsx`: `menu-styles.ts` needs
1910
+ * it, and importing a component module from a style module would pull the component into the
1911
+ * bundle graph for the sake of a class list.
1912
+ */
1913
+ declare const SCROLLBAR_CLASSES: string;
1914
+
1915
+ type ScrollAreaAxis = 'vertical' | 'horizontal' | 'both';
1916
+ interface ScrollAreaProps extends HTMLAttributes<HTMLDivElement> {
1917
+ children: ReactNode;
1918
+ axis?: ScrollAreaAxis;
622
1919
  /**
623
- * Surface tint. This is a prop rather than a `className` because a tone has to
624
- * un-set the base `border-default bg-default` pair, not add to it.
1920
+ * Accessible name for the scrollable region. Strongly recommended — a scroll container
1921
+ * that becomes focusable (see below) needs to announce what it is.
625
1922
  */
626
- tone?: CardTone;
1923
+ label?: string;
627
1924
  }
1925
+
628
1926
  /**
629
- * The card shell. Composed from `CardHeader`, `CardBody` and `CardFooter` — or from
630
- * nothing at all, if you want content to bleed to the edges (drop `CardBody` and put
631
- * a `DataTable` straight inside).
632
- *
633
- * Replaces `SectionCard` and the two monolithic cards that shipped beside it,
634
- * `AlertCard` and `BenchmarkCard`. Both of those are now documented compositions; see
635
- * the Cards page. The vocabulary follows shadcn/ui so it is already familiar, with
636
- * `CardBody` in place of its `CardContent`.
1927
+ * A scrollable region with styled scrollbars.
1928
+ *
1929
+ * **Native scrolling, deliberately.** shadcn/Radix replaces the scrollbar with a rendered
1930
+ * one, which looks tidier and costs real accessibility: an overlay scrollbar has to
1931
+ * reimplement keyboard scrolling, momentum, trackpad and pen behaviour, and the OS
1932
+ * "click the track to page" convention — and it drops out entirely if the JS fails. Styling
1933
+ * `::-webkit-scrollbar` plus `scrollbar-width`/`scrollbar-color` gets most of the look with
1934
+ * none of that risk, and degrades to a normal scrollbar where unsupported.
1935
+ *
1936
+ * The one thing this *does* add is the piece browsers get wrong: a scroll container is not
1937
+ * keyboard focusable by default in Chrome or Safari, so a keyboard-only user cannot scroll
1938
+ * an overflowing `<div>` at all unless something inside it is focusable. This measures its
1939
+ * own content and sets `tabIndex={0}` only while it actually overflows, so the region is
1940
+ * scrollable with the arrow keys without adding a pointless tab stop when it does not.
637
1941
  */
638
- declare function Card({ children, radius, tone, className, ...rest }: CardProps): react.JSX.Element;
639
- interface CardHeaderProps extends HTMLAttributes<HTMLDivElement> {
1942
+ declare const ScrollArea: react.ForwardRefExoticComponent<ScrollAreaProps & react.RefAttributes<HTMLDivElement>>;
1943
+
1944
+ interface CarouselProps extends HTMLAttributes<HTMLDivElement> {
640
1945
  children: ReactNode;
641
- size?: CardSize;
642
- /** Bottom rule separating the header from the body. */
643
- divider?: boolean;
1946
+ /** Names the carousel region. Required — a nameless region is not navigable. */
1947
+ label: string;
1948
+ index?: number;
1949
+ defaultIndex?: number;
1950
+ onIndexChange?: (index: number) => void;
1951
+ /** Number of slides. Needed up front for the controls; `CarouselSlide` count is checked against it. */
1952
+ count: number;
1953
+ loop?: boolean;
1954
+ /** Advance every N ms. Omit for a manual carousel. */
1955
+ autoplayInterval?: number;
644
1956
  }
645
1957
  /**
646
- * Header row. Holds `CardTitle`, `CardDescription` and an optional `CardAction`.
647
- *
648
- * The `has-[…]` selector switches to a two-column grid only when a `CardAction` is
649
- * present, which is what lets title, description and action share a header with no
650
- * wrapper div and no stray gap when the action is absent.
1958
+ * A slide carousel.
1959
+ *
1960
+ * Carousels are one of the most reliably inaccessible patterns on the web, so the parts that
1961
+ * look like polish here are the requirements:
1962
+ *
1963
+ * - **`aria-roledescription="carousel"`** on a named region, so it is announced as a carousel
1964
+ * rather than as an anonymous group of divs.
1965
+ * - **Slides are `role="group"` with `aria-roledescription="slide"` and an
1966
+ * "N of M" label** — position is otherwise invisible to anyone not seeing the dots.
1967
+ * - **Off-screen slides are `hidden`**, not merely translated out of view. A slide moved with
1968
+ * `transform` keeps its links in the tab order, so keyboard users tab into content they
1969
+ * cannot see. This is the single most common carousel bug.
1970
+ * - **Autoplay stops on hover, on focus, and permanently once the user takes control**, and
1971
+ * there is a visible pause button whenever autoplay is on — required by WCAG 2.2.2 for any
1972
+ * motion lasting more than five seconds.
1973
+ * - **`prefers-reduced-motion` disables autoplay entirely**, rather than just shortening the
1974
+ * transition.
651
1975
  */
652
- declare function CardHeader({ children, size, divider, className, ...rest }: CardHeaderProps): react.JSX.Element;
653
- interface CardTitleProps extends HTMLAttributes<HTMLElement> {
1976
+ declare function Carousel({ children, label, index: indexProp, defaultIndex, onIndexChange, count, loop, autoplayInterval, className, ...rest }: CarouselProps): react.JSX.Element;
1977
+ interface CarouselViewportProps extends HTMLAttributes<HTMLDivElement> {
654
1978
  children: ReactNode;
655
- size?: CardSize;
656
- /** Heading level. Defaults to `p`; use h2/h3 where the page has a real hierarchy. */
657
- as?: 'h2' | 'h3' | 'h4' | 'p';
658
1979
  }
659
- declare function CardTitle({ children, size, as: Tag, className, ...rest }: CardTitleProps): react.JSX.Element;
660
- interface CardDescriptionProps extends HTMLAttributes<HTMLParagraphElement> {
1980
+ declare function CarouselViewport({ children, className, ...rest }: CarouselViewportProps): react.JSX.Element;
1981
+ interface CarouselSlideProps extends HTMLAttributes<HTMLDivElement> {
661
1982
  children: ReactNode;
662
1983
  }
663
- declare function CardDescription({ children, className, ...rest }: CardDescriptionProps): react.JSX.Element;
664
- interface CardActionProps extends HTMLAttributes<HTMLDivElement> {
665
- children: ReactNode;
1984
+ declare function CarouselSlide({ children, className, ...rest }: CarouselSlideProps): react.JSX.Element;
1985
+ interface CarouselControlsProps extends HTMLAttributes<HTMLDivElement> {
1986
+ /** Show the dot indicators. Default `true`. */
1987
+ showDots?: boolean;
666
1988
  }
667
- /** Right-hand slot in a `CardHeader` — a button, a count, a status badge, a menu. */
668
- declare function CardAction({ children, className, ...rest }: CardActionProps): react.JSX.Element;
669
- interface CardBodyProps extends HTMLAttributes<HTMLDivElement> {
1989
+ declare function CarouselControls({ showDots, className, ...rest }: CarouselControlsProps): react.JSX.Element;
1990
+
1991
+ type ResizableDirection = 'horizontal' | 'vertical';
1992
+ interface ResizableProps extends HTMLAttributes<HTMLDivElement> {
670
1993
  children: ReactNode;
671
- size?: CardSize;
1994
+ direction?: ResizableDirection;
1995
+ /** First pane's size as a percentage. Controlled. */
1996
+ size?: number;
1997
+ defaultSize?: number;
1998
+ onSizeChange?: (size: number) => void;
1999
+ /** Percentage bounds. Defaults `10` and `90`. */
2000
+ min?: number;
2001
+ max?: number;
672
2002
  }
673
2003
  /**
674
- * The content region. A vertical stack by default.
2004
+ * Two resizable panes with a draggable divider.
675
2005
  *
676
- * Because this file uses `cn`, `className` genuinely overrides the base — so
677
- * `className="flex-row items-center"` gives you a row, and
678
- * `className="grid grid-cols-3"` a grid. That is what makes the `AlertCard` and
679
- * `BenchmarkCard` rebuilds possible without a `layout` prop.
2006
+ * This is the APG **window splitter** pattern, and the handle is the whole component as far
2007
+ * as accessibility goes. A `<div>` with pointer listeners — the usual implementation — is
2008
+ * completely unusable without a mouse. `ResizableHandle` is therefore a real focusable
2009
+ * control with:
2010
+ *
2011
+ * - `role="separator"` plus `aria-valuenow`/`valuemin`/`valuemax`, so the current split is
2012
+ * announced as a percentage rather than being invisible;
2013
+ * - `tabIndex={0}` and arrow keys to move it in 1% steps, Shift+arrow in 10%, Home/End to
2014
+ * the bounds, and Enter to collapse and restore;
2015
+ * - `aria-controls` pointing at the pane it resizes.
2016
+ *
2017
+ * Sizes are percentages, not pixels, so the split survives a container resize — a pixel
2018
+ * split silently becomes wrong the moment the window changes.
680
2019
  */
681
- declare function CardBody({ children, size, className, ...rest }: CardBodyProps): react.JSX.Element;
682
- interface CardFooterProps extends HTMLAttributes<HTMLDivElement> {
2020
+ declare function Resizable({ children, direction, size: sizeProp, defaultSize, onSizeChange, min, max, className, ...rest }: ResizableProps): react.JSX.Element;
2021
+ interface ResizablePanelProps extends HTMLAttributes<HTMLDivElement> {
683
2022
  children: ReactNode;
684
- size?: CardSize;
685
- divider?: boolean;
686
- align?: CardFooterAlign;
2023
+ /** `first` is the pane the handle sizes; `second` fills the remainder. */
2024
+ which: 'first' | 'second';
687
2025
  }
688
- /** Action row at the foot of a card. Mirrors `ModalFooter` and `Drawer`'s footer. */
689
- declare function CardFooter({ children, size, divider, align, className, ...rest }: CardFooterProps): react.JSX.Element;
2026
+ declare function ResizablePanel({ children, which, className, ...rest }: ResizablePanelProps): react.JSX.Element;
2027
+ interface ResizableHandleProps extends HTMLAttributes<HTMLDivElement> {
2028
+ /** Names the splitter. Default `Resize panels`. */
2029
+ label?: string;
2030
+ /** Show the grip dots. Default `true`. */
2031
+ withGrip?: boolean;
2032
+ }
2033
+ declare function ResizableHandle({ label, withGrip, className, ...rest }: ResizableHandleProps): react.JSX.Element;
690
2034
 
691
2035
  /**
692
2036
  * Two genuinely different heading contexts, which the source markup distinguished:
@@ -729,7 +2073,13 @@ interface PageToolbarProps {
729
2073
  children: ReactNode;
730
2074
  /** Allow the row to wrap when the action cluster is wide (entity-detail has seven buttons). */
731
2075
  wrap?: boolean;
732
- /** Bar height and padding. `sm` suits a secondary bar under the main toolbar. */
2076
+ /**
2077
+ * The bar's **own** height and padding. `sm` suits a secondary bar under the main toolbar.
2078
+ *
2079
+ * Not to be confused with `FilterBar.size`, which sets the density of the controls
2080
+ * *inside* the row. Same literals, different subject: a bar sizes itself, a row of
2081
+ * controls sizes its children. `PageToolbar` passes nothing down.
2082
+ */
733
2083
  size?: PageToolbarSize;
734
2084
  className?: string;
735
2085
  }
@@ -749,30 +2099,50 @@ interface FilterBarProps {
749
2099
  children: ReactNode;
750
2100
  /** Right-aligned slot for a result count or a secondary action. */
751
2101
  trailing?: ReactNode;
752
- /** Gap between controls. `sm` for a filter row inside a card or drawer. */
2102
+ /**
2103
+ * Row density. Sets the gap between controls **and** the default `size` of the controls
2104
+ * inside — an Input, Select, Combobox, DatePicker or Button that is not given its own
2105
+ * `size` inherits this one. Pass `size` on a child to opt it out.
2106
+ *
2107
+ * `sm` is for a filter row inside a card or drawer: 8px gaps and 24px controls.
2108
+ */
753
2109
  size?: FilterBarSize;
754
2110
  className?: string;
755
2111
  }
756
2112
  /**
757
2113
  * Row of search inputs and filter selects above a table.
758
2114
  *
759
- * Replaces nine copies of `flex flex-wrap items-center gap-3`. Thin by design — the
760
- * value is that the spacing is decided once, not that it hides anything.
2115
+ * Replaces nine copies of `flex flex-wrap items-center gap-3`.
2116
+ *
2117
+ * Through 0.4.0 `size` set only the gap, so every caller had to repeat it on each control
2118
+ * and the page documenting this component got it wrong: its `size="sm"` example put a 24px
2119
+ * Input beside a 36px Select. A container with a size prop should mean it, so the size now
2120
+ * reaches the controls through `ControlSizeProvider`.
761
2121
  */
762
2122
  declare function FilterBar({ children, trailing, size, className }: FilterBarProps): react.JSX.Element;
763
2123
 
764
2124
  type TabsVariant = 'underline' | 'pill';
765
2125
  type TabsSize = 'sm' | 'md';
2126
+ type TabsOrientation = 'horizontal' | 'vertical';
2127
+ /**
2128
+ * `automatic` selects as focus moves, which is the APG default and right when panels are
2129
+ * cheap. `manual` requires Enter/Space — use it when switching tab triggers a fetch, so
2130
+ * arrowing across five tabs does not fire five requests.
2131
+ */
2132
+ type TabsActivation = 'automatic' | 'manual';
766
2133
  interface TabItem<K extends string = string> {
767
2134
  key: K;
768
2135
  label: string;
769
2136
  /** Renders a count chip after the label. */
770
2137
  count?: number;
2138
+ disabled?: boolean;
771
2139
  }
772
2140
  interface TabsProps<K extends string = string> {
773
2141
  items: TabItem<K>[];
774
- value: K;
775
- onChange: (key: K) => void;
2142
+ /** Controlled selection. Omit and pass `defaultValue` for uncontrolled. */
2143
+ value?: K;
2144
+ defaultValue?: K;
2145
+ onValueChange?: (key: K) => void;
776
2146
  /**
777
2147
  * `underline` is the detail-page form (entity detail, reviewer detail, role detail).
778
2148
  * `pill` is the filter-style form used by the reviewer queue.
@@ -780,31 +2150,113 @@ interface TabsProps<K extends string = string> {
780
2150
  variant?: TabsVariant;
781
2151
  /** `md` is the page-level strip; `sm` suits a tab strip inside a card or drawer. */
782
2152
  size?: TabsSize;
2153
+ orientation?: TabsOrientation;
2154
+ activation?: TabsActivation;
2155
+ /**
2156
+ * Shared prefix for the generated tab and panel ids. Pass the same value to `TabsPanel`
2157
+ * to wire `aria-controls` / `aria-labelledby`. Generated when omitted.
2158
+ */
2159
+ idPrefix?: string;
2160
+ /** Names the tab strip. Required by the APG when there is more than one on a page. */
2161
+ label?: string;
783
2162
  className?: string;
784
2163
  }
2164
+ declare const tabId: (prefix: string, key: string) => string;
2165
+ declare const tabPanelId: (prefix: string, key: string) => string;
785
2166
  /**
786
- * State-driven tab strip.
2167
+ * Tab strip.
2168
+ *
2169
+ * Reworked in 0.4.0. It previously carried `role="tablist"`, `role="tab"` and
2170
+ * `aria-selected` with **no `onKeyDown` at all** — no Arrow keys, no Home/End, no roving
2171
+ * tabindex, no `aria-controls`, and no `role="tabpanel"` counterpart anywhere in the
2172
+ * library. That combination is worse than shipping no ARIA: a screen reader announces
2173
+ * "tab 3 of 5", the user presses the arrow keys it implies, and nothing happens. Every
2174
+ * tab was also individually tabbable, so Tab walked the strip instead of leaving it.
787
2175
  *
788
2176
  * The `underline` active colour is `background-brand` (#0C2D58), which is what Figma
789
- * specifies. Two of the source copies also set `style={{ borderColor: '#0c2d58' }}`
790
- * redundantly next to the same Tailwind class — dropped here.
2177
+ * specifies.
2178
+ */
2179
+ declare function Tabs<K extends string = string>({ items, value: valueProp, defaultValue, onValueChange, variant, size, orientation, activation, idPrefix, label, className, }: TabsProps<K>): react.JSX.Element;
2180
+ interface TabsPanelProps extends HTMLAttributes<HTMLDivElement> {
2181
+ /** The `key` of the tab this panel belongs to. */
2182
+ tabKey: string;
2183
+ /** Must match the `idPrefix` given to `Tabs`. */
2184
+ idPrefix: string;
2185
+ /** Whether this panel's tab is the selected one. */
2186
+ active: boolean;
2187
+ children: ReactNode;
2188
+ /**
2189
+ * Keep the panel mounted while hidden. Default `false`. Mounting all panels preserves
2190
+ * scroll position and form state across tab switches at the cost of rendering them all.
2191
+ */
2192
+ keepMounted?: boolean;
2193
+ }
2194
+ /**
2195
+ * The `role="tabpanel"` half of the pattern, which the library had no equivalent of —
2196
+ * so `aria-controls` on a tab pointed at nothing and there was no labelled region for a
2197
+ * screen reader to move into.
2198
+ *
2199
+ * `tabIndex={0}` is deliberate and required: when a panel contains no focusable element,
2200
+ * it must be reachable itself, otherwise Tab from the selected tab skips the content
2201
+ * entirely.
791
2202
  */
792
- declare function Tabs<K extends string = string>({ items, value, onChange, variant, size, className, }: TabsProps<K>): react.JSX.Element;
2203
+ declare function TabsPanel({ tabKey, idPrefix, active, children, keepMounted, className, ...rest }: TabsPanelProps): react.JSX.Element | null;
793
2204
 
794
2205
  type NavItemSize = 'sm' | 'md';
795
- interface NavItemProps {
2206
+ type NavItemVariant = 'card' | 'plain';
2207
+ interface NavItemProps extends Omit<HTMLAttributes<HTMLElement>, 'children'> {
2208
+ /**
2209
+ * Leading glyph. Optional, but when `collapsed` it is the only thing left to look at, so
2210
+ * a row without one falls back to a monogram taken from the label.
2211
+ */
796
2212
  icon?: ReactNode;
797
2213
  label: string;
2214
+ /**
2215
+ * The row you are on — the current route. Paints the brand fill and, under `asChild`, sets
2216
+ * `aria-current="page"`; it also reflects to `data-state="active"`.
2217
+ *
2218
+ * Not the same thing as focus, though Figma's `MenuButton` names this variant
2219
+ * `state=focussed`. That is a misnomer to fix on the design side: keyboard focus is the
2220
+ * ring below, it is transient and can land on any row, and if it painted the brand fill
2221
+ * too there would be no way to see which row is the current one while tabbing past it.
2222
+ */
798
2223
  isActive?: boolean;
799
2224
  /** Red indicator dot at top-right corner (e.g. unread count) */
800
2225
  indicator?: boolean;
801
- /** Collapsed mode — icon only, label hidden */
2226
+ /** Collapsed mode — label is visually hidden but stays in the accessibility tree. */
802
2227
  collapsed?: boolean;
803
2228
  /** Row height. `sm` suits a dense secondary nav or a nested group. */
804
2229
  size?: NavItemSize;
2230
+ /**
2231
+ * Row weight.
2232
+ *
2233
+ * `card` gives every inactive row its own border and surface — right for a short primary
2234
+ * rail of eight or ten destinations, where each row is a target in its own right.
2235
+ * `plain` drops both, so an inactive row is just text: right for a long grouped nav,
2236
+ * where thirty bordered pills read as thirty cards rather than a list.
2237
+ *
2238
+ * A variant decides what a row looks like **at rest, and nothing else**. Hover and the
2239
+ * current-row fill are one vocabulary shared by both — see `STATE`. Through 0.5.0 each
2240
+ * variant defined its own, and `plain`'s was invisible against the rail it was written for.
2241
+ */
2242
+ variant?: NavItemVariant;
2243
+ /**
2244
+ * Render the single child element as the row, so the row itself is the link or button.
2245
+ *
2246
+ * `NavItem` is presentational by default — a `<span>` with hover styling. That is fine
2247
+ * inside a router `NavLink`, which is how `src/sidebar/` uses it, but on its own it is a
2248
+ * nav row that looks interactive and cannot be focused or activated. `asChild` is the
2249
+ * fix for anyone using it outside that wrapper:
2250
+ *
2251
+ * <NavItem asChild icon={<LuHouse />} label="Home">
2252
+ * <NavLink to="/" />
2253
+ * </NavItem>
2254
+ */
2255
+ asChild?: boolean;
2256
+ children?: ReactNode;
805
2257
  className?: string;
806
2258
  }
807
- declare function NavItem({ icon, label, isActive, indicator, collapsed, size, className, }: NavItemProps): react.JSX.Element;
2259
+ declare function NavItem({ icon, label, isActive, indicator, collapsed, size, variant, asChild, children, className, ...rest }: NavItemProps): react.JSX.Element;
808
2260
 
809
2261
  type EyebrowLabelVariant = 'uppercase' | 'plain';
810
2262
  interface EyebrowLabelProps {
@@ -831,6 +2283,265 @@ interface EyebrowLabelProps {
831
2283
  */
832
2284
  declare function EyebrowLabel({ children, variant, className }: EyebrowLabelProps): react.JSX.Element;
833
2285
 
2286
+ type SeparatorOrientation = 'horizontal' | 'vertical';
2287
+ interface SeparatorProps extends HTMLAttributes<HTMLDivElement> {
2288
+ orientation?: SeparatorOrientation;
2289
+ /**
2290
+ * `true` when the rule is purely visual, which is the common case. A decorative
2291
+ * separator is `role="none"` and stays out of the accessibility tree; a semantic one
2292
+ * is `role="separator"` and announces a break between groups.
2293
+ */
2294
+ decorative?: boolean;
2295
+ }
2296
+ /**
2297
+ * A hairline rule. Matches Figma's `Menu Separator`, generalised to both orientations.
2298
+ *
2299
+ * Drawn as a filled element rather than a border, because a 1px border on a flex child
2300
+ * collapses to nothing at some zoom levels while a `1px` height does not — which is why
2301
+ * the preset carries a `divider` background token separate from `border-default`.
2302
+ */
2303
+ declare const Separator: react.ForwardRefExoticComponent<SeparatorProps & react.RefAttributes<HTMLDivElement>>;
2304
+
2305
+ type KbdSize = 'sm' | 'md';
2306
+ interface KbdProps extends HTMLAttributes<HTMLElement> {
2307
+ children: ReactNode;
2308
+ size?: KbdSize;
2309
+ }
2310
+ /**
2311
+ * A keyboard key. Matches Figma's `Menu Shortcut`.
2312
+ *
2313
+ * Renders a real `<kbd>` so assistive tech announces it as key input rather than as a
2314
+ * stray glyph — `⌘K` read as plain text is "place of interest sign K".
2315
+ *
2316
+ * Pass one key per element and let the caller supply the joiner, so a shortcut reads as
2317
+ * separate keys instead of one run-together string:
2318
+ *
2319
+ * <Kbd>⌘</Kbd><Kbd>K</Kbd>
2320
+ */
2321
+ declare const Kbd: react.ForwardRefExoticComponent<KbdProps & react.RefAttributes<HTMLElement>>;
2322
+
2323
+ interface BreadcrumbProps extends HTMLAttributes<HTMLElement> {
2324
+ children: ReactNode;
2325
+ /** Names the landmark. Default `Breadcrumb`. */
2326
+ label?: string;
2327
+ }
2328
+ /**
2329
+ * Breadcrumb trail.
2330
+ *
2331
+ * A `<nav>` wrapping an ordered list, which is the whole semantic point: the order *is* the
2332
+ * hierarchy, so `<ol>` says something `<div>` cannot, and the landmark lets a screen reader
2333
+ * user jump to the trail without walking the header.
2334
+ *
2335
+ * The separators are `aria-hidden` and generated by the list, not passed in — a chevron
2336
+ * announced between every crumb is noise, and the `/` characters people usually hand-type
2337
+ * get read out one by one.
2338
+ */
2339
+ declare const Breadcrumb: react.ForwardRefExoticComponent<BreadcrumbProps & react.RefAttributes<HTMLElement>>;
2340
+ interface BreadcrumbItemProps extends AnchorHTMLAttributes<HTMLAnchorElement> {
2341
+ children: ReactNode;
2342
+ /**
2343
+ * The page you are on. Renders as plain text with `aria-current="page"` rather than a
2344
+ * link — a link to the current page is a dead control, and the APG says the last crumb
2345
+ * should not be one.
2346
+ */
2347
+ current?: boolean;
2348
+ /** Render a router `Link` instead of an `<a>`. */
2349
+ asChild?: boolean;
2350
+ /** Suppress the leading separator. Set automatically on the first item you render. */
2351
+ first?: boolean;
2352
+ }
2353
+ declare const BreadcrumbItem: react.ForwardRefExoticComponent<BreadcrumbItemProps & react.RefAttributes<HTMLAnchorElement>>;
2354
+ interface BreadcrumbEllipsisProps extends HTMLAttributes<HTMLSpanElement> {
2355
+ }
2356
+ /**
2357
+ * Stands in for collapsed middle crumbs on a deep trail.
2358
+ *
2359
+ * A `<span>`, not a button: it is a truncation marker, and making it a disabled control
2360
+ * puts an unusable stop in the tab order. If the hidden crumbs need to be reachable, wrap
2361
+ * this in a `DropdownMenuTrigger` and list them.
2362
+ */
2363
+ declare const BreadcrumbEllipsis: react.ForwardRefExoticComponent<BreadcrumbEllipsisProps & react.RefAttributes<HTMLSpanElement>>;
2364
+
2365
+ type PaginationType = 'default' | 'dots';
2366
+ interface PaginationProps extends Omit<HTMLAttributes<HTMLElement>, 'onChange'> {
2367
+ /** 1-based. */
2368
+ page: number;
2369
+ /** Total number of pages. Values below 1 render nothing. */
2370
+ pageCount: number;
2371
+ onPageChange: (page: number) => void;
2372
+ /** Matches Figma's `Type` axis. `dots` is the compact carousel form. */
2373
+ type?: PaginationType;
2374
+ /** How many numbered pages to show either side of the current one. Default `1`. */
2375
+ siblingCount?: number;
2376
+ /** Names the nav landmark. Default `Pagination`. */
2377
+ label?: string;
2378
+ }
2379
+ declare const GAP = "\u2026";
2380
+ /**
2381
+ * Builds the visible page list with ellipses.
2382
+ *
2383
+ * Always returns first and last, the current page, and `siblingCount` either side. The
2384
+ * window is widened rather than allowed to shrink near the ends, so the control does not
2385
+ * change width as the user pages through — a row of buttons that reflows under the cursor
2386
+ * is how you mis-click.
2387
+ */
2388
+ declare function paginationRange(page: number, pageCount: number, siblingCount?: number): (number | typeof GAP)[];
2389
+ /**
2390
+ * Pagination. Matches Figma's `Pagination` (`Type: Default | Dots`), `Pagination Page`
2391
+ * (`State: Default | Hover | Current | Current Hover`), `Pagination Next` / `Previous`
2392
+ * (`Default | Hover | Disabled`) and `Pagination dots` (`Active | Inactive`).
2393
+ *
2394
+ * `DataTable` had no pager at all, so every consumer built one. Notes on the semantics:
2395
+ *
2396
+ * - A `<nav>` landmark with a name, so it is reachable by landmark navigation.
2397
+ * - `aria-current="page"` on the active page. It is the only non-visual signal of which
2398
+ * page you are on; the filled background is not announced.
2399
+ * - Each page button is named "Page 3", not "3" — a bare number read out of context tells
2400
+ * a screen reader user nothing about what activating it does.
2401
+ * - The ellipsis is inert text, not a disabled button, so it is skipped rather than
2402
+ * announced as an unavailable control.
2403
+ */
2404
+ declare const Pagination: react.ForwardRefExoticComponent<PaginationProps & react.RefAttributes<HTMLElement>>;
2405
+
2406
+ type NavigationMenuOrientation = 'horizontal' | 'vertical';
2407
+ type NavigationMenuVariant = 'pill' | 'link';
2408
+ interface NavigationMenuProps extends HTMLAttributes<HTMLElement> {
2409
+ children: ReactNode;
2410
+ orientation?: NavigationMenuOrientation;
2411
+ /** Names the nav landmark. Required when a page has more than one `<nav>`. */
2412
+ label: string;
2413
+ }
2414
+ /**
2415
+ * A navigation landmark wrapping a list of links. Matches Figma's `Navigation Pill List`
2416
+ * and `Navigation Button List`.
2417
+ *
2418
+ * Why the `<nav>` + `<ul>` + `<li>` nesting rather than a flat row of anchors: the list is
2419
+ * what makes a screen reader announce "list, 5 items" and lets the user jump the whole
2420
+ * block. A bare row of links is announced one at a time with no sense of how many there
2421
+ * are or where the set ends. The `label` is required for the same reason — an unnamed
2422
+ * landmark in a page with a sidebar *and* a top bar is not navigable.
2423
+ */
2424
+ declare const NavigationMenu: react.ForwardRefExoticComponent<NavigationMenuProps & react.RefAttributes<HTMLElement>>;
2425
+ interface NavigationMenuItemProps extends AnchorHTMLAttributes<HTMLAnchorElement> {
2426
+ children: ReactNode;
2427
+ /** Matches Figma's `State: Active`. Sets `aria-current="page"`. */
2428
+ active?: boolean;
2429
+ variant?: NavigationMenuVariant;
2430
+ /** Render a router `Link` instead of an `<a>`. */
2431
+ asChild?: boolean;
2432
+ /** Leading glyph. Marked decorative automatically. */
2433
+ icon?: ReactNode;
2434
+ }
2435
+ /**
2436
+ * A single navigation link. Matches Figma's `Navigation Pill` and `Navigation Button`
2437
+ * (`State: Default | Active | Hover`).
2438
+ *
2439
+ * `aria-current="page"` is the point: the filled pill is not announced, so without it a
2440
+ * screen reader user cannot tell which page they are on.
2441
+ */
2442
+ declare const NavigationMenuItem: react.ForwardRefExoticComponent<NavigationMenuItemProps & react.RefAttributes<HTMLAnchorElement>>;
2443
+
2444
+ /**
2445
+ * The type ramp as components, mirroring Figma's `Text*` primitives one-for-one:
2446
+ * `Text`, `Text Strong`, `Text Emphasis`, `Text Small`, `Text Code`, `Text Link`,
2447
+ * `Text Heading`, `Text Subheading`, `Text Subtitle`, `Text Title Page`,
2448
+ * `Text Title Hero`, `Text List`, `Text List Item`, `Text Link List`.
2449
+ *
2450
+ * These existed in Figma with settled styles and had no code counterpart, so every
2451
+ * consumer reached for a raw `text-body-sm text-default` triplet and the ramp drifted.
2452
+ * Each component pins the size/weight/colour combination and nothing else, so layout
2453
+ * stays the caller's job.
2454
+ *
2455
+ * All of them take `asChild`, because the right element is contextual — a `Heading` is an
2456
+ * `<h2>` on a page and an `<h3>` inside a card, and only the caller knows the outline.
2457
+ */
2458
+ type BaseProps = HTMLAttributes<HTMLElement> & {
2459
+ children?: ReactNode;
2460
+ asChild?: boolean;
2461
+ };
2462
+ type TextProps = BaseProps;
2463
+ /** `Text` — the default body paragraph. */
2464
+ declare const Text: react.ForwardRefExoticComponent<HTMLAttributes<HTMLElement> & {
2465
+ children?: ReactNode;
2466
+ asChild?: boolean;
2467
+ } & react.RefAttributes<HTMLElement>>;
2468
+ /** `Text Small` — secondary body copy. */
2469
+ declare const TextSmall: react.ForwardRefExoticComponent<HTMLAttributes<HTMLElement> & {
2470
+ children?: ReactNode;
2471
+ asChild?: boolean;
2472
+ } & react.RefAttributes<HTMLElement>>;
2473
+ /** `Text Tiny` — the smallest readable step; captions and table meta. */
2474
+ declare const TextTiny: react.ForwardRefExoticComponent<HTMLAttributes<HTMLElement> & {
2475
+ children?: ReactNode;
2476
+ asChild?: boolean;
2477
+ } & react.RefAttributes<HTMLElement>>;
2478
+ /** `Text Strong` — emphasis by weight, in a real `<strong>`. */
2479
+ declare const TextStrong: react.ForwardRefExoticComponent<HTMLAttributes<HTMLElement> & {
2480
+ children?: ReactNode;
2481
+ asChild?: boolean;
2482
+ } & react.RefAttributes<HTMLElement>>;
2483
+ /** `Text Emphasis` — emphasis by slant, in a real `<em>`. */
2484
+ declare const TextEmphasis: react.ForwardRefExoticComponent<HTMLAttributes<HTMLElement> & {
2485
+ children?: ReactNode;
2486
+ asChild?: boolean;
2487
+ } & react.RefAttributes<HTMLElement>>;
2488
+ /** `Text Code` — inline monospace. */
2489
+ declare const TextCode: react.ForwardRefExoticComponent<HTMLAttributes<HTMLElement> & {
2490
+ children?: ReactNode;
2491
+ asChild?: boolean;
2492
+ } & react.RefAttributes<HTMLElement>>;
2493
+ /** `Text Title Hero` — the largest step, one per page at most. */
2494
+ declare const TitleHero: react.ForwardRefExoticComponent<HTMLAttributes<HTMLElement> & {
2495
+ children?: ReactNode;
2496
+ asChild?: boolean;
2497
+ } & react.RefAttributes<HTMLElement>>;
2498
+ /** `Text Title Page` — page title. */
2499
+ declare const TitlePage: react.ForwardRefExoticComponent<HTMLAttributes<HTMLElement> & {
2500
+ children?: ReactNode;
2501
+ asChild?: boolean;
2502
+ } & react.RefAttributes<HTMLElement>>;
2503
+ /** `Text Subtitle` — a lead paragraph under a title; regular weight by design. */
2504
+ declare const Subtitle: react.ForwardRefExoticComponent<HTMLAttributes<HTMLElement> & {
2505
+ children?: ReactNode;
2506
+ asChild?: boolean;
2507
+ } & react.RefAttributes<HTMLElement>>;
2508
+ /** `Text Heading` — section heading. */
2509
+ declare const Heading: react.ForwardRefExoticComponent<HTMLAttributes<HTMLElement> & {
2510
+ children?: ReactNode;
2511
+ asChild?: boolean;
2512
+ } & react.RefAttributes<HTMLElement>>;
2513
+ /** `Text Subheading` — subsection heading; regular weight, matching Figma. */
2514
+ declare const Subheading: react.ForwardRefExoticComponent<HTMLAttributes<HTMLElement> & {
2515
+ children?: ReactNode;
2516
+ asChild?: boolean;
2517
+ } & react.RefAttributes<HTMLElement>>;
2518
+ interface TextLinkProps extends AnchorHTMLAttributes<HTMLAnchorElement> {
2519
+ children?: ReactNode;
2520
+ asChild?: boolean;
2521
+ }
2522
+ /**
2523
+ * `Text Link`. Underlined rather than colour-only: colour alone is not a sufficient
2524
+ * distinction for a link inside a run of text (WCAG 1.4.1).
2525
+ */
2526
+ declare const TextLink: react.ForwardRefExoticComponent<TextLinkProps & react.RefAttributes<HTMLAnchorElement>>;
2527
+ type TextListVariant = 'bulleted' | 'numbered' | 'plain';
2528
+ type TextListDensity = 'default' | 'compact';
2529
+ interface TextListProps extends HTMLAttributes<HTMLElement> {
2530
+ children?: ReactNode;
2531
+ variant?: TextListVariant;
2532
+ /** Matches Figma's `Density` axis on `Text List` / `Text Link List`. */
2533
+ density?: TextListDensity;
2534
+ }
2535
+ /** `Text List` — a real `<ul>`/`<ol>`, so item count is announced. */
2536
+ declare const TextList: react.ForwardRefExoticComponent<TextListProps & react.RefAttributes<HTMLElement>>;
2537
+ type TextListItemProps = HTMLAttributes<HTMLLIElement> & {
2538
+ children?: ReactNode;
2539
+ };
2540
+ /** `Text List Item`. */
2541
+ declare const TextListItem: react.ForwardRefExoticComponent<HTMLAttributes<HTMLLIElement> & {
2542
+ children?: ReactNode;
2543
+ } & react.RefAttributes<HTMLLIElement>>;
2544
+
834
2545
  type WidgetTitleSize = 'sm' | 'md' | 'lg';
835
2546
  interface WidgetTitleProps {
836
2547
  children: ReactNode;
@@ -1129,6 +2840,15 @@ interface SparklineProps {
1129
2840
  strokeWidth?: number;
1130
2841
  /** Dot on the final point — useful when the line is the "current value". */
1131
2842
  showEndDot?: boolean;
2843
+ /**
2844
+ * Stretch to fill the container instead of drawing at a fixed pixel size.
2845
+ *
2846
+ * The `size` preset still sets the viewBox, so it decides the sampling density; the SVG then
2847
+ * scales to the box it is given. Stroke width is held constant with `non-scaling-stroke`,
2848
+ * without which a non-uniform stretch would thin the line on one axis and thicken it on the
2849
+ * other.
2850
+ */
2851
+ fill?: boolean;
1132
2852
  /** Accessible description. Omit to keep the chart decorative. */
1133
2853
  label?: string;
1134
2854
  className?: string;
@@ -1140,7 +2860,7 @@ interface SparklineProps {
1140
2860
  * draw, which is what makes a sparkline readable at `lg` where a bare 1.5px stroke
1141
2861
  * looks thin.
1142
2862
  */
1143
- declare function Sparkline({ data, variant, tone, color, size, width, height, strokeWidth, showEndDot, label, className, }: SparklineProps): react.JSX.Element | null;
2863
+ declare function Sparkline({ data, variant, tone, color, size, width, height, strokeWidth, showEndDot, fill: stretch, label, className, }: SparklineProps): react.JSX.Element | null;
1144
2864
 
1145
2865
  type MiniBarChartSize = 'sm' | 'md' | 'lg';
1146
2866
  type MiniBarChartOrientation = 'vertical' | 'horizontal';
@@ -1165,11 +2885,20 @@ interface MiniBarChartProps {
1165
2885
  gap?: number;
1166
2886
  orientation?: MiniBarChartOrientation;
1167
2887
  radius?: number;
2888
+ /**
2889
+ * Stretch to fill the container instead of drawing at a fixed pixel size.
2890
+ *
2891
+ * The `size` preset still sets the viewBox, so it decides the bar-to-gap proportions; the
2892
+ * SVG then scales to whatever box it is given. Without this a widget body could only hold a
2893
+ * chart at a hardcoded width, which stops being the right width as soon as the widget
2894
+ * reflows.
2895
+ */
2896
+ fill?: boolean;
1168
2897
  label?: string;
1169
2898
  className?: string;
1170
2899
  }
1171
2900
  /** A compact bar series with no axes — a distribution or a per-period count. */
1172
- declare function MiniBarChart({ bars, tone, color, restColor, highlight, size, width, height, gap, orientation, radius, label, className, }: MiniBarChartProps): react.JSX.Element | null;
2901
+ declare function MiniBarChart({ bars, tone, color, restColor, highlight, size, width, height, gap, orientation, radius, fill: stretch, label, className, }: MiniBarChartProps): react.JSX.Element | null;
1173
2902
 
1174
2903
  type LegendDotSize = 'sm' | 'md';
1175
2904
  /** `line` is the swatch for a line series; `dot` and `square` for areas and bars. */
@@ -1257,6 +2986,11 @@ interface ListRowProps {
1257
2986
  /** Render an `<li>` instead of a `<div>` — use inside a `<ul>`/`<ol>`. */
1258
2987
  as?: 'div' | 'li';
1259
2988
  onClick?: () => void;
2989
+ /**
2990
+ * Accessible name for a clickable row. Strongly recommended whenever `onClick` is set:
2991
+ * without it the name is the concatenation of every slot's text.
2992
+ */
2993
+ 'aria-label'?: string;
1260
2994
  className?: string;
1261
2995
  }
1262
2996
  /**
@@ -1267,7 +3001,7 @@ interface ListRowProps {
1267
3001
  * unicode-glyph labels — into the library. Every feature of those rows is reachable by
1268
3002
  * composing this with `FileRow`, `FileDropZone` and `StatusBadge`; see the docs.
1269
3003
  */
1270
- declare function ListRow({ leading, title, titleMeta, description, meta, trailing, footer, density, divider, as: Tag, onClick, className, }: ListRowProps): react.JSX.Element;
3004
+ declare function ListRow({ leading, title, titleMeta, description, meta, trailing, footer, density, divider, as: Tag, onClick, 'aria-label': ariaLabel, className, }: ListRowProps): react.JSX.Element;
1271
3005
 
1272
3006
  interface FileRowProps {
1273
3007
  name: string;
@@ -1359,27 +3093,39 @@ interface ProgressBarProps {
1359
3093
  */
1360
3094
  declare function ProgressBar({ value, tone, size, label, showValue, radius, 'aria-label': ariaLabel, className, }: ProgressBarProps): react.JSX.Element;
1361
3095
 
1362
- interface RankedRowProps {
1363
- rank?: number;
1364
- name: string;
1365
- sublabel?: string;
3096
+ interface NumberedListItem {
3097
+ title: string;
3098
+ /** Second line under the title — a region, a category, an id. */
3099
+ subtitle?: string;
1366
3100
  score: number;
1367
- /** Bar and value colour. `auto` derives it from `score`. */
3101
+ /** Bar and value colour for this row. `auto` derives it from `score`. */
1368
3102
  tone?: ProgressBarTone | 'auto';
1369
- /** Which end of the scale is bad, when `tone` is `auto`. */
3103
+ }
3104
+ type NumberedListGap = 'sm' | 'md';
3105
+ interface NumberedListProps {
3106
+ items: NumberedListItem[];
3107
+ /** Which end of the scale is bad, for rows resolving `tone` automatically. */
1370
3108
  direction?: ScoreDirection;
1371
3109
  scoreSize?: ScoreValueSize;
1372
3110
  scoreWeight?: ScoreValueWeight;
3111
+ /** First ordinal. Set it to continue a list across a page boundary. */
3112
+ startAt?: number;
3113
+ gap?: NumberedListGap;
1373
3114
  className?: string;
1374
3115
  }
1375
3116
  /**
1376
- * A leaderboard row: rank, name, score, and a full-width bar underneath.
3117
+ * A ranked leaderboard: ordinal, title, score, and a full-width bar under each row.
1377
3118
  *
1378
- * Was `RankedListItem` — the only `…Item` in a folder of `…Row`s. Its three raw-hex
1379
- * colour props (`scoreColor`, `barColor`, `barTrackColor`) are gone in favour of
1380
- * `tone`, and its `gap` CSS string is now the `gap-1.5` it always resolved to.
3119
+ * Was `RankedRow`, which was one row and made the caller supply both the `<ol>` and every
3120
+ * `rank` by hand — so a filtered or re-sorted list silently kept stale numbers. Owning the
3121
+ * list means the ordinal is derived from position and cannot disagree with the order on
3122
+ * screen. It also puts it at the same granularity as `StepsList`, its neighbour.
3123
+ *
3124
+ * It still hardcodes `ProgressBar` and `ScoreValue`, and that is the point: a leaderboard
3125
+ * row *is* those three things. Where the pieces need to vary, reach for `ScoredRow`, whose
3126
+ * slots take arbitrary content.
1381
3127
  */
1382
- declare function RankedRow({ rank, name, sublabel, score, tone, direction, scoreSize, scoreWeight, className, }: RankedRowProps): react.JSX.Element;
3128
+ declare function NumberedList({ items, direction, scoreSize, scoreWeight, startAt, gap, className, }: NumberedListProps): react.JSX.Element;
1383
3129
 
1384
3130
  interface IconTextRowProps {
1385
3131
  icon: ReactNode;
@@ -1414,58 +3160,76 @@ interface ChecklistRowProps {
1414
3160
  */
1415
3161
  declare function ChecklistRow({ label, state, className }: ChecklistRowProps): react.JSX.Element;
1416
3162
 
1417
- interface NumberedStepsListProps {
3163
+ interface StepsListProps {
1418
3164
  steps: ReactNode[];
1419
3165
  className?: string;
1420
3166
  }
1421
3167
  /**
1422
- * Ordered list with small filled number bullets.
3168
+ * Ordered list of instructions with small filled number bullets.
1423
3169
  *
1424
- * Promoted from entity-detail's "what happens next" panel. The panel's copy is
1425
- * review-lifecycle business content and stays there; only the list chrome moves.
3170
+ * Was `NumberedStepsList`. Renamed in 0.5.0 because `NumberedList` — the ranked
3171
+ * leaderboard — also numbers its rows, and two components whose names both led with
3172
+ * "Numbered" gave no hint which was which. The distinction is what the numbers *mean*:
3173
+ * here they are sequence ("do this, then this"), there they are rank.
1426
3174
  *
1427
3175
  * The bullet was `bg-[#e7edfb] text-[#1d4ed8]` — a pale blue pair that is not in the
1428
3176
  * token set. It now uses the brand-tertiary background and brand text, which is the
1429
3177
  * documented treatment for a subtle brand-tinted chip.
1430
3178
  */
1431
- declare function NumberedStepsList({ steps, className }: NumberedStepsListProps): react.JSX.Element;
3179
+ declare function StepsList({ steps, className }: StepsListProps): react.JSX.Element;
1432
3180
 
1433
- type MetaFieldLayout = 'stacked' | 'inline';
1434
- interface MetaFieldProps {
3181
+ type DetailItemLayout = 'stacked' | 'inline';
3182
+ type DetailItemSpan = 1 | 2 | 'full';
3183
+ interface DetailItemProps {
1435
3184
  label: string;
1436
3185
  value: ReactNode;
1437
- /** Optional second line under the value (used by the onboarding review sections). */
3186
+ /** Optional second line under the value. */
1438
3187
  detail?: ReactNode;
1439
3188
  /**
1440
- * `stacked` puts the label above the value (detail pages, onboarding review).
3189
+ * `stacked` puts the label above the value (detail pages, review summaries).
1441
3190
  * `inline` puts a fixed-width label beside it (drawer detail rows).
1442
3191
  */
1443
- layout?: MetaFieldLayout;
1444
- /** Fixed width for the `stacked` form, e.g. `sm:w-[262px]` on the overview grid. */
3192
+ layout?: DetailItemLayout;
3193
+ /**
3194
+ * Columns to occupy inside a `DetailGrid`. `full` spans the row — for a long value
3195
+ * such as an alias list or a legal name that would otherwise truncate.
3196
+ */
3197
+ span?: DetailItemSpan;
3198
+ /**
3199
+ * Label column width for the `inline` layout. A `min-w`/`max-w` pair rather than a
3200
+ * fixed `w-`, so a long label wraps instead of colliding with the value.
3201
+ */
3202
+ labelWidth?: string;
1445
3203
  className?: string;
1446
3204
  }
1447
3205
  /**
1448
3206
  * A label/value pair.
1449
3207
  *
1450
- * Consolidates the same shape from six places: the entity-detail overview grid, the
1451
- * reviewer-detail metric column, three `DetailRow` copies in drawers (queues,
1452
- * filings, website-intel) and `ReviewMeta` in both onboarding wizards.
3208
+ * Was `MetaField` — an internal codename that said nothing about the shape. Consolidates
3209
+ * the same pair from six places: an entity-detail overview grid, a reviewer-detail metric
3210
+ * column, three `DetailRow` copies in drawers, and `ReviewMeta` in two onboarding wizards.
1453
3211
  *
1454
- * An empty value renders an em dash, which is what every source copy did by hand.
3212
+ * An empty value renders an em dash, which is what every source copy did by hand. Note
3213
+ * that the check is for `null`/`undefined`/`''` only — `0` and `false` are real values and
3214
+ * render as themselves.
1455
3215
  */
1456
- declare function MetaField({ label, value, detail, layout, className, }: MetaFieldProps): react.JSX.Element;
1457
- interface MetaFieldGridProps {
3216
+ declare function DetailItem({ label, value, detail, layout, span, labelWidth, className, }: DetailItemProps): react.JSX.Element;
3217
+ type DetailGridColumns = 2 | 3 | 4 | 'auto';
3218
+ interface DetailGridProps {
1458
3219
  children: ReactNode;
3220
+ columns?: DetailGridColumns;
1459
3221
  className?: string;
1460
3222
  }
1461
3223
  /**
1462
- * Wrapper for a set of `MetaField`s that wrap into columns.
3224
+ * Wrapper for a set of `DetailItem`s.
1463
3225
  *
1464
- * Matches the entity-detail overview grid, which relies on each field carrying its
1465
- * own width rather than on fixed grid columns — long values (aliases, legal names)
1466
- * need to be able to occupy a full row on narrow viewports.
3226
+ * A real grid, not the `flex flex-wrap` it was as `MetaFieldGrid`. Under flex-wrap every
3227
+ * item had to carry its own width (`sm:w-[262px]` was the documented idiom) and whatever
3228
+ * space was left over at the end of a row stayed empty — so a three-item row in a wide
3229
+ * card had a ragged gap on the right. `1fr` tracks divide the row exactly, and an item
3230
+ * that genuinely needs more room asks for it with `span` instead of a magic width.
1467
3231
  */
1468
- declare function MetaFieldGrid({ children, className }: MetaFieldGridProps): react.JSX.Element;
3232
+ declare function DetailGrid({ children, columns, className }: DetailGridProps): react.JSX.Element;
1469
3233
 
1470
3234
  type CheckedGroupListColumns = 1 | 2 | 3;
1471
3235
  /** One labelled group of ticked items. */
@@ -1494,6 +3258,68 @@ interface CheckedGroupListProps {
1494
3258
  */
1495
3259
  declare function CheckedGroupList({ groups, columns, icon, emptyLabel, className, }: CheckedGroupListProps): react.JSX.Element;
1496
3260
 
3261
+ type TableDensity = 'default' | 'compact';
3262
+ type TableSortDirection = 'ascending' | 'descending';
3263
+ /**
3264
+ * The composable table primitive, matching Figma's `Table` and `Table cell`.
3265
+ *
3266
+ * `DataTable` is the config-driven form — you give it `columns` and `rows` and it renders
3267
+ * everything. It is the right tool most of the time, and it is not going away. But it
3268
+ * cannot express a grouped header, a footer row, a colspan, or a cell layout outside its
3269
+ * `render` signature, so anything unusual meant abandoning it for a hand-rolled `<table>`
3270
+ * with none of the semantics. These parts are that escape hatch with the semantics kept.
3271
+ *
3272
+ * Figma's `Table cell` has a 32-value `Style` axis (lead checkbox, lead avatar, badges
3273
+ * multiple, trend positive/negative, action icons, star ratings, payment method…). Those
3274
+ * are *compositions*, not variants of one component — each is an existing library
3275
+ * component dropped into a cell — so they are expressed here as `TableCell` plus whatever
3276
+ * goes inside it, rather than 32 props.
3277
+ */
3278
+ interface TableProps extends HTMLAttributes<HTMLTableElement> {
3279
+ /** Names the table. Required unless you render a `TableCaption`. */
3280
+ label?: string;
3281
+ density?: TableDensity;
3282
+ /** Equal-width columns driven by `<colgroup>`, matching `DataTable`. Default `false`. */
3283
+ fixed?: boolean;
3284
+ }
3285
+ declare const Table: react.ForwardRefExoticComponent<TableProps & react.RefAttributes<HTMLTableElement>>;
3286
+ interface TableCaptionProps extends HTMLAttributes<HTMLTableCaptionElement> {
3287
+ }
3288
+ /**
3289
+ * A visible table title that also names the table. Prefer this over `label` when the
3290
+ * heading is on screen anyway — `DataTable` could not be named at all before 0.4.0.
3291
+ */
3292
+ declare const TableCaption: react.ForwardRefExoticComponent<TableCaptionProps & react.RefAttributes<HTMLTableCaptionElement>>;
3293
+ declare const TableHeader: react.ForwardRefExoticComponent<HTMLAttributes<HTMLTableSectionElement> & react.RefAttributes<HTMLTableSectionElement>>;
3294
+ declare const TableBody: react.ForwardRefExoticComponent<HTMLAttributes<HTMLTableSectionElement> & react.RefAttributes<HTMLTableSectionElement>>;
3295
+ declare const TableFooter: react.ForwardRefExoticComponent<HTMLAttributes<HTMLTableSectionElement> & react.RefAttributes<HTMLTableSectionElement>>;
3296
+ interface TableRowProps extends HTMLAttributes<HTMLTableRowElement> {
3297
+ selected?: boolean;
3298
+ }
3299
+ declare const TableRow: react.ForwardRefExoticComponent<TableRowProps & react.RefAttributes<HTMLTableRowElement>>;
3300
+ interface TableHeadProps extends ThHTMLAttributes<HTMLTableCellElement> {
3301
+ /**
3302
+ * Makes the header a sort control. `false` means sortable but not currently sorted.
3303
+ *
3304
+ * `aria-sort` goes on the `<th>` and must be present on exactly one column at a time —
3305
+ * it is the only non-visual signal of sort state, and `DataTable` had none.
3306
+ */
3307
+ sort?: TableSortDirection | false;
3308
+ onSort?: () => void;
3309
+ align?: 'left' | 'center' | 'right';
3310
+ /** Keeps the header visible while the body scrolls. */
3311
+ sticky?: boolean;
3312
+ }
3313
+ declare const TableHead: react.ForwardRefExoticComponent<TableHeadProps & react.RefAttributes<HTMLTableCellElement>>;
3314
+ interface TableCellProps extends TdHTMLAttributes<HTMLTableCellElement> {
3315
+ align?: 'left' | 'center' | 'right';
3316
+ /** Vertical rhythm. Matches `DataTable`'s `density`. */
3317
+ density?: TableDensity;
3318
+ /** Makes this the row's header cell — `scope="row"`, for a table with row headers. */
3319
+ header?: boolean;
3320
+ }
3321
+ declare const TableCell: react.ForwardRefExoticComponent<TableCellProps & react.RefAttributes<HTMLTableCellElement>>;
3322
+
1497
3323
  interface ColumnDef<T> {
1498
3324
  key: string;
1499
3325
  header: string;
@@ -1624,6 +3450,129 @@ interface EmptyStateProps {
1624
3450
  */
1625
3451
  declare function EmptyState({ message, variant, size, icon, action, className, }: EmptyStateProps): react.JSX.Element;
1626
3452
 
3453
+ type SpinnerSize = 'xs' | 'sm' | 'md' | 'lg';
3454
+ interface SpinnerProps extends HTMLAttributes<HTMLSpanElement> {
3455
+ size?: SpinnerSize;
3456
+ /**
3457
+ * Accessible name. When omitted the spinner is marked decorative — correct when it sits
3458
+ * inside a control that already announces the pending state (`Button loading` sets
3459
+ * `aria-busy`), and wrong when the spinner is the only thing on screen.
3460
+ */
3461
+ label?: string;
3462
+ }
3463
+ /**
3464
+ * Indeterminate loading indicator. `ProgressBar` is the determinate counterpart.
3465
+ *
3466
+ * The spin is a border-based ring rather than an SVG so it inherits `currentColor` and
3467
+ * needs no fill/stroke plumbing — it works on any button variant unchanged. The animation
3468
+ * is suppressed under `prefers-reduced-motion` by the preset's base rule, which leaves a
3469
+ * static ring; that is why the transparent segment is a full quarter and still legible
3470
+ * when frozen.
3471
+ */
3472
+ declare const Spinner: react.ForwardRefExoticComponent<SpinnerProps & react.RefAttributes<HTMLSpanElement>>;
3473
+
3474
+ type SkeletonShape = 'line' | 'block' | 'circle';
3475
+ interface SkeletonProps extends HTMLAttributes<HTMLDivElement> {
3476
+ shape?: SkeletonShape;
3477
+ /** Number of stacked lines. Only meaningful for `line`. */
3478
+ lines?: number;
3479
+ }
3480
+ /**
3481
+ * Loading placeholder.
3482
+ *
3483
+ * `aria-hidden` and no role: a skeleton is a picture of content that does not exist yet,
3484
+ * so announcing it produces a burst of meaningless nodes. The *region* it sits in should
3485
+ * carry the loading state — `EmptyState variant="loading"` or `aria-busy` on the
3486
+ * container — which is a decision only the caller can make.
3487
+ *
3488
+ * The pulse is suppressed by the preset's `prefers-reduced-motion` rule, leaving a plain
3489
+ * tinted block.
3490
+ */
3491
+ declare const Skeleton: react.ForwardRefExoticComponent<SkeletonProps & react.RefAttributes<HTMLDivElement>>;
3492
+
3493
+ type BannerVariant = 'message' | 'alert';
3494
+ interface BannerProps extends Omit<HTMLAttributes<HTMLDivElement>, 'title'> {
3495
+ /** Bold first line. Matches Figma's `Title`. */
3496
+ title: ReactNode;
3497
+ /** Supporting copy. Matches Figma's `Body`. */
3498
+ children?: ReactNode;
3499
+ /**
3500
+ * Matches Figma's `Variant` axis. `message` is informational; `alert` is urgent and is
3501
+ * announced immediately.
3502
+ */
3503
+ variant?: BannerVariant;
3504
+ tone?: InlineAlertTone;
3505
+ /** Replaces the tone glyph. Pass `null` to suppress it. Matches `Icon` / `Has Icon`. */
3506
+ icon?: ReactNode | null;
3507
+ /** Trailing action slot. Matches `Has Button`. */
3508
+ action?: ReactNode;
3509
+ /** Renders a dismiss button. Matches `Dismissible`. */
3510
+ onDismiss?: () => void;
3511
+ }
3512
+ /**
3513
+ * A page- or section-level banner with a title, body, optional action and optional dismiss.
3514
+ *
3515
+ * This is Figma's `Notification` set (`Variant: Message | Alert`, with `Title`, `Body`,
3516
+ * `Has Icon`, `Has Button` and `Dismissible`). Worth being precise about the name: its
3517
+ * Figma keywords are "message, alert, feedback, callout, banner" — it is a *persistent,
3518
+ * in-flow* notice, **not** a toast. A toast is transient, stacked, and announced from a
3519
+ * live region that already exists; that is `Toast`, and it is a different component.
3520
+ *
3521
+ * `InlineAlert` remains the compact single-line form for use inside a form or a card.
3522
+ * `Banner` is the one with a heading and an action.
3523
+ *
3524
+ * `variant` drives the announcement, not just the styling: `alert` is `role="alert"`
3525
+ * (interrupts), `message` is `role="status"` (waits its turn).
3526
+ */
3527
+ declare const Banner: react.ForwardRefExoticComponent<BannerProps & react.RefAttributes<HTMLDivElement>>;
3528
+
3529
+ type ToastTone = InlineAlertTone;
3530
+ type ToasterPosition = 'top-left' | 'top-center' | 'top-right' | 'bottom-left' | 'bottom-center' | 'bottom-right';
3531
+ interface ToastOptions {
3532
+ title: ReactNode;
3533
+ description?: ReactNode;
3534
+ tone?: ToastTone;
3535
+ /** Milliseconds before auto-dismiss. `0` keeps it until dismissed. Default `5000`. */
3536
+ duration?: number;
3537
+ action?: ReactNode;
3538
+ }
3539
+ interface ToastRecord extends ToastOptions {
3540
+ id: string;
3541
+ }
3542
+ interface ToastContextValue {
3543
+ toast: (options: ToastOptions) => string;
3544
+ dismiss: (id: string) => void;
3545
+ dismissAll: () => void;
3546
+ }
3547
+ /**
3548
+ * Queue a toast. Must be called under a `<Toaster>`.
3549
+ *
3550
+ * Returns the toast's id so a long-running action can dismiss its own "Saving…" toast when
3551
+ * it finishes.
3552
+ */
3553
+ declare function useToast(): ToastContextValue;
3554
+ interface ToasterProps {
3555
+ children: ReactNode;
3556
+ position?: ToasterPosition;
3557
+ /** Maximum simultaneous toasts. Oldest are dropped first. Default `4`. */
3558
+ max?: number;
3559
+ /** Default auto-dismiss for toasts that do not set their own. Default `5000`. */
3560
+ duration?: number;
3561
+ }
3562
+ /**
3563
+ * Provider plus the region toasts render into. Mount once, near the app root.
3564
+ *
3565
+ * The library had no toast and — more importantly — **no persistent live region at all**,
3566
+ * so nothing could announce an event that happened away from focus. The distinction that
3567
+ * matters here: a live region must already exist in the DOM before content is put into it.
3568
+ * A region that mounts at the same moment as its message is frequently not announced,
3569
+ * which is why the wrapper below renders unconditionally and only its children come and go.
3570
+ *
3571
+ * `aria-live="polite"` on the container, and `role="alert"` on individual `danger` toasts
3572
+ * so a failure interrupts rather than queueing behind a success message.
3573
+ */
3574
+ declare function Toaster({ children, position, max, duration, }: ToasterProps): react.JSX.Element;
3575
+
1627
3576
  type PasswordInputProps = Omit<InputProps, 'type' | 'trailingIcon' | 'trailingAction'>;
1628
3577
  /** Password field with a show/hide visibility toggle. */
1629
3578
  declare const PasswordInput: react.ForwardRefExoticComponent<PasswordInputProps & react.RefAttributes<HTMLInputElement>>;
@@ -1660,52 +3609,4 @@ declare function QuickActionsBar({ actions, active, onSelect, className }: Quick
1660
3609
  * with `relative`. */
1661
3610
  declare function AuroraBackdrop(): react.JSX.Element;
1662
3611
 
1663
- /** Bespoke icon art with no equivalent in the stroked icon set.
1664
- *
1665
- * The library's icons come from `react-icons/lu`, which is a *stroked* set. What
1666
- * lives here is the small set of *filled* 20×20 marks: swapping these for
1667
- * `LuInfo`/`LuArrowRight`/etc. would turn a solid glyph into an outline — a visual
1668
- * change, not a redraw. They keep their own `viewBox="0 0 20 20"` and
1669
- * `fill="currentColor"`, and size via `className` (e.g. `className="size-5"`).
1670
- *
1671
- * Do not add stroked icons here — import them from `react-icons/lu` instead.
1672
- */
1673
- interface SolidIconProps {
1674
- className?: string;
1675
- }
1676
- declare const SolidAlertTriangle: {
1677
- ({ className }: SolidIconProps): react.JSX.Element;
1678
- displayName: string;
1679
- };
1680
- declare const SolidShieldCheck: {
1681
- ({ className }: SolidIconProps): react.JSX.Element;
1682
- displayName: string;
1683
- };
1684
- declare const SolidGlobe: {
1685
- ({ className }: SolidIconProps): react.JSX.Element;
1686
- displayName: string;
1687
- };
1688
- declare const SolidMapPin: {
1689
- ({ className }: SolidIconProps): react.JSX.Element;
1690
- displayName: string;
1691
- };
1692
- declare const SolidClock: {
1693
- ({ className }: SolidIconProps): react.JSX.Element;
1694
- displayName: string;
1695
- };
1696
- declare const SolidArrowRight: {
1697
- ({ className }: SolidIconProps): react.JSX.Element;
1698
- displayName: string;
1699
- };
1700
- declare const SolidInfoCircle: {
1701
- ({ className }: SolidIconProps): react.JSX.Element;
1702
- displayName: string;
1703
- };
1704
- declare const SolidCheck: {
1705
- ({ className }: SolidIconProps): react.JSX.Element;
1706
- displayName: string;
1707
- };
1708
- /** Chart bars — the one mark here without a `fillRule`/`clipRule` pair. */
1709
- declare function SolidChartBar({ className }: SolidIconProps): react.JSX.Element;
1710
-
1711
- export { AIChatBar, type AIChatBarProps, AISuggestionChip, type AISuggestionChipProps, AuroraBackdrop, Avatar, AvatarBlock, type AvatarBlockProps, AvatarGroup, type AvatarGroupProps, type AvatarGroupSpacing, type AvatarImageProps, type AvatarInitialProps, type AvatarProps, type AvatarShape, type AvatarSize, Badge, type BadgeColor, type BadgeProps, type BadgeSize, type BadgeVariant, BarChart, type BarChartOrientation, type BarChartProps, type BarChartSeries, type BarChartSize, Button, ButtonGroup, type ButtonGroupAlign, type ButtonGroupItem, type ButtonGroupProps, type ButtonGroupVariant, type ButtonProps, type ButtonSize, type ButtonVariant, CHART_SEQUENCE, CHART_TONE, CHART_TRACK, Card, CardAction, type CardActionProps, CardBody, type CardBodyProps, CardDescription, type CardDescriptionProps, CardFooter, type CardFooterAlign, type CardFooterProps, CardHeader, type CardHeaderProps, type CardProps, type CardRadius, type CardSize, CardTitle, type CardTitleProps, type CardTone, ChartLegend, type ChartLegendItem, type ChartLegendOrientation, type ChartLegendProps, type ChartTone, CheckIndicator, type CheckIndicatorProps, type CheckIndicatorStatus, Checkbox, type CheckboxProps, type CheckedGroup, CheckedGroupList, type CheckedGroupListColumns, type CheckedGroupListProps, ChecklistRow, type ChecklistRowProps, type ChecklistRowState, type ColumnDef, ConfirmDialog, type ConfirmDialogProps, CountBadge, type CountBadgeProps, DEFAULT_SCORE_THRESHOLDS, DataTable, type DataTableAlign, type DataTableDensity, type DataTableProps, DatePicker, type DatePickerProps, DonutChart, type DonutChartProps, type DonutChartSize, type DonutSegment, Drawer, type DrawerProps, DropdownMenu, type DropdownMenuItem, type DropdownMenuProps, EmptyState, type EmptyStateProps, type EmptyStateSize, type EmptyStateVariant, EntityIconBadge, type EntityIconBadgeProps, type EntityIconBadgeSize, type EntityIconBadgeTone, EyebrowLabel, type EyebrowLabelProps, type EyebrowLabelVariant, FileDropZone, type FileDropZoneProps, FileRow, type FileRowProps, FilterBar, type FilterBarProps, type FilterBarSize, FormCard, FormCardFooter, type FormCardFooterProps, FormCardHeader, type FormCardHeaderProps, IconButton, type IconButtonProps, type IconButtonVariant, IconTextRow, type IconTextRowProps, InlineAlert, type InlineAlertProps, type InlineAlertTone, Input, type InputProps, type InputSize, LegendDot, type LegendDotProps, type LegendDotShape, type LegendDotSize, ListRow, type ListRowDensity, type ListRowDivider, type ListRowProps, MetaField, MetaFieldGrid, type MetaFieldGridProps, type MetaFieldLayout, type MetaFieldProps, MiniBarChart, type MiniBarChartOrientation, type MiniBarChartProps, type MiniBarChartSize, Modal, ModalBody, type ModalBodyProps, ModalDescription, type ModalDescriptionProps, ModalFooter, type ModalFooterAlign, type ModalFooterProps, ModalHeader, type ModalHeaderProps, type ModalProps, type ModalSize, ModalTitle, type ModalTitleProps, type ModalTone, MultiSelectCard, type MultiSelectCardProps, NavItem, type NavItemProps, type NavItemSize, NoteConfirmModal, type NoteConfirmModalProps, NumberedStepsList, type NumberedStepsListProps, OVERLAY_SCRIM, PageHeading, type PageHeadingProps, type PageHeadingSize, PageToolbar, type PageToolbarProps, type PageToolbarSize, PasswordInput, type PasswordInputProps, ProgressBar, type ProgressBarProps, type ProgressBarSize, type ProgressBarTone, type QuickAction, QuickActionsBar, type QuickActionsBarProps, ROLE_COMBO_OPTIONS, RadialGauge, type RadialGaugeProps, type RadialGaugeSize, RankedRow, type RankedRowProps, RoleBadge, type RoleBadgeProps, RoleComboBox, type RoleComboBoxProps, type RoleOption, type ScoreDirection, type ScoreRampTone, type ScoreThresholds, type ScoreTone, ScoreValue, type ScoreValueProps, type ScoreValueSize, type ScoreValueTone, type ScoreValueWeight, ScoredRow, type ScoredRowAlign, type ScoredRowGap, type ScoredRowProps, SegmentedControl, type SegmentedControlOption, type SegmentedControlProps, Select, type SelectOption, type SelectProps, SolidAlertTriangle, SolidArrowRight, SolidChartBar, SolidCheck, SolidClock, SolidGlobe, SolidInfoCircle, SolidMapPin, SolidShieldCheck, Sparkline, type SparklineProps, type SparklineSize, type SparklineVariant, StatNumber, type StatNumberProps, type StatNumberSize, type StatNumberWeight, StatTile, type StatTileProps, StatusBadge, type StatusBadgeProps, type StatusBadgeSize, StatusChip, type StatusChipProps, StatusDot, type StatusDotProps, type StatusDotTone, type StatusTone, type StepItem, type StepStatus, Stepper, type StepperProps, type TabItem, TableCellBadge, type TableCellBadgeProps, TableCellLeadText, type TableCellLeadTextProps, TableCellProgress, type TableCellProgressProps, type TableCellSize, TableCellText, type TableCellTextProps, Tabs, type TabsProps, type TabsSize, type TabsVariant, TagPill, type TagPillProps, type TagPillTone, Textarea, type TextareaProps, TileGrid, type TileGridBreakpoint, type TileGridColumns, type TileGridProps, Toggle, type ToggleProps, type ToggleSize, TrailChip, type TrailChipProps, type TrendDirection, TrendLabel, type TrendLabelProps, type TrendLabelSize, type TrendLabelWeight, type UserAccountStatus, UserStatusPill, type UserStatusPillProps, WidgetFooter, type WidgetFooterProps, WidgetHeader, type WidgetHeaderEyebrowVariant, type WidgetHeaderProps, WidgetTitle, type WidgetTitleProps, type WidgetTitleSize, cn, getScoreTone, resolveChartColor, useOverlayDismiss };
3612
+ export { AIChatBar, type AIChatBarProps, AISuggestionChip, type AISuggestionChipProps, Accordion, AccordionContent, type AccordionContentProps, AccordionItem, type AccordionItemProps, type AccordionProps, AccordionTrigger, type AccordionTriggerProps, type AccordionType, AspectRatio, type AspectRatioProps, AuroraBackdrop, Avatar, AvatarBlock, type AvatarBlockProps, AvatarGroup, type AvatarGroupProps, type AvatarGroupSpacing, type AvatarImageProps, type AvatarInitialProps, type AvatarProps, type AvatarShape, type AvatarSize, Badge, type BadgeColor, type BadgeProps, type BadgeSize, type BadgeVariant, Banner, type BannerProps, type BannerVariant, BarChart, type BarChartOrientation, type BarChartProps, type BarChartSeries, type BarChartSize, Breadcrumb, BreadcrumbEllipsis, type BreadcrumbEllipsisProps, BreadcrumbItem, type BreadcrumbItemProps, type BreadcrumbProps, Button, ButtonGroup, type ButtonGroupAlign, type ButtonGroupItem, type ButtonGroupProps, type ButtonGroupVariant, type ButtonProps, type ButtonSize, type ButtonVariant, CHART_SEQUENCE, CHART_TONE, CHART_TRACK, Calendar, type CalendarMode, type CalendarProps, Card, CardAction, type CardActionProps, CardBody, type CardBodyProps, CardDescription, type CardDescriptionProps, CardFooter, type CardFooterAlign, type CardFooterProps, CardHeader, type CardHeaderProps, type CardProps, type CardRadius, type CardSize, CardTitle, type CardTitleProps, type CardTone, Carousel, CarouselControls, type CarouselControlsProps, type CarouselProps, CarouselSlide, type CarouselSlideProps, CarouselViewport, type CarouselViewportProps, ChartLegend, type ChartLegendItem, type ChartLegendOrientation, type ChartLegendProps, type ChartTone, CheckIndicator, type CheckIndicatorProps, type CheckIndicatorStatus, Checkbox, type CheckboxProps, type CheckboxSize, type CheckedGroup, CheckedGroupList, type CheckedGroupListColumns, type CheckedGroupListProps, ChecklistRow, type ChecklistRowProps, type ChecklistRowState, Collapsible, CollapsibleContent, type CollapsibleContentProps, type CollapsibleProps, CollapsibleTrigger, type CollapsibleTriggerProps, type ColumnDef, Combobox, type ComboboxOption, type ComboboxProps, Command, type CommandItem, type CommandProps, ConfirmDialog, type ConfirmDialogProps, ContextMenu, MenuCheckboxItem as ContextMenuCheckboxItem, ContextMenuContent, type ContextMenuContentProps, MenuGroup as ContextMenuGroup, MenuItem as ContextMenuItem, MenuLabel as ContextMenuLabel, type ContextMenuProps, MenuRadioGroup as ContextMenuRadioGroup, MenuRadioItem as ContextMenuRadioItem, MenuSeparator as ContextMenuSeparator, MenuShortcut as ContextMenuShortcut, ContextMenuTrigger, type ContextMenuTriggerProps, ControlSizeProvider, type ControlSizeProviderProps, CountBadge, type CountBadgeProps, DEFAULT_SCORE_THRESHOLDS, DataTable, type DataTableAlign, type DataTableDensity, type DataTableProps, DatePicker, type DatePickerProps, type DateRange, DetailGrid, type DetailGridColumns, type DetailGridProps, DetailItem, type DetailItemLayout, type DetailItemProps, type DetailItemSpan, DonutChart, type DonutChartProps, type DonutChartSize, type DonutSegment, Drawer, type DrawerProps, DropdownMenu, MenuCheckboxItem as DropdownMenuCheckboxItem, type MenuCheckboxItemProps as DropdownMenuCheckboxItemProps, DropdownMenuContent, type DropdownMenuContentProps, MenuGroup as DropdownMenuGroup, type MenuGroupProps as DropdownMenuGroupProps, MenuItem as DropdownMenuItem, type MenuItemProps as DropdownMenuItemProps, type MenuItemTone as DropdownMenuItemTone, MenuLabel as DropdownMenuLabel, type MenuLabelProps as DropdownMenuLabelProps, type DropdownMenuProps, MenuRadioGroup as DropdownMenuRadioGroup, type MenuRadioGroupProps as DropdownMenuRadioGroupProps, MenuRadioItem as DropdownMenuRadioItem, type MenuRadioItemProps as DropdownMenuRadioItemProps, MenuSeparator as DropdownMenuSeparator, type MenuSeparatorProps as DropdownMenuSeparatorProps, MenuShortcut as DropdownMenuShortcut, type MenuShortcutProps as DropdownMenuShortcutProps, DropdownMenuTrigger, type DropdownMenuTriggerProps, EmptyState, type EmptyStateProps, type EmptyStateSize, type EmptyStateVariant, EntityIconBadge, type EntityIconBadgeProps, type EntityIconBadgeSize, type EntityIconBadgeTone, EyebrowLabel, type EyebrowLabelProps, type EyebrowLabelVariant, Field, type FieldContextValue, FieldDescription, FieldError, FieldGroup, type FieldGroupProps, FieldHint, FieldLabel, type FieldLabelProps, FieldLegend, type FieldLegendProps, type FieldOrientation, type FieldProps, FieldSeparator, type FieldSeparatorProps, FieldSet, type FieldSetProps, type FieldTextProps, FileDropZone, type FileDropZoneProps, FileRow, type FileRowProps, FilterBar, type FilterBarProps, type FilterBarSize, FormCard, FormCardFooter, type FormCardFooterProps, FormCardHeader, type FormCardHeaderProps, Heading, HoverCard, type HoverCardProps, IconButton, type IconButtonProps, type IconButtonVariant, IconTextRow, type IconTextRowProps, InlineAlert, type InlineAlertProps, type InlineAlertTone, Input, InputControl, type InputControlProps, InputGroup, InputGroupAddon, type InputGroupAddonProps, type InputGroupAlign, InputGroupInput, type InputGroupInputProps, type InputGroupProps, InputGroupText, type InputGroupTextProps, InputOTP, type InputOTPMode, type InputOTPProps, type InputProps, type InputSize, Kbd, type KbdProps, type KbdSize, Label, type LabelProps, LegendDot, type LegendDotProps, type LegendDotShape, type LegendDotSize, ListRow, type ListRowDensity, type ListRowDivider, type ListRowProps, Menubar, MenuCheckboxItem as MenubarCheckboxItem, MenubarContent, type MenubarContentProps, MenuGroup as MenubarGroup, MenuItem as MenubarItem, MenuLabel as MenubarLabel, MenubarMenu, type MenubarMenuProps, type MenubarProps, MenuRadioGroup as MenubarRadioGroup, MenuRadioItem as MenubarRadioItem, MenuSeparator as MenubarSeparator, MenuShortcut as MenubarShortcut, MenubarTrigger, type MenubarTriggerProps, MiniBarChart, type MiniBarChartOrientation, type MiniBarChartProps, type MiniBarChartSize, Modal, ModalBody, type ModalBodyProps, ModalDescription, type ModalDescriptionProps, ModalFooter, type ModalFooterAlign, type ModalFooterProps, ModalHeader, type ModalHeaderProps, type ModalProps, type ModalSize, ModalTitle, type ModalTitleProps, type ModalTone, MultiSelectCard, type MultiSelectCardProps, type MultiSelectCardSize, NavItem, type NavItemProps, type NavItemSize, type NavItemVariant, NavigationMenu, NavigationMenuItem, type NavigationMenuItemProps, type NavigationMenuOrientation, type NavigationMenuProps, type NavigationMenuVariant, NoteConfirmModal, type NoteConfirmModalProps, NumberedList, type NumberedListGap, type NumberedListItem, type NumberedListProps, OVERLAY_SCRIM, PageHeading, type PageHeadingProps, type PageHeadingSize, PageToolbar, type PageToolbarProps, type PageToolbarSize, Pagination, type PaginationProps, type PaginationType, PasswordInput, type PasswordInputProps, Popover, PopoverContent, type PopoverContentProps, type PopoverProps, PopoverTrigger, type PopoverTriggerProps, Portal, type PortalProps, ProgressBar, type ProgressBarProps, type ProgressBarSize, type ProgressBarTone, type QuickAction, QuickActionsBar, type QuickActionsBarProps, ROLE_COMBO_OPTIONS, RadialGauge, type RadialGaugeProps, type RadialGaugeSize, Radio, RadioGroup, type RadioGroupOrientation, type RadioGroupProps, type RadioProps, Resizable, type ResizableDirection, ResizableHandle, type ResizableHandleProps, ResizablePanel, type ResizablePanelProps, type ResizableProps, RoleBadge, type RoleBadgeProps, type RoleBadgeTone, RoleComboBox, type RoleComboBoxProps, type RoleOption, SCROLLBAR_CLASSES, type ScoreDirection, type ScoreRampTone, type ScoreThresholds, type ScoreTone, ScoreValue, type ScoreValueProps, type ScoreValueSize, type ScoreValueTone, type ScoreValueWeight, ScoredRow, type ScoredRowAlign, type ScoredRowGap, type ScoredRowProps, ScrollArea, type ScrollAreaAxis, type ScrollAreaProps, SearchInput, type SearchInputProps, SegmentedControl, type SegmentedControlOption, type SegmentedControlProps, Select, SelectControl, type SelectControlProps, type SelectOption, type SelectOptionGroup, type SelectProps, Separator, type SeparatorOrientation, type SeparatorProps, Skeleton, type SkeletonProps, type SkeletonShape, Slider, type SliderProps, Sparkline, type SparklineProps, type SparklineSize, type SparklineVariant, Spinner, type SpinnerProps, type SpinnerSize, StatNumber, type StatNumberProps, type StatNumberSize, type StatNumberWeight, StatTile, type StatTileProps, StatusBadge, type StatusBadgeProps, type StatusBadgeSize, StatusChip, type StatusChipProps, StatusDot, type StatusDotProps, type StatusDotTone, type StatusTone, type StepItem, type StepStatus, Stepper, type StepperProps, type StepperSize, StepsList, type StepsListProps, Subheading, Subtitle, Switch, type SwitchProps, type SwitchSize, type TabItem, Table, TableBody, TableCaption, type TableCaptionProps, TableCell, TableCellBadge, type TableCellBadgeProps, TableCellLeadText, type TableCellLeadTextProps, TableCellProgress, type TableCellProgressProps, type TableCellProps, type TableCellSize, TableCellText, type TableCellTextProps, type TableDensity, TableFooter, TableHead, type TableHeadProps, TableHeader, type TableProps, TableRow, type TableRowProps, type TableSortDirection, Tabs, type TabsActivation, type TabsOrientation, TabsPanel, type TabsPanelProps, type TabsProps, type TabsSize, type TabsVariant, TagPill, type TagPillProps, type TagPillTone, Text, TextCode, TextEmphasis, TextLink, type TextLinkProps, TextList, type TextListDensity, TextListItem, type TextListItemProps, type TextListProps, type TextListVariant, type TextProps, TextSmall, TextStrong, TextTiny, Textarea, TextareaControl, type TextareaControlProps, type TextareaProps, TileGrid, type TileGridBreakpoint, type TileGridColumns, type TileGridProps, TitleHero, TitlePage, type ToastOptions, type ToastRecord, type ToastTone, Toaster, type ToasterPosition, type ToasterProps, Toggle, ToggleGroup, ToggleGroupItem, type ToggleGroupItemProps, type ToggleGroupProps, type ToggleGroupType, type ToggleProps, type ToggleSize, type ToggleVariant, Tooltip, type TooltipProps, TrailChip, type TrailChipProps, type TrendDirection, TrendLabel, type TrendLabelProps, type TrendLabelSize, type TrendLabelWeight, type UserAccountStatus, UserStatusPill, type UserStatusPillProps, WidgetFooter, type WidgetFooterProps, WidgetHeader, type WidgetHeaderEyebrowVariant, type WidgetHeaderProps, WidgetTitle, type WidgetTitleProps, type WidgetTitleSize, cn, getScoreTone, paginationRange, resolveChartColor, tabId, tabPanelId, useControlSize, useFieldContext, useFieldControl, useOverlayDismiss, useToast };