@vjdesigns/vjdesigns-ui 1.5.0 → 2.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 +5 -4
- package/dist/ai/llms-full.txt +457 -448
- package/dist/ai/llms.txt +1 -1
- package/dist/ai/registry.json +126 -116
- package/dist/components/data-display/DataGrid/DataGrid.module.css.cjs.js +1 -1
- package/dist/components/data-display/DataGrid/DataGrid.module.css.mjs +1 -1
- package/dist/components/data-display/VirtualList/VirtualList.module.css.cjs.js +1 -1
- package/dist/components/data-display/VirtualList/VirtualList.module.css.mjs +1 -1
- package/dist/components/feedback/ErrorSummary/ErrorSummary.module.css.cjs.js +1 -1
- package/dist/components/feedback/ErrorSummary/ErrorSummary.module.css.mjs +1 -1
- package/dist/components/forms/DateTimePicker/DateTimePicker.module.css.cjs.js +1 -1
- package/dist/components/forms/DateTimePicker/DateTimePicker.module.css.mjs +1 -1
- package/dist/components/forms/Rating/Rating.module.css.cjs.js +1 -1
- package/dist/components/forms/Rating/Rating.module.css.mjs +1 -1
- package/dist/components/forms/TimePicker/TimePicker.module.css.cjs.js +1 -1
- package/dist/components/forms/TimePicker/TimePicker.module.css.mjs +1 -1
- package/dist/components/layout/ResizablePanels/ResizablePanels.cjs.js +1 -1
- package/dist/components/layout/ResizablePanels/ResizablePanels.mjs +1 -0
- package/dist/components/layout/ResizablePanels/ResizablePanels.module.css.cjs.js +1 -1
- package/dist/components/layout/ResizablePanels/ResizablePanels.module.css.mjs +1 -1
- package/dist/components/layout/ScrollArea/ScrollArea.module.css.cjs.js +1 -1
- package/dist/components/layout/ScrollArea/ScrollArea.module.css.mjs +1 -1
- package/dist/components/navigation/ContextMenu/ContextMenu.module.css.cjs.js +1 -1
- package/dist/components/navigation/ContextMenu/ContextMenu.module.css.mjs +1 -1
- package/dist/components/overlays/HoverCard/HoverCard.module.css.cjs.js +1 -1
- package/dist/components/overlays/HoverCard/HoverCard.module.css.mjs +2 -2
- package/dist/components/primitives/Button/Button.cjs.js +1 -1
- package/dist/components/primitives/Button/Button.mjs +37 -37
- package/dist/components/utilities/LocaleProvider/LocaleProvider.module.css.cjs.js +1 -1
- package/dist/components/utilities/LocaleProvider/LocaleProvider.module.css.mjs +1 -1
- package/dist/components/utilities/Theme/Theme.cjs.js +1 -1
- package/dist/components/utilities/Theme/Theme.d.ts +6 -6
- package/dist/components/utilities/Theme/Theme.mjs +49 -45
- package/dist/hooks/useFormValidation.cjs.js +1 -1
- package/dist/hooks/useFormValidation.mjs +1 -1
- package/dist/i18n/en.cjs.js +1 -1
- package/dist/i18n/en.mjs +50 -0
- package/dist/i18n/types.d.ts +56 -0
- package/dist/index.cjs.js +1 -1
- package/dist/index.mjs +106 -106
- package/dist/locales/ar.cjs.js +1 -1
- package/dist/locales/ar.mjs +50 -0
- package/dist/locales/bn.cjs.js +1 -1
- package/dist/locales/bn.mjs +50 -0
- package/dist/locales/cs.cjs.js +1 -1
- package/dist/locales/cs.mjs +50 -0
- package/dist/locales/da.cjs.js +1 -1
- package/dist/locales/da.mjs +50 -0
- package/dist/locales/de.cjs.js +1 -1
- package/dist/locales/de.mjs +50 -0
- package/dist/locales/el.cjs.js +1 -1
- package/dist/locales/el.mjs +50 -0
- package/dist/locales/es.cjs.js +1 -1
- package/dist/locales/es.mjs +50 -0
- package/dist/locales/fa.cjs.js +1 -1
- package/dist/locales/fa.mjs +50 -0
- package/dist/locales/fi.cjs.js +1 -1
- package/dist/locales/fi.mjs +50 -0
- package/dist/locales/fr.cjs.js +1 -1
- package/dist/locales/fr.mjs +50 -0
- package/dist/locales/he.cjs.js +1 -1
- package/dist/locales/he.mjs +50 -0
- package/dist/locales/hi.cjs.js +1 -1
- package/dist/locales/hi.mjs +50 -0
- package/dist/locales/hu.cjs.js +1 -1
- package/dist/locales/hu.mjs +50 -0
- package/dist/locales/id.cjs.js +1 -1
- package/dist/locales/id.mjs +50 -0
- package/dist/locales/it.cjs.js +1 -1
- package/dist/locales/it.mjs +50 -0
- package/dist/locales/ja.cjs.js +1 -1
- package/dist/locales/ja.mjs +50 -0
- package/dist/locales/ko.cjs.js +1 -1
- package/dist/locales/ko.mjs +50 -0
- package/dist/locales/nb.cjs.js +1 -1
- package/dist/locales/nb.mjs +50 -0
- package/dist/locales/nl.cjs.js +1 -1
- package/dist/locales/nl.mjs +50 -0
- package/dist/locales/pl.cjs.js +1 -1
- package/dist/locales/pl.mjs +50 -0
- package/dist/locales/pt-BR.cjs.js +1 -1
- package/dist/locales/pt-BR.mjs +50 -0
- package/dist/locales/ro.cjs.js +1 -1
- package/dist/locales/ro.mjs +50 -0
- package/dist/locales/ru.cjs.js +1 -1
- package/dist/locales/ru.mjs +50 -0
- package/dist/locales/sv.cjs.js +1 -1
- package/dist/locales/sv.mjs +50 -0
- package/dist/locales/th.cjs.js +1 -1
- package/dist/locales/th.mjs +50 -0
- package/dist/locales/tr.cjs.js +1 -1
- package/dist/locales/tr.mjs +50 -0
- package/dist/locales/uk.cjs.js +1 -1
- package/dist/locales/uk.mjs +50 -0
- package/dist/locales/ur.cjs.js +1 -1
- package/dist/locales/ur.mjs +50 -0
- package/dist/locales/vi.cjs.js +1 -1
- package/dist/locales/vi.mjs +50 -0
- package/dist/locales/zh-Hans.cjs.js +1 -1
- package/dist/locales/zh-Hans.mjs +50 -0
- package/dist/locales/zh-Hant.cjs.js +1 -1
- package/dist/locales/zh-Hant.mjs +50 -0
- package/dist/utils/brandPalette.cjs.js +3 -3
- package/dist/utils/brandPalette.d.ts +4 -2
- package/dist/utils/brandPalette.mjs +20 -20
- package/dist/vjdesigns-ui.css +1 -1
- package/package.json +1 -1
package/dist/ai/llms-full.txt
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
- Install: `npm install @vjdesigns/vjdesigns-ui` (peer: react, react-dom 18 or 19).
|
|
6
6
|
- Import the stylesheet once: `import "@vjdesigns/vjdesigns-ui/dist/vjdesigns-ui.css";`
|
|
7
7
|
- Import components from the package root: `import { Button, Field, Input } from "@vjdesigns/vjdesigns-ui";`
|
|
8
|
-
- Theme: wrap the app in `<Theme brand="blue" | "purple" | ... | "#hex" mode="light" | "dark" accent="brand" | "
|
|
8
|
+
- Theme: wrap the app in `<Theme brand="blue" | "purple" | ... | "#hex" mode="light" | "dark" accent="brand" | "lime" | "#hex">`.
|
|
9
9
|
- Language: `<LocaleProvider locale="es" messages={es}>` with `import es from "@vjdesigns/vjdesigns-ui/locales/es"`.
|
|
10
10
|
- Forms: wrap each control in `Field` (label, hint, error, required); validate with `useFormValidation` + `ErrorSummary`.
|
|
11
11
|
- Style with the props (variant, tone, size) and the --color-*, --space-*, --radius-* CSS variables; don't override internal class names.
|
|
@@ -281,13 +281,13 @@ import { Theme, Button } from "@vjdesigns/vjdesigns-ui";
|
|
|
281
281
|
| --- | --- | --- | --- |
|
|
282
282
|
| `mode` | `"light" \| "dark"` | inherited | Color mode for everything inside. |
|
|
283
283
|
| `brand` | `"black" \| "blue" \| "gold" \| "green" \| "purple"`, a hex color, or `{ light, dark }` | inherited | Brand palette for buttons, links, focus rings and indicators. |
|
|
284
|
-
| `accent` | `"brand" | "
|
|
284
|
+
| `accent` | `"brand" | "lime"`, a hex color, or `{ light, dark }` | inherited (the brand's own) | The bright highlight on badges, switches, progress bars, sliders, steppers, and active navigation. |
|
|
285
285
|
| `fill` | `boolean` | `false` | Paints the theme's background and text color on the wrapper. |
|
|
286
286
|
|
|
287
287
|
Outside React (or to theme the whole page), set the attributes on `<html>` instead:
|
|
288
288
|
|
|
289
289
|
```html
|
|
290
|
-
<html data-theme="dark" data-brand="purple" data-accent="
|
|
290
|
+
<html data-theme="dark" data-brand="purple" data-accent="lime">
|
|
291
291
|
```
|
|
292
292
|
|
|
293
293
|
### Accent color
|
|
@@ -300,13 +300,13 @@ The accent is the energetic highlight: badges, switches, progress bars, sliders,
|
|
|
300
300
|
| `purple` | lavender `#c0b0ff` |
|
|
301
301
|
| `gold` | amber `#f5ad5f` |
|
|
302
302
|
| `green` | mint `#72d4ad` |
|
|
303
|
-
| `black` |
|
|
303
|
+
| `black` | lime `#c8f031` (black has no hue to build on) |
|
|
304
304
|
| a custom hex | generated from that color |
|
|
305
305
|
|
|
306
306
|
To choose a different one:
|
|
307
307
|
|
|
308
308
|
```tsx
|
|
309
|
-
<Theme accent="
|
|
309
|
+
<Theme accent="lime">…</Theme> // the original bright yellow-green ("volt", its former name, still works)
|
|
310
310
|
<Theme accent="#ff6b00">…</Theme> // any color
|
|
311
311
|
<Theme accent="brand">…</Theme> // back to the brand's own, inside an area with another accent
|
|
312
312
|
```
|
|
@@ -1107,36 +1107,36 @@ import { DataGrid } from "@vjdesigns/vjdesigns-ui";
|
|
|
1107
1107
|
|
|
1108
1108
|
Category: data-display · Storybook: Data display/DataGrid
|
|
1109
1109
|
|
|
1110
|
-
An interactive data table (WAI-ARIA APG "Data Grid"): sortable columns
|
|
1111
|
-
(with Shift for multi-column sorts), search filtering, single or
|
|
1112
|
-
multiple row selection, pagination, and a full keyboard model. Works with
|
|
1113
|
-
client-side data, or server-side data with `manual`.
|
|
1114
|
-
|
|
1115
|
-
Keyboard: the grid is one Tab stop. Arrow keys move between cells
|
|
1116
|
-
(mirrored in RTL), Home / End go to the row's first or last cell, Ctrl+Home
|
|
1117
|
-
/ Ctrl+End to the first or last cell of the grid, Page Up / Page Down move
|
|
1118
|
-
ten rows. On a header, Enter sorts (Shift+Enter adds a secondary sort).
|
|
1119
|
-
Space selects the row, Shift+click or Shift+Space selects a range, and
|
|
1120
|
-
Ctrl/⌘+A selects every row. A cell with a single button, link, or
|
|
1121
|
-
checkbox focuses it directly; for cells with several controls or a text
|
|
1122
|
-
field, Enter or F2 moves into the cell, Tab cycles inside it, and Escape
|
|
1123
|
-
returns to the grid.
|
|
1124
|
-
|
|
1125
|
-
Screen readers hear sort changes and filter result counts; the grid is a
|
|
1126
|
-
real `<table role="grid">` with `aria-sort`, `aria-selected`,
|
|
1127
|
-
`aria-rowcount`, and `aria-rowindex`.
|
|
1128
|
-
|
|
1129
|
-
```tsx
|
|
1130
|
-
<DataGrid
|
|
1131
|
-
aria-label="Roster"
|
|
1132
|
-
rows={players}
|
|
1133
|
-
columns={[
|
|
1134
|
-
{ key: "name", header: "Player", sortable: true, rowHeader: true },
|
|
1135
|
-
{ key: "ppg", header: "PPG", sortable: true, numeric: true },
|
|
1136
|
-
]}
|
|
1137
|
-
selectionMode="multiple"
|
|
1138
|
-
pageSize={10}
|
|
1139
|
-
/>
|
|
1110
|
+
An interactive data table (WAI-ARIA APG "Data Grid"): sortable columns
|
|
1111
|
+
(with Shift for multi-column sorts), search filtering, single or
|
|
1112
|
+
multiple row selection, pagination, and a full keyboard model. Works with
|
|
1113
|
+
client-side data, or server-side data with `manual`.
|
|
1114
|
+
|
|
1115
|
+
Keyboard: the grid is one Tab stop. Arrow keys move between cells
|
|
1116
|
+
(mirrored in RTL), Home / End go to the row's first or last cell, Ctrl+Home
|
|
1117
|
+
/ Ctrl+End to the first or last cell of the grid, Page Up / Page Down move
|
|
1118
|
+
ten rows. On a header, Enter sorts (Shift+Enter adds a secondary sort).
|
|
1119
|
+
Space selects the row, Shift+click or Shift+Space selects a range, and
|
|
1120
|
+
Ctrl/⌘+A selects every row. A cell with a single button, link, or
|
|
1121
|
+
checkbox focuses it directly; for cells with several controls or a text
|
|
1122
|
+
field, Enter or F2 moves into the cell, Tab cycles inside it, and Escape
|
|
1123
|
+
returns to the grid.
|
|
1124
|
+
|
|
1125
|
+
Screen readers hear sort changes and filter result counts; the grid is a
|
|
1126
|
+
real `<table role="grid">` with `aria-sort`, `aria-selected`,
|
|
1127
|
+
`aria-rowcount`, and `aria-rowindex`.
|
|
1128
|
+
|
|
1129
|
+
```tsx
|
|
1130
|
+
<DataGrid
|
|
1131
|
+
aria-label="Roster"
|
|
1132
|
+
rows={players}
|
|
1133
|
+
columns={[
|
|
1134
|
+
{ key: "name", header: "Player", sortable: true, rowHeader: true },
|
|
1135
|
+
{ key: "ppg", header: "PPG", sortable: true, numeric: true },
|
|
1136
|
+
]}
|
|
1137
|
+
selectionMode="multiple"
|
|
1138
|
+
pageSize={10}
|
|
1139
|
+
/>
|
|
1140
1140
|
```
|
|
1141
1141
|
|
|
1142
1142
|
### Props
|
|
@@ -1816,25 +1816,25 @@ import { VirtualList } from "@vjdesigns/vjdesigns-ui";
|
|
|
1816
1816
|
|
|
1817
1817
|
Category: data-display · Storybook: Data display/VirtualList
|
|
1818
1818
|
|
|
1819
|
-
A list that renders only the items in view, so tens of thousands of rows
|
|
1820
|
-
scroll smoothly. Items may have any height (they're measured as they
|
|
1821
|
-
render). Built on `useVirtualizer` and `ScrollArea`.
|
|
1822
|
-
|
|
1823
|
-
Accessibility: a real `role="list"` whose items carry `aria-setsize` and
|
|
1824
|
-
`aria-posinset`, so screen readers announce "item 4,812 of 10,000" even
|
|
1825
|
-
though only a few dozen exist in the page. The scroll area is keyboard
|
|
1826
|
-
scrollable, and Tab through items' links and buttons keeps working (new
|
|
1827
|
-
items render as focus scrolls them into view). Browser find-in-page only
|
|
1828
|
-
sees rendered items, so offer search for long lists.
|
|
1829
|
-
|
|
1830
|
-
```tsx
|
|
1831
|
-
<VirtualList
|
|
1832
|
-
aria-label="All players"
|
|
1833
|
-
items={players}
|
|
1834
|
-
height="24rem"
|
|
1835
|
-
getKey={(p) => p.id}
|
|
1836
|
-
renderItem={(p) => <PlayerRow player={p} />}
|
|
1837
|
-
/>
|
|
1819
|
+
A list that renders only the items in view, so tens of thousands of rows
|
|
1820
|
+
scroll smoothly. Items may have any height (they're measured as they
|
|
1821
|
+
render). Built on `useVirtualizer` and `ScrollArea`.
|
|
1822
|
+
|
|
1823
|
+
Accessibility: a real `role="list"` whose items carry `aria-setsize` and
|
|
1824
|
+
`aria-posinset`, so screen readers announce "item 4,812 of 10,000" even
|
|
1825
|
+
though only a few dozen exist in the page. The scroll area is keyboard
|
|
1826
|
+
scrollable, and Tab through items' links and buttons keeps working (new
|
|
1827
|
+
items render as focus scrolls them into view). Browser find-in-page only
|
|
1828
|
+
sees rendered items, so offer search for long lists.
|
|
1829
|
+
|
|
1830
|
+
```tsx
|
|
1831
|
+
<VirtualList
|
|
1832
|
+
aria-label="All players"
|
|
1833
|
+
items={players}
|
|
1834
|
+
height="24rem"
|
|
1835
|
+
getKey={(p) => p.id}
|
|
1836
|
+
renderItem={(p) => <PlayerRow player={p} />}
|
|
1837
|
+
/>
|
|
1838
1838
|
```
|
|
1839
1839
|
|
|
1840
1840
|
### Props
|
|
@@ -1969,7 +1969,7 @@ Accessibility:
|
|
|
1969
1969
|
|
|
1970
1970
|
- Playground
|
|
1971
1971
|
- Tones: Every tone, solid. `accent` is the promo strip, always with dark text.
|
|
1972
|
-
-
|
|
1972
|
+
- Accent Promo: The accent promo strip: bold, dark text on accent, with a strong call to action.
|
|
1973
1973
|
- Variants: Solid and soft side by side for every tone. Check both themes.
|
|
1974
1974
|
- Sizes: Small, medium, and large. Buttons inside are one step smaller than the strip.
|
|
1975
1975
|
- With Actions: Buttons get a verified default look for the strip. Links in the message use `tone="neutral"` so they take the strip's text color and stay underlined.
|
|
@@ -2013,15 +2013,15 @@ import { ErrorSummary } from "@vjdesigns/vjdesigns-ui";
|
|
|
2013
2013
|
|
|
2014
2014
|
Category: feedback · Storybook: Feedback/ErrorSummary
|
|
2015
2015
|
|
|
2016
|
-
The list of a form's errors, shown above it after a failed submit: a danger
|
|
2017
|
-
`Alert` whose items link to their fields (activating one moves focus to the
|
|
2018
|
-
field). It's focusable (`tabIndex={-1}`): give `useFormValidation`'s
|
|
2019
|
-
`summaryRef` as `ref` and a failed submit moves focus here, so screen
|
|
2020
|
-
readers announce the heading and the list. The title is a real heading
|
|
2021
|
-
(`h2` by default; set `headingLevel` to fit the page outline).
|
|
2022
|
-
|
|
2023
|
-
```tsx
|
|
2024
|
-
<ErrorSummary ref={form.summaryRef} errors={form.errorList} />
|
|
2016
|
+
The list of a form's errors, shown above it after a failed submit: a danger
|
|
2017
|
+
`Alert` whose items link to their fields (activating one moves focus to the
|
|
2018
|
+
field). It's focusable (`tabIndex={-1}`): give `useFormValidation`'s
|
|
2019
|
+
`summaryRef` as `ref` and a failed submit moves focus here, so screen
|
|
2020
|
+
readers announce the heading and the list. The title is a real heading
|
|
2021
|
+
(`h2` by default; set `headingLevel` to fit the page outline).
|
|
2022
|
+
|
|
2023
|
+
```tsx
|
|
2024
|
+
<ErrorSummary ref={form.summaryRef} errors={form.errorList} />
|
|
2025
2025
|
```
|
|
2026
2026
|
|
|
2027
2027
|
### Props
|
|
@@ -2519,16 +2519,16 @@ import { ColorInput } from "@vjdesigns/vjdesigns-ui";
|
|
|
2519
2519
|
|
|
2520
2520
|
Category: forms · Storybook: Forms/ColorPicker
|
|
2521
2521
|
|
|
2522
|
-
A pill field showing a swatch and the color value; pressing it opens a
|
|
2523
|
-
`ColorPicker` in a `Popover` (a non-modal dialog on the shared overlay
|
|
2524
|
-
layer stack: Escape and outside presses close it, focus returns to the
|
|
2525
|
-
field). Takes the same value, format, alpha, swatch, and state props as
|
|
2526
|
-
`ColorPicker`.
|
|
2527
|
-
|
|
2528
|
-
The trigger is a native `<button>` with `aria-haspopup="dialog"` and
|
|
2529
|
-
`aria-expanded`. Its name is the label plus the current value and a plain
|
|
2530
|
-
description ("Jersey color, #1d4ed8, dark blue"). Inside a `Field`, the
|
|
2531
|
-
label, hint, error, invalid, disabled, and read-only state are wired to
|
|
2522
|
+
A pill field showing a swatch and the color value; pressing it opens a
|
|
2523
|
+
`ColorPicker` in a `Popover` (a non-modal dialog on the shared overlay
|
|
2524
|
+
layer stack: Escape and outside presses close it, focus returns to the
|
|
2525
|
+
field). Takes the same value, format, alpha, swatch, and state props as
|
|
2526
|
+
`ColorPicker`.
|
|
2527
|
+
|
|
2528
|
+
The trigger is a native `<button>` with `aria-haspopup="dialog"` and
|
|
2529
|
+
`aria-expanded`. Its name is the label plus the current value and a plain
|
|
2530
|
+
description ("Jersey color, #1d4ed8, dark blue"). Inside a `Field`, the
|
|
2531
|
+
label, hint, error, invalid, disabled, and read-only state are wired to
|
|
2532
2532
|
it. A read-only field still opens, so the values can be inspected.
|
|
2533
2533
|
|
|
2534
2534
|
### Props
|
|
@@ -2729,22 +2729,22 @@ import { DatePicker } from "@vjdesigns/vjdesigns-ui";
|
|
|
2729
2729
|
|
|
2730
2730
|
Category: forms · Storybook: Forms/DatePicker
|
|
2731
2731
|
|
|
2732
|
-
A date field: type a date in the locale's short format (or ISO), or press
|
|
2733
|
-
the calendar button to pick one from a `Calendar` in a popup dialog.
|
|
2734
|
-
|
|
2735
|
-
The value is an ISO date string ("YYYY-MM-DD"), so it never shifts with
|
|
2736
|
-
time zones. The text field shows it in the locale's numeric format; on
|
|
2737
|
-
blur (or Enter), typed text is parsed and normalized, or rejected with an
|
|
2738
|
-
inline error. Inside a `Field`, label, hint, error, required, disabled,
|
|
2739
|
-
and invalid state are wired to the text input.
|
|
2740
|
-
|
|
2741
|
-
The popup is a modal `Popover` on the shared overlay layer stack, so
|
|
2742
|
-
Escape closes only the calendar, also inside a `Modal` or `Drawer`.
|
|
2743
|
-
|
|
2744
|
-
```tsx
|
|
2745
|
-
<Field label="Game day">
|
|
2746
|
-
<DatePicker name="gameDay" min="2026-10-01" onValueChange={setDay} />
|
|
2747
|
-
</Field>
|
|
2732
|
+
A date field: type a date in the locale's short format (or ISO), or press
|
|
2733
|
+
the calendar button to pick one from a `Calendar` in a popup dialog.
|
|
2734
|
+
|
|
2735
|
+
The value is an ISO date string ("YYYY-MM-DD"), so it never shifts with
|
|
2736
|
+
time zones. The text field shows it in the locale's numeric format; on
|
|
2737
|
+
blur (or Enter), typed text is parsed and normalized, or rejected with an
|
|
2738
|
+
inline error. Inside a `Field`, label, hint, error, required, disabled,
|
|
2739
|
+
and invalid state are wired to the text input.
|
|
2740
|
+
|
|
2741
|
+
The popup is a modal `Popover` on the shared overlay layer stack, so
|
|
2742
|
+
Escape closes only the calendar, also inside a `Modal` or `Drawer`.
|
|
2743
|
+
|
|
2744
|
+
```tsx
|
|
2745
|
+
<Field label="Game day">
|
|
2746
|
+
<DatePicker name="gameDay" min="2026-10-01" onValueChange={setDay} />
|
|
2747
|
+
</Field>
|
|
2748
2748
|
```
|
|
2749
2749
|
|
|
2750
2750
|
### Props
|
|
@@ -2816,25 +2816,25 @@ import { DateRangePicker } from "@vjdesigns/vjdesigns-ui";
|
|
|
2816
2816
|
|
|
2817
2817
|
Category: forms · Storybook: Forms/DatePicker
|
|
2818
2818
|
|
|
2819
|
-
A date range field: two text fields (start and end) typed in the locale's
|
|
2820
|
-
short format, plus a calendar button that opens a range `Calendar` (two
|
|
2821
|
-
months by default) in a modal popup.
|
|
2822
|
-
|
|
2823
|
-
The value is `{ start, end }` with ISO dates ("YYYY-MM-DD"). In the
|
|
2824
|
-
calendar, the first pick sets the start and the second the end; the range
|
|
2825
|
-
is committed (and the popup closes) only when both are picked, so Escape
|
|
2826
|
-
after one pick changes nothing. Typed dates are validated like
|
|
2827
|
-
`DatePicker`'s, plus an end before the start is rejected.
|
|
2828
|
-
|
|
2829
|
-
Accessibility: the pair is a `role="group"` named by the `Field` label
|
|
2830
|
-
(or `aria-label`); each field is named by that label plus its own
|
|
2831
|
-
visible label ("Season dates, Start date"). Field hint, error, required, disabled, and
|
|
2832
|
-
invalid state reach both fields. Errors are announced politely.
|
|
2833
|
-
|
|
2834
|
-
```tsx
|
|
2835
|
-
<Field label="Season dates">
|
|
2836
|
-
<DateRangePicker startName="from" endName="to" onValueChange={setRange} />
|
|
2837
|
-
</Field>
|
|
2819
|
+
A date range field: two text fields (start and end) typed in the locale's
|
|
2820
|
+
short format, plus a calendar button that opens a range `Calendar` (two
|
|
2821
|
+
months by default) in a modal popup.
|
|
2822
|
+
|
|
2823
|
+
The value is `{ start, end }` with ISO dates ("YYYY-MM-DD"). In the
|
|
2824
|
+
calendar, the first pick sets the start and the second the end; the range
|
|
2825
|
+
is committed (and the popup closes) only when both are picked, so Escape
|
|
2826
|
+
after one pick changes nothing. Typed dates are validated like
|
|
2827
|
+
`DatePicker`'s, plus an end before the start is rejected.
|
|
2828
|
+
|
|
2829
|
+
Accessibility: the pair is a `role="group"` named by the `Field` label
|
|
2830
|
+
(or `aria-label`); each field is named by that label plus its own
|
|
2831
|
+
visible label ("Season dates, Start date"). Field hint, error, required, disabled, and
|
|
2832
|
+
invalid state reach both fields. Errors are announced politely.
|
|
2833
|
+
|
|
2834
|
+
```tsx
|
|
2835
|
+
<Field label="Season dates">
|
|
2836
|
+
<DateRangePicker startName="from" endName="to" onValueChange={setRange} />
|
|
2837
|
+
</Field>
|
|
2838
2838
|
```
|
|
2839
2839
|
|
|
2840
2840
|
### Props
|
|
@@ -2881,25 +2881,25 @@ import { DateTimePicker } from "@vjdesigns/vjdesigns-ui";
|
|
|
2881
2881
|
|
|
2882
2882
|
Category: forms · Storybook: Forms/DateTimePicker
|
|
2883
2883
|
|
|
2884
|
-
A date and a time together: a `DatePicker` and a `TimePicker` side by
|
|
2885
|
-
side, with one value, "YYYY-MM-DDTHH:mm" (the format of a native
|
|
2886
|
-
`datetime-local` input, with no time zone). Each half keeps its full
|
|
2887
|
-
behavior: typed dates in the locale's format or the calendar popup, typed
|
|
2888
|
-
times in any common form or the list of times.
|
|
2889
|
-
|
|
2890
|
-
`min` and `max` limit the calendar by their dates, and the time list by
|
|
2891
|
-
their times on those boundary dates. `defaultTime` fills the time when a
|
|
2892
|
-
date is picked first.
|
|
2893
|
-
|
|
2894
|
-
Accessibility: the pair is a `role="group"` named by the `Field` label
|
|
2895
|
-
(or `aria-label`); each field is named by that label plus its own
|
|
2896
|
-
visible label ("Tip-off, Date", "Tip-off, Time"). Field hint, error,
|
|
2897
|
-
required, disabled, and invalid state reach both.
|
|
2898
|
-
|
|
2899
|
-
```tsx
|
|
2900
|
-
<Field label="Tip-off">
|
|
2901
|
-
<DateTimePicker name="tipoff" defaultTime="19:00" step={15} />
|
|
2902
|
-
</Field>
|
|
2884
|
+
A date and a time together: a `DatePicker` and a `TimePicker` side by
|
|
2885
|
+
side, with one value, "YYYY-MM-DDTHH:mm" (the format of a native
|
|
2886
|
+
`datetime-local` input, with no time zone). Each half keeps its full
|
|
2887
|
+
behavior: typed dates in the locale's format or the calendar popup, typed
|
|
2888
|
+
times in any common form or the list of times.
|
|
2889
|
+
|
|
2890
|
+
`min` and `max` limit the calendar by their dates, and the time list by
|
|
2891
|
+
their times on those boundary dates. `defaultTime` fills the time when a
|
|
2892
|
+
date is picked first.
|
|
2893
|
+
|
|
2894
|
+
Accessibility: the pair is a `role="group"` named by the `Field` label
|
|
2895
|
+
(or `aria-label`); each field is named by that label plus its own
|
|
2896
|
+
visible label ("Tip-off, Date", "Tip-off, Time"). Field hint, error,
|
|
2897
|
+
required, disabled, and invalid state reach both.
|
|
2898
|
+
|
|
2899
|
+
```tsx
|
|
2900
|
+
<Field label="Tip-off">
|
|
2901
|
+
<DateTimePicker name="tipoff" defaultTime="19:00" step={15} />
|
|
2902
|
+
</Field>
|
|
2903
2903
|
```
|
|
2904
2904
|
|
|
2905
2905
|
### Props
|
|
@@ -3586,10 +3586,10 @@ import { Rating } from "@vjdesigns/vjdesigns-ui";
|
|
|
3586
3586
|
|
|
3587
3587
|
Category: forms · Storybook: Forms/Rating
|
|
3588
3588
|
|
|
3589
|
-
An editable star (or custom icon) rating, built on real native radios
|
|
3590
|
-
(visually hidden but focusable, sharing one `name`) inside
|
|
3591
|
-
`role="radiogroup"`. Tab lands on the selected value (or the first option),
|
|
3592
|
-
arrow keys move and select, and the value submits with a form. Supports
|
|
3589
|
+
An editable star (or custom icon) rating, built on real native radios
|
|
3590
|
+
(visually hidden but focusable, sharing one `name`) inside
|
|
3591
|
+
`role="radiogroup"`. Tab lands on the selected value (or the first option),
|
|
3592
|
+
arrow keys move and select, and the value submits with a form. Supports
|
|
3593
3593
|
half values, clearing, hover preview, and Field/Fieldset wiring.
|
|
3594
3594
|
|
|
3595
3595
|
### Props
|
|
@@ -3645,9 +3645,9 @@ import { RatingDisplay } from "@vjdesigns/vjdesigns-ui";
|
|
|
3645
3645
|
|
|
3646
3646
|
Category: forms · Storybook: Forms/Rating
|
|
3647
3647
|
|
|
3648
|
-
A read-only rating: a row of icons with fractional fill, exposed to
|
|
3649
|
-
assistive tech as a single `role="img"` named "Rated 4.5 out of 5",
|
|
3650
|
-
optionally followed by the value ("4.5 / 5") and a review count.
|
|
3648
|
+
A read-only rating: a row of icons with fractional fill, exposed to
|
|
3649
|
+
assistive tech as a single `role="img"` named "Rated 4.5 out of 5",
|
|
3650
|
+
optionally followed by the value ("4.5 / 5") and a review count.
|
|
3651
3651
|
Not focusable. For an editable rating use `Rating`.
|
|
3652
3652
|
|
|
3653
3653
|
### Props
|
|
@@ -3994,29 +3994,29 @@ import { TagInput } from "@vjdesigns/vjdesigns-ui";
|
|
|
3994
3994
|
|
|
3995
3995
|
Category: forms · Storybook: Forms/TagInput
|
|
3996
3996
|
|
|
3997
|
-
A text field that turns entries into removable tags (chips). Type and
|
|
3998
|
-
press Enter (or a delimiter such as a comma) to add; paste "a, b, c" to
|
|
3999
|
-
add several at once.
|
|
4000
|
-
|
|
4001
|
-
Keyboard:
|
|
4002
|
-
- Enter / delimiters (and Tab with `addOnTab`): add the typed text.
|
|
4003
|
-
- Backspace in an empty input, or Left Arrow with the caret at the
|
|
4004
|
-
start: move focus to the last tag's remove button. A second Backspace
|
|
4005
|
-
(or Delete) removes that tag and focus returns to the next tag, or the
|
|
4006
|
-
input. This two-step pattern avoids deleting a tag by accident and
|
|
4007
|
-
lets screen readers announce which tag is about to be removed.
|
|
4008
|
-
- On a tag: Left / Right Arrow move between tags and back to the input;
|
|
4009
|
-
Home / End jump to the first tag / the input; Backspace or Delete removes.
|
|
4010
|
-
|
|
4011
|
-
Inside a `Field`, the label, hint, error, required, disabled, read-only,
|
|
4012
|
-
and size are wired automatically. `ref` points at the `<input>`;
|
|
4013
|
-
native input props are spread onto it, while `className` and `style` go
|
|
4014
|
-
to the outer wrapper.
|
|
4015
|
-
|
|
4016
|
-
```tsx
|
|
4017
|
-
<Field label="Skills">
|
|
4018
|
-
<TagInput defaultValue={["Defense"]} placeholder="Add a skill" />
|
|
4019
|
-
</Field>
|
|
3997
|
+
A text field that turns entries into removable tags (chips). Type and
|
|
3998
|
+
press Enter (or a delimiter such as a comma) to add; paste "a, b, c" to
|
|
3999
|
+
add several at once.
|
|
4000
|
+
|
|
4001
|
+
Keyboard:
|
|
4002
|
+
- Enter / delimiters (and Tab with `addOnTab`): add the typed text.
|
|
4003
|
+
- Backspace in an empty input, or Left Arrow with the caret at the
|
|
4004
|
+
start: move focus to the last tag's remove button. A second Backspace
|
|
4005
|
+
(or Delete) removes that tag and focus returns to the next tag, or the
|
|
4006
|
+
input. This two-step pattern avoids deleting a tag by accident and
|
|
4007
|
+
lets screen readers announce which tag is about to be removed.
|
|
4008
|
+
- On a tag: Left / Right Arrow move between tags and back to the input;
|
|
4009
|
+
Home / End jump to the first tag / the input; Backspace or Delete removes.
|
|
4010
|
+
|
|
4011
|
+
Inside a `Field`, the label, hint, error, required, disabled, read-only,
|
|
4012
|
+
and size are wired automatically. `ref` points at the `<input>`;
|
|
4013
|
+
native input props are spread onto it, while `className` and `style` go
|
|
4014
|
+
to the outer wrapper.
|
|
4015
|
+
|
|
4016
|
+
```tsx
|
|
4017
|
+
<Field label="Skills">
|
|
4018
|
+
<TagInput defaultValue={["Defense"]} placeholder="Add a skill" />
|
|
4019
|
+
</Field>
|
|
4020
4020
|
```
|
|
4021
4021
|
|
|
4022
4022
|
### Props
|
|
@@ -4125,23 +4125,23 @@ import { TimePicker } from "@vjdesigns/vjdesigns-ui";
|
|
|
4125
4125
|
|
|
4126
4126
|
Category: forms · Storybook: Forms/TimePicker
|
|
4127
4127
|
|
|
4128
|
-
A time field: type a time in almost any form ("2:30 pm", "1430", "230p",
|
|
4129
|
-
"14h30", the locale's own format), or pick one from a list of times
|
|
4130
|
-
`step` minutes apart. Built on `Combobox`, so the list follows the
|
|
4131
|
-
WAI-ARIA combobox pattern: ArrowDown opens it on the selected time,
|
|
4132
|
-
arrows move, Enter picks, Escape closes, and typing filters it.
|
|
4133
|
-
|
|
4134
|
-
The value is a 24-hour "HH:mm" string, the same as a native
|
|
4135
|
-
`<input type="time">`, so it never shifts with time zones. The field
|
|
4136
|
-
shows it in the locale's clock (12- or 24-hour, override with
|
|
4137
|
-
`hourCycle`). On blur (or Enter), typed text is parsed and normalized, or
|
|
4138
|
-
rejected with an inline, announced error. Inside a `Field`, label, hint,
|
|
4139
|
-
error, required, disabled, and invalid state are wired to the input.
|
|
4140
|
-
|
|
4141
|
-
```tsx
|
|
4142
|
-
<Field label="Tip-off">
|
|
4143
|
-
<TimePicker name="tipoff" min="08:00" max="22:00" step={15} />
|
|
4144
|
-
</Field>
|
|
4128
|
+
A time field: type a time in almost any form ("2:30 pm", "1430", "230p",
|
|
4129
|
+
"14h30", the locale's own format), or pick one from a list of times
|
|
4130
|
+
`step` minutes apart. Built on `Combobox`, so the list follows the
|
|
4131
|
+
WAI-ARIA combobox pattern: ArrowDown opens it on the selected time,
|
|
4132
|
+
arrows move, Enter picks, Escape closes, and typing filters it.
|
|
4133
|
+
|
|
4134
|
+
The value is a 24-hour "HH:mm" string, the same as a native
|
|
4135
|
+
`<input type="time">`, so it never shifts with time zones. The field
|
|
4136
|
+
shows it in the locale's clock (12- or 24-hour, override with
|
|
4137
|
+
`hourCycle`). On blur (or Enter), typed text is parsed and normalized, or
|
|
4138
|
+
rejected with an inline, announced error. Inside a `Field`, label, hint,
|
|
4139
|
+
error, required, disabled, and invalid state are wired to the input.
|
|
4140
|
+
|
|
4141
|
+
```tsx
|
|
4142
|
+
<Field label="Tip-off">
|
|
4143
|
+
<TimePicker name="tipoff" min="08:00" max="22:00" step={15} />
|
|
4144
|
+
</Field>
|
|
4145
4145
|
```
|
|
4146
4146
|
|
|
4147
4147
|
### Props
|
|
@@ -4689,24 +4689,24 @@ import { ScrollArea } from "@vjdesigns/vjdesigns-ui";
|
|
|
4689
4689
|
|
|
4690
4690
|
Category: layout · Storybook: Layout/ScrollArea
|
|
4691
4691
|
|
|
4692
|
-
A scrolling region with slim, on-brand scrollbars that work the same in
|
|
4693
|
-
every browser. Scrolling itself stays native (wheel, touch, trackpad
|
|
4694
|
-
momentum, keyboard, find-in-page, scroll anchoring); only the look of the
|
|
4695
|
-
bars is custom. The thumbs can be dragged, and pressing the track pages
|
|
4696
|
-
toward the press.
|
|
4697
|
-
|
|
4698
|
-
Accessibility: while the content overflows, the viewport is focusable
|
|
4699
|
-
(`tabIndex=0`) so keyboard users can scroll it with the arrow keys, Page
|
|
4700
|
-
Up / Page Down, and Home / End. Give it a name with `aria-label` or
|
|
4701
|
-
`aria-labelledby`, which also makes it a `region` landmark. The custom
|
|
4702
|
-
bars are hidden from assistive technology (they duplicate native
|
|
4703
|
-
scrolling). Edge shadows show there is more to see. In Windows High
|
|
4704
|
-
Contrast mode the native scrollbars come back.
|
|
4705
|
-
|
|
4706
|
-
```tsx
|
|
4707
|
-
<ScrollArea maxHeight="20rem" aria-label="Roster">
|
|
4708
|
-
<List>…</List>
|
|
4709
|
-
</ScrollArea>
|
|
4692
|
+
A scrolling region with slim, on-brand scrollbars that work the same in
|
|
4693
|
+
every browser. Scrolling itself stays native (wheel, touch, trackpad
|
|
4694
|
+
momentum, keyboard, find-in-page, scroll anchoring); only the look of the
|
|
4695
|
+
bars is custom. The thumbs can be dragged, and pressing the track pages
|
|
4696
|
+
toward the press.
|
|
4697
|
+
|
|
4698
|
+
Accessibility: while the content overflows, the viewport is focusable
|
|
4699
|
+
(`tabIndex=0`) so keyboard users can scroll it with the arrow keys, Page
|
|
4700
|
+
Up / Page Down, and Home / End. Give it a name with `aria-label` or
|
|
4701
|
+
`aria-labelledby`, which also makes it a `region` landmark. The custom
|
|
4702
|
+
bars are hidden from assistive technology (they duplicate native
|
|
4703
|
+
scrolling). Edge shadows show there is more to see. In Windows High
|
|
4704
|
+
Contrast mode the native scrollbars come back.
|
|
4705
|
+
|
|
4706
|
+
```tsx
|
|
4707
|
+
<ScrollArea maxHeight="20rem" aria-label="Roster">
|
|
4708
|
+
<List>…</List>
|
|
4709
|
+
</ScrollArea>
|
|
4710
4710
|
```
|
|
4711
4711
|
|
|
4712
4712
|
### Props
|
|
@@ -4857,32 +4857,32 @@ import { ContextMenu } from "@vjdesigns/vjdesigns-ui";
|
|
|
4857
4857
|
|
|
4858
4858
|
Category: navigation · Storybook: Navigation/ContextMenu
|
|
4859
4859
|
|
|
4860
|
-
A menu that opens at the pointer on right-click (or a long press on touch
|
|
4861
|
-
screens), for actions on the thing under the pointer. It is a `Menu` in
|
|
4862
|
-
every other way: compose it from the same items (`ContextMenu.Item`,
|
|
4863
|
-
`.CheckboxItem`, `.RadioGroup` / `.RadioItem`, `.Group` / `.Label`,
|
|
4864
|
-
`.Separator`, and submenus), with the same keyboard model (arrows, Home /
|
|
4865
|
-
End, typeahead, Escape, Tab) and RTL support.
|
|
4866
|
-
|
|
4867
|
-
Keyboard: with focus inside the trigger area, Shift+F10 or the Menu key
|
|
4868
|
-
opens the menu next to the focused element and focuses its first item.
|
|
4869
|
-
On close, focus goes back to where it was.
|
|
4870
|
-
|
|
4871
|
-
Right-click menus are hard to discover, and many touch screens and
|
|
4872
|
-
assistive technologies never open them, so offer the same actions
|
|
4873
|
-
somewhere visible too (a `Menu` button, a toolbar). Treat the context
|
|
4874
|
-
menu as a shortcut, never the only way.
|
|
4875
|
-
|
|
4876
|
-
```tsx
|
|
4877
|
-
<ContextMenu>
|
|
4878
|
-
<ContextMenu.Trigger>
|
|
4879
|
-
<Card tabIndex={0}>Game film</Card>
|
|
4880
|
-
</ContextMenu.Trigger>
|
|
4881
|
-
<ContextMenu.Content>
|
|
4882
|
-
<ContextMenu.Item onSelect={rename}>Rename</ContextMenu.Item>
|
|
4883
|
-
<ContextMenu.Item tone="danger" onSelect={remove}>Delete</ContextMenu.Item>
|
|
4884
|
-
</ContextMenu.Content>
|
|
4885
|
-
</ContextMenu>
|
|
4860
|
+
A menu that opens at the pointer on right-click (or a long press on touch
|
|
4861
|
+
screens), for actions on the thing under the pointer. It is a `Menu` in
|
|
4862
|
+
every other way: compose it from the same items (`ContextMenu.Item`,
|
|
4863
|
+
`.CheckboxItem`, `.RadioGroup` / `.RadioItem`, `.Group` / `.Label`,
|
|
4864
|
+
`.Separator`, and submenus), with the same keyboard model (arrows, Home /
|
|
4865
|
+
End, typeahead, Escape, Tab) and RTL support.
|
|
4866
|
+
|
|
4867
|
+
Keyboard: with focus inside the trigger area, Shift+F10 or the Menu key
|
|
4868
|
+
opens the menu next to the focused element and focuses its first item.
|
|
4869
|
+
On close, focus goes back to where it was.
|
|
4870
|
+
|
|
4871
|
+
Right-click menus are hard to discover, and many touch screens and
|
|
4872
|
+
assistive technologies never open them, so offer the same actions
|
|
4873
|
+
somewhere visible too (a `Menu` button, a toolbar). Treat the context
|
|
4874
|
+
menu as a shortcut, never the only way.
|
|
4875
|
+
|
|
4876
|
+
```tsx
|
|
4877
|
+
<ContextMenu>
|
|
4878
|
+
<ContextMenu.Trigger>
|
|
4879
|
+
<Card tabIndex={0}>Game film</Card>
|
|
4880
|
+
</ContextMenu.Trigger>
|
|
4881
|
+
<ContextMenu.Content>
|
|
4882
|
+
<ContextMenu.Item onSelect={rename}>Rename</ContextMenu.Item>
|
|
4883
|
+
<ContextMenu.Item tone="danger" onSelect={remove}>Delete</ContextMenu.Item>
|
|
4884
|
+
</ContextMenu.Content>
|
|
4885
|
+
</ContextMenu>
|
|
4886
4886
|
```
|
|
4887
4887
|
|
|
4888
4888
|
### Props
|
|
@@ -4900,8 +4900,8 @@ menu as a shortcut, never the only way.
|
|
|
4900
4900
|
|
|
4901
4901
|
Also exported as `ContextMenuTrigger`.
|
|
4902
4902
|
|
|
4903
|
-
The area that opens the menu: right-click, a touch long press, or
|
|
4904
|
-
Shift+F10 / the Menu key while focus is inside it. Make the area (or the
|
|
4903
|
+
The area that opens the menu: right-click, a touch long press, or
|
|
4904
|
+
Shift+F10 / the Menu key while focus is inside it. Make the area (or the
|
|
4905
4905
|
items in it) focusable so keyboard users can reach the menu.
|
|
4906
4906
|
|
|
4907
4907
|
- `children`: `ReactNode`. The area that answers right-clicks: plain content (wrapped in a `div`) or a single element.
|
|
@@ -4912,8 +4912,8 @@ items in it) focusable so keyboard users can reach the menu.
|
|
|
4912
4912
|
|
|
4913
4913
|
Also exported as `ContextMenuContent`.
|
|
4914
4914
|
|
|
4915
|
-
The floating menu (`role="menu"`), opened at the pointer. Takes the same
|
|
4916
|
-
props as `Menu.Content`; `placement` is relative to the pointer, and
|
|
4915
|
+
The floating menu (`role="menu"`), opened at the pointer. Takes the same
|
|
4916
|
+
props as `Menu.Content`; `placement` is relative to the pointer, and
|
|
4917
4917
|
flips and clamps to stay on screen. @see MenuContent
|
|
4918
4918
|
|
|
4919
4919
|
- `children`: `ReactNode`. Menu items, groups, separators, and submenus.
|
|
@@ -5130,30 +5130,30 @@ import { Menu } from "@vjdesigns/vjdesigns-ui";
|
|
|
5130
5130
|
|
|
5131
5131
|
Category: navigation · Storybook: Navigation/Menu
|
|
5132
5132
|
|
|
5133
|
-
A dropdown menu of actions or options, opened from a button (WAI-ARIA APG
|
|
5134
|
-
"Menu Button" and "Menu" patterns). Compose it from `Menu.Trigger`,
|
|
5135
|
-
`Menu.Content`, `Menu.Item`, `Menu.CheckboxItem`, `Menu.RadioGroup` /
|
|
5136
|
-
`Menu.RadioItem`, `Menu.Group` / `Menu.Label`, `Menu.Separator`, and
|
|
5137
|
-
submenus (`Menu.Sub`, `Menu.SubTrigger`, `Menu.SubContent`).
|
|
5138
|
-
|
|
5139
|
-
Keyboard: Enter, Space, or ArrowDown on the trigger opens the menu and
|
|
5140
|
-
focuses the first item (ArrowUp: the last). Inside, ArrowUp/ArrowDown move
|
|
5141
|
-
(wrapping), Home/End jump, typing a character jumps to the next matching
|
|
5142
|
-
item, Enter/Space activates, ArrowRight opens a submenu and ArrowLeft
|
|
5143
|
-
closes it (mirrored in RTL), Escape closes the current level and returns
|
|
5144
|
-
focus to its trigger, and Tab closes the whole menu.
|
|
5145
|
-
|
|
5146
|
-
Disabled items stay focusable (`aria-disabled="true"`) so keyboard and
|
|
5147
|
-
screen reader users can still discover them, but can't be activated.
|
|
5148
|
-
|
|
5149
|
-
```tsx
|
|
5150
|
-
<Menu>
|
|
5151
|
-
<Menu.Trigger>Actions</Menu.Trigger>
|
|
5152
|
-
<Menu.Content>
|
|
5153
|
-
<Menu.Item onSelect={edit}>Edit</Menu.Item>
|
|
5154
|
-
<Menu.Item tone="danger" onSelect={remove}>Delete</Menu.Item>
|
|
5155
|
-
</Menu.Content>
|
|
5156
|
-
</Menu>
|
|
5133
|
+
A dropdown menu of actions or options, opened from a button (WAI-ARIA APG
|
|
5134
|
+
"Menu Button" and "Menu" patterns). Compose it from `Menu.Trigger`,
|
|
5135
|
+
`Menu.Content`, `Menu.Item`, `Menu.CheckboxItem`, `Menu.RadioGroup` /
|
|
5136
|
+
`Menu.RadioItem`, `Menu.Group` / `Menu.Label`, `Menu.Separator`, and
|
|
5137
|
+
submenus (`Menu.Sub`, `Menu.SubTrigger`, `Menu.SubContent`).
|
|
5138
|
+
|
|
5139
|
+
Keyboard: Enter, Space, or ArrowDown on the trigger opens the menu and
|
|
5140
|
+
focuses the first item (ArrowUp: the last). Inside, ArrowUp/ArrowDown move
|
|
5141
|
+
(wrapping), Home/End jump, typing a character jumps to the next matching
|
|
5142
|
+
item, Enter/Space activates, ArrowRight opens a submenu and ArrowLeft
|
|
5143
|
+
closes it (mirrored in RTL), Escape closes the current level and returns
|
|
5144
|
+
focus to its trigger, and Tab closes the whole menu.
|
|
5145
|
+
|
|
5146
|
+
Disabled items stay focusable (`aria-disabled="true"`) so keyboard and
|
|
5147
|
+
screen reader users can still discover them, but can't be activated.
|
|
5148
|
+
|
|
5149
|
+
```tsx
|
|
5150
|
+
<Menu>
|
|
5151
|
+
<Menu.Trigger>Actions</Menu.Trigger>
|
|
5152
|
+
<Menu.Content>
|
|
5153
|
+
<Menu.Item onSelect={edit}>Edit</Menu.Item>
|
|
5154
|
+
<Menu.Item tone="danger" onSelect={remove}>Delete</Menu.Item>
|
|
5155
|
+
</Menu.Content>
|
|
5156
|
+
</Menu>
|
|
5157
5157
|
```
|
|
5158
5158
|
|
|
5159
5159
|
### Props
|
|
@@ -5169,8 +5169,8 @@ screen reader users can still discover them, but can't be activated.
|
|
|
5169
5169
|
|
|
5170
5170
|
Also exported as `MenuTrigger`.
|
|
5171
5171
|
|
|
5172
|
-
The button that opens the menu. Adds `aria-haspopup="menu"`,
|
|
5173
|
-
`aria-expanded`, and `aria-controls`. Pass a single `Button`/`IconButton`
|
|
5172
|
+
The button that opens the menu. Adds `aria-haspopup="menu"`,
|
|
5173
|
+
`aria-expanded`, and `aria-controls`. Pass a single `Button`/`IconButton`
|
|
5174
5174
|
to use it as-is, or plain content to get a default `Button`.
|
|
5175
5175
|
|
|
5176
5176
|
- `variant`: `ButtonVariant` (default "solid"). Visual style. Inherits from a surrounding `ButtonGroup`.
|
|
@@ -6266,27 +6266,27 @@ import { HoverCard } from "@vjdesigns/vjdesigns-ui";
|
|
|
6266
6266
|
|
|
6267
6267
|
Category: overlays · Storybook: Overlays/HoverCard
|
|
6268
6268
|
|
|
6269
|
-
A preview card that opens while the pointer rests on a link or button, or
|
|
6270
|
-
while it has keyboard focus: a player's profile behind their name, a page
|
|
6271
|
-
preview behind a link. Unlike `Tooltip`, the card can hold rich and
|
|
6272
|
-
interactive content (links, buttons).
|
|
6273
|
-
|
|
6274
|
-
Meets WCAG 1.4.13: the pointer can move onto the card, it stays open
|
|
6275
|
-
while hovered or focused, and Escape closes it. Keyboard users get it
|
|
6276
|
-
too: focusing the trigger opens it, Tab moves into the card's links, and
|
|
6277
|
-
Tab past the last one continues to whatever follows the trigger.
|
|
6278
|
-
|
|
6279
|
-
Touch screens have no hover, so the card never opens from a tap (the tap
|
|
6280
|
-
follows the link). Treat it as a preview: everything in it must also be
|
|
6281
|
-
reachable from the page the trigger leads to.
|
|
6282
|
-
|
|
6283
|
-
```tsx
|
|
6284
|
-
<HoverCard>
|
|
6285
|
-
<HoverCard.Trigger>
|
|
6286
|
-
<Link href="/players/23">Jordan Reyes</Link>
|
|
6287
|
-
</HoverCard.Trigger>
|
|
6288
|
-
<HoverCard.Content>…profile…</HoverCard.Content>
|
|
6289
|
-
</HoverCard>
|
|
6269
|
+
A preview card that opens while the pointer rests on a link or button, or
|
|
6270
|
+
while it has keyboard focus: a player's profile behind their name, a page
|
|
6271
|
+
preview behind a link. Unlike `Tooltip`, the card can hold rich and
|
|
6272
|
+
interactive content (links, buttons).
|
|
6273
|
+
|
|
6274
|
+
Meets WCAG 1.4.13: the pointer can move onto the card, it stays open
|
|
6275
|
+
while hovered or focused, and Escape closes it. Keyboard users get it
|
|
6276
|
+
too: focusing the trigger opens it, Tab moves into the card's links, and
|
|
6277
|
+
Tab past the last one continues to whatever follows the trigger.
|
|
6278
|
+
|
|
6279
|
+
Touch screens have no hover, so the card never opens from a tap (the tap
|
|
6280
|
+
follows the link). Treat it as a preview: everything in it must also be
|
|
6281
|
+
reachable from the page the trigger leads to.
|
|
6282
|
+
|
|
6283
|
+
```tsx
|
|
6284
|
+
<HoverCard>
|
|
6285
|
+
<HoverCard.Trigger>
|
|
6286
|
+
<Link href="/players/23">Jordan Reyes</Link>
|
|
6287
|
+
</HoverCard.Trigger>
|
|
6288
|
+
<HoverCard.Content>…profile…</HoverCard.Content>
|
|
6289
|
+
</HoverCard>
|
|
6290
6290
|
```
|
|
6291
6291
|
|
|
6292
6292
|
### Props
|
|
@@ -6310,7 +6310,7 @@ The link or button that opens the card. Its own role and name are left untouched
|
|
|
6310
6310
|
|
|
6311
6311
|
Also exported as `HoverCardContent`.
|
|
6312
6312
|
|
|
6313
|
-
The floating card. Rendered in a portal, positioned against the trigger
|
|
6313
|
+
The floating card. Rendered in a portal, positioned against the trigger
|
|
6314
6314
|
with flip and viewport clamping, and mounted only while open.
|
|
6315
6315
|
|
|
6316
6316
|
- `placement`: `Placement` (default "bottom"). Preferred side and alignment. Flips to the other side when there isn't room.
|
|
@@ -6730,6 +6730,7 @@ is passed.
|
|
|
6730
6730
|
- With Icons
|
|
6731
6731
|
- Loading: The button keeps its width, sets `aria-busy`, ignores clicks, and stays focusable.
|
|
6732
6732
|
- Disabled
|
|
6733
|
+
- Disabled but focusable: `aria-disabled="true"` instead of `disabled`: the button looks and acts unavailable (clicks are ignored) but stays focusable, so a tooltip or a countdown ("Resend code in 0:24") can still be reached and read.
|
|
6733
6734
|
- As Router Link: `as` renders your router's link with the button's styling, and its props (here `to`) are typed. While disabled or loading it becomes a plain `<a aria-disabled="true">`, since a router link can't render without a destination.
|
|
6734
6735
|
- As Link: Passing `href` renders an `<a>` with the same styling. Disabled links drop `href` and get `aria-disabled`.
|
|
6735
6736
|
- Full Width
|
|
@@ -7064,12 +7065,12 @@ any part of it; themes nest (a blue area inside a purple app, a dark panel
|
|
|
7064
7065
|
on a light page). Overlays opened inside (Popover, Menu, Modal, Tooltip,
|
|
7065
7066
|
Toast, ...) render elsewhere in the page but keep this theme. For the whole
|
|
7066
7067
|
page you can instead set the attributes on `<html>`:
|
|
7067
|
-
`<html data-theme="dark" data-brand="purple" data-accent="
|
|
7068
|
+
`<html data-theme="dark" data-brand="purple" data-accent="lime">`.
|
|
7068
7069
|
|
|
7069
7070
|
### Props
|
|
7070
7071
|
|
|
7071
7072
|
- `brand`: `ThemeBrand | BrandColor`. Brand palette for everything inside: buttons, links, focus rings, selection, and indicators all switch at once. Leave unset to inherit. A preset name, or any hex color (`"#e11d48"`) for a custom palette generated in both modes. One hex is used as given in the mode where it meets WCAG AA (dark colors in light mode, light colors in dark mode) and the other mode gets a matching shade; pass `{ light, dark }` to choose both. A color that fails contrast is shifted lighter or darker (same hue) just enough to pass, with a console warning in development.
|
|
7072
|
-
- `accent`: `ThemeAccent | BrandColor`. The accent: the energetic highlight on badges, switches, progress bars, sliders, steppers, and active navigation. Leave unset to inherit; with no accent set anywhere, each brand uses its own (a bright shade of its hue). `"
|
|
7073
|
+
- `accent`: `ThemeAccent | BrandColor`. The accent: the energetic highlight on badges, switches, progress bars, sliders, steppers, and active navigation. Leave unset to inherit; with no accent set anywhere, each brand uses its own (a bright shade of its hue). `"lime"` for the original bright yellow-green, `"brand"` to go back to the brand's own inside an area with another accent, or any hex color for a custom accent. Accents always carry dark text, so a color too dark for that is lightened (same hue), with a console warning in development. An accent set here also holds inside nested brands.
|
|
7073
7074
|
- `mode`: `ThemeMode`. Color mode for everything inside. Leave unset to inherit.
|
|
7074
7075
|
- `fill`: `boolean` (default false). Paint the page background and text color of the theme on this wrapper (useful when `mode` differs from the page around it).
|
|
7075
7076
|
- Plus every native `<div>` attribute (className, style, id, aria-*, data-*, event handlers), spread onto the root.
|
|
@@ -7084,7 +7085,7 @@ page you can instead set the attributes on `<html>`:
|
|
|
7084
7085
|
- Custom colors per mode: `{ light, dark }` picks the color for each mode; each is still checked for contrast.
|
|
7085
7086
|
- Custom colors in overlays: Overlays opened inside a custom-colored Theme keep the generated palette.
|
|
7086
7087
|
- Theme builder: Pick any color and see the generated palette in both modes, with code to copy.
|
|
7087
|
-
- Accents: The accent (badges, switches, progress, sliders, active navigation) follows the brand by default: a bright shade of its hue, always with dark text. `accent="
|
|
7088
|
+
- Accents: The accent (badges, switches, progress, sliders, active navigation) follows the brand by default: a bright shade of its hue, always with dark text. `accent="lime"` restores the original bright yellow-green, and any hex makes a custom accent (kept accessible: too-dark colors are lightened).
|
|
7088
7089
|
- Accent nesting: An explicit accent holds inside nested brands; `accent="brand"` goes back to the nearest brand's own accent. Overlays keep the accent of their area.
|
|
7089
7090
|
|
|
7090
7091
|
## VisuallyHidden
|
|
@@ -7303,13 +7304,13 @@ During server rendering it returns `base` (or `fallback`).
|
|
|
7303
7304
|
useDisclosure(initial = false, options: UseDisclosureOptions = {}): [opened: boolean, handlers: DisclosureHandlers]
|
|
7304
7305
|
```
|
|
7305
7306
|
|
|
7306
|
-
Open/closed state for anything that shows and hides (a Modal, Drawer,
|
|
7307
|
-
Popover, a collapsible section), with stable handlers.
|
|
7308
|
-
|
|
7309
|
-
```tsx
|
|
7310
|
-
const [opened, { open, close }] = useDisclosure();
|
|
7311
|
-
<Button onClick={open}>Edit</Button>
|
|
7312
|
-
<Modal open={opened} onOpenChange={(next) => (next ? open() : close())}>…</Modal>
|
|
7307
|
+
Open/closed state for anything that shows and hides (a Modal, Drawer,
|
|
7308
|
+
Popover, a collapsible section), with stable handlers.
|
|
7309
|
+
|
|
7310
|
+
```tsx
|
|
7311
|
+
const [opened, { open, close }] = useDisclosure();
|
|
7312
|
+
<Button onClick={open}>Edit</Button>
|
|
7313
|
+
<Modal open={opened} onOpenChange={(next) => (next ? open() : close())}>…</Modal>
|
|
7313
7314
|
```
|
|
7314
7315
|
|
|
7315
7316
|
## useToggle
|
|
@@ -7318,13 +7319,13 @@ const [opened, { open, close }] = useDisclosure();
|
|
|
7318
7319
|
useToggle(values: readonly T[] = [false, true] as unknown as readonly T[]): [value: T, toggle: (value?: T) => void]
|
|
7319
7320
|
```
|
|
7320
7321
|
|
|
7321
|
-
Cycles through values: `[false, true]` by default (a boolean toggle), or
|
|
7322
|
-
any list (`["list", "grid"]`). `toggle()` moves to the next value (wrapping);
|
|
7323
|
-
`toggle(value)` jumps to one.
|
|
7324
|
-
|
|
7325
|
-
```tsx
|
|
7326
|
-
const [view, toggleView] = useToggle(["list", "grid"] as const);
|
|
7327
|
-
<Button onClick={() => toggleView()}>Show {view === "list" ? "grid" : "list"}</Button>
|
|
7322
|
+
Cycles through values: `[false, true]` by default (a boolean toggle), or
|
|
7323
|
+
any list (`["list", "grid"]`). `toggle()` moves to the next value (wrapping);
|
|
7324
|
+
`toggle(value)` jumps to one.
|
|
7325
|
+
|
|
7326
|
+
```tsx
|
|
7327
|
+
const [view, toggleView] = useToggle(["list", "grid"] as const);
|
|
7328
|
+
<Button onClick={() => toggleView()}>Show {view === "list" ? "grid" : "list"}</Button>
|
|
7328
7329
|
```
|
|
7329
7330
|
|
|
7330
7331
|
## useDebouncedCallback
|
|
@@ -7333,13 +7334,13 @@ const [view, toggleView] = useToggle(["list", "grid"] as const);
|
|
|
7333
7334
|
useDebouncedCallback(callback: (...args: A) => void, wait: number, { leading = false, maxWait }: { leading?: boolean; maxWait?: number } = {}): ControlledCallback<A>
|
|
7334
7335
|
```
|
|
7335
7336
|
|
|
7336
|
-
A function that waits until calls stop for `wait` ms, then runs once with
|
|
7337
|
-
the last arguments. Always calls the latest `callback`; a pending call is
|
|
7338
|
-
dropped on unmount. Use it to save, search, or validate after typing pauses.
|
|
7339
|
-
|
|
7340
|
-
```tsx
|
|
7341
|
-
const save = useDebouncedCallback((text: string) => api.saveDraft(text), 500);
|
|
7342
|
-
<Textarea onChange={(e) => save(e.target.value)} />
|
|
7337
|
+
A function that waits until calls stop for `wait` ms, then runs once with
|
|
7338
|
+
the last arguments. Always calls the latest `callback`; a pending call is
|
|
7339
|
+
dropped on unmount. Use it to save, search, or validate after typing pauses.
|
|
7340
|
+
|
|
7341
|
+
```tsx
|
|
7342
|
+
const save = useDebouncedCallback((text: string) => api.saveDraft(text), 500);
|
|
7343
|
+
<Textarea onChange={(e) => save(e.target.value)} />
|
|
7343
7344
|
```
|
|
7344
7345
|
|
|
7345
7346
|
## useThrottledCallback
|
|
@@ -7348,12 +7349,12 @@ const save = useDebouncedCallback((text: string) => api.saveDraft(text), 500);
|
|
|
7348
7349
|
useThrottledCallback(callback: (...args: A) => void, wait: number): ControlledCallback<A>
|
|
7349
7350
|
```
|
|
7350
7351
|
|
|
7351
|
-
A function that runs at most once every `wait` ms: the first call runs
|
|
7352
|
-
right away, and the last call made during the wait runs when it ends.
|
|
7353
|
-
Use it for scroll, resize, or pointer-move handlers.
|
|
7354
|
-
|
|
7355
|
-
```tsx
|
|
7356
|
-
const track = useThrottledCallback((x: number) => setPosition(x), 100);
|
|
7352
|
+
A function that runs at most once every `wait` ms: the first call runs
|
|
7353
|
+
right away, and the last call made during the wait runs when it ends.
|
|
7354
|
+
Use it for scroll, resize, or pointer-move handlers.
|
|
7355
|
+
|
|
7356
|
+
```tsx
|
|
7357
|
+
const track = useThrottledCallback((x: number) => setPosition(x), 100);
|
|
7357
7358
|
```
|
|
7358
7359
|
|
|
7359
7360
|
## useDebouncedValue
|
|
@@ -7362,13 +7363,13 @@ const track = useThrottledCallback((x: number) => setPosition(x), 100);
|
|
|
7362
7363
|
useDebouncedValue(value: T, wait: number): [debounced: T, controls: { cancel: () => void; flush: () => void }]
|
|
7363
7364
|
```
|
|
7364
7365
|
|
|
7365
|
-
The value, updated only after it stops changing for `wait` ms. Use it to
|
|
7366
|
-
search or fetch as someone types, without a request per keystroke.
|
|
7367
|
-
|
|
7368
|
-
```tsx
|
|
7369
|
-
const [query, setQuery] = useState("");
|
|
7370
|
-
const [debouncedQuery] = useDebouncedValue(query, 300);
|
|
7371
|
-
useEffect(() => { search(debouncedQuery); }, [debouncedQuery]);
|
|
7366
|
+
The value, updated only after it stops changing for `wait` ms. Use it to
|
|
7367
|
+
search or fetch as someone types, without a request per keystroke.
|
|
7368
|
+
|
|
7369
|
+
```tsx
|
|
7370
|
+
const [query, setQuery] = useState("");
|
|
7371
|
+
const [debouncedQuery] = useDebouncedValue(query, 300);
|
|
7372
|
+
useEffect(() => { search(debouncedQuery); }, [debouncedQuery]);
|
|
7372
7373
|
```
|
|
7373
7374
|
|
|
7374
7375
|
## useInterval
|
|
@@ -7377,12 +7378,12 @@ useEffect(() => { search(debouncedQuery); }, [debouncedQuery]);
|
|
|
7377
7378
|
useInterval(callback: () => void, delay: number | null): void
|
|
7378
7379
|
```
|
|
7379
7380
|
|
|
7380
|
-
Calls `callback` every `delay` ms while `delay` is a number; pass `null`
|
|
7381
|
-
to pause. Always calls the latest `callback`, and stops on unmount.
|
|
7382
|
-
|
|
7383
|
-
```tsx
|
|
7384
|
-
const [running, setRunning] = useState(true);
|
|
7385
|
-
useInterval(() => setSeconds((s) => s + 1), running ? 1000 : null);
|
|
7381
|
+
Calls `callback` every `delay` ms while `delay` is a number; pass `null`
|
|
7382
|
+
to pause. Always calls the latest `callback`, and stops on unmount.
|
|
7383
|
+
|
|
7384
|
+
```tsx
|
|
7385
|
+
const [running, setRunning] = useState(true);
|
|
7386
|
+
useInterval(() => setSeconds((s) => s + 1), running ? 1000 : null);
|
|
7386
7387
|
```
|
|
7387
7388
|
|
|
7388
7389
|
## useTimeout
|
|
@@ -7391,12 +7392,12 @@ useInterval(() => setSeconds((s) => s + 1), running ? 1000 : null);
|
|
|
7391
7392
|
useTimeout(callback: () => void, delay: number | null): { clear: () => void; reset: () => void }
|
|
7392
7393
|
```
|
|
7393
7394
|
|
|
7394
|
-
Calls `callback` once, `delay` ms after mount (or after `delay` changes);
|
|
7395
|
-
pass `null` to not schedule it. Returns `clear` and `reset` (restart the
|
|
7396
|
-
wait).
|
|
7397
|
-
|
|
7398
|
-
```tsx
|
|
7399
|
-
const { reset } = useTimeout(() => setSaved(false), 2000);
|
|
7395
|
+
Calls `callback` once, `delay` ms after mount (or after `delay` changes);
|
|
7396
|
+
pass `null` to not schedule it. Returns `clear` and `reset` (restart the
|
|
7397
|
+
wait).
|
|
7398
|
+
|
|
7399
|
+
```tsx
|
|
7400
|
+
const { reset } = useTimeout(() => setSaved(false), 2000);
|
|
7400
7401
|
```
|
|
7401
7402
|
|
|
7402
7403
|
## usePrevious
|
|
@@ -7405,10 +7406,10 @@ const { reset } = useTimeout(() => setSaved(false), 2000);
|
|
|
7405
7406
|
usePrevious(value: T): T | undefined
|
|
7406
7407
|
```
|
|
7407
7408
|
|
|
7408
|
-
The value from before its last change (undefined until it first changes).
|
|
7409
|
-
|
|
7410
|
-
```tsx
|
|
7411
|
-
const previousCount = usePrevious(count);
|
|
7409
|
+
The value from before its last change (undefined until it first changes).
|
|
7410
|
+
|
|
7411
|
+
```tsx
|
|
7412
|
+
const previousCount = usePrevious(count);
|
|
7412
7413
|
```
|
|
7413
7414
|
|
|
7414
7415
|
## useLocalStorage
|
|
@@ -7417,13 +7418,13 @@ const previousCount = usePrevious(count);
|
|
|
7417
7418
|
useLocalStorage(key: string, defaultValue: T, options?: UseStorageOptions<T>)
|
|
7418
7419
|
```
|
|
7419
7420
|
|
|
7420
|
-
State saved in `localStorage` under `key`: it survives reloads and stays in
|
|
7421
|
-
sync across every component using the key and across browser tabs. Values
|
|
7422
|
-
are JSON by default. Returns `defaultValue` during server rendering, when
|
|
7423
|
-
nothing is stored, or when storage is blocked (it never throws).
|
|
7424
|
-
|
|
7425
|
-
```tsx
|
|
7426
|
-
const [density, setDensity] = useLocalStorage("table-density", "comfortable");
|
|
7421
|
+
State saved in `localStorage` under `key`: it survives reloads and stays in
|
|
7422
|
+
sync across every component using the key and across browser tabs. Values
|
|
7423
|
+
are JSON by default. Returns `defaultValue` during server rendering, when
|
|
7424
|
+
nothing is stored, or when storage is blocked (it never throws).
|
|
7425
|
+
|
|
7426
|
+
```tsx
|
|
7427
|
+
const [density, setDensity] = useLocalStorage("table-density", "comfortable");
|
|
7427
7428
|
```
|
|
7428
7429
|
|
|
7429
7430
|
## useSessionStorage
|
|
@@ -7440,14 +7441,14 @@ Like `useLocalStorage`, in `sessionStorage`: kept until the tab closes.
|
|
|
7440
7441
|
useClipboard({ timeout = 2000 }: { timeout?: number } = {}): UseClipboardResult
|
|
7441
7442
|
```
|
|
7442
7443
|
|
|
7443
|
-
Copies text to the clipboard, with a `copied` flag that resets after
|
|
7444
|
-
`timeout` ms. Uses the Clipboard API, with a fallback for browsers or
|
|
7445
|
-
contexts that block it. Pair a visible "Copied" change with an
|
|
7446
|
-
announcement (`announce`) so screen readers hear it too.
|
|
7447
|
-
|
|
7448
|
-
```tsx
|
|
7449
|
-
const { copy, copied } = useClipboard();
|
|
7450
|
-
<Button onClick={() => copy(inviteLink)}>{copied ? "Copied" : "Copy link"}</Button>
|
|
7444
|
+
Copies text to the clipboard, with a `copied` flag that resets after
|
|
7445
|
+
`timeout` ms. Uses the Clipboard API, with a fallback for browsers or
|
|
7446
|
+
contexts that block it. Pair a visible "Copied" change with an
|
|
7447
|
+
announcement (`announce`) so screen readers hear it too.
|
|
7448
|
+
|
|
7449
|
+
```tsx
|
|
7450
|
+
const { copy, copied } = useClipboard();
|
|
7451
|
+
<Button onClick={() => copy(inviteLink)}>{copied ? "Copied" : "Copy link"}</Button>
|
|
7451
7452
|
```
|
|
7452
7453
|
|
|
7453
7454
|
## useHotkeys
|
|
@@ -7456,19 +7457,19 @@ const { copy, copied } = useClipboard();
|
|
|
7456
7457
|
useHotkeys(hotkeys: HotkeyItem[], { enabled = true, target }: UseHotkeysOptions = {}): void
|
|
7457
7458
|
```
|
|
7458
7459
|
|
|
7459
|
-
Keyboard shortcuts for the whole page (or one element). `mod` is ⌘ on Mac
|
|
7460
|
-
and Ctrl elsewhere; separate alternatives with commas (`"mod+k, /"`).
|
|
7461
|
-
Shortcuts with ⌘, Ctrl, or Alt work everywhere; plain keys don't fire while
|
|
7462
|
-
typing in a text field. Show each shortcut to users (`Kbd`,
|
|
7463
|
-
`aria-keyshortcuts`) so it can be found, and avoid single-key shortcuts that
|
|
7464
|
-
screen readers or browsers use, or let users turn them off (WCAG 2.1.4).
|
|
7465
|
-
|
|
7466
|
-
```tsx
|
|
7467
|
-
useHotkeys([
|
|
7468
|
-
["mod+k", () => setPaletteOpen(true)],
|
|
7469
|
-
["/", () => searchRef.current?.focus()],
|
|
7470
|
-
["shift+?", () => setHelpOpen(true)],
|
|
7471
|
-
]);
|
|
7460
|
+
Keyboard shortcuts for the whole page (or one element). `mod` is ⌘ on Mac
|
|
7461
|
+
and Ctrl elsewhere; separate alternatives with commas (`"mod+k, /"`).
|
|
7462
|
+
Shortcuts with ⌘, Ctrl, or Alt work everywhere; plain keys don't fire while
|
|
7463
|
+
typing in a text field. Show each shortcut to users (`Kbd`,
|
|
7464
|
+
`aria-keyshortcuts`) so it can be found, and avoid single-key shortcuts that
|
|
7465
|
+
screen readers or browsers use, or let users turn them off (WCAG 2.1.4).
|
|
7466
|
+
|
|
7467
|
+
```tsx
|
|
7468
|
+
useHotkeys([
|
|
7469
|
+
["mod+k", () => setPaletteOpen(true)],
|
|
7470
|
+
["/", () => searchRef.current?.focus()],
|
|
7471
|
+
["shift+?", () => setHelpOpen(true)],
|
|
7472
|
+
]);
|
|
7472
7473
|
```
|
|
7473
7474
|
|
|
7474
7475
|
## useEventListener
|
|
@@ -7477,13 +7478,13 @@ useHotkeys([
|
|
|
7477
7478
|
useEventListener(type: K, handler: (event: WindowEventMap[K]) => void, target?: ListenerTarget | RefObject<HTMLElement | null>, options?: boolean | AddEventListenerOptions): void
|
|
7478
7479
|
```
|
|
7479
7480
|
|
|
7480
|
-
Adds an event listener and removes it on unmount. Always calls the latest
|
|
7481
|
-
`handler` (no re-subscribing when it changes). `target` defaults to
|
|
7482
|
-
`window`; pass an element, `document`, or a ref.
|
|
7483
|
-
|
|
7484
|
-
```tsx
|
|
7485
|
-
useEventListener("beforeunload", (e) => { if (dirty) e.preventDefault(); });
|
|
7486
|
-
useEventListener("scroll", onScroll, panelRef, { passive: true });
|
|
7481
|
+
Adds an event listener and removes it on unmount. Always calls the latest
|
|
7482
|
+
`handler` (no re-subscribing when it changes). `target` defaults to
|
|
7483
|
+
`window`; pass an element, `document`, or a ref.
|
|
7484
|
+
|
|
7485
|
+
```tsx
|
|
7486
|
+
useEventListener("beforeunload", (e) => { if (dirty) e.preventDefault(); });
|
|
7487
|
+
useEventListener("scroll", onScroll, panelRef, { passive: true });
|
|
7487
7488
|
```
|
|
7488
7489
|
|
|
7489
7490
|
## useClickOutside
|
|
@@ -7492,14 +7493,14 @@ useEventListener("scroll", onScroll, panelRef, { passive: true });
|
|
|
7492
7493
|
useClickOutside(handler: (event: Event) => void, { enabled = true, ignore = [] }: { enabled?: boolean; ignore?: Array<RefObject<HTMLElement | null> | HTMLElement | null> } = {}): RefObject<T | null>
|
|
7493
7494
|
```
|
|
7494
7495
|
|
|
7495
|
-
Calls `handler` when a pointer press or a focus move lands outside the
|
|
7496
|
-
returned ref's element (and outside any `ignore` elements). Use it for
|
|
7497
|
-
custom popups; the library's own overlays already close on outside
|
|
7498
|
-
presses, through the shared layer stack.
|
|
7499
|
-
|
|
7500
|
-
```tsx
|
|
7501
|
-
const ref = useClickOutside<HTMLDivElement>(() => setOpen(false));
|
|
7502
|
-
<div ref={ref}>…</div>
|
|
7496
|
+
Calls `handler` when a pointer press or a focus move lands outside the
|
|
7497
|
+
returned ref's element (and outside any `ignore` elements). Use it for
|
|
7498
|
+
custom popups; the library's own overlays already close on outside
|
|
7499
|
+
presses, through the shared layer stack.
|
|
7500
|
+
|
|
7501
|
+
```tsx
|
|
7502
|
+
const ref = useClickOutside<HTMLDivElement>(() => setOpen(false));
|
|
7503
|
+
<div ref={ref}>…</div>
|
|
7503
7504
|
```
|
|
7504
7505
|
|
|
7505
7506
|
## useIntersection
|
|
@@ -7508,13 +7509,13 @@ const ref = useClickOutside<HTMLDivElement>(() => setOpen(false));
|
|
|
7508
7509
|
useIntersection({ root, rootMargin, threshold = 0, once = false, }: UseIntersectionOptions = {}): { ref: (node: T | null) => void; entry: IntersectionObserverEntry | null; isIntersecting: boolean }
|
|
7509
7510
|
```
|
|
7510
7511
|
|
|
7511
|
-
Whether an element is in view (IntersectionObserver). Attach the returned
|
|
7512
|
-
`ref`; read `isIntersecting` or the full `entry`. Returns false during
|
|
7513
|
-
server rendering.
|
|
7514
|
-
|
|
7515
|
-
```tsx
|
|
7516
|
-
const { ref, isIntersecting } = useIntersection<HTMLDivElement>({ rootMargin: "200px", once: true });
|
|
7517
|
-
<div ref={ref}>{isIntersecting && <HeavyChart />}</div>
|
|
7512
|
+
Whether an element is in view (IntersectionObserver). Attach the returned
|
|
7513
|
+
`ref`; read `isIntersecting` or the full `entry`. Returns false during
|
|
7514
|
+
server rendering.
|
|
7515
|
+
|
|
7516
|
+
```tsx
|
|
7517
|
+
const { ref, isIntersecting } = useIntersection<HTMLDivElement>({ rootMargin: "200px", once: true });
|
|
7518
|
+
<div ref={ref}>{isIntersecting && <HeavyChart />}</div>
|
|
7518
7519
|
```
|
|
7519
7520
|
|
|
7520
7521
|
## useElementSize
|
|
@@ -7523,13 +7524,13 @@ const { ref, isIntersecting } = useIntersection<HTMLDivElement>({ rootMargin: "2
|
|
|
7523
7524
|
useElementSize(): { ref: (node: T | null) => void; width: number; height: number; }
|
|
7524
7525
|
```
|
|
7525
7526
|
|
|
7526
|
-
An element's content-box size, kept current as it resizes
|
|
7527
|
-
(ResizeObserver). Attach the returned `ref`. Both are 0 until measured
|
|
7528
|
-
(and during server rendering).
|
|
7529
|
-
|
|
7530
|
-
```tsx
|
|
7531
|
-
const { ref, width } = useElementSize<HTMLDivElement>();
|
|
7532
|
-
<div ref={ref}>{width > 600 ? <WideLayout /> : <NarrowLayout />}</div>
|
|
7527
|
+
An element's content-box size, kept current as it resizes
|
|
7528
|
+
(ResizeObserver). Attach the returned `ref`. Both are 0 until measured
|
|
7529
|
+
(and during server rendering).
|
|
7530
|
+
|
|
7531
|
+
```tsx
|
|
7532
|
+
const { ref, width } = useElementSize<HTMLDivElement>();
|
|
7533
|
+
<div ref={ref}>{width > 600 ? <WideLayout /> : <NarrowLayout />}</div>
|
|
7533
7534
|
```
|
|
7534
7535
|
|
|
7535
7536
|
## useHydrated
|
|
@@ -7538,13 +7539,13 @@ const { ref, width } = useElementSize<HTMLDivElement>();
|
|
|
7538
7539
|
useHydrated(): boolean
|
|
7539
7540
|
```
|
|
7540
7541
|
|
|
7541
|
-
False during server rendering and hydration, true after. Use it to render
|
|
7542
|
-
browser-only content (dates in the user's time zone, `window` values)
|
|
7543
|
-
without a hydration mismatch.
|
|
7544
|
-
|
|
7545
|
-
```tsx
|
|
7546
|
-
const hydrated = useHydrated();
|
|
7547
|
-
return <span>{hydrated ? new Date().toLocaleTimeString() : null}</span>;
|
|
7542
|
+
False during server rendering and hydration, true after. Use it to render
|
|
7543
|
+
browser-only content (dates in the user's time zone, `window` values)
|
|
7544
|
+
without a hydration mismatch.
|
|
7545
|
+
|
|
7546
|
+
```tsx
|
|
7547
|
+
const hydrated = useHydrated();
|
|
7548
|
+
return <span>{hydrated ? new Date().toLocaleTimeString() : null}</span>;
|
|
7548
7549
|
```
|
|
7549
7550
|
|
|
7550
7551
|
## useReducedMotion
|
|
@@ -7553,8 +7554,8 @@ return <span>{hydrated ? new Date().toLocaleTimeString() : null}</span>;
|
|
|
7553
7554
|
useReducedMotion(): boolean
|
|
7554
7555
|
```
|
|
7555
7556
|
|
|
7556
|
-
True when the user asked the system to reduce motion. The library's own
|
|
7557
|
-
transitions already respect it (through the duration tokens); use this for
|
|
7557
|
+
True when the user asked the system to reduce motion. The library's own
|
|
7558
|
+
transitions already respect it (through the duration tokens); use this for
|
|
7558
7559
|
motion you drive from JavaScript (autoplay, scroll animations).
|
|
7559
7560
|
|
|
7560
7561
|
## useColorScheme
|
|
@@ -7563,7 +7564,7 @@ motion you drive from JavaScript (autoplay, scroll animations).
|
|
|
7563
7564
|
useColorScheme(): "light" | "dark"
|
|
7564
7565
|
```
|
|
7565
7566
|
|
|
7566
|
-
The system color scheme, `"light"` or `"dark"`, kept in sync (`"light"`
|
|
7567
|
+
The system color scheme, `"light"` or `"dark"`, kept in sync (`"light"`
|
|
7567
7568
|
during server rendering). To follow it, pass it to `Theme mode`.
|
|
7568
7569
|
|
|
7569
7570
|
## useOnline
|
|
@@ -7572,8 +7573,8 @@ during server rendering). To follow it, pass it to `Theme mode`.
|
|
|
7572
7573
|
useOnline(): boolean
|
|
7573
7574
|
```
|
|
7574
7575
|
|
|
7575
|
-
Whether the browser has a network connection, kept in sync (true during
|
|
7576
|
-
server rendering). Pair a visible change (a Banner) with a polite
|
|
7576
|
+
Whether the browser has a network connection, kept in sync (true during
|
|
7577
|
+
server rendering). Pair a visible change (a Banner) with a polite
|
|
7577
7578
|
announcement when it goes offline.
|
|
7578
7579
|
|
|
7579
7580
|
## useDocumentVisibility
|
|
@@ -7582,7 +7583,7 @@ announcement when it goes offline.
|
|
|
7582
7583
|
useDocumentVisibility(): DocumentVisibilityState
|
|
7583
7584
|
```
|
|
7584
7585
|
|
|
7585
|
-
`"visible"` or `"hidden"` (another tab, minimized window), kept in sync.
|
|
7586
|
+
`"visible"` or `"hidden"` (another tab, minimized window), kept in sync.
|
|
7586
7587
|
Use it to pause polling, video, or animations in the background.
|
|
7587
7588
|
|
|
7588
7589
|
## useViewportSize
|
|
@@ -7591,8 +7592,8 @@ Use it to pause polling, video, or animations in the background.
|
|
|
7591
7592
|
useViewportSize(): { width: number; height: number }
|
|
7592
7593
|
```
|
|
7593
7594
|
|
|
7594
|
-
The viewport's width and height in CSS pixels, kept in sync (0 × 0 during
|
|
7595
|
-
server rendering). For layout decisions, prefer CSS or `useMediaQuery`;
|
|
7595
|
+
The viewport's width and height in CSS pixels, kept in sync (0 × 0 during
|
|
7596
|
+
server rendering). For layout decisions, prefer CSS or `useMediaQuery`;
|
|
7596
7597
|
use this when you need the numbers.
|
|
7597
7598
|
|
|
7598
7599
|
## useVirtualizer
|
|
@@ -7601,27 +7602,27 @@ use this when you need the numbers.
|
|
|
7601
7602
|
useVirtualizer({ count, scrollElement, estimateSize, overscan = 6, gap = 0, paddingStart = 0, paddingEnd = 0, initialCount = 10, }: UseVirtualizerOptions): Virtualizer
|
|
7602
7603
|
```
|
|
7603
7604
|
|
|
7604
|
-
Headless list virtualization: renders only the items in view (plus
|
|
7605
|
-
`overscan`), so lists of 100,000 rows stay fast. Works with variable
|
|
7606
|
-
heights by measuring rendered items, and is SSR-safe (the server renders
|
|
7607
|
-
the first `initialCount` items). `VirtualList` is built on it; use the
|
|
7608
|
-
hook directly for custom layouts.
|
|
7609
|
-
|
|
7610
|
-
```tsx
|
|
7611
|
-
const scrollRef = useRef<HTMLDivElement>(null);
|
|
7612
|
-
const { virtualItems, totalSize, measureElement } = useVirtualizer({
|
|
7613
|
-
count: rows.length, scrollElement: scrollRef, estimateSize: 48,
|
|
7614
|
-
});
|
|
7615
|
-
<div ref={scrollRef} style={{ overflow: "auto", height: 400 }}>
|
|
7616
|
-
<div style={{ position: "relative", height: totalSize }}>
|
|
7617
|
-
{virtualItems.map((item) => (
|
|
7618
|
-
<div key={item.index} data-index={item.index} ref={measureElement}
|
|
7619
|
-
style={{ position: "absolute", top: 0, width: "100%", transform: `translateY(${item.start}px)` }}>
|
|
7620
|
-
{rows[item.index].name}
|
|
7621
|
-
</div>
|
|
7622
|
-
))}
|
|
7623
|
-
</div>
|
|
7624
|
-
</div>
|
|
7605
|
+
Headless list virtualization: renders only the items in view (plus
|
|
7606
|
+
`overscan`), so lists of 100,000 rows stay fast. Works with variable
|
|
7607
|
+
heights by measuring rendered items, and is SSR-safe (the server renders
|
|
7608
|
+
the first `initialCount` items). `VirtualList` is built on it; use the
|
|
7609
|
+
hook directly for custom layouts.
|
|
7610
|
+
|
|
7611
|
+
```tsx
|
|
7612
|
+
const scrollRef = useRef<HTMLDivElement>(null);
|
|
7613
|
+
const { virtualItems, totalSize, measureElement } = useVirtualizer({
|
|
7614
|
+
count: rows.length, scrollElement: scrollRef, estimateSize: 48,
|
|
7615
|
+
});
|
|
7616
|
+
<div ref={scrollRef} style={{ overflow: "auto", height: 400 }}>
|
|
7617
|
+
<div style={{ position: "relative", height: totalSize }}>
|
|
7618
|
+
{virtualItems.map((item) => (
|
|
7619
|
+
<div key={item.index} data-index={item.index} ref={measureElement}
|
|
7620
|
+
style={{ position: "absolute", top: 0, width: "100%", transform: `translateY(${item.start}px)` }}>
|
|
7621
|
+
{rows[item.index].name}
|
|
7622
|
+
</div>
|
|
7623
|
+
))}
|
|
7624
|
+
</div>
|
|
7625
|
+
</div>
|
|
7625
7626
|
```
|
|
7626
7627
|
|
|
7627
7628
|
## useFillSlot
|
|
@@ -7648,7 +7649,7 @@ Pixel widths for each breakpoint, for use in JS.
|
|
|
7648
7649
|
getLocaleDirection(locale: string): "ltr" | "rtl"
|
|
7649
7650
|
```
|
|
7650
7651
|
|
|
7651
|
-
The writing direction of a BCP 47 locale: `"rtl"` for Arabic, Hebrew,
|
|
7652
|
+
The writing direction of a BCP 47 locale: `"rtl"` for Arabic, Hebrew,
|
|
7652
7653
|
Persian, Urdu, and other right-to-left languages and scripts, else `"ltr"`.
|
|
7653
7654
|
|
|
7654
7655
|
## plural
|
|
@@ -7657,11 +7658,11 @@ Persian, Urdu, and other right-to-left languages and scripts, else `"ltr"`.
|
|
|
7657
7658
|
plural(locale: string): PluralFn
|
|
7658
7659
|
```
|
|
7659
7660
|
|
|
7660
|
-
Plural selector bound to a locale:
|
|
7661
|
-
|
|
7662
|
-
```ts
|
|
7663
|
-
const p = plural("ru");
|
|
7664
|
-
p(3, { one: "# файл", few: "# файла", many: "# файлов", other: "# файла" }); // "3 файла"
|
|
7661
|
+
Plural selector bound to a locale:
|
|
7662
|
+
|
|
7663
|
+
```ts
|
|
7664
|
+
const p = plural("ru");
|
|
7665
|
+
p(3, { one: "# файл", few: "# файла", many: "# файлов", other: "# файла" }); // "3 файла"
|
|
7665
7666
|
```
|
|
7666
7667
|
|
|
7667
7668
|
## en
|
|
@@ -7678,7 +7679,7 @@ English: the default messages, and the template for every other locale.
|
|
|
7678
7679
|
mergeMessages(base: Messages, override: PartialMessages | undefined): Messages
|
|
7679
7680
|
```
|
|
7680
7681
|
|
|
7681
|
-
Overlays partial messages on a complete set: missing strings keep the
|
|
7682
|
+
Overlays partial messages on a complete set: missing strings keep the
|
|
7682
7683
|
base value. Functions and arrays replace whole.
|
|
7683
7684
|
|
|
7684
7685
|
## resolveElement
|
|
@@ -7822,12 +7823,12 @@ Locks page scrolling. Returns a function that releases this lock (safe to call t
|
|
|
7822
7823
|
getHotkeyHandler(hotkeys: HotkeyItem[])
|
|
7823
7824
|
```
|
|
7824
7825
|
|
|
7825
|
-
A `keydown` handler for one element (an editor, a list): pass it to
|
|
7826
|
-
`onKeyDown`. Same shortcut format as `useHotkeys`; shortcuts fire while
|
|
7827
|
-
typing in that element.
|
|
7828
|
-
|
|
7829
|
-
```tsx
|
|
7830
|
-
<Textarea onKeyDown={getHotkeyHandler([["mod+enter", send]])} />
|
|
7826
|
+
A `keydown` handler for one element (an editor, a list): pass it to
|
|
7827
|
+
`onKeyDown`. Same shortcut format as `useHotkeys`; shortcuts fire while
|
|
7828
|
+
typing in that element.
|
|
7829
|
+
|
|
7830
|
+
```tsx
|
|
7831
|
+
<Textarea onKeyDown={getHotkeyHandler([["mod+enter", send]])} />
|
|
7831
7832
|
```
|
|
7832
7833
|
|
|
7833
7834
|
## cx
|
|
@@ -8029,13 +8030,21 @@ createBrandPalette(color: BrandColor): BrandPalette
|
|
|
8029
8030
|
Builds an accessible brand palette, for both modes, from any hex color.
|
|
8030
8031
|
Throws a TypeError for anything that isn't `#rgb` or `#rrggbb`.
|
|
8031
8032
|
|
|
8033
|
+
## LIME_ACCENT
|
|
8034
|
+
|
|
8035
|
+
```ts
|
|
8036
|
+
LIME_ACCENT: AccentPalette
|
|
8037
|
+
```
|
|
8038
|
+
|
|
8039
|
+
The lime accent (`accent="lime"`, and the black brand's accent): the original bright yellow-green.
|
|
8040
|
+
|
|
8032
8041
|
## VOLT_ACCENT
|
|
8033
8042
|
|
|
8034
8043
|
```ts
|
|
8035
|
-
VOLT_ACCENT
|
|
8044
|
+
VOLT_ACCENT
|
|
8036
8045
|
```
|
|
8037
8046
|
|
|
8038
|
-
|
|
8047
|
+
@deprecated Renamed to `LIME_ACCENT`.
|
|
8039
8048
|
|
|
8040
8049
|
## createAccentPalette
|
|
8041
8050
|
|
|
@@ -8056,7 +8065,7 @@ brandAccent(primary: string): AccentPalette
|
|
|
8056
8065
|
|
|
8057
8066
|
The default accent of a brand: a bright, lighter shade of its primary
|
|
8058
8067
|
hue (blue gets a sky blue, purple a lavender, gold an amber, green a
|
|
8059
|
-
mint). Colorless brands (black) keep the
|
|
8068
|
+
mint). Colorless brands (black) keep the lime.
|
|
8060
8069
|
|
|
8061
8070
|
## accentPaletteVars
|
|
8062
8071
|
|
|
@@ -8108,9 +8117,9 @@ Then use `<html data-brand="acme">`. Names are letters, digits, and dashes.
|
|
|
8108
8117
|
isEmail(value: string, { requireTld = true }: EmailOptions = {}): boolean
|
|
8109
8118
|
```
|
|
8110
8119
|
|
|
8111
|
-
True for an email address in the usual format: the HTML spec's rules
|
|
8112
|
-
(what browsers check for `type="email"`), plus no leading, trailing, or
|
|
8113
|
-
doubled dots before the `@`, length limits (64 before the `@`, 254 in all),
|
|
8120
|
+
True for an email address in the usual format: the HTML spec's rules
|
|
8121
|
+
(what browsers check for `type="email"`), plus no leading, trailing, or
|
|
8122
|
+
doubled dots before the `@`, length limits (64 before the `@`, 254 in all),
|
|
8114
8123
|
and, by default, a top-level domain.
|
|
8115
8124
|
|
|
8116
8125
|
## isIPv4
|
|
@@ -8119,7 +8128,7 @@ and, by default, a top-level domain.
|
|
|
8119
8128
|
isIPv4(value: string): boolean
|
|
8120
8129
|
```
|
|
8121
8130
|
|
|
8122
|
-
True for a dotted IPv4 address: four numbers 0-255 (`192.168.0.1`), no
|
|
8131
|
+
True for a dotted IPv4 address: four numbers 0-255 (`192.168.0.1`), no
|
|
8123
8132
|
leading zeros (`010.0.0.1` is ambiguous, so it's rejected).
|
|
8124
8133
|
|
|
8125
8134
|
## isIPv6
|
|
@@ -8128,9 +8137,9 @@ leading zeros (`010.0.0.1` is ambiguous, so it's rejected).
|
|
|
8128
8137
|
isIPv6(value: string): boolean
|
|
8129
8138
|
```
|
|
8130
8139
|
|
|
8131
|
-
True for an IPv6 address: eight groups of 1-4 hex digits, with `::`
|
|
8132
|
-
standing for one or more zero groups (once at most), and an optional
|
|
8133
|
-
IPv4 tail (`::ffff:192.168.0.1`). Zone ids (`%eth0`) and brackets aren't
|
|
8140
|
+
True for an IPv6 address: eight groups of 1-4 hex digits, with `::`
|
|
8141
|
+
standing for one or more zero groups (once at most), and an optional
|
|
8142
|
+
IPv4 tail (`::ffff:192.168.0.1`). Zone ids (`%eth0`) and brackets aren't
|
|
8134
8143
|
accepted.
|
|
8135
8144
|
|
|
8136
8145
|
## isIP
|
|
@@ -8163,10 +8172,10 @@ True when a value counts as empty (nothing, blank text, or an empty file input).
|
|
|
8163
8172
|
rules
|
|
8164
8173
|
```
|
|
8165
8174
|
|
|
8166
|
-
Rule helpers for `useFormValidation`, with messages from the locale:
|
|
8167
|
-
|
|
8168
|
-
```ts
|
|
8169
|
-
useFormValidation({ rules: { email: rules.email(), server: rules.ip({ version: 4 }) } });
|
|
8175
|
+
Rule helpers for `useFormValidation`, with messages from the locale:
|
|
8176
|
+
|
|
8177
|
+
```ts
|
|
8178
|
+
useFormValidation({ rules: { email: rules.email(), server: rules.ip({ version: 4 }) } });
|
|
8170
8179
|
```
|
|
8171
8180
|
|
|
8172
8181
|
## detectPlatform
|
|
@@ -8183,8 +8192,8 @@ The current platform from the browser (`"windows"` during server rendering).
|
|
|
8183
8192
|
parseHotkey(hotkey: string, platform: HotkeyPlatform = detectPlatform()): ParsedHotkey | null
|
|
8184
8193
|
```
|
|
8185
8194
|
|
|
8186
|
-
Parses a shortcut like `"mod+k"`, `"shift+mod+p"`, `"ctrl+/"`, or
|
|
8187
|
-
`"escape"` into modifiers and a key. `mod` is ⌘ on Mac and Ctrl
|
|
8195
|
+
Parses a shortcut like `"mod+k"`, `"shift+mod+p"`, `"ctrl+/"`, or
|
|
8196
|
+
`"escape"` into modifiers and a key. `mod` is ⌘ on Mac and Ctrl
|
|
8188
8197
|
elsewhere. Returns null when there is no key.
|
|
8189
8198
|
|
|
8190
8199
|
## matchesHotkey
|
|
@@ -8217,6 +8226,6 @@ True when the element accepts typed text, so a global hotkey must not steal its
|
|
|
8217
8226
|
copyToClipboard(text: string): Promise<void>
|
|
8218
8227
|
```
|
|
8219
8228
|
|
|
8220
|
-
Copies text to the clipboard: the async Clipboard API when it's allowed,
|
|
8221
|
-
else a hidden-textarea fallback (insecure contexts, denied permission,
|
|
8229
|
+
Copies text to the clipboard: the async Clipboard API when it's allowed,
|
|
8230
|
+
else a hidden-textarea fallback (insecure contexts, denied permission,
|
|
8222
8231
|
older browsers). Focus returns to where it was. Rejects when both fail.
|