@nxgt/material 2.8.0 → 2.10.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.
Files changed (86) hide show
  1. package/CHANGELOG.md +43 -0
  2. package/README.md +2 -2
  3. package/dist/{_Uint8Array-CALbCR7W.js → _Uint8Array-azThpjEP.js} +1 -1
  4. package/dist/{_overRest-BQ8agsDH.js → _overRest-DMn4Dt71.js} +1 -1
  5. package/dist/{async-slice-BHMdvnqm.js → async-slice-DhZDjEtw.js} +2 -2
  6. package/dist/{blockDiagram-BEXU5L5S-D4gI6nqs.js → blockDiagram-BEXU5L5S-B8_AJyBb.js} +2 -2
  7. package/dist/{chunk-3FUC2YCW-BLMCnCFE.js → chunk-3FUC2YCW-AfTluaJD.js} +2 -2
  8. package/dist/{chunk-7M6MHVWA-CUtKEeuL.js → chunk-7M6MHVWA-B2FTOUoo.js} +1 -1
  9. package/dist/{chunk-GNY47TPC-CB_83G7J.js → chunk-GNY47TPC-CscSFMWi.js} +4 -4
  10. package/dist/{chunk-NETBCI7D-Cywmx0rz.js → chunk-NETBCI7D-iu8QN4Le.js} +1 -1
  11. package/dist/{chunk-Z7XXMR3K-Ccb3Rfjl.js → chunk-Z7XXMR3K-BICnZMWs.js} +1 -1
  12. package/dist/{classDiagram-v2-NBCMYWYE-CRgxPgLD.js → classDiagram-v2-NBCMYWYE-Cg2qBPTZ.js} +2 -2
  13. package/dist/{components-Bg1bqGbc.js → components-BfXTx1uS.js} +20734 -20660
  14. package/dist/components.js +5 -5
  15. package/dist/{dagre-6A5THRUB-c8yG3_vh.js → dagre-6A5THRUB-B9m4hqWN.js} +11 -11
  16. package/dist/{diagram-22UHCM2B-C3Xcfy6D.js → diagram-22UHCM2B-ChYYeBFB.js} +2 -2
  17. package/dist/{diagram-3UASUU5V-maEO61Bh.js → diagram-3UASUU5V-BoEmx9Kd.js} +1 -1
  18. package/dist/dnd.js +1 -1
  19. package/dist/{elk-276RUBZZ-BoWoJr6K.js → elk-276RUBZZ-CxNgT7Wb.js} +3 -3
  20. package/dist/{erDiagram-OPXOYQCR-CVvgZCSJ.js → erDiagram-OPXOYQCR-DiqLuL4t.js} +2 -2
  21. package/dist/{field-blur-Bwa48QBk.js → field-blur--x_n3oMy.js} +1 -1
  22. package/dist/{flowDiagram-KWPJA3E3-RdU0csul.js → flowDiagram-KWPJA3E3-CcUm8XN5.js} +3 -3
  23. package/dist/{ganttDiagram-FUAMR5RP-DPLDPJtJ.js → ganttDiagram-FUAMR5RP-fN1MVB5K.js} +1 -1
  24. package/dist/{graphlib-DHgEBs83.js → graphlib-DLjE3QPd.js} +6 -6
  25. package/dist/hooks.js +2 -2
  26. package/dist/{i18n-provider-CA8YAlje.js → i18n-provider-CQL7fqLy.js} +1 -1
  27. package/dist/i18n.js +6 -6
  28. package/dist/{isArrayLikeObject-BSfDsA7T.js → isArrayLikeObject-CO-5KAzG.js} +3 -3
  29. package/dist/{isEmpty-BEe-nNXw.js → isEmpty-Bl1drJE7.js} +3 -3
  30. package/dist/{journeyDiagram-ZHPQQLJL-CTGnr-JY.js → journeyDiagram-ZHPQQLJL-Cj7Vcat2.js} +1 -1
  31. package/dist/lib/components/ui/feedback/toast/index.d.ts +1 -0
  32. package/dist/lib/components/ui/feedback/toast/partials/toast-actions.d.ts +12 -2
  33. package/dist/lib/components/ui/feedback/toast/toast-data.d.ts +26 -0
  34. package/dist/lib/components/ui/feedback/toast/toast.d.ts +6 -3
  35. package/dist/lib/components/ui/feedback/toast/toasts.d.ts +18 -6
  36. package/dist/lib/components/ui/primitives/tabs/partials/tabs-content.d.ts +3 -0
  37. package/dist/lib/components/ui/primitives/tabs/partials/tabs-indicator.d.ts +13 -0
  38. package/dist/lib/components/ui/primitives/tabs/partials/tabs-list.d.ts +3 -0
  39. package/dist/lib/components/ui/primitives/tabs/partials/tabs-trigger.d.ts +6 -0
  40. package/dist/lib/components/ui/primitives/tabs/tabs-classes.d.ts +27 -0
  41. package/dist/lib/components/ui/primitives/tabs/tabs-variant.d.ts +5 -0
  42. package/dist/lib/components/ui/primitives/tabs/tabs.d.ts +11 -7
  43. package/dist/lib/components/ui/widgets/emoji/types.d.ts +1 -6
  44. package/dist/lib/i18n/resources/en/en.d.ts +14 -0
  45. package/dist/lib/i18n/resources/en/material.json.d.ts +15 -1
  46. package/dist/lib/i18n/resources/fr/fr.d.ts +14 -0
  47. package/dist/lib/i18n/resources/fr/material.json.d.ts +15 -1
  48. package/dist/lib/i18n/resources/resources.d.ts +28 -0
  49. package/dist/lib/i18n/translator.d.ts +1 -1
  50. package/dist/lib.js +3 -3
  51. package/dist/main.js +11 -11
  52. package/dist/map.js +2 -2
  53. package/dist/material.css +1 -1
  54. package/dist/{merge-CRXQ4NSv.js → merge-CwwtONfp.js} +4 -4
  55. package/dist/{mermaid.core-C_JPRVNa.js → mermaid.core-Be3u4qna.js} +21 -21
  56. package/dist/{mindmap-definition-NLK3R4M7-OTZIWZah.js → mindmap-definition-NLK3R4M7-Dw8Z4Lyy.js} +2 -2
  57. package/dist/{pieDiagram-5QR66LMP-BpmwlCYh.js → pieDiagram-5QR66LMP-Cv_V3nnp.js} +1 -1
  58. package/dist/print.js +2 -2
  59. package/dist/{quadrantDiagram-O4NWA36T-CIFt4MgA.js → quadrantDiagram-O4NWA36T-Bavlu0dy.js} +1 -1
  60. package/dist/{requirementDiagram-PLB6GJNP-BJaiDsKj.js → requirementDiagram-PLB6GJNP-6fInAtPO.js} +2 -2
  61. package/dist/{sankeyDiagram-IPEJSGJF-XDAIB5as.js → sankeyDiagram-IPEJSGJF-wzaUoPP7.js} +1 -1
  62. package/dist/{sortable-provider-MCgOzfRp.js → sortable-provider-WZT5I34N.js} +1 -1
  63. package/dist/{stateDiagram-v2-GCMORJYK-CGo16q99.js → stateDiagram-v2-GCMORJYK-BRIjnDU3.js} +2 -2
  64. package/dist/{stored-language-Cz89IYZX.js → stored-language-BW32owje.js} +30 -2
  65. package/dist/{swimlanes-2SLR337P-DXZt0zyd.js → swimlanes-2SLR337P-BNephno6.js} +3 -3
  66. package/dist/{swimlanesDiagram-TC7HE7FX-Cno6MSMH.js → swimlanesDiagram-TC7HE7FX-CUARDUGc.js} +3 -3
  67. package/dist/{timeline-definition-EJHVYXUP-CbPIZcT7.js → timeline-definition-EJHVYXUP-By2gWxfd.js} +1 -1
  68. package/dist/{translate-material-Caxsy0bp.js → translate-material-ZEzF-LKH.js} +2 -2
  69. package/dist/{translator-B85Q_O55.js → translator-BfqVlNGW.js} +1 -1
  70. package/dist/{use-heading-spy-C4yWEr5c.js → use-heading-spy-DvZVu15k.js} +2 -2
  71. package/dist/{use-material-translation-Cm3Ej3bT.js → use-material-translation-B2GUtxUY.js} +2 -2
  72. package/dist/{usecaseDiagram-POWQR4AR-D_gyFA3m.js → usecaseDiagram-POWQR4AR-CleiKWa8.js} +2 -2
  73. package/dist/{xychartDiagram-PMCCYNJV-W-fXV6iN.js → xychartDiagram-PMCCYNJV-gwrRH4uJ.js} +1 -1
  74. package/docs/components/data-display.md +1 -1
  75. package/docs/components/feedback-and-status.md +35 -6
  76. package/docs/components/primitives.md +80 -5
  77. package/docs/components/rich-widgets.md +10 -0
  78. package/docs/guides/i18n.md +19 -2
  79. package/docs/guides/theming.md +17 -3
  80. package/docs/previews/data-display-codegroup.webp +0 -0
  81. package/docs/previews/primitives-tabs.webp +0 -0
  82. package/docs/previews/rich-widgets-emojipicker.webp +0 -0
  83. package/docs/roadmap.md +12 -0
  84. package/docs/troubleshooting.md +82 -0
  85. package/package.json +2 -2
  86. package/dist/lib/components/ui/widgets/emoji/emoji.groups.d.ts +0 -6
@@ -327,10 +327,27 @@ and description and against the English ones, ignoring accents: in French,
327
327
 
328
328
  Some strings are still English in every language, among them the filter's
329
329
  validation messages, the camera's error messages, the editor's callout type
330
- names and default block content, and the names of the emoji picker's category
331
- tabs. File sizes (`2.0 KB`) and the filter chips' dates are not formatted for
330
+ names and default block content. File sizes (`2.0 KB`) and the filter chips' dates are not formatted for
332
331
  the provider's language.
333
332
 
333
+ The emoji picker's category tabs are icon-only; their name, read by screen
334
+ readers and shown as a tooltip, comes from `material.emoji.groups.<group>`.
335
+ Both languages ship `all`, `recent`, `general`, `people_body`, `components`,
336
+ `animals_nature`, `food_drink`, `travel_places`, `activities`, `objects`,
337
+ `symbols` and `flags`:
338
+
339
+ ```ts
340
+ // English / French values of the shipped keys
341
+ material.emoji.groups.people_body; // "People & body" / "Personnes et corps"
342
+ material.emoji.groups.food_drink; // "Food & drink" / "Nourriture et boissons"
343
+ material.emoji.groups.flags; // "Flags" / "Drapeaux"
344
+ ```
345
+
346
+ A group your `EmojiItem`s name that is not in this list (`hand_signs`) reads
347
+ as its words in English (`Hand signs`). As for every `material.*` key above,
348
+ the components read their own bundle: your own translator sees a key you add,
349
+ the tab does not.
350
+
334
351
  ```tsx
335
352
  // Under <I18nProvider defaultLanguage="fr">
336
353
  <CarouselNext /> // screen reader: "Diapositive suivante"
@@ -190,9 +190,23 @@ Storybook's `Guides/Theming/Contrast` measures all of this in both themes:
190
190
  the surfaces' text, the error text (`HelperText` and a field's message on
191
191
  `--background` and `--card`), the `Alert`s and the `Timeline`, `Button` and
192
192
  `IconButton` in every variant and colour, and a `Badge` link in every colour,
193
- at rest, hovered, focused and pressed, and the tracks; `Data display/ListTile`
194
- measures the selected tile. Run them against your own tokens after an
195
- override.
193
+ at rest, hovered, focused and pressed, the tracks and the tabs;
194
+ `Data display/ListTile` measures the selected tile. Run them against your own
195
+ tokens after an override.
196
+
197
+ **Tabs.** An `underline` tab's active label is `--primary` in the light
198
+ theme (7.3:1 on `--background` and `--card`, 6.7:1 on `--muted`) and
199
+ `--primary` mixed with 60 % white in the dark one (10.0:1, 9.0:1 and 7.4:1);
200
+ its bar and every tab's focus outline are `--primary` in the light theme and
201
+ `--track-fill` in the dark one (at least 6.7:1 and 9.0:1 on those surfaces).
202
+ An inactive label is `--muted-foreground`, and turns to `--foreground` when
203
+ hovered. A `segmented` tab's active label is `--foreground` on the raised
204
+ surface (19.9:1 light, 17.0:1 dark); that surface is only 1.1:1 to 1.2:1 on
205
+ the track, so it has a `--muted-foreground` border (5.0:1 light, 4.7:1 dark
206
+ on the track), and the label also changes colour and weight. Storybook's
207
+ `Guides/Theming/Contrast` story `Tabs` measures each label at rest, hovered
208
+ and focused, the outline, the bar and the border, on the three surfaces, in
209
+ both themes.
196
210
 
197
211
  `--muted-foreground` is 5.5:1 on `--background` and `--card`, 5.1:1 on the
198
212
  "paper" tint (`bg-background-paper`, 5 % primary) and 5.0:1 on `--muted` in
Binary file
package/docs/roadmap.md CHANGED
@@ -88,6 +88,18 @@ Nothing in progress right now; see Next.
88
88
 
89
89
  ## Shipped
90
90
 
91
+ - **Toast actions that work everywhere** — `toasts.success(message, { action })`
92
+ and every other preset take sonner's own call shape and keep their action,
93
+ and a dialog a toast's action opens keeps the focus, then gives it back to
94
+ where it was before the toast. 2.10.0.
95
+
96
+ - **Tabs in two looks** — `underline`, the new default, whose bar slides to
97
+ the active tab, and a neutral `segmented` pill; a list that scrolls
98
+ sideways on a phone instead of widening the page, right-to-left, a visible
99
+ focus ring, labels that read 4.5:1 in both themes, and an indicator that
100
+ stops sliding under `prefers-reduced-motion`. `bar` and `line` still work,
101
+ as deprecated aliases of `underline` and `segmented`. 2.9.0.
102
+
91
103
  - **Accessible by default** — error text in its own `--error-text` colour that
92
104
  reads 4.5:1 in both themes, the empty part of sliders and meters in a
93
105
  `--track` colour that reads 3:1, buttons, badges and status colours that
@@ -32,6 +32,8 @@ words in your error.
32
32
  - [A toast covers the form's button on a phone](#a-toast-covers-the-forms-button-on-a-phone)
33
33
  - [A toast never goes away after a tap](#a-toast-never-goes-away-after-a-tap)
34
34
  - [A toast's action cannot be clicked while a dialog is open](#a-toasts-action-cannot-be-clicked-while-a-dialog-is-open)
35
+ - [`toasts.success(message, { action })` shows no action button](#toastssuccessmessage--action--shows-no-action-button)
36
+ - [The focus leaves a dialog that a toast's action opened](#the-focus-leaves-a-dialog-that-a-toasts-action-opened)
35
37
  - [A `ConfirmationDialog` reopened with new content blocks clicks](#a-confirmationdialog-reopened-with-new-content-blocks-clicks)
36
38
  - [The first Escape after closing a nested dialog does nothing](#the-first-escape-after-closing-a-nested-dialog-does-nothing)
37
39
 
@@ -39,6 +41,8 @@ words in your error.
39
41
 
40
42
  - [A `ListTile` link reloads the whole page](#a-listtile-link-reloads-the-whole-page)
41
43
  - [The phone menu needs two Escapes to close, or a tooltip shows over it](#the-phone-menu-needs-two-escapes-to-close-or-a-tooltip-shows-over-it)
44
+ - [`Tabs` look different after upgrading](#tabs-look-different-after-upgrading)
45
+ - [A screen reader announces an icon-only tab as "tab", with no name](#a-screen-reader-announces-an-icon-only-tab-as-tab-with-no-name)
42
46
 
43
47
  **SSR & build**
44
48
 
@@ -640,6 +644,51 @@ counted a pointer down on a toast as outside the dialog.
640
644
  inside the `Toaster` as inside, so the action runs and the dialog stays open.
641
645
  Sonner's own `Toaster` keeps the old behaviour.
642
646
 
647
+ ### `toasts.success(message, { action })` shows no action button
648
+
649
+ **When:** a preset is called the way sonner's own `toast.success` is, with a
650
+ message and a `data` object: `toasts.success('Staff member restored', {
651
+ action: { label: 'Send an invitation', onClick } })`. The toast shows the
652
+ preset's default title ("Success") and its "Close" button, not your message,
653
+ description or action.
654
+ **Why:** the presets took one props object only (`{ title, description,
655
+ action, options }`): a string first argument was read as that object, and
656
+ the second argument was ignored.
657
+ **Fix:** update `@nxgt/material`: every preset (`custom`, `success`, `info`,
658
+ `warning`, `error`, `loading`) now takes `(message, data)` too, the message as
659
+ the title and `data.description` and `data.action` shown, the rest of `data`
660
+ as sonner's options. The props object works as before:
661
+
662
+ ```ts
663
+ toasts.success('Staff member restored', { action: { label: 'Send an invitation', onClick } });
664
+ toasts.success({ title: 'Staff member restored', action: { label: 'Send an invitation', onClick } });
665
+ ```
666
+
667
+ `data` takes no `icon` (a preset draws its own) and no `cancel` (the X button
668
+ beside the action stands for it).
669
+
670
+ ### The focus leaves a dialog that a toast's action opened
671
+
672
+ **When:** a toast's action opens a `Dialog` (or an `AlertDialog`, a `Sheet`,
673
+ a `Drawer`, or moves the focus anywhere else). Once the toast has gone, the
674
+ focus is no longer on the dialog's control (it is on the dialog itself, on
675
+ the page behind it, or on `document.body`), and closing the dialog leaves the
676
+ focus on `document.body` instead of where it was before the toast.
677
+ **Why:** sonner remembers the control focused before the focus entered the
678
+ `Toaster`, and focuses it again as soon as the focus leaves the `Toaster`.
679
+ The dialog taking the focus counted as leaving, so sonner pulled it back out
680
+ of the dialog (WCAG 2.4.3). The dialog, opened while the toast's button had
681
+ the focus, also gave the focus back to that button once closed: it had gone
682
+ with its toast, so the focus fell to `document.body`.
683
+ **Fix:** update `@nxgt/material` and give the toast an `action` (a `{ label,
684
+ onClick }`, or a function that calls the `dismiss` it is given): the action
685
+ gives the focus back to where it was before the toast first, then runs. The
686
+ dialog keeps its control, and gives the focus back to that earlier control
687
+ when it closes. A workaround that blurs the button and opens the dialog on
688
+ the next frame can go. A button you render in a function action and that
689
+ opens a dialog without calling `dismiss` is not covered: call `dismiss()`
690
+ before opening the dialog.
691
+
643
692
  ### A `ConfirmationDialog` reopened with new content blocks clicks
644
693
 
645
694
  **When:** a `ConfirmationDialog` or a `ConfirmDialog` (or a `Dialog`,
@@ -754,6 +803,39 @@ the tooltip's own layer takes the first Escape.
754
803
  tooltip, since it shows its label; a collapsed one keeps it, and an explicit
755
804
  `tooltip` is always shown. A `SidebarMenuItem` of your own needs no change.
756
805
 
806
+ ### `Tabs` look different after upgrading
807
+
808
+ **When:** a `Tabs` with no `variant`, or with `variant="bar"`, renders a row of
809
+ tabs over a border with a bar under the active one, where it rendered
810
+ boxed tabs, a primary ring around the active one;
811
+ one with `variant="line"` renders a rounded pill.
812
+ **Why:** `underline` is now the default look. `bar` and `line` are deprecated
813
+ aliases: `bar` renders as `underline`, `line` as `segmented`.
814
+ **Fix:** write the look you want. `underline` needs no `variant`; for a pill,
815
+ set `segmented`:
816
+
817
+ ```tsx
818
+ <Tabs defaultValue="week" variant="segmented">
819
+ ```
820
+
821
+ A test that queried the old classes should query the state instead:
822
+ `getByRole('tab', { selected: true })`, and `data-variant` on
823
+ `[data-slot="tabs"]` for the look.
824
+
825
+ ### A screen reader announces an icon-only tab as "tab", with no name
826
+
827
+ **When:** a `TabsTrigger` holds only an icon; an accessibility audit reports a
828
+ tab with no accessible name.
829
+ **Why:** a tab is named by its text, and an icon has none.
830
+ **Fix:** give the trigger `aria-label`, and `title` for a hover hint:
831
+
832
+ ```tsx
833
+ <TabsTrigger value="recent" icon={<Clock />} aria-label="Recent" title="Recent" />
834
+ ```
835
+
836
+ `EmojiList` and `EmojiPicker` name their group tabs themselves; update
837
+ `@nxgt/material` if yours read "tab" only.
838
+
757
839
  ## SSR & build
758
840
 
759
841
  ### `ReferenceError: window is not defined`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nxgt/material",
3
- "version": "2.8.0",
3
+ "version": "2.10.0",
4
4
  "license": "MIT",
5
5
  "bugs": {
6
6
  "email": "stevegires@gmail.com"
@@ -114,7 +114,7 @@
114
114
  "docs:previews": "vitest run --project previews"
115
115
  },
116
116
  "dependencies": {
117
- "@nxgt/material-core": "^0.5.0",
117
+ "@nxgt/material-core": "^0.7.0",
118
118
  "@base-ui/react": "^1.6.0",
119
119
  "@dnd-kit/core": "^6.3.1",
120
120
  "@dnd-kit/sortable": "^10.0.0",
@@ -1,6 +0,0 @@
1
- import { EmojiItem } from './types';
2
- export declare function groupKey(group?: string | null): string;
3
- export declare function groupEmojis(emojis: EmojiItem[], recent: string[]): {
4
- [k: string]: EmojiItem[];
5
- };
6
- export declare function searchEmojis(emojis: EmojiItem[], query: string): EmojiItem[] | null;