@minimalstuff/ui 3.2.0 → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Sonny
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/dist/index.d.ts CHANGED
@@ -8,6 +8,7 @@ import { ReactElement } from 'react';
8
8
  import { ReactNode } from 'react';
9
9
  import { ReactPortal } from 'react';
10
10
  import { Ref } from 'react';
11
+ import { RefObject } from 'react';
11
12
  import { StoreApi } from 'zustand';
12
13
  import { UseBoundStore } from 'zustand';
13
14
 
@@ -53,7 +54,6 @@ export declare type BadgeSize = ControlSize;
53
54
 
54
55
  export declare type BadgeVariant = 'solid' | 'outline' | 'subtle';
55
56
 
56
- /** Chrome shared by every text-entry control (Input, Textarea, Select, Combobox). */
57
57
  export declare const BASE_INPUT_STYLES = "w-full border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 placeholder-gray-500 dark:placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all duration-200 disabled:opacity-50 disabled:cursor-not-allowed";
58
58
 
59
59
  export declare function Button(buttonProps: Readonly<ButtonProps>): JSX.Element;
@@ -122,7 +122,7 @@ export declare interface CardProps {
122
122
  className?: string;
123
123
  }
124
124
 
125
- export declare function CharacterCount({ current, min, max, showMin, showMax, unstyled, className, }: Readonly<CharacterCountProps>): JSX.Element;
125
+ export declare function CharacterCount({ current, min, max, showMin, showMax, unstyled, id, className, }: Readonly<CharacterCountProps>): JSX.Element;
126
126
 
127
127
  export declare interface CharacterCountProps {
128
128
  current: number;
@@ -131,28 +131,64 @@ export declare interface CharacterCountProps {
131
131
  showMin?: boolean;
132
132
  showMax?: boolean;
133
133
  unstyled?: boolean;
134
+ id?: string;
134
135
  className?: string;
135
136
  }
136
137
 
137
- export declare function Checkbox({ label, description, error, radius, unstyled, className, wrapperClassName, checked, defaultChecked, onChange, id, ...props }: Readonly<CheckboxProps>): JSX.Element;
138
+ export declare function Checkbox({ label, indeterminate, description, error, radius, unstyled, fullWidth, variant, className, wrapperClassName, checked, defaultChecked, onChange, id, 'aria-describedby': callerDescribedBy, ref, ...props }: Readonly<CheckboxProps>): JSX.Element;
139
+
140
+ export declare type CheckboxOption = ChoiceOption;
141
+
142
+ export declare function CheckboxOptions({ options, orientation, values, defaultValues, onChange, name: nameProp, label, error, required, requiredLabel, disabled, radius, unstyled, className, wrapperClassName, id, 'aria-describedby': callerDescribedBy, ...props }: Readonly<CheckboxOptionsProps>): JSX.Element;
143
+
144
+ export declare interface CheckboxOptionsProps extends Omit<ComponentPropsWithRef<'fieldset'>, 'onChange'> {
145
+ options: string[] | CheckboxOption[];
146
+ orientation?: 'vertical' | 'horizontal';
147
+ values?: readonly string[];
148
+ defaultValues?: readonly string[];
149
+ onChange?: (values: readonly string[]) => void;
150
+ name?: string;
151
+ label?: string | React.ReactNode;
152
+ error?: string;
153
+ required?: boolean;
154
+ requiredLabel?: string;
155
+ radius?: Radius;
156
+ unstyled?: boolean;
157
+ className?: string;
158
+ wrapperClassName?: string;
159
+ id?: string;
160
+ }
138
161
 
139
162
  export declare interface CheckboxProps extends Omit<ComponentPropsWithRef<'input'>, 'type' | 'className'> {
140
163
  label?: string | React.ReactNode;
164
+ /** Shows a dash instead of the checkmark and exposes the mixed state to assistive technology. */
165
+ indeterminate?: boolean;
141
166
  description?: string | React.ReactNode;
142
167
  error?: string;
143
168
  radius?: Radius;
144
169
  unstyled?: boolean;
170
+ fullWidth?: boolean;
171
+ variant?: 'inline' | 'card';
145
172
  className?: string;
146
173
  wrapperClassName?: string;
147
174
  }
148
175
 
176
+ /** One choice in a `RadioOptions` or `CheckboxOptions` list. */
177
+ export declare interface ChoiceOption {
178
+ value: string;
179
+ label: string;
180
+ description?: string;
181
+ icon?: string;
182
+ disabled?: boolean;
183
+ }
184
+
149
185
  export declare function ClientOnly({ children, fallback }: Readonly<ClientOnlyProps>): string | number | bigint | boolean | JSX.Element | Iterable< ReactNode> | Promise<string | number | bigint | boolean | ReactPortal | ReactElement<unknown, string | JSXElementConstructor<any>> | Iterable< ReactNode> | null | undefined> | null;
150
186
 
151
187
  export declare interface ClientOnlyProps extends React.PropsWithChildren {
152
188
  fallback?: React.ReactNode;
153
189
  }
154
190
 
155
- export declare function Combobox({ options, label, error, placeholder, noResultsText, clearLabel, radius, unstyled, disabled, required, className, wrapperClassName, value, defaultValue, onChange, id, }: Readonly<ComboboxProps>): JSX.Element;
191
+ export declare function Combobox({ options, label, 'aria-label': ariaLabel, error, placeholder, noResultsText, clearLabel, radius, unstyled, disabled, required, className, wrapperClassName, value, defaultValue, onChange, id, }: Readonly<ComboboxProps>): JSX.Element;
156
192
 
157
193
  export declare interface ComboboxOption {
158
194
  value: string;
@@ -162,6 +198,7 @@ export declare interface ComboboxOption {
162
198
  export declare interface ComboboxProps {
163
199
  options: ComboboxOption[];
164
200
  label?: string | ReactNode;
201
+ 'aria-label'?: string;
165
202
  error?: string;
166
203
  placeholder?: string;
167
204
  noResultsText?: string;
@@ -202,10 +239,16 @@ export declare type ConfirmModalResponse = boolean;
202
239
  * `MenuSeparator`s — at the cursor position. Right-click again elsewhere on
203
240
  * the wrapped area to reposition it.
204
241
  *
242
+ * Keyboard-only users reach it via Shift+F10 or the Menu key instead of a
243
+ * right-click, but only once the wrapped area (or something inside it) can
244
+ * hold focus — give `children` a focusable element, or a `tabIndex={0}` plus
245
+ * a `role` and `aria-label` on the wrapper itself, or Shift+F10 has nothing
246
+ * to fire on. See `context_menu.stories.tsx`'s `Default` story.
247
+ *
205
248
  * For a menu anchored to a specific button (e.g. a kebab icon) instead of a
206
249
  * right-click, use `Menu`.
207
250
  */
208
- export declare function ContextMenu({ children, items, radius, className, ref, }: Readonly<ContextMenuProps>): JSX.Element;
251
+ export declare function ContextMenu({ children, items, radius, className, ref, 'aria-label': ariaLabel, }: Readonly<ContextMenuProps>): JSX.Element;
209
252
 
210
253
  export declare interface ContextMenuProps {
211
254
  /** The area that opens the menu on right-click. */
@@ -215,6 +258,8 @@ export declare interface ContextMenuProps {
215
258
  radius?: Radius;
216
259
  className?: string;
217
260
  ref?: Ref<HTMLDivElement>;
261
+ /** Names the menu for assistive tech, since there is no trigger element to label it from. */
262
+ 'aria-label'?: string;
218
263
  }
219
264
 
220
265
  /** The size scale every inline control shares (Button, IconButton, Badge, Kbd). */
@@ -256,6 +301,7 @@ export declare type IconButtonProps = ComponentPropsWithRef<'button'> & {
256
301
  'aria-label': string;
257
302
  size?: ControlSize;
258
303
  children?: ReactNode;
304
+ tooltip?: IconButtonTooltip;
259
305
  } & IconButtonStyle;
260
306
 
261
307
  declare type IconButtonStyle = {
@@ -267,10 +313,28 @@ declare type IconButtonStyle = {
267
313
  radius?: Radius;
268
314
  };
269
315
 
270
- export declare function Input({ label, error, showCharCount, minLength, maxLength, radius, unstyled, className, wrapperClassName, value, defaultValue, onChange, id, ...props }: Readonly<InputProps>): JSX.Element;
316
+ /**
317
+ * Wraps the button in a `Tooltip`. `true` shows the `aria-label` at the
318
+ * default position, a position string moves it, and an object also allows
319
+ * custom `content`. When the tooltip repeats the `aria-label` it does not
320
+ * describe the button, so screen readers do not announce the name twice.
321
+ */
322
+ export declare type IconButtonTooltip =
323
+ | boolean
324
+ | TooltipPosition
325
+ | IconButtonTooltipOptions;
326
+
327
+ declare interface IconButtonTooltipOptions {
328
+ position?: TooltipPosition;
329
+ /** Defaults to the button's `aria-label`. */
330
+ content?: ReactNode;
331
+ }
332
+
333
+ export declare function Input({ label, description, error, showCharCount, minLength, maxLength, radius, unstyled, className, wrapperClassName, value, defaultValue, onChange, id, 'aria-describedby': callerDescribedBy, ...props }: Readonly<InputProps>): JSX.Element;
271
334
 
272
335
  export declare interface InputProps extends ComponentPropsWithRef<'input'> {
273
336
  label?: string | ReactNode;
337
+ description?: string | ReactNode;
274
338
  error?: string;
275
339
  showCharCount?: boolean;
276
340
  minLength?: number;
@@ -295,20 +359,27 @@ export declare type KbdSize = ControlSize;
295
359
 
296
360
  /**
297
361
  * A dropdown anchored to `trigger` (e.g. a kebab `IconButton`): click to
298
- * open, click again/click outside/Escape to close. `children` is made of
299
- * `MenuItem`s, optionally wrapped in `MenuGroup`s and split by
300
- * `MenuSeparator`s.
362
+ * open, click again/click outside/Escape to close, or ArrowDown/ArrowUp on
363
+ * the closed trigger to open focused on the first/last item respectively.
364
+ * `children` is made of `MenuItem`s, optionally wrapped in `MenuGroup`s and
365
+ * split by `MenuSeparator`s.
301
366
  *
302
367
  * For "right-click anywhere on this area" instead of a specific trigger
303
368
  * button, use `ContextMenu`.
304
369
  *
305
- * Opening a `Modal` from a `MenuItem`'s `onClick` is safe: the menu returns
306
- * focus to `trigger` synchronously during the click, then the modal mounts a
307
- * render later and takes focus from there. That ordering is what makes the
308
- * modal record `trigger` as its restore target, so focus lands back on the
309
- * trigger when the modal closes. The menu panel outlives the click by one
310
- * exit animation, but the modal sits above it and owns Escape (a document
311
- * listener), so the fading panel is inert. See `menu_with_modal.test.tsx`.
370
+ * Safe to nest inside a `Modal`: Escape on the open menu calls
371
+ * `event.preventDefault()` before closing it (see `MenuSurface`), so the
372
+ * modal's own Escape handler — which ignores an already-`defaultPrevented`
373
+ * event — leaves the dialog open and only the menu closes.
374
+ *
375
+ * Opening a `Modal` from a `MenuItem`'s `onClick` is also safe: the menu
376
+ * returns focus to `trigger` synchronously during the click, then the modal
377
+ * mounts a render later and takes focus from there. That ordering is what
378
+ * makes the modal record `trigger` as its restore target, so focus lands
379
+ * back on the trigger when the modal closes. The menu panel outlives the
380
+ * click by one exit animation, but the modal sits above it and owns Escape
381
+ * (a document listener), so the fading panel is inert. See
382
+ * `menu_with_modal.test.tsx`.
312
383
  */
313
384
  export declare function Menu({ trigger, children, side, align, radius, className, ref, }: Readonly<MenuProps>): JSX.Element;
314
385
 
@@ -432,9 +503,10 @@ export declare const Modal: Callable<ModalProps, void, {}>;
432
503
  * Declares `children` as the modal's pinned footer, wherever this is
433
504
  * rendered in the content tree — including inside a separate content
434
505
  * component, any number of levels below `Modal`'s own `children`. Renders
435
- * nothing itself; `Modal` places the actual footer in its own layout.
506
+ * nothing in place; the children are portaled into the modal's own footer
507
+ * slot, so they stay React children of this component.
436
508
  */
437
- export declare function ModalFooter({ children }: Readonly<ModalFooterProps>): null;
509
+ export declare function ModalFooter({ children }: Readonly<ModalFooterProps>): ReactPortal | null;
438
510
 
439
511
  export declare interface ModalFooterProps {
440
512
  children: ReactNode;
@@ -448,23 +520,72 @@ export declare interface ModalProps {
448
520
  className?: string;
449
521
  dismissible?: boolean;
450
522
  closeLabel?: string;
523
+ /** `alertdialog` for urgent messages that need a response (describes the dialog by its content); pair with `dismissible={false}` when it must not be dismissed. */
524
+ role?: ModalRole;
525
+ /** Wins over the first-tabbable rule for where focus lands on open; may point at an element in the content or in a `ModalFooter`. */
526
+ initialFocusRef?: RefObject<HTMLElement | null>;
527
+ /** Names the dialog when there is no `title`; ignored when `title` is set since the title labels it. */
528
+ 'aria-label'?: string;
451
529
  }
452
530
 
453
531
  export declare function ModalProvider(): JSX.Element;
454
532
 
455
533
  declare type ModalRenderProp = ReactNode | ((close: () => void) => ReactNode);
456
534
 
535
+ export declare type ModalRole = 'dialog' | 'alertdialog';
536
+
457
537
  export declare type ModalSize = 'sm' | 'md' | 'lg' | 'xl';
458
538
 
459
- export declare interface RadioOption {
539
+ /**
540
+ * Multi-select combobox: a trigger button showing the selected options as
541
+ * pills opens a searchable dropdown of checkbox-style options. Selecting an
542
+ * option never closes the dropdown, unlike the single-select `Combobox`.
543
+ */
544
+ export declare function MultiCombobox({ options, label, 'aria-label': ariaLabel, error, placeholder, searchPlaceholder, noResultsText, clearLabel, clearText, maxSelectedValues, isOptionDisabled, maxDisplayedValues, formatOverflowCount, formatSelectedCount, formatMaxSelectedHint, radius, unstyled, disabled, required, className, wrapperClassName, values, defaultValues, onChange, onDropdownClose, id, }: Readonly<MultiComboboxProps>): ReactElement;
545
+
546
+ export declare interface MultiComboboxOption {
460
547
  value: string;
461
548
  label: string;
462
- description?: string;
463
- icon?: string;
549
+ }
550
+
551
+ export declare interface MultiComboboxProps {
552
+ options: readonly MultiComboboxOption[];
553
+ label?: string | ReactNode;
554
+ 'aria-label'?: string;
555
+ error?: string;
556
+ placeholder?: string;
557
+ searchPlaceholder?: string;
558
+ noResultsText?: string;
559
+ clearLabel?: string;
560
+ clearText?: string;
561
+ maxSelectedValues?: number;
562
+ isOptionDisabled?: (optionValue: string, selectedValues: readonly string[]) => boolean;
563
+ maxDisplayedValues?: number;
564
+ formatOverflowCount?: (hiddenCount: number) => string;
565
+ formatSelectedCount?: (selectedCount: number) => string;
566
+ formatMaxSelectedHint?: (maxSelectedValues: number) => string;
567
+ radius?: Radius;
568
+ unstyled?: boolean;
464
569
  disabled?: boolean;
570
+ required?: boolean;
571
+ className?: string;
572
+ wrapperClassName?: string;
573
+ values?: readonly string[];
574
+ defaultValues?: readonly string[];
575
+ onChange?: (values: readonly string[]) => void;
576
+ /**
577
+ * Fires with the final selection whenever the user is done editing:
578
+ * when the dropdown closes (Escape, outside click, focus leaving the
579
+ * wrapper), and when the selection is cleared from the trigger's X
580
+ * button while the dropdown is closed.
581
+ */
582
+ onDropdownClose?: (values: readonly string[]) => void;
583
+ id?: string;
465
584
  }
466
585
 
467
- export declare function RadioOptions({ options, orientation, value, defaultValue, onChange, name: nameProp, label, error, required, disabled, radius, unstyled, className, wrapperClassName, id, ...props }: Readonly<RadioOptionsProps>): JSX.Element;
586
+ export declare type RadioOption = ChoiceOption;
587
+
588
+ export declare function RadioOptions({ options, orientation, value, defaultValue, onChange, name: nameProp, label, error, required, disabled, radius, unstyled, className, wrapperClassName, id, 'aria-describedby': callerDescribedBy, ...props }: Readonly<RadioOptionsProps>): JSX.Element;
468
589
 
469
590
  export declare interface RadioOptionsProps extends Omit<ComponentPropsWithRef<'fieldset'>, 'onChange'> {
470
591
  options: string[] | RadioOption[];
@@ -485,7 +606,7 @@ export declare interface RadioOptionsProps extends Omit<ComponentPropsWithRef<'f
485
606
 
486
607
  declare type Radius = 'none' | 'sm' | 'md' | 'lg' | 'xl' | 'full';
487
608
 
488
- export declare function Select({ options, label, error, placeholder, radius, unstyled, className, wrapperClassName, value, defaultValue, onChange, id, ...props }: Readonly<SelectProps>): JSX.Element;
609
+ export declare function Select({ options, label, description, error, placeholder, radius, unstyled, className, wrapperClassName, value, defaultValue, onChange, id, 'aria-describedby': callerDescribedBy, ...props }: Readonly<SelectProps>): JSX.Element;
489
610
 
490
611
  export declare interface SelectOption {
491
612
  value: string;
@@ -495,6 +616,7 @@ export declare interface SelectOption {
495
616
  export declare interface SelectProps extends Omit<ComponentPropsWithRef<'select'>, 'children'> {
496
617
  options: SelectOption[];
497
618
  label?: string | ReactNode;
619
+ description?: string | ReactNode;
498
620
  error?: string;
499
621
  placeholder?: string;
500
622
  radius?: Radius;
@@ -543,13 +665,14 @@ export declare function splitIntoHighlightSegments(
543
665
  return segments;
544
666
  }
545
667
 
546
- export declare function Switch({ label, description, error, unstyled, className, wrapperClassName, checked, defaultChecked, onChange, id, ...props }: Readonly<SwitchProps>): JSX.Element;
668
+ export declare function Switch({ label, description, error, unstyled, fullWidth, className, wrapperClassName, checked, defaultChecked, onChange, id, 'aria-describedby': callerDescribedBy, ...props }: Readonly<SwitchProps>): JSX.Element;
547
669
 
548
670
  export declare interface SwitchProps extends Omit<ComponentPropsWithRef<'input'>, 'type' | 'className'> {
549
671
  label?: string | ReactNode;
550
672
  description?: string | ReactNode;
551
673
  error?: string;
552
674
  unstyled?: boolean;
675
+ fullWidth?: boolean;
553
676
  className?: string;
554
677
  wrapperClassName?: string;
555
678
  }
@@ -561,24 +684,35 @@ export declare interface TabItem {
561
684
  icon?: string;
562
685
  }
563
686
 
564
- export declare function Tabs({ items, value, defaultIndex, radius, unstyled, className, tabListClassName, panelClassName, onChange, }: Readonly<TabsProps>): JSX.Element;
687
+ export declare function Tabs({ items, value, defaultIndex, variant, size, radius, fullWidth, unstyled, animated, className, tabListClassName, panelClassName, onChange, }: Readonly<TabsProps>): JSX.Element;
565
688
 
566
689
  export declare interface TabsProps {
567
690
  items: TabItem[];
568
691
  value?: number;
569
692
  defaultIndex?: number;
693
+ variant?: TabsVariant;
694
+ size?: ControlSize;
695
+ /**
696
+ * Only visibly rounds the `segmented` variant's track and tabs. The `line`
697
+ * variant has no filled surface to round, so radius is a no-op there.
698
+ */
570
699
  radius?: Radius;
700
+ fullWidth?: boolean;
571
701
  unstyled?: boolean;
702
+ animated?: boolean;
572
703
  className?: string;
573
704
  tabListClassName?: string;
574
705
  panelClassName?: string;
575
706
  onChange?: (index: number) => void;
576
707
  }
577
708
 
578
- export declare function Textarea({ label, error, showCharCount, minLength, maxLength, radius, unstyled, className, wrapperClassName, value, defaultValue, onChange, id, ...props }: Readonly<TextareaProps>): JSX.Element;
709
+ export declare type TabsVariant = 'line' | 'segmented';
710
+
711
+ export declare function Textarea({ label, description, error, showCharCount, minLength, maxLength, radius, unstyled, className, wrapperClassName, value, defaultValue, onChange, id, 'aria-describedby': callerDescribedBy, ...props }: Readonly<TextareaProps>): JSX.Element;
579
712
 
580
713
  export declare interface TextareaProps extends ComponentPropsWithRef<'textarea'> {
581
714
  label?: string | ReactNode;
715
+ description?: string | ReactNode;
582
716
  error?: string;
583
717
  showCharCount?: boolean;
584
718
  minLength?: number;
@@ -591,26 +725,63 @@ export declare interface TextareaProps extends ComponentPropsWithRef<'textarea'>
591
725
 
592
726
  export declare type Theme = 'light' | 'dark' | 'system';
593
727
 
594
- declare type Theme_2 = 'light' | 'dark' | 'system';
595
-
596
728
  declare interface ThemeStore {
597
- theme: Theme_2;
598
- setTheme: (theme: Theme_2) => void;
729
+ theme: Theme;
730
+ setTheme: (theme: Theme) => void;
599
731
  }
600
732
 
601
- export declare function ThemeToggle({ isTransitionEnabled, transitionDuration, transitionEasing, size, radius, variant, getAriaLabel, }: Readonly<ThemeToggleProps>): JSX.Element;
733
+ export declare function ThemeToggle({ isTransitionEnabled, transitionDuration, transitionEasing, size, radius, variant, getAriaLabel, tooltip, }: Readonly<ThemeToggleProps>): JSX.Element;
602
734
 
603
735
  export declare interface ThemeToggleProps {
736
+ /**
737
+ * Animate the theme change with the View Transition API.
738
+ * Defaults to automatic: enabled, except on WebKitGTK where
739
+ * `startViewTransition` crashes the web process (2.54).
740
+ * `prefers-reduced-motion` is always respected.
741
+ */
604
742
  isTransitionEnabled?: boolean;
605
743
  transitionDuration?: number;
606
744
  transitionEasing?: string;
607
745
  size?: 'sm' | 'md' | 'lg';
608
746
  radius?: Radius;
609
747
  variant?: ButtonVariant;
610
- getAriaLabel?: (theme: Theme_2) => string;
748
+ getAriaLabel?: (theme: Theme) => string;
749
+ tooltip?: IconButtonTooltip;
611
750
  }
612
751
 
613
- export declare function Tooltip({ content, children, position, showOnClick, temporaryContent, temporaryDuration, disabled, radius, onTemporaryShow, className, ref, }: Readonly<TooltipProps>): JSX.Element;
752
+ /**
753
+ * A group of related controls with a single tab stop (WAI-ARIA toolbar).
754
+ * Tab enters the toolbar on the last focused item (the first enabled one
755
+ * initially); the arrow keys of the orientation (Left/Right horizontally,
756
+ * Up/Down vertically) move focus between items and wrap at the ends, Home and
757
+ * End jump to the first and last item, and disabled items are skipped. Arrow
758
+ * keys are left alone inside text fields. Requires `aria-label` or
759
+ * `aria-labelledby`.
760
+ */
761
+ export declare function Toolbar(toolbarProps: Readonly<ToolbarProps>): JSX.Element;
762
+
763
+ declare type ToolbarAccessibleName = {
764
+ 'aria-label': string;
765
+ 'aria-labelledby'?: undefined;
766
+ } | {
767
+ 'aria-labelledby': string;
768
+ 'aria-label'?: undefined;
769
+ };
770
+
771
+ declare type ToolbarOrientation = 'horizontal' | 'vertical';
772
+
773
+ export declare type ToolbarProps = Omit<ComponentPropsWithRef<'div'>, 'role' | 'aria-label' | 'aria-labelledby' | 'aria-orientation'> & {
774
+ orientation?: ToolbarOrientation;
775
+ unstyled?: boolean;
776
+ } & ToolbarAccessibleName;
777
+
778
+ /**
779
+ * The trigger (`children`) must be focusable, otherwise the tooltip is
780
+ * unreachable by keyboard. Shows on hover and focus; Escape dismisses it.
781
+ * `temporaryContent` is announced to screen readers through a polite status
782
+ * region.
783
+ */
784
+ export declare function Tooltip({ content, children, position, showOnClick, temporaryContent, temporaryDuration, disabled, radius, onTemporaryShow, className, describeChild, portalContainer, ref, }: Readonly<TooltipProps>): JSX.Element;
614
785
 
615
786
  export declare type TooltipPosition = 'top' | 'bottom' | 'left' | 'right';
616
787
 
@@ -625,10 +796,76 @@ export declare interface TooltipProps {
625
796
  radius?: Radius;
626
797
  onTemporaryShow?: () => void;
627
798
  className?: string;
799
+ /**
800
+ * Whether the trigger is described by the tooltip (`aria-describedby`).
801
+ * `true` always describes, `false` never does. By default the trigger is
802
+ * described unless the tooltip text repeats its accessible name, which
803
+ * screen readers would otherwise announce twice.
804
+ */
805
+ describeChild?: boolean;
806
+ /**
807
+ * Where the tooltip is rendered. Defaults to the trigger's closest
808
+ * landmark or dialog (so it stays inside a landmark and inside an open
809
+ * modal), falling back to `document.body`. Transformed ancestors (such as the modal
810
+ * panel) can clip it; pass `portalContainer` to escape.
811
+ */
812
+ portalContainer?: HTMLElement | null;
628
813
  /** Attaches to the wrapper `<span>` around `children`, alongside `Tooltip`'s own internal ref. */
629
814
  ref?: Ref<HTMLSpanElement>;
630
815
  }
631
816
 
817
+ export declare interface UILabels {
818
+ /** Accessible name of the modal close button. */
819
+ close: string;
820
+ /** Confirm button of `ConfirmModal`. */
821
+ confirm: string;
822
+ /** Cancel button of `ConfirmModal`. */
823
+ cancel: string;
824
+ /** Empty state of `Combobox` and `MultiCombobox`. */
825
+ noResults: string;
826
+ /** Accessible name of the button clearing a selection. */
827
+ clearSelection: string;
828
+ /** Placeholder and accessible name of the `MultiCombobox` search field. */
829
+ search: string;
830
+ /** Visible text of the `MultiCombobox` clear button. */
831
+ clear: string;
832
+ /** Screen-reader suffix of a required `CheckboxOptions` group. */
833
+ required: string;
834
+ /** Accessible name of `ThemeToggle` for the current theme. */
835
+ currentTheme: (theme: Theme) => string;
836
+ /** `MultiCombobox` badge summarising the values that do not fit. */
837
+ overflowCount: (hiddenCount: number) => string;
838
+ /** `MultiCombobox` summary of the number of selected values. */
839
+ selectedCount: (selectedCount: number) => string;
840
+ /** `MultiCombobox` hint shown when the selection limit is reached. */
841
+ maxSelectedHint: (maxSelectedValues: number) => string;
842
+ }
843
+
844
+ /**
845
+ * Provides default user-facing labels (close, confirm, no results...) to every
846
+ * component below it. Precedence: explicit prop > provider > English default.
847
+ *
848
+ * `Modal` and `ConfirmModal` render where `<ModalProvider />` is mounted, so
849
+ * mount `ModalProvider` inside `UIProvider` for them to receive the labels.
850
+ */
851
+ export declare function UIProvider({ labels, announceFieldErrors, children, }: Readonly<UIProviderProps>): JSX.Element;
852
+
853
+ export declare interface UIProviderProps {
854
+ /** Overrides the default labels. Nested providers merge over their parent. */
855
+ labels?: Partial<UILabels>;
856
+ /**
857
+ * Whether field errors are announced as they appear (`role="alert"`).
858
+ * Defaults to `true`; nested providers inherit the parent value unless set.
859
+ * Set it to `false` when the app announces errors itself (an error summary
860
+ * or focus on the first invalid field): it avoids several alerts firing at
861
+ * once on submit, and lets WebKitGTK re-read the error on focus, since it
862
+ * leaves `role="alert"` content out of the computed description. The error
863
+ * stays linked by `aria-describedby` either way.
864
+ */
865
+ announceFieldErrors?: boolean;
866
+ children: ReactNode;
867
+ }
868
+
632
869
  export declare function useDisableHotkeysWhileMounted(): void;
633
870
 
634
871
  export declare const useGlobalHotkeysStore: UseBoundStore<StoreApi<GlobalHotkeysStore>>;
@@ -641,3 +878,10 @@ export declare const useThemeStore: UseBoundStore<StoreApi<ThemeStore>>;
641
878
  export declare const withClientOnly: <TProps extends object>(Component: React.ComponentType<TProps>) => React.ComponentType<TProps>;
642
879
 
643
880
  export { }
881
+
882
+
883
+
884
+ declare module 'vitest' {
885
+ interface Assertion<T = unknown> extends AxeMatchers {}
886
+ interface AsymmetricMatchersContaining extends AxeMatchers {}
887
+ }