@nxgt/material 3.72.0 → 3.74.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/CHANGELOG.md +44 -0
- package/README.md +3 -1
- package/dist/{alert-dialog-A8K8zai1.js → alert-dialog-BfO_ri-N.js} +1 -1
- package/dist/{async-slice-B8933IHY.js → async-slice-roMAJVzG.js} +1 -1
- package/dist/{button-C8moFnIT.js → button-DgenqmpS.js} +1 -1
- package/dist/charts.js +3 -3
- package/dist/{chip-B6AY1E91.js → chip-CiDczNxO.js} +2 -2
- package/dist/{code-editor-DQZIKL54.js → code-editor-CohlhFsA.js} +5 -5
- package/dist/code-editor.js +5 -5
- package/dist/{code-language-items-8VL0aMKG.js → code-language-items-Cs8GLYDp.js} +2 -2
- package/dist/components/ui/display/seat-ring/seat-ring.css +26 -0
- package/dist/components/ui/feedback/feedback.css +2 -0
- package/dist/components/ui/feedback/moment/moment.css +22 -0
- package/dist/{components-EHdmrvV4.js → components-y18qSFzl.js} +14184 -13894
- package/dist/components.js +28 -28
- package/dist/{dialog-WuLTwxkr.js → dialog-AGsB3bv4.js} +4 -4
- package/dist/dnd.js +1 -1
- package/dist/{dropdown-menu-tadySeGH.js → dropdown-menu-CzR6JP31.js} +1 -1
- package/dist/editor.js +10 -10
- package/dist/{empty-state-ZYiFSSBQ.js → empty-state-DjHGMp5F.js} +2 -2
- package/dist/{field-blur-BYR0yE5L.js → field-blur-CdASxjL7.js} +1 -1
- package/dist/{field-blur-context-bEhByoK-.js → field-blur-context-kZ4SD7xu.js} +1 -1
- package/dist/{hooks-GpwD8iDu.js → hooks-Dqq8O3Az.js} +2 -2
- package/dist/hooks.js +2 -2
- package/dist/{hover-card-BowaI_ra.js → hover-card-BPKqte4a.js} +1 -1
- package/dist/i18n.js +3 -3
- package/dist/{icon-badge-B1B0Lg02.js → icon-badge-B9uvDoyY.js} +3 -3
- package/dist/{icon-button-BbGU17cb.js → icon-button-Cr-DyDGg.js} +1 -1
- package/dist/lib/components/ui/collections/filter/bar/filter-bar-classes.d.ts +2 -2
- package/dist/lib/components/ui/collections/filter/bar/filter-bar-view.d.ts +1 -1
- package/dist/lib/components/ui/collections/filter/facets/filter-facets.d.ts +1 -1
- package/dist/lib/components/ui/collections/filter/query/types.d.ts +6 -0
- package/dist/lib/components/ui/collections/filter/query/view-types.d.ts +1 -0
- package/dist/lib/components/ui/collections/filter/sections/chips/filter-chip-body.d.ts +1 -1
- package/dist/lib/components/ui/collections/filter/sections/filter-search.d.ts +1 -0
- package/dist/lib/components/ui/collections/filter/sections/filter-sections-classes.d.ts +8 -0
- package/dist/lib/components/ui/collections/server-table/partials/server-table-empty-page.d.ts +4 -0
- package/dist/lib/components/ui/collections/server-table/types.d.ts +7 -1
- package/dist/lib/components/ui/display/highlighted-text/highlight-ranges.d.ts +11 -0
- package/dist/lib/components/ui/display/highlighted-text/highlighted-text.d.ts +16 -0
- package/dist/lib/components/ui/display/highlighted-text/index.d.ts +2 -0
- package/dist/lib/components/ui/display/index.d.ts +1 -0
- package/dist/lib/components/ui/display/list-tile/list-tile.d.ts +10 -1
- package/dist/lib/components/ui/display/list-tile/partials/list-tile-box.d.ts +16 -0
- package/dist/lib/components/ui/display/list-tile/partials/list-tile-classes.d.ts +3 -1
- package/dist/lib/components/ui/display/list-tile/partials/list-tile-line.d.ts +1 -1
- package/dist/lib/components/ui/display/list-tile/partials/list-tile-row.d.ts +1 -1
- package/dist/lib/components/ui/display/seat-ring/types.d.ts +6 -0
- package/dist/lib/components/ui/feedback/index.d.ts +1 -0
- package/dist/lib/components/ui/feedback/moment/index.d.ts +1 -0
- package/dist/lib/components/ui/feedback/moment/moment-body.d.ts +9 -0
- package/dist/lib/components/ui/feedback/moment/moment.d.ts +33 -0
- package/dist/lib/components/ui/fields/choice-list/choice-list-control.d.ts +17 -0
- package/dist/lib/components/ui/fields/choice-list/choice-list-focus.d.ts +49 -0
- package/dist/lib/components/ui/fields/contacts/placeholders.d.ts +1 -1
- package/dist/lib/components/ui/overlays/command/command-dialog.d.ts +8 -1
- package/dist/lib/components/ui/selection/autocomplete/autocomplete-enter.d.ts +7 -3
- package/dist/lib/i18n/resources/en/en.d.ts +4 -0
- package/dist/lib/i18n/resources/en/material.json.d.ts +5 -1
- package/dist/lib/i18n/resources/fr/fr.d.ts +4 -0
- package/dist/lib/i18n/resources/fr/material.json.d.ts +5 -1
- package/dist/lib/i18n/resources/resources.d.ts +8 -0
- package/dist/lib/i18n/translator.d.ts +1 -1
- package/dist/lib.js +1 -1
- package/dist/main.js +42 -42
- package/dist/map.js +8 -8
- package/dist/material.css +1 -1
- package/dist/pdf-reader.js +1 -1
- package/dist/print.js +1 -1
- package/dist/{public-CFj2qn7l.js → public-DC9VQw4Z.js} +9 -9
- package/dist/{rich-code-block-B7Teg7-e.js → rich-code-block-DBSL9zEN.js} +5 -5
- package/dist/{sortable-provider-y5sFhRDj.js → sortable-provider-C4tk5esY.js} +19 -13
- package/dist/{spinner-C5Kb6MWu.js → spinner-B2MubVWb.js} +1 -1
- package/dist/theme-picker.js +2 -2
- package/dist/{theme-toggle-B1JZg7mU.js → theme-toggle-BInlu21G.js} +1 -1
- package/dist/{toolbar-items-m_1FTFPQ.js → toolbar-items-CRJSx1MU.js} +3 -3
- package/dist/{translate-material-D1ndrd7a.js → translate-material-pVlPJ1v4.js} +1 -1
- package/dist/{translator-CtEC_AQa.js → translator-BoYCward.js} +10 -2
- package/dist/{typography-prQHb3gI.js → typography-B6YMbCge.js} +1 -1
- package/dist/{use-chat-composer-DBiyNXvL.js → use-chat-composer-Cn6yaeO0.js} +1924 -1911
- package/dist/{use-heading-spy-Bzj5mIUZ.js → use-heading-spy-B_Z4ArDh.js} +4 -4
- package/dist/{use-material-translation-C6H0B4kE.js → use-material-translation-CIS2n3RB.js} +1 -1
- package/dist/{use-return-focus-CkUX1HFl.js → use-return-focus-DNQtADAR.js} +1 -1
- package/docs/components/data-display.md +58 -5
- package/docs/components/data-table-filter-and-lists.md +8 -3
- package/docs/components/feedback-and-status.md +40 -0
- package/docs/components/form-fields.md +16 -0
- package/docs/components/overlays-and-menus.md +2 -1
- package/docs/components/primitives.md +2 -1
- package/docs/components/selection-and-choice.md +4 -2
- package/docs/guides/i18n.md +4 -1
- package/docs/guides/theming.md +4 -0
- package/docs/previews/data-display-highlightedtext.webp +0 -0
- package/docs/roadmap.md +1 -0
- package/docs/troubleshooting.md +37 -0
- package/lib/components/ui/display/seat-ring/seat-ring.css +26 -0
- package/lib/components/ui/feedback/feedback.css +2 -0
- package/lib/components/ui/feedback/moment/moment.css +22 -0
- package/package.json +3 -3
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { t as e } from "./utils-BLfntITJ.js";
|
|
2
|
-
import { a as t, c as n, d as r, i, n as a, r as o, t as s, u as c } from "./alert-dialog-
|
|
3
|
-
import { a as l } from "./button-
|
|
4
|
-
import { i as u } from "./translate-material-
|
|
5
|
-
import { t as d } from "./use-material-translation-
|
|
2
|
+
import { a as t, c as n, d as r, i, n as a, r as o, t as s, u as c } from "./alert-dialog-BfO_ri-N.js";
|
|
3
|
+
import { a as l } from "./button-DgenqmpS.js";
|
|
4
|
+
import { i as u } from "./translate-material-pVlPJ1v4.js";
|
|
5
|
+
import { t as d } from "./use-material-translation-CIS2n3RB.js";
|
|
6
6
|
import { _ as f, g as p, h as m, n as h, v as g, y as _ } from "./number.utils-BG_eEt5g.js";
|
|
7
7
|
import { useCallback as v, useEffect as y, useMemo as b, useRef as x, useState as S } from "react";
|
|
8
8
|
import { Fragment as C, jsx as w, jsxs as T } from "react/jsx-runtime";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { o as e, r as t } from "./dist-DVRQkaTK.js";
|
|
2
2
|
import { a as n, c as r, i, l as a, o, r as s, s as c } from "./dist-lmHmz_bu.js";
|
|
3
|
-
import { C as l, S as u, w as d } from "./spinner-
|
|
3
|
+
import { C as l, S as u, w as d } from "./spinner-B2MubVWb.js";
|
|
4
4
|
import { c as f, i as p, l as m, o as h, r as g, s as ee } from "./in-dialog-Vwkyp-M5.js";
|
|
5
5
|
import { r as _ } from "./escape-owner-DpaP0lm1.js";
|
|
6
6
|
import * as v from "react";
|
|
@@ -13,6 +13,7 @@ from `@nxgt/material/components`.
|
|
|
13
13
|
| <img src="../previews/data-display-shape.webp" width="96" alt=""> | [Shape](#shape) | Material 3 Expressive's shapes as a backdrop, an icon container or a mask for a photo |
|
|
14
14
|
| <img src="../previews/data-display-badge.webp" width="96" alt=""> | [Badge](#badge) | Status pill, 20 px, in seven tones, soft or outlined, with an optional decorative `icon` before the words |
|
|
15
15
|
| <img src="../previews/data-display-countbadge.webp" width="96" alt=""> | [CountBadge](#countbadge) | Count in the corner of its children |
|
|
16
|
+
| <img src="../previews/data-display-highlightedtext.webp" width="96" alt=""> | [HighlightedText](#highlightedtext) | A string with the words of a search query in a themed `<mark>` |
|
|
16
17
|
| <img src="../previews/data-display-dayseparator.webp" width="96" alt=""> | [DaySeparator](#dayseparator) | "Today", "Yesterday" or the date between two hairlines |
|
|
17
18
|
| <img src="../previews/data-display-periodcards.webp" width="96" alt=""> | [PeriodCards](#periodcards) | Consecutive date ranges (terms, sprints) as cards, with a current marker and an optional link per card |
|
|
18
19
|
| <img src="../previews/data-display-chip.webp" width="96" alt=""> | [Chip](#chip) | Three looks and a dashed add pill, with slots, a selected state and a dismiss button |
|
|
@@ -147,6 +148,7 @@ import { SeatRing } from '@nxgt/material/components';
|
|
|
147
148
|
seats={[
|
|
148
149
|
{ id: 'ada', label: 'Ada Example', status: { label: 'Ready', tone: 'success' }, badge: 'Host' },
|
|
149
150
|
{ id: 'bo', label: 'Bo Sample', status: { label: 'Away', tone: 'warning' } },
|
|
151
|
+
{ id: 'cy', label: 'Cy Demo', out: true },
|
|
150
152
|
{ id: 'free', label: 'Free', empty: true },
|
|
151
153
|
]}
|
|
152
154
|
highlightedId="ada"
|
|
@@ -159,7 +161,7 @@ import { SeatRing } from '@nxgt/material/components';
|
|
|
159
161
|
|
|
160
162
|
| Prop | Type | Default | Notes |
|
|
161
163
|
| --- | --- | --- | --- |
|
|
162
|
-
| `seats` | `Seat[]` | required | `{ id, label, avatar?: { src?, fallback? }, status?: { label, tone? }, badge?, disabled?, empty? }`; clockwise from the top |
|
|
164
|
+
| `seats` | `Seat[]` | required | `{ id, label, avatar?: { src?, fallback? }, status?: { label, tone? }, badge?, disabled?, out?, empty? }`; clockwise from the top |
|
|
163
165
|
| `layout` | `'ring' \| 'grid'` | `'ring'` | `ring` falls back to the grid in a narrow box and past the seat limit (10 seats) |
|
|
164
166
|
| `size` | `'sm' \| 'md' \| 'lg'` | `'md'` | seat width 4.75, 6 or 8rem; ring from a box of 32, 38 or 46rem; at most 10 seats on the circle |
|
|
165
167
|
| `selectionMode` | `'none' \| 'single' \| 'multiple'` | `'none'` | `none`: a list; otherwise a listbox |
|
|
@@ -183,6 +185,7 @@ no `style` attribute and a strict CSP is fine.
|
|
|
183
185
|
keys, Home and End move the focus (an empty seat is skipped); Space or Enter
|
|
184
186
|
picks, and pressing the chosen seat again clears it.
|
|
185
187
|
- A seat is named by its label and its status text, never by colour alone.
|
|
188
|
+
- `out: true` marks an eliminated seat: it stays visible, dimmed, with the name struck through, the avatar greyed and the word "Out" (`material.seat-ring.out`, "Éliminé" in French) written in it, so the word is part of the seat's name (label, status, "Out", then the badge); it stays pickable unless `disabled`. An empty seat ignores it. Seat status words ("Eliminated") remain the app's own.
|
|
186
189
|
- In a listbox, empty and `disabled` seats are `aria-disabled`, and a disabled
|
|
187
190
|
seat can be reached but not picked (in a list, `disabled` only dims the seat).
|
|
188
191
|
- Put no button in a selectable seat: interactive content (an "Invite" action
|
|
@@ -417,6 +420,35 @@ import { CountBadge, IconButton } from '@nxgt/material/components';
|
|
|
417
420
|
|
|
418
421
|
---
|
|
419
422
|
|
|
423
|
+
## HighlightedText
|
|
424
|
+
|
|
425
|
+

|
|
426
|
+
|
|
427
|
+
A string with the words of a search query in a themed `<mark>`. Case, accents and ligatures are folded (`œ` is `oe`, `æ` is `ae`, `ß` is `ss`), and a query word matches at the start of a word, as a search engine's normaliser does.
|
|
428
|
+
|
|
429
|
+
```tsx
|
|
430
|
+
import { HighlightedText, highlightRanges } from '@nxgt/material/components';
|
|
431
|
+
|
|
432
|
+
<HighlightedText text="Œuvres d'été" query="oeuvre ete" />
|
|
433
|
+
// <mark>Œuvre</mark>s d'<mark>été</mark>
|
|
434
|
+
|
|
435
|
+
// For a table or a custom renderer: offsets into the original text.
|
|
436
|
+
highlightRanges("Œuvres d'été", 'oeuvre ete'); // [[0, 5], [9, 12]]
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
| Prop | Type | Default | Effect |
|
|
440
|
+
| --- | --- | --- | --- |
|
|
441
|
+
| `text` | `string` | — | the string to show |
|
|
442
|
+
| `query` | `string` | — | search words; a blank query marks nothing |
|
|
443
|
+
| `locale` | `string` | runtime's | language for lowercasing |
|
|
444
|
+
| span props | | | `className` and the other `span` props go to the wrapping `span` |
|
|
445
|
+
|
|
446
|
+
`highlightRanges(text, query, locale?)` is pure and returns sorted, non-overlapping `[start, end)` offsets. The marks use theme tokens (readable in dark mode) and the system `Mark` colours in forced colours.
|
|
447
|
+
|
|
448
|
+
**Storybook:** `Data display/HighlightedText`
|
|
449
|
+
|
|
450
|
+
---
|
|
451
|
+
|
|
420
452
|
## DaySeparator
|
|
421
453
|
|
|
422
454
|

|
|
@@ -974,15 +1006,16 @@ A tile with an `href` ends with a discreet chevron after `trailing`: decorative
|
|
|
974
1006
|
| `linkComponent` | `AppShellLinkComponent` | plain `<a>` | the link element, as in the app shell: takes `href`, spreads every other prop, forwards `ref`. Defaults to the [`LinkComponentProvider`](./primitives.md#linkcomponentprovider)'s link when one is set. |
|
|
975
1007
|
| `onClick` | `MouseEventHandler` | — | renders a `<button>` |
|
|
976
1008
|
| `selected` | `boolean` | `false` | the current row: drawn selected; a link gets `aria-current="page"` (your own `aria-current` replaces it), a button `aria-pressed` |
|
|
977
|
-
| `toggle` | `Switch` props | — | makes the tile a switch row (see below): the whole row toggles a Switch at its end; `href`, `onClick`, `actions`, `chips`, `chevron` and `linkComponent` are refused beside it by type |
|
|
1009
|
+
| `toggle` | `Switch` props | — | makes the tile a switch row (see below): the whole row toggles a Switch at its end; `href`, `onClick`, `actions`, `chips`, `content`, `chevron` and `linkComponent` are refused beside it by type |
|
|
978
1010
|
| `size` | `'sm' \| 'md'` | `'md'` | `sm` is the dense row (with `chips`, the record row, see below) |
|
|
979
1011
|
| `leading`, `trailing`, `subtitle` | `ReactNode` | — | slots; `trailing` sits inside the link, so it holds decoration only |
|
|
980
1012
|
| `actions` | `ReactNode` | — | buttons at the end of the tile, outside the link, vertically centred (`data-slot="item-actions"`) |
|
|
981
1013
|
| `chips` | `ReactNode` | — | tags after the text, in the compact record row (see below); inside the link, so decoration only; part of the row's accessible name, keep labels short |
|
|
1014
|
+
| `content` | `ReactNode` | — | full-width content under the title row, inside the tile's box and outside its link or button: it may hold inputs and buttons (an expected value beside an editable field), and its clicks do not reach `onClick`. Not available on a `toggle` row |
|
|
982
1015
|
| `variant` | `'tonal' \| 'divided'` | `'tonal'` | `divided`: flat rows with no tonal surface, a hover tint and the record-row layout; the hairline comes with `as="li"` |
|
|
983
1016
|
| `inset` | `boolean` | `false` | With `variant="divided"`: 16px of inline padding (M3's list-item inset) in place of 4px, for a list inside a `Card`; the hairlines on the `<li>` still run edge to edge. Ignored by `tonal` |
|
|
984
1017
|
| `as` | `'li'` | — | renders the tile inside a `<li>`, for a `<ul>` you own |
|
|
985
|
-
| `disabled` | `boolean` | — | disables the link or button, and the `actions` with it |
|
|
1018
|
+
| `disabled` | `boolean` | — | disables the link or button, and the `actions` and `content` with it (both become inert) |
|
|
986
1019
|
|
|
987
1020
|
With a router, pass `linkComponent` so a click navigates on the client instead of reloading the page (React Router's `Link` takes `to`, so wrap it):
|
|
988
1021
|
|
|
@@ -999,7 +1032,27 @@ export function SettingsLink() {
|
|
|
999
1032
|
}
|
|
1000
1033
|
```
|
|
1001
1034
|
|
|
1002
|
-
A link tile's `trailing` sits inside its `<a>`, which cannot hold buttons. Put edit / remove / menu buttons in `actions`: they render outside the link, in the tile's box, while the link still covers the whole tile (a click on the text navigates, a click on a button does not) and hover and selected styles stay on the tile. Tab goes to the link, then to the buttons
|
|
1035
|
+
A link tile's `trailing` sits inside its `<a>`, which cannot hold buttons. Put edit / remove / menu buttons in `actions`: they render outside the link, in the tile's box, while the link still covers the whole tile (a click on the text navigates, a click on a button does not) and hover and selected styles stay on the tile. Tab goes to the link, then to the buttons, then to the controls of `content`. A tile without `href` renders `actions` the same way. With `actions`, `className`, `style` and `data-*` go on the tile's box and every other prop (`aria-label`, `id`, handlers…) on the link or button; `actions={null}` (or `false`) is no actions. and the text of a link tile with actions cannot be selected (the link is stretched over the tile).
|
|
1036
|
+
|
|
1037
|
+
**Content under the row.** `content` renders full-width under the title row, inside the tile's box and outside its link or button, so it may hold inputs and buttons (an expected value beside an editable field). Its clicks never reach the tile's `onClick`.
|
|
1038
|
+
|
|
1039
|
+
```tsx
|
|
1040
|
+
<ul className="m-0 list-none p-0">
|
|
1041
|
+
<ListTile
|
|
1042
|
+
as="li"
|
|
1043
|
+
variant="divided"
|
|
1044
|
+
title="Item"
|
|
1045
|
+
subtitle="SKU-1 · LOT-2"
|
|
1046
|
+
actions={<IconButton label="Remove" onClick={remove}><Trash2 /></IconButton>}
|
|
1047
|
+
content={
|
|
1048
|
+
<label className="flex items-center justify-between gap-2">
|
|
1049
|
+
Expected 12
|
|
1050
|
+
<NumberField aria-label="Counted" value={counted} onChange={setCounted} />
|
|
1051
|
+
</label>
|
|
1052
|
+
}
|
|
1053
|
+
/>
|
|
1054
|
+
</ul>
|
|
1055
|
+
```
|
|
1003
1056
|
|
|
1004
1057
|
```tsx
|
|
1005
1058
|
import { Pencil } from 'lucide-react';
|
|
@@ -1070,7 +1123,7 @@ function GuideList({ guides }: { guides: { to: string; title: string }[] }) {
|
|
|
1070
1123
|
}
|
|
1071
1124
|
```
|
|
1072
1125
|
|
|
1073
|
-
**A switch row.** `toggle` takes a Switch's props (`checked`, `defaultChecked`, `onCheckedChange`, `name`, `thumbIcons`…). The tile is then a `<label>` for the switch, so a press anywhere on the row toggles it; the switch is the one tab stop (Space or Enter), named by `title` and described by `subtitle`, and `disabled` on the tile disables it. A switch row is neither a link nor a button: `href`, `onClick`, `actions` and `chevron` do not apply, and `trailing` sits before the switch.
|
|
1126
|
+
**A switch row.** `toggle` takes a Switch's props (`checked`, `defaultChecked`, `onCheckedChange`, `name`, `thumbIcons`…). The tile is then a `<label>` for the switch, so a press anywhere on the row toggles it; the switch is the one tab stop (Space or Enter), named by `title` and described by `subtitle`, and `disabled` on the tile disables it. A switch row is neither a link nor a button: `href`, `onClick`, `actions`, `content` and `chevron` do not apply, and `trailing` sits before the switch.
|
|
1074
1127
|
|
|
1075
1128
|
```tsx
|
|
1076
1129
|
const [on, setOn] = useState(true);
|
|
@@ -1018,7 +1018,7 @@ export default function Students() {
|
|
|
1018
1018
|
table: [Cards and tiles](../guides/cards-and-tiles.md)).
|
|
1019
1019
|
|
|
1020
1020
|
Its props are `ServerTableProps<T>`; `filter` is a `ServerTableFilter`,
|
|
1021
|
-
`empty`
|
|
1021
|
+
`empty` an optional `ServerTableEmpty`, and `bulkActions` gets a
|
|
1022
1022
|
`ServerTableSelection`.
|
|
1023
1023
|
|
|
1024
1024
|
| Prop | Type | Default | Effect |
|
|
@@ -1045,7 +1045,7 @@ Its props are `ServerTableProps<T>`; `filter` is a `ServerTableFilter`,
|
|
|
1045
1045
|
| `filterRef` | `Ref<ServerTableFilterHandle>` | — | with `filter`: `filterRef.current.focus()` focuses the Filter's first control, the search, else the first quick filter, "Add filter" or "Filters (N)" the width shows |
|
|
1046
1046
|
| `sorting` | `createSorting(…)` | — | headers sorted from the URL; without it, no column is sortable (the server sorts, so pass `sorting` to let people sort), and the phone list bar shows only for selection |
|
|
1047
1047
|
| `filters` | `tableFilters(model)` | — | without `filter`: "nothing matches" and its clear |
|
|
1048
|
-
| `empty` | `ServerTableEmpty`: `{ none, noMatch, clear?, headingLevel?, iconStyle? }` |
|
|
1048
|
+
| `empty` | `ServerTableEmpty`: `{ none, noMatch, clear?, headingLevel?, iconStyle? }` | the `DataTable` default ("No data available", or "No results" when filtered) | the empty page. Leave it out when your page answers "nothing yet" and "nothing matches" itself and renders the table only when there are rows; the failure with Retry and the page past the last show either way. When given: `none` and `noMatch` are a title or a `ListEmptyPage` (`{ title, description?, illustration?, action? }`); `headingLevel` (default 2) is the level of its title and of the error's; `iconStyle` styles the scenes (see below) |
|
|
1049
1049
|
| `error` | `ServerTableError \| null` | — | the fetch failed: the failure and a Retry replace the rows |
|
|
1050
1050
|
| `onRetry` | `() => unknown` | — | the error's Retry; a returned promise keeps it loading |
|
|
1051
1051
|
| `onClearFilters` | `() => void` | focus the table | without `filter`, after "clear" |
|
|
@@ -1936,8 +1936,13 @@ function Notifications({ items }: { items: Notification[] }) {
|
|
|
1936
1936
|
the loader's own; see [A field's default](#a-fields-default)),
|
|
1937
1937
|
`resultCount`, `loading`; every other prop of `Filter variant="bar"`
|
|
1938
1938
|
(`quick`, `counts`, `previewCount`, `fieldProps`, `density`, `shortcuts`,
|
|
1939
|
-
`searchApply`, `searchMinLength`, `errors`, `label`...) passes through. There is no `query`,
|
|
1939
|
+
`searchApply`, `searchMinLength`, `searchAutoFocus`, `errors`, `label`...) passes through. There is no `query`,
|
|
1940
1940
|
`defaultQuery` nor `onQueryChange`: the URL is the query.
|
|
1941
|
+
- **Focus on arrival.** `searchAutoFocus` puts focus in the search field when
|
|
1942
|
+
the bar mounts (React's `autoFocus`, so it is right on the server too). Use it
|
|
1943
|
+
on a search page reached with an empty query; leave it off on a list page,
|
|
1944
|
+
where it would take focus from the page. `/` still focuses the field. `ServerTable`'s `filter` does not take
|
|
1945
|
+
`searchAutoFocus`, on purpose: a list page should not steal focus.
|
|
1941
1946
|
- **One write.** An edit writes the search, every `f=` and the aliased params,
|
|
1942
1947
|
drops the `reset` ones and keeps the page's others (a tab, a sort).
|
|
1943
1948
|
`onParamsChange` receives the next params for your router; the bar then
|
|
@@ -14,6 +14,7 @@ centre.
|
|
|
14
14
|
| <img src="../previews/feedback-status-stepupdialog.webp" width="96" alt=""> | [StepUpDialog](#stepupdialog) | "Confirm it's you": a dialog that asks for a one-time code, driven by props |
|
|
15
15
|
| <img src="../previews/feedback-status-unsaveddialog.webp" width="96" alt=""> | [UnsavedDialog](#unsaveddialog) | "Leave without saving?": a destructive confirm with Stay focused, used by the unsaved-changes guards |
|
|
16
16
|
| <img src="../previews/feedback-status-stalenotice.webp" width="96" alt=""> | [StaleNotice](#stalenotice) | "This record changed": a warning that another write came first, with one Reload action and no overwrite |
|
|
17
|
+
| | [Moment](#moment) | A full-screen one-off announcement (a player is eliminated, a role revealed): illustration, title, description and action, dismissed by Escape, a tap, its action or a timer |
|
|
17
18
|
| <img src="../previews/feedback-status-emptystate.webp" width="96" alt=""> | [EmptyState](#emptystate) | Illustration, title, description and action, by kind (empty, search, not-found, unauthorized) |
|
|
18
19
|
| <img src="../previews/feedback-status-pageloadfailed.webp" width="96" alt=""> | [PageLoadFailed](#pageloadfailed) | An empty state for a page opened at a cursor that failed, with a link back to the start |
|
|
19
20
|
| <img src="../previews/feedback-status-errorstate.webp" width="96" alt=""> | [ErrorState](#errorstate) | Failure block with Retry and technical details |
|
|
@@ -522,6 +523,45 @@ import { UnsavedDialog } from '@nxgt/material/components';
|
|
|
522
523
|
|
|
523
524
|
---
|
|
524
525
|
|
|
526
|
+
## Moment
|
|
527
|
+
|
|
528
|
+
A transient full-screen announcement for a dramatic one-off event: a player is eliminated, a role is revealed. It is a modal dialog named by its `title` (and described by its `description`), so a screen reader announces it as it opens. Focus moves into it and goes back to the element that had it when it closes; the page behind is inert. Escape, a tap anywhere, the close button and the `action` dismiss it, and so does `duration`. It fades in and its picture pops in; under `prefers-reduced-motion` both stop. The surface is the tone's container with the foreground colour on it, so it holds AA in light and dark, and it fills a phone.
|
|
529
|
+
|
|
530
|
+
```tsx
|
|
531
|
+
import { Moment } from '@nxgt/material/components';
|
|
532
|
+
import { Illustration } from '@nxgt/material/illustrations';
|
|
533
|
+
|
|
534
|
+
<Moment
|
|
535
|
+
open={eliminated != null}
|
|
536
|
+
onOpenChange={(open) => !open && setEliminated(null)}
|
|
537
|
+
duration={6000}
|
|
538
|
+
tone="error"
|
|
539
|
+
illustration={<Illustration scene="error" />}
|
|
540
|
+
title={`${eliminated?.name} was eliminated`}
|
|
541
|
+
description="The village chose her. She was the seer."
|
|
542
|
+
action={<Button onClick={nextNight}>Next night</Button>}
|
|
543
|
+
/>
|
|
544
|
+
```
|
|
545
|
+
|
|
546
|
+
| Prop | Type | Default | Effect |
|
|
547
|
+
| --- | --- | --- | --- |
|
|
548
|
+
| `open` | `boolean` | — | shown or not (controlled) |
|
|
549
|
+
| `onOpenChange` | `(open: boolean) => void` | — | called with `false` on every dismissal |
|
|
550
|
+
| `duration` | `number` (ms) | — | dismisses by itself after this long; unset: stays until dismissed |
|
|
551
|
+
| `illustration` | `ReactNode` | — | the picture (a scene, a pictogram, an icon); decorative, hidden from assistive technology |
|
|
552
|
+
| `title` | `ReactNode` | — | what happened; the accessible name |
|
|
553
|
+
| `description` | `ReactNode` | — | the line under it, in a `<p>` (phrasing content only) |
|
|
554
|
+
| `action` | `ReactNode` | — | a button or link; its click dismisses after its own handler, unless that handler calls `event.preventDefault()` |
|
|
555
|
+
| `tone` | `Tone` | `neutral` | the colour of the meaning: a named tone or one of your `AppTones` |
|
|
556
|
+
| `closeLabel` | `string` | translated | name of the close button |
|
|
557
|
+
| `className` | `string` | — | on the full-screen surface |
|
|
558
|
+
|
|
559
|
+
A tap anywhere dismisses, so keep text a reader must act on out of a short `duration`. Without a `description` the dialog is described by the hint `material.moment.hint` ("Press Escape or tap to dismiss."), read by assistive technology only. The close button is named by `material.buttons.close`.
|
|
560
|
+
|
|
561
|
+
**Storybook:** `Feedback & status/Moment` · **Vue:** not yet (a `vue` issue)
|
|
562
|
+
|
|
563
|
+
---
|
|
564
|
+
|
|
525
565
|
## StaleNotice
|
|
526
566
|
|
|
527
567
|

|
|
@@ -375,6 +375,22 @@ up / down buttons, `min` and `max` rows (Remove is disabled at `min`, Add is
|
|
|
375
375
|
announcements. Without a form library, `ChoiceListField` takes `value` and
|
|
376
376
|
`onChange`.
|
|
377
377
|
|
|
378
|
+
**Focus.** `ChoiceListFormField` gives React Hook Form's `field.ref` a handle
|
|
379
|
+
that focuses the first refused row's text input: the row of the first
|
|
380
|
+
`choices.<i>.text` error (a resolver's), or the first blank row when the
|
|
381
|
+
built-in blank rule refused the list. An error on the list itself (too few
|
|
382
|
+
rows, no row marked) focuses its first control. So `shouldFocusError`,
|
|
383
|
+
`setFocus('choices')` and `setError('choices', …, { shouldFocus: true })` land
|
|
384
|
+
on the refused row when there is an error, and on the first control otherwise.
|
|
385
|
+
A row path works too: `setFocus('choices.1.text')` and
|
|
386
|
+
`setError('choices.1.text', …, { shouldFocus: true })` (a server's refusal)
|
|
387
|
+
focus that row's text input. The form needs no `[aria-invalid="true"]` lookup.
|
|
388
|
+
|
|
389
|
+
```tsx
|
|
390
|
+
// After the server refused the second row:
|
|
391
|
+
form.setError('choices.1.text', { message }, { shouldFocus: true });
|
|
392
|
+
```
|
|
393
|
+
|
|
378
394
|
| Prop | Type | Default | What it does |
|
|
379
395
|
| --- | --- | --- | --- |
|
|
380
396
|
| `control`, `name` | `Control<T>`, `Path<T>` | — | the form and its array (`ChoiceListFormField`) |
|
|
@@ -641,7 +641,7 @@ in a desktop application.
|
|
|
641
641
|
|
|
642
642
|

|
|
643
643
|
|
|
644
|
-
Command palette with filtering, groups and shortcuts. `CommandDialog` shows it in a modal.
|
|
644
|
+
Command palette with filtering, groups and shortcuts. `CommandDialog` shows it in a modal, with a visible close button (`showCloseButton`, on by default; `false` removes it) at the end of the input row: named "Close" (`material.buttons.close`) and 44px on a coarse pointer, since a phone has no Escape key.
|
|
645
645
|
|
|
646
646
|
```tsx
|
|
647
647
|
import {
|
|
@@ -700,6 +700,7 @@ children and they replace that, as before.
|
|
|
700
700
|
| `shouldFilter` (`Command`) | `boolean` | `true` | `false` when you filter the items yourself (server search) |
|
|
701
701
|
| `title` / `description` (`CommandDialog`) | `string` | `"Command Palette"` / `"Search for a command to run..."` (translated) | the dialog's title and description, inside the dialog and visually hidden |
|
|
702
702
|
| `mobilePresentation` (`CommandDialog`) | `'dialog' \| 'top' \| 'fullscreen'` | `'top'` | below 640 px: pinned under the top edge (so the input and the results stay above the on-screen keyboard), the whole screen, or the centred modal it was before |
|
|
703
|
+
| `showCloseButton` (`CommandDialog`) | `boolean` | `true` | a visible close button at the end of the input row, named `material.buttons.close` and 44 px on a coarse pointer; `false` leaves Escape and the backdrop |
|
|
703
704
|
| `commandProps` (`CommandDialog`) | `Pick<CommandProps, 'shouldFilter' \| 'value' \| 'onValueChange' \| 'loop' \| 'filter' \| 'label'>` | — | reaches the inner `Command`: `{ shouldFilter: false }` for a palette whose results come from a server (cmdk then does not hide them again by the typed text), `value` / `onValueChange` for the highlighted item, `label` for the input's accessible name. The input's sizing, the dialog's title and its focus stay as they are |
|
|
704
705
|
| `open`, `onOpenChange` (`CommandDialog`) | as `Dialog` | — | every other prop goes to the `Dialog` |
|
|
705
706
|
|
|
@@ -163,7 +163,8 @@ import {
|
|
|
163
163
|
Parts: `Card`, `CardHeader`, `CardTitle`, `CardDescription`, `CardAction`,
|
|
164
164
|
`CardContent`, `CardFooter` — each a styled `<div>` taking its element's props,
|
|
165
165
|
except `CardTitle`, a heading: an `h3` by default, another level or a `div`
|
|
166
|
-
with `as` (`<CardTitle as="h2">`), so `getByRole('heading', { name })` finds it.
|
|
166
|
+
with `as` (`<CardTitle as="h2">`), so `getByRole('heading', { name })` finds it. The title takes its text size's
|
|
167
|
+
line height; pass a `leading-*` class to override.
|
|
167
168
|
`CardAction` sits top-right of the header.
|
|
168
169
|
|
|
169
170
|
**Storybook:** `Primitives/Card` · **Vue:** `Card` (same parts)
|
|
@@ -436,8 +436,10 @@ disabled with the field; Backspace in the empty input removes the last one.
|
|
|
436
436
|
Enter in a form: it acts on the list and does not submit the form while it has
|
|
437
437
|
something to do (WAI-ARIA combobox practice). It picks the highlighted option;
|
|
438
438
|
with `freeSolo` and no option highlighted it adds the typed text; with the list
|
|
439
|
-
open it is only default-prevented.
|
|
440
|
-
submits,
|
|
439
|
+
open it is only default-prevented. In `mode="multiple"` (a tags box, `freeSolo`
|
|
440
|
+
or not) Enter never submits the form, closed list and empty input included, so
|
|
441
|
+
the Enter after a pick does not save the form. In `single` mode, on a closed
|
|
442
|
+
list with nothing typed it submits, as a plain input does.
|
|
441
443
|
|
|
442
444
|
An avatar in the rows and the chips:
|
|
443
445
|
`getOptionLeading={(person) => <Avatar src={person.photo} alt="" />}`; see
|
package/docs/guides/i18n.md
CHANGED
|
@@ -312,7 +312,7 @@ title), `show` "Show results", `show-count` (an ICU plural over `count`:
|
|
|
312
312
|
filters" (the list atop it); its Close is `material.buttons.close`.
|
|
313
313
|
|
|
314
314
|
Smaller labels follow the language the same way: `CommandDialog`'s default
|
|
315
|
-
title and description (`material.command.title` / `description`) and
|
|
315
|
+
title and description (`material.command.title` / `description`), its close button (`material.buttons.close`) and
|
|
316
316
|
`CommandList`'s accessible name (`material.command.list`); the filter's empty state and
|
|
317
317
|
`+N more` chip (`material.filter.empty` / `more`) and the Yes/No, From, Until
|
|
318
318
|
and Up to of its chips (`material.filter.value.*`; `formatFilterValue` takes
|
|
@@ -578,6 +578,9 @@ places that use them read:
|
|
|
578
578
|
| `material.table.labels.select-page` / `select-item` | Select all on this page / Select | Tout sélectionner sur cette page / Sélectionner | The cards list bar's select-all (its accessible name), and a card's checkbox (named "Select <title>"). Inside a `ServerTable`'s two-row phone header the select-all also shows `material.table.labels.select-all` ("Select all") as its short visible label |
|
|
579
579
|
| `material.table.labels.clear-selection` | Clear selection | Effacer la sélection | The cards list bar's button, shown while rows are selected; on a narrow list it is an icon button, and this string is its accessible name and tooltip |
|
|
580
580
|
| `material.table.labels.scroll-list` | Scrollable list | Liste défilante | The region of a cards or tiles list with `maxHeight` (`scrollLabel` overrides it) |
|
|
581
|
+
| `material.seat-ring.empty` | Empty seat | Place libre | `SeatRing`'s default empty seat (`renderEmptySeat` replaces it) |
|
|
582
|
+
| `material.seat-ring.out` | Out | Éliminé | the word written in a `SeatRing` seat with `out: true`, part of its accessible name |
|
|
583
|
+
| `material.moment.hint` | Press Escape or tap to dismiss. | Appuyez sur Échap ou touchez l'écran pour fermer. | `Moment`'s description for assistive technology when it has no `description` |
|
|
581
584
|
| `material.command.empty` | No results | Aucun résultat | `CommandEmpty` with no children |
|
|
582
585
|
| `material.pdf-reader.retry` | Retry | Réessayer | the `PdfReader` button |
|
|
583
586
|
|
package/docs/guides/theming.md
CHANGED
|
@@ -1171,6 +1171,10 @@ are, without growing what is painted (nothing changes for a mouse):
|
|
|
1171
1171
|
visible label (only an `aria-label`) is still its drawn size plus the
|
|
1172
1172
|
`.nxgt-touch-target` hit area: wrap it in a `<label>` of 44px, or give it a
|
|
1173
1173
|
label.
|
|
1174
|
+
- **A `FilterBar` chip is 44px tall and at least 44px wide**: the quick pills and toggles, the
|
|
1175
|
+
scope pill, an active condition's chip and the default hint (`height` and
|
|
1176
|
+
`min-width`, so a long label still grows it; a mouse keeps 24-28px), and
|
|
1177
|
+
"Add filter" and "Clear all" are 44px tall.
|
|
1174
1178
|
|
|
1175
1179
|
A toast covering a control is out of scope: it physically hides what is under
|
|
1176
1180
|
it.
|
|
Binary file
|
package/docs/roadmap.md
CHANGED
|
@@ -371,6 +371,7 @@ version they shipped in, and planned entries may name the major they target.
|
|
|
371
371
|
|
|
372
372
|
## Shipped
|
|
373
373
|
|
|
374
|
+
- **Moment (next minor)** — a transient full-screen announcement for a one-off event (a player is eliminated, a role is revealed): a modal dialog named by its title, with an illustration, description, action and tone, dismissed by Escape, a tap, its action or a timer, and no motion under reduced motion ([#2220](https://github.com/softistx/nxgt-material/issues/2220)).
|
|
374
375
|
- **RecordActionsMenu (next minor)** — one menu for a record's lifecycle: archive with an Undo toast (or confirm first with `archivePolicy="confirm"`), restore, and delete that always confirms and shows the backend's refusal, with `ConfirmDialog` gaining `details` and `refusal` slots.
|
|
375
376
|
- **Assistant approval card (next minor)** — `ChatActionProposal` shows an action an assistant proposes, with its status, deadline and Confirm / Reject, and `ChatToolActivity` is a compact row for a tool step in a chat thread ([#2134](https://github.com/softistx/nxgt-material/issues/2134)).
|
|
376
377
|
|
package/docs/troubleshooting.md
CHANGED
|
@@ -313,6 +313,7 @@ words in your error.
|
|
|
313
313
|
- [A click on the next field right after an `Autocomplete` pick is lost](#a-click-on-the-next-field-right-after-an-autocomplete-pick-is-lost)
|
|
314
314
|
- [An older search's results replace the newer ones in an `Autocomplete`](#an-older-searchs-results-replace-the-newer-ones-in-an-autocomplete)
|
|
315
315
|
- [An `Autocomplete` option does nothing on click or Enter](#an-autocomplete-option-does-nothing-on-click-or-enter)
|
|
316
|
+
- [Enter in a multiple `Autocomplete` no longer submits the form](#enter-in-a-multiple-autocomplete-no-longer-submits-the-form)
|
|
316
317
|
- ["The search failed. Try again." no longer shows in an `Autocomplete`](#the-search-failed-try-again-no-longer-shows-in-an-autocomplete)
|
|
317
318
|
- [A test no longer finds `aria-invalid` on an `OtpField` slot](#a-test-no-longer-finds-aria-invalid-on-an-otpfield-slot)
|
|
318
319
|
- [A test no longer finds `aria-invalid` on a `CodeEditor`](#a-test-no-longer-finds-aria-invalid-on-a-codeeditor)
|
|
@@ -4880,6 +4881,21 @@ on a desktop and on a phone alike: closing the picker with OK hands focus back
|
|
|
4880
4881
|
to the trigger, and the next Tab or click elsewhere touches it. See the next
|
|
4881
4882
|
entry.
|
|
4882
4883
|
|
|
4884
|
+
### A failed submit focuses a `ChoiceListFormField` but not the refused row
|
|
4885
|
+
|
|
4886
|
+
**When:** a form with a `ChoiceListFormField` fails validation (a row's text
|
|
4887
|
+
is blank, `choices.2.text` in a resolver) and `document.activeElement` is the
|
|
4888
|
+
list's first control, or nothing, instead of the refused row. In versions
|
|
4889
|
+
before this fix.
|
|
4890
|
+
**Why:** the field gave React Hook Form a handle that focused the first
|
|
4891
|
+
control of the list, whichever row was refused.
|
|
4892
|
+
**Fix:** upgrade to the release that lists this fix in its changelog:
|
|
4893
|
+
`shouldFocusError` and `setFocus(name)` focus the first refused row's text
|
|
4894
|
+
input, and so do `setFocus('choices.1.text')` and
|
|
4895
|
+
`setError('choices.1.text', …, { shouldFocus: true })` on a row path, as a
|
|
4896
|
+
server's refusal sets. Remove a workaround that queries `[aria-invalid="true"]`
|
|
4897
|
+
after submit. For the other fields, see the next entry.
|
|
4898
|
+
|
|
4883
4899
|
### `setError(…, { shouldFocus: true })` or a failed submit does not focus the field
|
|
4884
4900
|
|
|
4885
4901
|
**When:** a form wired with `*FormField`s: `handleSubmit` fails validation, or
|
|
@@ -5712,6 +5728,27 @@ may be chosen:
|
|
|
5712
5728
|
/>
|
|
5713
5729
|
```
|
|
5714
5730
|
|
|
5731
|
+
### Enter in a multiple `Autocomplete` no longer submits the form
|
|
5732
|
+
|
|
5733
|
+
**When:** after upgrading, Enter in an `Autocomplete` (or `AutocompleteFormField`,
|
|
5734
|
+
a tags field) with `mode="multiple"` no longer submits the surrounding form
|
|
5735
|
+
when the list is closed and the input is empty.
|
|
5736
|
+
**Why:** the field is a tags box: the Enter that follows a pick used to save the
|
|
5737
|
+
whole form by surprise (#2199). Enter in `mode="multiple"` now only picks or
|
|
5738
|
+
adds. `single` mode is unchanged.
|
|
5739
|
+
**Fix:** submit with the form's button, or with a key handler of your own on the
|
|
5740
|
+
form if a keyboard shortcut is wanted (Ctrl/Cmd + Enter); drop any
|
|
5741
|
+
`onKeyDown` that prevented Enter on the combobox.
|
|
5742
|
+
|
|
5743
|
+
```tsx
|
|
5744
|
+
<form
|
|
5745
|
+
onSubmit={save}
|
|
5746
|
+
onKeyDown={(e) => {
|
|
5747
|
+
if (e.key === 'Enter' && (e.ctrlKey || e.metaKey)) e.currentTarget.requestSubmit();
|
|
5748
|
+
}}
|
|
5749
|
+
>
|
|
5750
|
+
```
|
|
5751
|
+
|
|
5715
5752
|
### "The search failed. Try again." no longer shows in an `Autocomplete`
|
|
5716
5753
|
|
|
5717
5754
|
**When:** after upgrading, an `Autocomplete` whose `onSearch` rejects shows
|
|
@@ -101,6 +101,32 @@
|
|
|
101
101
|
border-style: dashed;
|
|
102
102
|
background: transparent;
|
|
103
103
|
}
|
|
104
|
+
/* Out: dimmed, the name struck through, the avatar greyed, and the word
|
|
105
|
+
* "Out" written under the name, so colour and opacity are never the only cue. */
|
|
106
|
+
.nxgt-seat-ring [data-out] {
|
|
107
|
+
background: color-mix(in oklab, var(--muted) 60%, transparent);
|
|
108
|
+
border-color: var(--border);
|
|
109
|
+
}
|
|
110
|
+
.nxgt-seat-ring [data-out] [data-slot="seat-ring-avatar"] {
|
|
111
|
+
opacity: 0.55;
|
|
112
|
+
filter: grayscale(1);
|
|
113
|
+
}
|
|
114
|
+
.nxgt-seat-ring [data-out] [data-slot="seat-ring-label"] {
|
|
115
|
+
color: var(--muted-foreground);
|
|
116
|
+
text-decoration: line-through;
|
|
117
|
+
text-decoration-thickness: 2px;
|
|
118
|
+
}
|
|
119
|
+
.nxgt-seat-ring [data-slot="seat-ring-out"] {
|
|
120
|
+
padding-inline: 0.375rem;
|
|
121
|
+
border: 1px solid currentColor;
|
|
122
|
+
border-radius: 9999px;
|
|
123
|
+
color: var(--muted-foreground);
|
|
124
|
+
font-size: 0.6875rem;
|
|
125
|
+
font-weight: 600;
|
|
126
|
+
line-height: 1.25rem;
|
|
127
|
+
text-transform: uppercase;
|
|
128
|
+
letter-spacing: 0.04em;
|
|
129
|
+
}
|
|
104
130
|
.nxgt-seat-ring [data-highlighted] {
|
|
105
131
|
border-color: var(--primary-indicator, var(--primary));
|
|
106
132
|
box-shadow: 0 0 0 2px var(--primary-indicator, var(--primary));
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
@import "./spinner/spinner.css";
|
|
2
|
+
/* Moment: the full-screen announcement. */
|
|
3
|
+
@import "./moment/moment.css";
|
|
2
4
|
/* Illustration: the classes of the state scenes (EmptyState, ErrorState, @nxgt/material/illustrations). */
|
|
3
5
|
@import "./state-frame/illustration.css";
|
|
4
6
|
@import "./progress/progress.css";
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/* Moment: a full-screen one-off announcement. The surface is the tone's
|
|
2
|
+
* container (the `data-tone` channel), the text the foreground colour, so it
|
|
3
|
+
* reads at AA in light and dark. It fades in and its picture pops in (the
|
|
4
|
+
* keyframes are dialog.css's `nxgt-fade-in` and the `nxgt-pop` of styles.css);
|
|
5
|
+
* under prefers-reduced-motion reduced-motion.css ends both at once (the
|
|
6
|
+
* content carries `data-slot`). */
|
|
7
|
+
@layer components {
|
|
8
|
+
.nxgt-moment {
|
|
9
|
+
background-color: var(--nxgt-tone-container, var(--background));
|
|
10
|
+
color: var(--foreground);
|
|
11
|
+
}
|
|
12
|
+
.nxgt-moment[data-state="open"] {
|
|
13
|
+
animation: nxgt-fade-in 240ms var(--nxgt-ease-effects) backwards;
|
|
14
|
+
}
|
|
15
|
+
.nxgt-moment[data-state="closed"] {
|
|
16
|
+
animation: nxgt-fade-out 160ms var(--nxgt-ease-emphasized-accelerate) both;
|
|
17
|
+
}
|
|
18
|
+
.nxgt-moment[data-state="open"] [data-slot="moment-illustration"] {
|
|
19
|
+
animation: nxgt-pop 520ms var(--nxgt-ease-emphasized-decelerate) 80ms
|
|
20
|
+
backwards;
|
|
21
|
+
}
|
|
22
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nxgt/material",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.74.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"bugs": {
|
|
6
6
|
"email": "stevegires@gmail.com"
|
|
@@ -372,7 +372,7 @@
|
|
|
372
372
|
"docs:previews": "rm -rf node_modules/.cache/nxgt-preview-free/missing && NXGT_PREVIEW_FREE=1 vitest run --project previews && bun .storybook/preview-free-report.ts"
|
|
373
373
|
},
|
|
374
374
|
"dependencies": {
|
|
375
|
-
"@nxgt/material-core": "^0.47.
|
|
375
|
+
"@nxgt/material-core": "^0.47.1",
|
|
376
376
|
"@base-ui/react": "^1.6.0",
|
|
377
377
|
"@dnd-kit/core": "^6.3.1",
|
|
378
378
|
"@dnd-kit/sortable": "^10.0.0",
|
|
@@ -459,7 +459,7 @@
|
|
|
459
459
|
"@fontsource-variable/inter": "^5",
|
|
460
460
|
"@fortawesome/fontawesome-free": "7.3.1",
|
|
461
461
|
"@nxgt/material-testing": "0.0.0",
|
|
462
|
-
"@nxgt/playwright": "^0.
|
|
462
|
+
"@nxgt/playwright": "^0.11.0",
|
|
463
463
|
"@react-leaflet/core": "^3.0.0",
|
|
464
464
|
"@react-pdf/renderer": "^4.9.0",
|
|
465
465
|
"@storybook/addon-a11y": "10.6.0",
|