@minimalstuff/ui 4.3.2 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,74 +1,78 @@
1
1
  # @minimalstuff/ui
2
2
 
3
- React UI component library.
3
+ A small, unambitious React component library, styled with UnoCSS and focused on accessibility.
4
4
 
5
- ## Installation
5
+ Browse every component in the [Storybook](https://minimalstuff.github.io/ui/) (latest release), or the [`next` Storybook](https://minimalstuff.github.io/ui/next/) built from `main`.
6
+
7
+ ## Install
6
8
 
7
9
  ```bash
8
10
  pnpm add @minimalstuff/ui react react-dom
9
11
  ```
10
12
 
11
- Peer dependencies: React 19.
13
+ Requires React 19.
12
14
 
13
- ## Usage
15
+ ## Use the components
14
16
 
15
17
  ```tsx
16
18
  import { Button } from '@minimalstuff/ui';
17
19
  import '@minimalstuff/ui/style.css';
18
20
 
19
21
  export function App() {
20
- return <Button variant="primary">Click me</Button>;
22
+ return <Button color="primary">Click me</Button>;
23
+ }
24
+ ```
25
+
26
+ The `@minimalstuff/ui/style.css` import is required for styles and icons to render. It can load before your app's own utilities (UnoCSS or Tailwind): component sizing does not depend on load order.
27
+
28
+ ### Mount the providers
29
+
30
+ `Modal` and `ConfirmModal` are opened with `Modal.call(...)` and `ConfirmModal.call(...)`, and render where `<ModalProvider />` is mounted. `UIProvider` overrides the default English labels (close, confirm, no results…) for every component below it; mount `ModalProvider` inside it so modals receive the labels too.
31
+
32
+ ```tsx
33
+ import { ModalProvider, UIProvider } from '@minimalstuff/ui';
34
+
35
+ export function Root() {
36
+ return (
37
+ <UIProvider labels={{ close: 'Fermer' }}>
38
+ <App />
39
+ <ModalProvider />
40
+ </UIProvider>
41
+ );
21
42
  }
22
43
  ```
23
44
 
24
- The `@minimalstuff/ui/style.css` import is required for styles and icons to render.
45
+ ### Dark mode
25
46
 
26
- The stylesheet can be loaded before your app's own utilities (UnoCSS or Tailwind): component sizing does not depend on load order.
47
+ Dark styles apply when `<html>` has the `dark` class. `useThemeStore` (and the `ThemeToggle` built on it) sets that class from the `light`, `dark` or `system` preference and keeps it in `localStorage`.
27
48
 
28
49
  ### Modals and drawers lock page scroll
29
50
 
30
51
  While a `Modal` or `Drawer` is open, page scroll is locked on `<html>`. The scrollbar width this frees is compensated with right padding on `<html>`, so the page does not shift. That padding does not move `position: fixed` elements: anchor right-aligned ones with `right: var(--scrollbar-compensation, 0px)`. Paint the page background on `<html>` or `<body>` rather than only on a wrapper element, or the padding shows the root's background as a strip on the right.
31
52
 
32
- ## Development
53
+ ## Develop
33
54
 
34
55
  ```bash
35
56
  pnpm install
36
- pnpm run dev # Storybook on :6006
37
- pnpm run lint
38
- pnpm run test
39
- pnpm run build # Library build → dist/
57
+ pnpm dev
40
58
  ```
41
59
 
42
- ## Releasing
43
-
44
- CI (lint, test, build) and npm publish run together when a GitHub Release is published.
45
-
46
- ### Prerequisites
47
-
48
- Publishing uses npm [trusted publishing](https://docs.npmjs.com/trusted-publishers) (OIDC), no token needed. On npmjs.com, `@minimalstuff/ui` > **Settings > Trusted publishing** must list GitHub Actions with organization `minimalstuff`, repository `ui` and workflow `publish.yml`.
60
+ `pnpm dev` starts Storybook on port 6006.
49
61
 
50
- ### Procedure
62
+ Before pushing, run what CI runs (see [`ci.yml`](.github/workflows/ci.yml)):
51
63
 
52
- 1. **Bump version** (optional if using tag-based versioning):
53
-
54
- ```bash
55
- pnpm version 1.2.0 # or 1.2.0-alpha.0 for prerelease
56
- git push && git push --tags
57
- ```
64
+ ```bash
65
+ pnpm verify
66
+ ```
58
67
 
59
- 2. **Create a GitHub Release**
60
- **Releases → Draft a new release**:
61
- - Choose or create a tag (e.g. `v1.2.0`). Use the same version as in `package.json` if you bumped it; otherwise the workflow sets the package version from the tag (e.g. `v1.2.0` → `1.2.0`).
62
- - Add release notes and publish.
68
+ `pnpm test:stories` runs the stories in a real browser and needs Playwright's Chromium once: `pnpm exec playwright install chromium`.
63
69
 
64
- 3. **Workflow**
65
- The **CI & Publish** workflow runs on **release published**. It sets the package version from the tag, runs lint, test, build, then `pnpm publish --no-git-checks`. The package is published under the tag `latest` (or the tag you set for prereleases).
70
+ Releases follow [docs/releasing.md](docs/releasing.md). Changes are listed in the [CHANGELOG](CHANGELOG.md).
66
71
 
67
- ### Prereleases
72
+ ## Report a bug
68
73
 
69
- Semver prereleases (e.g. `1.0.0-0`, `1.0.0-alpha.1`) are supported. To avoid making them the default install:
74
+ Open an issue on [GitHub Issues](https://github.com/minimalstuff/ui/issues).
70
75
 
71
- - Publish with a dist-tag, e.g. `pnpm publish --tag next`, or
72
- - Rely on consumers installing an explicit version: `pnpm add @minimalstuff/ui@1.0.0-alpha.1`.
76
+ ## License
73
77
 
74
- If you want CI to publish prereleases automatically (e.g. on tag `v1.0.0-alpha.1`), add a separate workflow or extend the existing one to run on prerelease tags and use `--tag next`.
78
+ [MIT](LICENSE)
package/dist/index.d.ts CHANGED
@@ -4,6 +4,7 @@ import type { HTMLAttributeAnchorTarget } from 'react';
4
4
  import { JSX } from 'react';
5
5
  import { JSXElementConstructor } from 'react';
6
6
  import type { MouseEvent as MouseEvent_2 } from 'react';
7
+ import { MouseEventHandler } from 'react';
7
8
  import { ReactElement } from 'react';
8
9
  import { ReactNode } from 'react';
9
10
  import { ReactPortal } from 'react';
@@ -40,7 +41,7 @@ export declare interface AvatarProps {
40
41
 
41
42
  export declare type AvatarSize = ControlSize;
42
43
 
43
- export declare const Badge: ({ children, color, variant, size, radius, className, ...props }: Readonly<BadgeProps>) => JSX.Element;
44
+ export declare const Badge: ({ children, color, variant, size, radius, unstyled, className, ...props }: Readonly<BadgeProps>) => JSX.Element;
44
45
 
45
46
  export declare interface BadgeProps extends ComponentPropsWithRef<'span'> {
46
47
  children: ReactNode;
@@ -48,13 +49,18 @@ export declare interface BadgeProps extends ComponentPropsWithRef<'span'> {
48
49
  variant?: BadgeVariant;
49
50
  size?: BadgeSize;
50
51
  radius?: Radius;
52
+ /**
53
+ * Strips the library's styling and keeps only `inline-flex items-center`.
54
+ * `color`, `variant`, `size` and `radius` then have no effect.
55
+ */
56
+ unstyled?: boolean;
51
57
  }
52
58
 
53
59
  export declare type BadgeSize = ControlSize;
54
60
 
55
61
  export declare type BadgeVariant = 'solid' | 'outline' | 'subtle';
56
62
 
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";
63
+ 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-hidden focus:ring-2 focus:ring-blue-500 focus:border-transparent transition-all duration-200 disabled:opacity-50 disabled:cursor-not-allowed";
58
64
 
59
65
  export declare function Button(buttonProps: Readonly<ButtonProps>): JSX.Element;
60
66
 
@@ -140,7 +146,7 @@ export declare interface CharacterCountProps {
140
146
  className?: string;
141
147
  }
142
148
 
143
- 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;
149
+ export declare function Checkbox({ label, indeterminate, description, error, radius, unstyled, fullWidth, variant, className, wrapperClassName, checked, defaultChecked, onChange, id, 'aria-describedby': callerDescribedBy, 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledBy, ref, ...props }: Readonly<CheckboxProps>): JSX.Element;
144
150
 
145
151
  export declare type CheckboxOption = ChoiceOption;
146
152
 
@@ -193,7 +199,7 @@ export declare interface ClientOnlyProps extends React.PropsWithChildren {
193
199
  fallback?: React.ReactNode;
194
200
  }
195
201
 
196
- 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;
202
+ export declare function Combobox({ options, label, description, 'aria-label': ariaLabel, error, placeholder, noResultsText, clearLabel, radius, unstyled, disabled, required, className, wrapperClassName, value, defaultValue, onChange, id, }: Readonly<ComboboxProps>): JSX.Element;
197
203
 
198
204
  export declare interface ComboboxOption {
199
205
  value: string;
@@ -203,6 +209,7 @@ export declare interface ComboboxOption {
203
209
  export declare interface ComboboxProps {
204
210
  options: ComboboxOption[];
205
211
  label?: string | ReactNode;
212
+ description?: string | ReactNode;
206
213
  'aria-label'?: string;
207
214
  error?: string;
208
215
  placeholder?: string;
@@ -253,7 +260,7 @@ export declare type ConfirmModalResponse = boolean;
253
260
  * For a menu anchored to a specific button (e.g. a kebab icon) instead of a
254
261
  * right-click, use `Menu`.
255
262
  */
256
- export declare function ContextMenu({ children, items, radius, className, ref, 'aria-label': ariaLabel, }: Readonly<ContextMenuProps>): JSX.Element;
263
+ export declare function ContextMenu({ children, items, radius, unstyled, panelClassName, className, ref, 'aria-label': ariaLabel, }: Readonly<ContextMenuProps>): JSX.Element;
257
264
 
258
265
  export declare interface ContextMenuProps {
259
266
  /** The area that opens the menu on right-click. */
@@ -262,6 +269,18 @@ export declare interface ContextMenuProps {
262
269
  items: ReactNode;
263
270
  radius?: Radius;
264
271
  className?: string;
272
+ /**
273
+ * Strips the panel's visual styling (border, background, shadow, blur,
274
+ * padding, radius, width bounds and the open/close animation). Positioning,
275
+ * the backdrop and the keyboard handling stay. `radius` is ignored.
276
+ */
277
+ unstyled?: boolean;
278
+ /**
279
+ * Styles the floating panel (`role="menu"`), with or without `unstyled`.
280
+ * Its position comes from inline floating styles: don't set
281
+ * `position`, `top` or `left` on it.
282
+ */
283
+ panelClassName?: string;
265
284
  ref?: Ref<HTMLDivElement>;
266
285
  /** Names the menu for assistive tech, since there is no trigger element to label it from. */
267
286
  'aria-label'?: string;
@@ -306,6 +325,12 @@ export declare interface DrawerProps {
306
325
  radius?: Radius;
307
326
  /** Applied to the scrollable body. */
308
327
  className?: string;
328
+ /** Applied to the `role=dialog` element. A `transform`, `filter` or `backdrop-filter` on the open panel makes it the containing block of `position: fixed` descendants, so Menus opened inside it get clipped. Keep these off the open state. Carries `data-state="open"` or `"closed"`, so `data-[state=closed]:` variants can animate it. Put your own transitions behind `motion-reduce:` variants, since `unstyled` drops the library's reduced-motion handling along with its animations. */
329
+ panelClassName?: string;
330
+ /** Applied to the backdrop element, which carries the click-to-dismiss. */
331
+ backdropClassName?: string;
332
+ /** Strips the library's visual styling (background, shadow, radius, slide transition, backdrop tint, header and body typography and padding), keeping layout, `side`, `size`, scrolling and behaviour. `radius` is ignored. The close button keeps a 24px minimum target size. */
333
+ unstyled?: boolean;
309
334
  /** `false` hides the close button and blocks Escape and backdrop dismissal. */
310
335
  dismissible?: boolean;
311
336
  closeLabel?: string;
@@ -322,12 +347,27 @@ declare interface GlobalHotkeysStore {
322
347
  setGlobalHotkeysEnabled: (value: boolean) => void;
323
348
  }
324
349
 
325
- declare function Highlight_2({ text, ranges }: Readonly<HighlightProps>): JSX.Element;
350
+ declare function Highlight_2({ text, ranges, radius, unstyled, markClassName, }: Readonly<HighlightProps>): JSX.Element;
326
351
  export { Highlight_2 as Highlight }
327
352
 
328
353
  export declare interface HighlightProps {
329
354
  text: string;
330
355
  ranges: readonly number[];
356
+ /**
357
+ * Corner radius of each `<mark>`. The default (`sm`) renders the same
358
+ * `border-radius` as the previous hard-coded `rounded`. Ignored when
359
+ * `unstyled` is set.
360
+ */
361
+ radius?: Radius;
362
+ /**
363
+ * Removes the library's classes from each `<mark>` (radius, background and
364
+ * text colours). `radius` then has no effect. Matches then rely on
365
+ * `markClassName` (or the browser's default `<mark>` style) to stay visible,
366
+ * so a consumer who resets `mark` styles must style `markClassName`.
367
+ */
368
+ unstyled?: boolean;
369
+ /** Applied to every `<mark>`, whether or not `unstyled` is set. */
370
+ markClassName?: string;
331
371
  }
332
372
 
333
373
  export declare interface HighlightSegment {
@@ -371,7 +411,7 @@ declare interface IconButtonTooltipOptions {
371
411
  content?: ReactNode;
372
412
  }
373
413
 
374
- 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;
414
+ export declare function Input({ label, description, error, showCharCount, minLength, maxLength, radius, unstyled, className, wrapperClassName, value, defaultValue, onChange, id, 'aria-describedby': callerDescribedBy, 'aria-label': ariaLabel, ...props }: Readonly<InputProps>): JSX.Element;
375
415
 
376
416
  export declare interface InputProps extends ComponentPropsWithRef<'input'> {
377
417
  label?: string | ReactNode;
@@ -422,7 +462,7 @@ export declare type KbdSize = ControlSize;
422
462
  * (a document listener), so the fading panel is inert. See
423
463
  * `menu_with_modal.test.tsx`.
424
464
  */
425
- export declare function Menu({ trigger, children, side, align, radius, className, ref, }: Readonly<MenuProps>): JSX.Element;
465
+ export declare function Menu({ trigger, children, side, align, radius, unstyled, panelClassName, className, disabled, ref, }: Readonly<MenuProps>): JSX.Element;
426
466
 
427
467
  export declare type MenuAlign = 'start' | 'center' | 'end';
428
468
 
@@ -485,6 +525,20 @@ declare type MenuItemBaseProps = {
485
525
  danger?: boolean;
486
526
  disabled?: boolean;
487
527
  children: ReactNode;
528
+ /**
529
+ * Rounds the row, which shows on its hover and focus background. Unset by
530
+ * default (square corners). Ignored when `unstyled`.
531
+ */
532
+ radius?: Radius;
533
+ /**
534
+ * Strips the row's visual styling (padding, text colour and size, hover and
535
+ * focus backgrounds, icon and trailing colours) and keeps its layout, the
536
+ * disabled behaviour. The library's focus outline is removed, so the browser's
537
+ * native focus indicator applies. Don't add `outline-none` through `className`
538
+ * without your own `focus-visible:` indicator (WCAG 2.4.7). Style the row
539
+ * through `className`.
540
+ */
541
+ unstyled?: boolean;
488
542
  className?: string;
489
543
  };
490
544
 
@@ -520,6 +574,24 @@ export declare interface MenuProps {
520
574
  align?: MenuAlign;
521
575
  radius?: Radius;
522
576
  className?: string;
577
+ /**
578
+ * Strips the panel's visual styling (border, background, shadow, blur,
579
+ * padding, radius, width bounds and the open/close animation). Positioning,
580
+ * the backdrop and the keyboard handling stay. `radius` is ignored.
581
+ */
582
+ unstyled?: boolean;
583
+ /**
584
+ * Styles the floating panel (`role="menu"`), with or without `unstyled`.
585
+ * Its position comes from inline floating styles: don't set
586
+ * `position`, `top` or `left` on it.
587
+ */
588
+ panelClassName?: string;
589
+ /**
590
+ * Keeps the menu closed (and closes it if open): the trigger's click and
591
+ * ArrowDown/ArrowUp no longer open it. The trigger itself is left alone, so
592
+ * it can stay focusable; mark it `aria-disabled` or `disabled` yourself.
593
+ */
594
+ disabled?: boolean;
523
595
  /** Attaches to the wrapper `<span>` around `trigger`, alongside `Menu`'s own internal ref. */
524
596
  ref?: Ref<HTMLSpanElement>;
525
597
  }
@@ -540,6 +612,15 @@ export declare type MenuSide = 'top' | 'bottom' | 'left' | 'right';
540
612
 
541
613
  export declare const Modal: Callable<ModalProps, void, {}>;
542
614
 
615
+ declare type ModalAccessibleName = {
616
+ title: NonNullable<ReactNode>;
617
+ 'aria-label'?: undefined;
618
+ } | {
619
+ title?: undefined;
620
+ /** Names the dialog when there is no `title`; ignored when `title` is set since the title labels it. */
621
+ 'aria-label': string;
622
+ };
623
+
543
624
  /**
544
625
  * Declares `children` as the modal's pinned footer, wherever this is
545
626
  * rendered in the content tree — including inside a separate content
@@ -555,23 +636,26 @@ export declare interface ModalFooterProps {
555
636
 
556
637
  export declare type ModalHeight = 'auto' | 'fixed';
557
638
 
558
- export declare interface ModalProps {
559
- title?: ReactNode;
639
+ export declare type ModalProps = {
560
640
  children: ModalRenderProp;
561
641
  size?: ModalSize;
562
642
  /** `fixed` gives the dialog a stable height so it does not jump when content changes; the content area stops scrolling and a child with `flex-1 min-h-0 overflow-y-auto` scrolls on its own. */
563
643
  height?: ModalHeight;
564
644
  radius?: Radius;
565
645
  className?: string;
646
+ /** Applied to the `role=dialog` element. A `transform`, `filter` or `backdrop-filter` on the open panel makes it the containing block of `position: fixed` descendants, so Menus opened inside it get clipped. Keep these off the open state. Carries `data-state="open"` or `"closed"`, so `data-[state=closed]:` variants can animate it. Put your own transitions behind `motion-reduce:` variants, since `unstyled` drops the library's reduced-motion handling along with its animations. */
647
+ panelClassName?: string;
648
+ /** Applied to the backdrop element, which carries the click-to-dismiss. */
649
+ backdropClassName?: string;
650
+ /** Strips the library's visual styling (background, shadow, radius, transitions, backdrop tint, header and content typography and padding), keeping layout, sizing, scrolling and behaviour. `radius` is ignored. The close button keeps a 24px minimum target size. */
651
+ unstyled?: boolean;
566
652
  dismissible?: boolean;
567
653
  closeLabel?: string;
568
654
  /** `alertdialog` for urgent messages that need a response (describes the dialog by its content); pair with `dismissible={false}` when it must not be dismissed. */
569
655
  role?: ModalRole;
570
656
  /** Wins over the first-tabbable rule for where focus lands on open; may point at an element in the content or in a `ModalFooter`. */
571
657
  initialFocusRef?: RefObject<HTMLElement | null>;
572
- /** Names the dialog when there is no `title`; ignored when `title` is set since the title labels it. */
573
- 'aria-label'?: string;
574
- }
658
+ } & ModalAccessibleName;
575
659
 
576
660
  export declare function ModalProvider(): JSX.Element;
577
661
 
@@ -586,7 +670,7 @@ export declare type ModalSize = 'sm' | 'md' | 'lg' | 'xl';
586
670
  * pills opens a searchable dropdown of checkbox-style options. Selecting an
587
671
  * option never closes the dropdown, unlike the single-select `Combobox`.
588
672
  */
589
- 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;
673
+ export declare function MultiCombobox({ options, label, description, '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;
590
674
 
591
675
  export declare interface MultiComboboxOption {
592
676
  value: string;
@@ -596,6 +680,7 @@ export declare interface MultiComboboxOption {
596
680
  export declare interface MultiComboboxProps {
597
681
  options: readonly MultiComboboxOption[];
598
682
  label?: string | ReactNode;
683
+ description?: string | ReactNode;
599
684
  'aria-label'?: string;
600
685
  error?: string;
601
686
  placeholder?: string;
@@ -651,7 +736,7 @@ export declare interface RadioOptionsProps extends Omit<ComponentPropsWithRef<'f
651
736
 
652
737
  declare type Radius = 'none' | 'sm' | 'md' | 'lg' | 'xl' | 'full';
653
738
 
654
- 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;
739
+ export declare function Select({ options, label, description, error, placeholder, radius, unstyled, className, wrapperClassName, value, defaultValue, onChange, id, 'aria-describedby': callerDescribedBy, 'aria-label': ariaLabel, ...props }: Readonly<SelectProps>): JSX.Element;
655
740
 
656
741
  export declare interface SelectOption {
657
742
  value: string;
@@ -670,6 +755,49 @@ export declare interface SelectProps extends Omit<ComponentPropsWithRef<'select'
670
755
  wrapperClassName?: string;
671
756
  }
672
757
 
758
+ /**
759
+ * A primary action joined to a chevron `Menu` trigger that offers secondary
760
+ * variants of that action. Both halves share variant, color, size and radius:
761
+ * the inner corners are square. The menu cannot open while `disabled` or
762
+ * `loading`; while loading, the trigger stays focusable as `aria-disabled`.
763
+ */
764
+ export declare function SplitButton(splitButtonProps: Readonly<SplitButtonProps>): JSX.Element;
765
+
766
+ export declare type SplitButtonProps = {
767
+ /** Label of the main button. */
768
+ children: ReactNode;
769
+ onClick?: MouseEventHandler<HTMLButtonElement>;
770
+ /** `MenuItem`s, `MenuGroup`s and `MenuSeparator`s offered by the chevron trigger. */
771
+ menu: ReactNode;
772
+ /** Accessible name of the chevron trigger, also shown as its tooltip. */
773
+ menuLabel: string;
774
+ menuIcon?: string;
775
+ menuAlign?: MenuAlign;
776
+ startIcon?: string;
777
+ size?: ControlSize;
778
+ /** Shows the main button's loading state and keeps the menu closed. */
779
+ loading?: boolean;
780
+ /** Disables both halves. */
781
+ disabled?: boolean;
782
+ /** Accessible name of the group formed by both halves. */
783
+ 'aria-label'?: string;
784
+ /** Id of the element that names the group. Takes precedence over `aria-label`. */
785
+ 'aria-labelledby'?: string;
786
+ /** Class on the wrapper around both halves. */
787
+ className?: string;
788
+ /** Ref to the main button. */
789
+ ref?: Ref<HTMLButtonElement>;
790
+ } & SplitButtonStyle;
791
+
792
+ declare type SplitButtonStyle = {
793
+ unstyled: true;
794
+ } | {
795
+ unstyled?: false;
796
+ variant?: ButtonVariant;
797
+ color?: ButtonColor;
798
+ radius?: Radius;
799
+ };
800
+
673
801
  /**
674
802
  * Splits `text` into consecutive segments, flagging the ones covered by
675
803
  * `ranges` (flat `[start0, end0, start1, end1, ...]` pairs, ascending and
@@ -710,7 +838,7 @@ export declare function splitIntoHighlightSegments(
710
838
  return segments;
711
839
  }
712
840
 
713
- export declare function Switch({ label, description, error, unstyled, fullWidth, className, wrapperClassName, checked, defaultChecked, onChange, id, 'aria-describedby': callerDescribedBy, ...props }: Readonly<SwitchProps>): JSX.Element;
841
+ export declare function Switch({ label, description, error, unstyled, fullWidth, className, wrapperClassName, checked, defaultChecked, onChange, id, 'aria-describedby': callerDescribedBy, 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledBy, ...props }: Readonly<SwitchProps>): JSX.Element;
714
842
 
715
843
  export declare interface SwitchProps extends Omit<ComponentPropsWithRef<'input'>, 'type' | 'className'> {
716
844
  label?: string | ReactNode;
@@ -736,7 +864,7 @@ export declare interface TabItem {
736
864
  badge?: ReactNode;
737
865
  }
738
866
 
739
- export declare function Tabs({ items, value, defaultIndex, variant, orientation, size, radius, fullWidth, unstyled, animated, keepMounted, className, tabListClassName, panelClassName, onChange, }: Readonly<TabsProps>): JSX.Element;
867
+ export declare function Tabs({ items, value, defaultIndex, variant, orientation, size, radius, fullWidth, unstyled, animated, keepMounted, 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledby, className, tabListClassName, panelClassName, onChange, }: Readonly<TabsProps>): JSX.Element;
740
868
 
741
869
  export declare type TabsOrientation = 'horizontal' | 'vertical';
742
870
 
@@ -773,6 +901,10 @@ export declare interface TabsProps {
773
901
  * `false`.
774
902
  */
775
903
  keepMounted?: boolean;
904
+ /** Accessible name of the tablist. Distinguishes several tab sets on one page. */
905
+ 'aria-label'?: string;
906
+ /** Id of the element that names the tablist. Takes precedence over `aria-label`. */
907
+ 'aria-labelledby'?: string;
776
908
  className?: string;
777
909
  tabListClassName?: string;
778
910
  panelClassName?: string;
@@ -781,7 +913,7 @@ export declare interface TabsProps {
781
913
 
782
914
  export declare type TabsVariant = 'line' | 'segmented';
783
915
 
784
- 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;
916
+ export declare function Textarea({ label, description, error, showCharCount, minLength, maxLength, radius, unstyled, className, wrapperClassName, value, defaultValue, onChange, id, 'aria-describedby': callerDescribedBy, 'aria-label': ariaLabel, ...props }: Readonly<TextareaProps>): JSX.Element;
785
917
 
786
918
  export declare interface TextareaProps extends ComponentPropsWithRef<'textarea'> {
787
919
  label?: string | ReactNode;
@@ -803,7 +935,7 @@ declare interface ThemeStore {
803
935
  setTheme: (theme: Theme) => void;
804
936
  }
805
937
 
806
- export declare function ThemeToggle({ isTransitionEnabled, transitionDuration, transitionEasing, size, radius, variant, getAriaLabel, tooltip, }: Readonly<ThemeToggleProps>): JSX.Element;
938
+ export declare function ThemeToggle({ isTransitionEnabled, transitionDuration, transitionEasing, size, unstyled, radius, variant, getAriaLabel, tooltip, }: Readonly<ThemeToggleProps>): JSX.Element;
807
939
 
808
940
  export declare interface ThemeToggleProps {
809
941
  /**
@@ -818,6 +950,11 @@ export declare interface ThemeToggleProps {
818
950
  size?: 'sm' | 'md' | 'lg';
819
951
  radius?: Radius;
820
952
  variant?: ButtonVariant;
953
+ /**
954
+ * Strips the library's styling, including the icon colours. `variant` and
955
+ * `radius` are ignored when it is set. The view transition still runs.
956
+ */
957
+ unstyled?: boolean;
821
958
  getAriaLabel?: (theme: Theme) => string;
822
959
  tooltip?: IconButtonTooltip;
823
960
  }
@@ -855,7 +992,7 @@ export declare type ToolbarProps = Omit<ComponentPropsWithRef<'div'>, 'role' | '
855
992
  * `temporaryContent` is announced to screen readers through a polite status
856
993
  * region.
857
994
  */
858
- export declare function Tooltip({ content, children, position, showOnClick, temporaryContent, temporaryDuration, disabled, radius, onTemporaryShow, className, describeChild, portalContainer, ref, }: Readonly<TooltipProps>): JSX.Element;
995
+ export declare function Tooltip({ content, children, position, showOnClick, temporaryContent, temporaryDuration, disabled, radius, unstyled, panelClassName, onTemporaryShow, className, describeChild, hoverable, portalContainer, ref, }: Readonly<TooltipProps>): JSX.Element;
859
996
 
860
997
  export declare type TooltipPosition = 'top' | 'bottom' | 'left' | 'right';
861
998
 
@@ -868,6 +1005,15 @@ export declare interface TooltipProps {
868
1005
  temporaryDuration?: number;
869
1006
  disabled?: boolean;
870
1007
  radius?: Radius;
1008
+ /**
1009
+ * Strips the bubble's visual styling (background, text colour and size,
1010
+ * padding, radius, shadow, enter animation) and removes the arrow.
1011
+ * Positioning, `data-state` and the hover handling stay. `radius` is
1012
+ * ignored.
1013
+ */
1014
+ unstyled?: boolean;
1015
+ /** Styles the bubble (`role="tooltip"`), with or without `unstyled`. */
1016
+ panelClassName?: string;
871
1017
  onTemporaryShow?: () => void;
872
1018
  className?: string;
873
1019
  /**
@@ -877,6 +1023,13 @@ export declare interface TooltipProps {
877
1023
  * screen readers would otherwise announce twice.
878
1024
  */
879
1025
  describeChild?: boolean;
1026
+ /**
1027
+ * Keeps the tooltip open while the pointer moves onto it, so people who zoom
1028
+ * can read long content (WCAG 1.4.13). The tooltip then captures the pointer
1029
+ * and can block clicks on controls it covers: use it for long content away
1030
+ * from other controls.
1031
+ */
1032
+ hoverable?: boolean;
880
1033
  /**
881
1034
  * Where the tooltip is rendered. Defaults to the trigger's closest
882
1035
  * landmark or dialog (so it stays inside a landmark and inside an open
@@ -905,6 +1058,12 @@ export declare interface UILabels {
905
1058
  clear: string;
906
1059
  /** Screen-reader suffix of a required `CheckboxOptions` group. */
907
1060
  required: string;
1061
+ /** Screen-reader announcement of `CopyButton` after a successful copy. */
1062
+ copied: string;
1063
+ /** Screen-reader text added to a `Button` while it is loading. */
1064
+ loading: string;
1065
+ /** Screen-reader announcement of `CharacterCount` near and at the limit. */
1066
+ charactersRemaining: (remainingCount: number) => string;
908
1067
  /** Accessible name of `ThemeToggle` for the current theme. */
909
1068
  currentTheme: (theme: Theme) => string;
910
1069
  /** `MultiCombobox` badge summarising the values that do not fit. */