@nxgt/material 2.19.0 → 2.20.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 (82) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/dist/{_Uint8Array-B6RHzY7k.js → _Uint8Array-DGVY6NfN.js} +1 -1
  3. package/dist/{_overRest-Cs3RIAVd.js → _overRest-DCKNcrF0.js} +1 -1
  4. package/dist/{async-slice-CgbRYTRY.js → async-slice-DAVXvBm1.js} +3 -3
  5. package/dist/{blockDiagram-BEXU5L5S-D5ptXmBP.js → blockDiagram-BEXU5L5S-BrCVxVRd.js} +2 -2
  6. package/dist/{chunk-3FUC2YCW-al8CepY8.js → chunk-3FUC2YCW-DWaNSANO.js} +2 -2
  7. package/dist/{chunk-7M6MHVWA-BERAnmfo.js → chunk-7M6MHVWA-x-N4hnls.js} +1 -1
  8. package/dist/{chunk-GNY47TPC-DMMDhC9T.js → chunk-GNY47TPC-Dzk3o85s.js} +4 -4
  9. package/dist/{chunk-NETBCI7D-CsMBdu5o.js → chunk-NETBCI7D-WvAAUJne.js} +1 -1
  10. package/dist/{chunk-Z7XXMR3K-CLYmaWUD.js → chunk-Z7XXMR3K-DY6U0Uq4.js} +1 -1
  11. package/dist/{classDiagram-v2-NBCMYWYE-C-6ddqhF.js → classDiagram-v2-NBCMYWYE-QeFmLU9L.js} +2 -2
  12. package/dist/components/base-content.css +64 -4
  13. package/dist/{components-C5y9FL-6.js → components-DH5dpaU8.js} +20768 -20704
  14. package/dist/components.js +5 -5
  15. package/dist/{dagre-6A5THRUB-Ck8np52h.js → dagre-6A5THRUB-D-NdHe_L.js} +11 -11
  16. package/dist/{diagram-22UHCM2B-oIfSvE0L.js → diagram-22UHCM2B-DZ4jejn3.js} +2 -2
  17. package/dist/{diagram-3UASUU5V-CAG93Qkg.js → diagram-3UASUU5V-DRoFk6qc.js} +1 -1
  18. package/dist/dnd.js +1 -1
  19. package/dist/{elk-276RUBZZ-BfEvNh_f.js → elk-276RUBZZ-BG0kHR2f.js} +3 -3
  20. package/dist/{erDiagram-OPXOYQCR-B966QSkJ.js → erDiagram-OPXOYQCR-B6XRmJuU.js} +2 -2
  21. package/dist/{field-blur-B6VqkpE6.js → field-blur-B1VUvTws.js} +941 -927
  22. package/dist/{flowDiagram-KWPJA3E3-CzUHW7vw.js → flowDiagram-KWPJA3E3-BghxpN0G.js} +3 -3
  23. package/dist/{ganttDiagram-FUAMR5RP-B4JstFXN.js → ganttDiagram-FUAMR5RP-C3aoaoXQ.js} +1 -1
  24. package/dist/{graphlib-CORKO6lR.js → graphlib-Dc5Siwxn.js} +6 -6
  25. package/dist/hooks.js +2 -2
  26. package/dist/{i18n-provider-BC7MMAID.js → i18n-provider-Cq_VScPv.js} +1 -1
  27. package/dist/i18n.js +6 -6
  28. package/dist/{isArrayLikeObject-gzSxxbGJ.js → isArrayLikeObject-DeHDPOEB.js} +3 -3
  29. package/dist/{isEmpty-SD8ldTK-.js → isEmpty-Sic-RRp7.js} +3 -3
  30. package/dist/{journeyDiagram-ZHPQQLJL-DcgTl4Bw.js → journeyDiagram-ZHPQQLJL-DcUX0asi.js} +1 -1
  31. package/dist/lib/components/ui/collections/data-table/data-table-density.d.ts +15 -0
  32. package/dist/lib/components/ui/collections/data-table/data-table.d.ts +1 -1
  33. package/dist/lib/components/ui/collections/data-table/types.d.ts +7 -0
  34. package/dist/lib/components/ui/overlays/dialog/dialog-outside.d.ts +4 -2
  35. package/dist/lib/components/ui/overlays/dialog/dialog-parts.d.ts +7 -0
  36. package/dist/lib/components/ui/overlays/dialog/dialog.d.ts +2 -5
  37. package/dist/lib/components/ui/overlays/dialog/in-dialog.d.ts +13 -0
  38. package/dist/lib/components/ui/overlays/menubar/menubar-items.d.ts +18 -0
  39. package/dist/lib/components/ui/overlays/menubar/menubar-sub.d.ts +8 -0
  40. package/dist/lib/components/ui/overlays/menubar/menubar.d.ts +3 -21
  41. package/dist/lib/components/ui/overlays/sheet/sheet-parts.d.ts +7 -0
  42. package/dist/lib/components/ui/overlays/sheet/sheet.d.ts +2 -5
  43. package/dist/lib/components/ui/selection/autocomplete/partials/autocomplete-chips.d.ts +2 -0
  44. package/dist/lib/components/ui/selection/autocomplete/partials/autocomplete-popup.d.ts +2 -1
  45. package/dist/lib/components/ui/selection/combobox/combobox-content.d.ts +14 -0
  46. package/dist/lib/components/ui/selection/combobox/combobox.d.ts +1 -4
  47. package/dist/lib/i18n/resources/en/en.d.ts +1 -0
  48. package/dist/lib/i18n/resources/en/material.json.d.ts +1 -0
  49. package/dist/lib/i18n/resources/fr/fr.d.ts +1 -0
  50. package/dist/lib/i18n/resources/fr/material.json.d.ts +1 -0
  51. package/dist/lib/i18n/resources/resources.d.ts +2 -0
  52. package/dist/lib/i18n/translator.d.ts +1 -1
  53. package/dist/lib.js +2 -2
  54. package/dist/main.js +11 -11
  55. package/dist/map.js +8 -8
  56. package/dist/material.css +1 -1
  57. package/dist/{merge-Cek5eQP5.js → merge-VyOzRzYB.js} +4 -4
  58. package/dist/{mermaid.core-DZMjEtsT.js → mermaid.core-DLu6PrQ9.js} +21 -21
  59. package/dist/{mindmap-definition-NLK3R4M7-BWaJFjFb.js → mindmap-definition-NLK3R4M7-B7Y8Yx12.js} +2 -2
  60. package/dist/{pieDiagram-5QR66LMP-C8iomTeg.js → pieDiagram-5QR66LMP-Bv9VMy5P.js} +1 -1
  61. package/dist/print.js +2 -2
  62. package/dist/{quadrantDiagram-O4NWA36T-D529X2yn.js → quadrantDiagram-O4NWA36T-Dr2CLVD8.js} +1 -1
  63. package/dist/{requirementDiagram-PLB6GJNP-Cs5ieS_S.js → requirementDiagram-PLB6GJNP-XuNWo4K8.js} +2 -2
  64. package/dist/{sankeyDiagram-IPEJSGJF-BOIAba-k.js → sankeyDiagram-IPEJSGJF-DzXzUNs5.js} +1 -1
  65. package/dist/{sortable-provider-DNmv3XmW.js → sortable-provider-XneXCqY1.js} +1 -1
  66. package/dist/{stateDiagram-v2-GCMORJYK-CT46B5KK.js → stateDiagram-v2-GCMORJYK-BN2OBfZa.js} +2 -2
  67. package/dist/{stored-language-FHwsTPoM.js → stored-language-DqlfjXt8.js} +2 -0
  68. package/dist/{swimlanes-2SLR337P-C8TrgNLm.js → swimlanes-2SLR337P-Ma7iLhhV.js} +3 -3
  69. package/dist/{swimlanesDiagram-TC7HE7FX-Dii9S4bC.js → swimlanesDiagram-TC7HE7FX-DWBnIppx.js} +3 -3
  70. package/dist/{timeline-definition-EJHVYXUP-K00somtn.js → timeline-definition-EJHVYXUP-BBwvY1Xf.js} +1 -1
  71. package/dist/{translate-material-cZ6VSQ98.js → translate-material-B6HO6ykL.js} +2 -2
  72. package/dist/{translator-DX_ArUA5.js → translator-B_lmafJN.js} +1 -1
  73. package/dist/{use-heading-spy-DR1jat6E.js → use-heading-spy-D1Ifooi5.js} +2 -2
  74. package/dist/{use-material-translation-W6jOKCbO.js → use-material-translation-Bp4ECeT4.js} +2 -2
  75. package/dist/{usecaseDiagram-POWQR4AR-liF9q6mE.js → usecaseDiagram-POWQR4AR-B1HduAbh.js} +2 -2
  76. package/dist/{xychartDiagram-PMCCYNJV-B9Qx3wAO.js → xychartDiagram-PMCCYNJV-ByjPOY-5.js} +1 -1
  77. package/docs/components/data-table-filter-and-lists.md +3 -1
  78. package/docs/guides/forms.md +49 -0
  79. package/docs/guides/i18n.md +2 -1
  80. package/docs/troubleshooting.md +27 -0
  81. package/lib/components/base-content.css +64 -4
  82. package/package.json +1 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,26 @@
1
1
  # @nxgt/material
2
2
 
3
+ ## 2.20.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#588](https://github.com/softistx/nxgt-material/pull/588) [`f8ef212`](https://github.com/softistx/nxgt-material/commit/f8ef2120be53d5a60a976ff47355d1eb487672b1) Thanks [@SteveGT96](https://github.com/SteveGT96)! - `DataTable` takes a `density` prop, `'comfortable'` (default, the look it always had) or `'compact'`, which tightens the cell padding above and below, the row and header heights, the sort and expand buttons (the expand button keeps 28px, above the 24px target minimum) and the gap between rows, the selection column included. The table carries it as `data-density`, styled with classes, so a strict CSP is unaffected; a `DataTable` nested in an expanded row keeps its own density. The toolbar band, the empty state and the print variant keep their size. The `DataTableDensity` type is exported.
8
+
9
+ Also in this release:
10
+
11
+ - `@nxgt/material`: `TableHead` now sets `text-foreground`, as `@nxgt/material-vue`'s does. It affects every React `Table` header: the header text is the foreground colour, no longer the muted inherited one (3.97:1 contrast on the header band, now above 4.5:1).
12
+ - Both: the `expand` column's header is no longer empty. It holds a visually hidden "Expand" (`material.table.labels.expand`, "Déplier" in French), which fixes axe's `empty-table-header`. An app that overrides the `material.table.labels` bundle can add the key.
13
+
14
+ Nothing to change in an existing app.
15
+
16
+ ### Patch Changes
17
+
18
+ - [#579](https://github.com/softistx/nxgt-material/pull/579) [`69562df`](https://github.com/softistx/nxgt-material/commit/69562dff2d874d60f066d45dd6dc7df418112041) Thanks [@SteveGT96](https://github.com/SteveGT96)! - Autocomplete in a dialog: the open list no longer covers the dialog's own controls ([#577](https://github.com/softistx/nxgt-material/issues/577)). Inside a `DialogContent`, `DialogScrollContent`, `AlertDialogContent` or `SheetContent`, the list opens under the field's helper text, in the layer's flow, and pushes what follows (the footer, the Save button) down instead of floating over it. It never flips up over the title, and its options scroll past 15rem. The layer grows while the list is open (a dialog stays capped at the viewport and scrolls) and shrinks back at once on a pick, so the next field does not move under a click aimed at it. A closed field is as tall in a dialog as outside one. A `PopoverContent`, `HoverCardContent` or menu content opened from a dialog keeps a floating list, as on the page. A `DrawerContent` on the page is not covered yet: its list still floats ([#582](https://github.com/softistx/nxgt-material/issues/582)). Outside these layers nothing changes. No API change.
19
+
20
+ - [#586](https://github.com/softistx/nxgt-material/pull/586) [`a3d9c79`](https://github.com/softistx/nxgt-material/commit/a3d9c79310c09e14d25b67db5c5c73afa4f875b4) Thanks [@SteveGT96](https://github.com/SteveGT96)! - `.form-grid-layout` no longer caps its height (`max-h-[calc(100lvh-…)]`) nor scrolls `[data-slot="form-fields"]` in a box of its own: a long form grows with the page, and the page (or the `DialogContent` / `SheetContent` around it) is the one scroll. `[data-slot="form-actions"]` is sticky at the bottom of that scroll on a blurred `bg-background/90`, so Cancel and Save stay in reach. In a `DialogContent` or an `AlertDialogContent` the stuck actions fill the dialog's padding below them, and `ConfirmationDialog`'s footer sticks the same way when it holds a form (any dialog holding a `.form-grid-layout` without `form-actions` does). A form that is a direct child of `DrawerContent` scrolls itself, since a drawer does not. The fields' controls and links carry `scroll-margin-bottom` (6rem plus a dialog's bottom padding, 7.5rem above `ConfirmationDialog`'s footer), so a field tabbed to is scrolled clear of the actions in any scroll box (WCAG 2.4.11); `--form-actions-clearance` raises it for taller actions, and `--form-actions-fill` names a dialog's bottom padding when it is not the default.
21
+
22
+ Migration: search for `form-grid-layout` in a box with a fixed height that relied on the fields scrolling inside it; give that form (or box) the height and the scroll yourself (`max-h-[60vh] overflow-y-auto`), and the actions stick to its bottom. To keep the actions in place, add `static` to `[data-slot="form-actions"]`. An app's own fixed bottom bar or floating button now sits under the sticky actions (`z-index: 10`): give it a z-index above 10. Storybook: `Guides/Forms/Form grid layout`, `Guides/Forms/Form grid layout, overlays` and `Guides/Forms/Form grid layout, dialogs`.
23
+
3
24
  ## 2.19.0
4
25
 
5
26
  ### Minor Changes
@@ -1,4 +1,4 @@
1
- import { S as e, T as t, d as n, g as r, l as i, u as a, v as o, w as s, x as c } from "./translator-DX_ArUA5.js";
1
+ import { S as e, T as t, d as n, g as r, l as i, u as a, v as o, w as s, x as c } from "./translator-B_lmafJN.js";
2
2
  //#region ../../node_modules/lodash-es/_isIndex.js
3
3
  var l = 9007199254740991, u = /^(?:0|[1-9]\d*)$/;
4
4
  function d(e, t) {
@@ -1,4 +1,4 @@
1
- import { m as e, p as t } from "./translator-DX_ArUA5.js";
1
+ import { m as e, p as t } from "./translator-B_lmafJN.js";
2
2
  //#region ../../node_modules/lodash-es/identity.js
3
3
  function n(e) {
4
4
  return e;
@@ -1,6 +1,6 @@
1
- import { a as e, i as t, t as n } from "./stored-language-FHwsTPoM.js";
2
- import { C as r, S as i, h as a, l as o, m as s, p as c, r as l, u, v as d, w as f, x as p } from "./translator-DX_ArUA5.js";
3
- import { a as m, c as h, d as g, i as _, n as v, r as y, t as b, u as ee } from "./_Uint8Array-B6RHzY7k.js";
1
+ import { a as e, i as t, t as n } from "./stored-language-DqlfjXt8.js";
2
+ import { C as r, S as i, h as a, l as o, m as s, p as c, r as l, u, v as d, w as f, x as p } from "./translator-B_lmafJN.js";
3
+ import { a as m, c as h, d as g, i as _, n as v, r as y, t as b, u as ee } from "./_Uint8Array-DGVY6NfN.js";
4
4
  import { L as te } from "./number.utils-BiBN2hWJ.js";
5
5
  import { Suspense as ne, createContext as re, createElement as x, useContext as ie, useEffect as ae, useMemo as S, useReducer as oe, useState as se, useSyncExternalStore as ce } from "react";
6
6
  import { asyncThunkCreator as le, buildCreateSlice as ue } from "@reduxjs/toolkit";
@@ -1,4 +1,4 @@
1
- import { t as e } from "./graphlib-CORKO6lR.js";
1
+ import { t as e } from "./graphlib-Dc5Siwxn.js";
2
2
  import { n as t, t as n } from "./src-CsLQInsN.js";
3
3
  import { A as r, B as i, C as a, D as o, E as s, F as c, G as l, H as u, I as d, L as f, M as p, N as m, O as h, P as g, R as _, T as v, U as ee, V as y, W as b, b as x, j as S, k as C, l as w, v as T, w as E, z as D } from "./chunk-ZIGJFQKS-9VXArDKF.js";
4
4
  import { n as O } from "./chunk-Y2CYZVJY-BAad7w_K.js";
@@ -12,7 +12,7 @@ import "./chunk-7PRAP22T-0C6_H8Li.js";
12
12
  import { i as se, n as ce, o as le, r as ue, s as de } from "./chunk-J5ZVWO5B-DmRRmhon.js";
13
13
  import "./chunk-7INBJB4K-k-I67NSP.js";
14
14
  import { i as fe, r as pe } from "./chunk-5DYCD2WN-Cd1zazNp.js";
15
- import { a as me, c as he, i as ge, l as _e } from "./chunk-Z7XXMR3K-CLYmaWUD.js";
15
+ import { a as me, c as he, i as ge, l as _e } from "./chunk-Z7XXMR3K-DY6U0Uq4.js";
16
16
  //#region ../../node_modules/es-toolkit/dist/compat/predicate/isArray.mjs
17
17
  function ve(e) {
18
18
  return Array.isArray(e);
@@ -1,11 +1,11 @@
1
- import { t as e } from "./graphlib-CORKO6lR.js";
1
+ import { t as e } from "./graphlib-Dc5Siwxn.js";
2
2
  import { n as t } from "./src-CsLQInsN.js";
3
3
  import { g as n } from "./chunk-ZIGJFQKS-9VXArDKF.js";
4
4
  import { n as r } from "./chunk-Y2CYZVJY-BAad7w_K.js";
5
5
  import { b as i, x as a } from "./chunk-O7XYJQB3-BChweQ_V.js";
6
6
  import { o } from "./chunk-7INBJB4K-k-I67NSP.js";
7
7
  import { i as s, n as c, r as l, t as u } from "./chunk-5DYCD2WN-Cd1zazNp.js";
8
- import { a as d, c as f, i as p, n as m, r as h, t as g, u as _ } from "./chunk-Z7XXMR3K-CLYmaWUD.js";
8
+ import { a as d, c as f, i as p, n as m, r as h, t as g, u as _ } from "./chunk-Z7XXMR3K-DY6U0Uq4.js";
9
9
  import { r as v, t as y } from "./chunk-UA2S7LBM-ChuksCDg.js";
10
10
  //#region ../../node_modules/mermaid/dist/chunks/mermaid.core/chunk-3FUC2YCW.mjs
11
11
  function b(e, { edgePathsClass: t = "edges edgePaths" } = {}) {
@@ -9,7 +9,7 @@ import { a as b } from "./chunk-7INBJB4K-k-I67NSP.js";
9
9
  import { t as x } from "./chunk-GWA4HPMP-B8jXI0Tl.js";
10
10
  import { t as S } from "./chunk-XXDRQBXY-dKXxu_aj.js";
11
11
  import { t as C } from "./chunk-WEXAMYUT-CbFOhEve.js";
12
- import { r as w, t as T } from "./chunk-GNY47TPC-DMMDhC9T.js";
12
+ import { r as w, t as T } from "./chunk-GNY47TPC-Dzk3o85s.js";
13
13
  import { n as E, t as D } from "./chunk-LNGE3PJU-DJjGTS7O.js";
14
14
  //#region ../../node_modules/mermaid/dist/chunks/mermaid.core/chunk-7M6MHVWA.mjs
15
15
  var ie = "flowchart-", ae = class {
@@ -5,7 +5,7 @@ import { b as r, s as i } from "./chunk-O7XYJQB3-BChweQ_V.js";
5
5
  import { t as a } from "./chunk-DUW6YSOI-9R-v-IIp.js";
6
6
  import { o } from "./chunk-7INBJB4K-k-I67NSP.js";
7
7
  import { r as s } from "./chunk-5DYCD2WN-Cd1zazNp.js";
8
- import { a as c, c as l, i as u, l as d } from "./chunk-Z7XXMR3K-CLYmaWUD.js";
8
+ import { a as c, c as l, i as u, l as d } from "./chunk-Z7XXMR3K-DY6U0Uq4.js";
9
9
  import { r as f } from "./chunk-UA2S7LBM-ChuksCDg.js";
10
10
  //#region ../../node_modules/mermaid/dist/chunks/mermaid.core/chunk-GNY47TPC.mjs
11
11
  var p = {
@@ -30,7 +30,7 @@ var p = {
30
30
  ], h = /* @__PURE__ */ Object.create(null), g = /* @__PURE__ */ n((e) => {
31
31
  for (let t of e) h[t.name] = t;
32
32
  }, "registerLayoutLoaders"), _ = /* @__PURE__ */ n(() => {
33
- let e = /* @__PURE__ */ n(async () => await import("./elk-276RUBZZ-BfEvNh_f.js"), "loader");
33
+ let e = /* @__PURE__ */ n(async () => await import("./elk-276RUBZZ-BG0kHR2f.js"), "loader");
34
34
  return [{
35
35
  name: "elk",
36
36
  loader: e,
@@ -45,11 +45,11 @@ var p = {
45
45
  g([
46
46
  {
47
47
  name: "dagre",
48
- loader: /* @__PURE__ */ n(async () => await import("./dagre-6A5THRUB-Ck8np52h.js"), "loader")
48
+ loader: /* @__PURE__ */ n(async () => await import("./dagre-6A5THRUB-D-NdHe_L.js"), "loader")
49
49
  },
50
50
  {
51
51
  name: "swimlane",
52
- loader: /* @__PURE__ */ n(async () => await import("./swimlanes-2SLR337P-C8TrgNLm.js"), "loader")
52
+ loader: /* @__PURE__ */ n(async () => await import("./swimlanes-2SLR337P-Ma7iLhhV.js"), "loader")
53
53
  },
54
54
  {
55
55
  name: "cose-bilkent",
@@ -1,5 +1,5 @@
1
1
  import { n as e } from "./chunk-Y2CYZVJY-BAad7w_K.js";
2
- import { o as t } from "./chunk-Z7XXMR3K-CLYmaWUD.js";
2
+ import { o as t } from "./chunk-Z7XXMR3K-DY6U0Uq4.js";
3
3
  //#region ../../node_modules/mermaid/dist/chunks/mermaid.core/chunk-NETBCI7D.mjs
4
4
  var n = 5, r = 1e-5, i = 2, a = .6, o = 1e-6;
5
5
  function s(e) {
@@ -1,4 +1,4 @@
1
- import { st as e } from "./components-C5y9FL-6.js";
1
+ import { st as e } from "./components-DH5dpaU8.js";
2
2
  import { n as t, t as n } from "./src-CsLQInsN.js";
3
3
  import { _ as r, a as i, i as a, n as o, o as s, p as c, r as l, t as u, u as d, v as f } from "./step-Dt43c9X4.js";
4
4
  import { K as p, g as m, q as h, u as g } from "./chunk-ZIGJFQKS-9VXArDKF.js";
@@ -9,12 +9,12 @@ import "./chunk-7PRAP22T-0C6_H8Li.js";
9
9
  import { i as v, n as y, o as b, r as x } from "./chunk-J5ZVWO5B-DmRRmhon.js";
10
10
  import "./chunk-7INBJB4K-k-I67NSP.js";
11
11
  import "./chunk-5DYCD2WN-Cd1zazNp.js";
12
- import "./chunk-Z7XXMR3K-CLYmaWUD.js";
12
+ import "./chunk-Z7XXMR3K-DY6U0Uq4.js";
13
13
  import { t as S } from "./chunk-GWA4HPMP-B8jXI0Tl.js";
14
14
  import { t as C } from "./chunk-XXDRQBXY-dKXxu_aj.js";
15
15
  import { t as w } from "./chunk-WEXAMYUT-CbFOhEve.js";
16
16
  import "./chunk-UA2S7LBM-ChuksCDg.js";
17
- import { r as T, t as E } from "./chunk-GNY47TPC-DMMDhC9T.js";
17
+ import { r as T, t as E } from "./chunk-GNY47TPC-Dzk3o85s.js";
18
18
  //#region ../../node_modules/mermaid/dist/chunks/mermaid.core/classDiagram-v2-NBCMYWYE.mjs
19
19
  var D = (function() {
20
20
  var e = /* @__PURE__ */ i(function(e, t, n, r) {
@@ -97,7 +97,7 @@
97
97
  .form-grid-layout {
98
98
  @apply relative flex flex-col gap-2 @container;
99
99
  [data-slot="form-fields"] {
100
- @apply grid @2xl:grid-cols-2 @4xl:grid-cols-3 @6xl:grid-cols-4 gap-2 bg-background/80 p-4 place-items-start overflow-auto;
100
+ @apply grid @2xl:grid-cols-2 @4xl:grid-cols-3 @6xl:grid-cols-4 gap-2 bg-background/80 p-4 place-items-start;
101
101
 
102
102
  [data-slot="separator"] {
103
103
  @apply col-start-full;
@@ -125,13 +125,73 @@
125
125
  @apply col-start-full;
126
126
  }
127
127
  }
128
+ /* A focused control scrolls into view clear of the actions and a line
129
+ of helper text, in any scroll box (WCAG 2.4.11 Focus Not Obscured). */
130
+ [data-slot="form-fields"]
131
+ :is(
132
+ input,
133
+ textarea,
134
+ select,
135
+ button,
136
+ a[href],
137
+ summary,
138
+ [tabindex],
139
+ [contenteditable]
140
+ ) {
141
+ scroll-margin-bottom: calc(
142
+ var(--form-actions-clearance, 6rem) +
143
+ var(--form-actions-fill, 0px)
144
+ );
145
+ }
146
+ /* Sticky at the bottom of whatever scrolls the form: in reach. */
128
147
  [data-slot="form-actions"] {
129
- @apply flex w-full justify-end gap-2 bottom-2 p-4 max-sm:*:flex-1;
148
+ @apply sticky bottom-0 z-10 flex w-full justify-end gap-2 bg-background/90 p-4 backdrop-blur-sm max-sm:*:flex-1;
130
149
  }
131
150
  }
132
151
 
133
- .form-grid-layout {
134
- @apply max-h-[calc(100lvh-184px)] md:max-h-[calc(100lvh-242px)] lg:max-h-[calc(100lvh-280px)];
152
+ /* No height cap and no scroll of its own: the page (or the overlay) is
153
+ the one scroll. A Drawer's content does not scroll: the form does. */
154
+ [data-slot="drawer-content"] > .form-grid-layout {
155
+ @apply min-h-0 overflow-y-auto;
156
+ }
157
+
158
+ /* In a dialog, the stuck actions sit above its bottom padding
159
+ (`--form-actions-fill`: p-6 by default; set it for another one). */
160
+ :is([data-slot="dialog-content"], [data-slot="alert-dialog-content"]) {
161
+ --form-actions-fill: 1.5rem;
162
+ &:is(.p-0, .py-0, .pb-0) {
163
+ --form-actions-fill: 0px;
164
+ }
165
+ &:is(.p-4, .py-4, .pb-4) {
166
+ --form-actions-fill: 1rem;
167
+ }
168
+ }
169
+
170
+ /* ConfirmationDialog's form has no actions of its own: the dialog's
171
+ footer (two stacked buttons on a phone) sticks instead. */
172
+ :is([data-slot="dialog-content"], [data-slot="alert-dialog-content"]):has(
173
+ .form-grid-layout
174
+ ):not(:has([data-slot="form-actions"])) {
175
+ --form-actions-clearance: 7.5rem;
176
+ > :is([data-slot="dialog-footer"], [data-slot="alert-dialog-footer"]) {
177
+ @apply sticky bottom-0 z-10 bg-background/90 backdrop-blur-sm;
178
+ }
179
+ }
180
+
181
+ /* A sticky element stops at the scroll box's padding: in a dialog, an
182
+ `::after` as tall as that padding fills the strip below the stuck
183
+ actions, so no field shows there, and adds no overflow. */
184
+ :is([data-slot="dialog-content"], [data-slot="alert-dialog-content"])
185
+ .form-grid-layout
186
+ > [data-slot="form-actions"]::after,
187
+ :is([data-slot="dialog-content"], [data-slot="alert-dialog-content"]):has(
188
+ .form-grid-layout
189
+ ):not(:has([data-slot="form-actions"]))
190
+ > :is(
191
+ [data-slot="dialog-footer"],
192
+ [data-slot="alert-dialog-footer"]
193
+ )::after {
194
+ @apply absolute inset-x-0 top-full h-(--form-actions-fill) bg-background content-[""];
135
195
  }
136
196
 
137
197
  /* No height cap on `DataTable` here (it nested a scroll in the page's):