@camunda/design-system 0.32.1 → 0.32.2

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 (42) hide show
  1. package/dist/carbon-compat/c3-cluster-tag.d.ts.map +1 -1
  2. package/dist/carbon-compat/c3-cluster-tag.js +10 -4
  3. package/dist/carbon-compat/c3-cluster-tag.js.map +1 -1
  4. package/dist/src/components/ui/alert-dialog.d.ts +1 -1
  5. package/dist/src/components/ui/alert-dialog.d.ts.map +1 -1
  6. package/dist/src/components/ui/alert-dialog.js +6 -2
  7. package/dist/src/components/ui/alert-dialog.js.map +1 -1
  8. package/dist/src/components/ui/button.js +1 -1
  9. package/dist/src/components/ui/button.js.map +1 -1
  10. package/dist/src/components/ui/c4-provider.d.ts.map +1 -1
  11. package/dist/src/components/ui/c4-provider.js +6 -0
  12. package/dist/src/components/ui/c4-provider.js.map +1 -1
  13. package/dist/src/components/ui/dialog.d.ts +1 -1
  14. package/dist/src/components/ui/dialog.d.ts.map +1 -1
  15. package/dist/src/components/ui/dialog.js +9 -2
  16. package/dist/src/components/ui/dialog.js.map +1 -1
  17. package/dist/src/components/ui/dropdown.d.ts +1 -1
  18. package/dist/src/components/ui/dropdown.d.ts.map +1 -1
  19. package/dist/src/components/ui/dropdown.js +6 -2
  20. package/dist/src/components/ui/dropdown.js.map +1 -1
  21. package/dist/src/components/ui/popover.d.ts +1 -1
  22. package/dist/src/components/ui/popover.d.ts.map +1 -1
  23. package/dist/src/components/ui/popover.js +6 -2
  24. package/dist/src/components/ui/popover.js.map +1 -1
  25. package/dist/src/components/ui/select.d.ts +1 -1
  26. package/dist/src/components/ui/select.d.ts.map +1 -1
  27. package/dist/src/components/ui/select.js +7 -3
  28. package/dist/src/components/ui/select.js.map +1 -1
  29. package/dist/src/components/ui/sheet.d.ts +1 -1
  30. package/dist/src/components/ui/sheet.d.ts.map +1 -1
  31. package/dist/src/components/ui/sheet.js +6 -2
  32. package/dist/src/components/ui/sheet.js.map +1 -1
  33. package/dist/src/lib/focus-visible-on-close.d.ts +39 -0
  34. package/dist/src/lib/focus-visible-on-close.d.ts.map +1 -0
  35. package/dist/src/lib/focus-visible-on-close.js +61 -0
  36. package/dist/src/lib/focus-visible-on-close.js.map +1 -0
  37. package/dist/src/lib/inert-aria-hidden.d.ts +34 -0
  38. package/dist/src/lib/inert-aria-hidden.d.ts.map +1 -0
  39. package/dist/src/lib/inert-aria-hidden.js +76 -0
  40. package/dist/src/lib/inert-aria-hidden.js.map +1 -0
  41. package/dist/styles.css +790 -1625
  42. package/package.json +12 -12
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Makes the focus ring visible when a modal overlay restores focus to its
3
+ * trigger on close (#259 follow-up).
4
+ *
5
+ * Why: Radix restores focus with a programmatic `.focus()`. The browser's
6
+ * `:focus-visible` heuristic shows a ring only when the last input was a
7
+ * keyboard, so closing an overlay by mouse (clicking the X or the backdrop)
8
+ * returns focus to the trigger with no visible ring — a keyboard user who
9
+ * happened to click cannot see where focus landed. We stamp a transient marker
10
+ * on the restored element so the DS `Button` shows its ring regardless of the
11
+ * input modality that closed the overlay.
12
+ *
13
+ * The marker is self-clearing: it is removed on the next `pointerdown` anywhere
14
+ * and when the element loses focus. Without that, a sticky attribute would show
15
+ * a ring on every ordinary mouse click of that Button — a worse regression than
16
+ * the missing ring it fixes.
17
+ *
18
+ * Styling target: the marker lands on the element Radix focuses — the trigger,
19
+ * a DS `Button` in every DS overlay. A non-`Button` custom trigger would carry
20
+ * the attribute but has no matching ring style; same known-scope caveat as the
21
+ * inert body-child mirror in `inert-aria-hidden.ts`.
22
+ */
23
+ export const FOCUS_VISIBLE_RESTORE_ATTR = "data-focus-visible-restore";
24
+ /**
25
+ * Use as a Radix overlay `Content`'s `onCloseAutoFocus`. Does not
26
+ * `preventDefault`, so Radix still restores focus to the trigger; on the next
27
+ * frame the restored element (`document.activeElement`) is stamped with the
28
+ * self-clearing marker. No-ops if a prior handler already prevented the default
29
+ * restore.
30
+ */
31
+ export function markFocusVisibleOnClose(event) {
32
+ if (event.defaultPrevented || typeof requestAnimationFrame === "undefined") {
33
+ return;
34
+ }
35
+ requestAnimationFrame(() => {
36
+ const el = document.activeElement;
37
+ if (!(el instanceof HTMLElement) || el === document.body)
38
+ return;
39
+ el.setAttribute(FOCUS_VISIBLE_RESTORE_ATTR, "");
40
+ const clear = () => {
41
+ el.removeAttribute(FOCUS_VISIBLE_RESTORE_ATTR);
42
+ el.removeEventListener("blur", clear);
43
+ document.removeEventListener("pointerdown", clear, true);
44
+ };
45
+ el.addEventListener("blur", clear);
46
+ document.addEventListener("pointerdown", clear, true);
47
+ });
48
+ }
49
+ /**
50
+ * Wraps a Radix overlay `Content`'s `onCloseAutoFocus`: runs the consumer's
51
+ * handler first (so it can `preventDefault`), then stamps the focus-visible
52
+ * marker. Use in every DS overlay whose trigger is a `Button` so the restored
53
+ * focus ring is visible regardless of the closing input modality.
54
+ */
55
+ export function composeCloseAutoFocus(handler) {
56
+ return (event) => {
57
+ handler?.(event);
58
+ markFocusVisibleOnClose(event);
59
+ };
60
+ }
61
+ //# sourceMappingURL=focus-visible-on-close.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"focus-visible-on-close.js","sourceRoot":"","sources":["../../../src/lib/focus-visible-on-close.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,MAAM,CAAC,MAAM,0BAA0B,GAAG,4BAA4B,CAAC;AAEvE;;;;;;GAMG;AACH,MAAM,UAAU,uBAAuB,CAAC,KAAY;IAClD,IAAI,KAAK,CAAC,gBAAgB,IAAI,OAAO,qBAAqB,KAAK,WAAW,EAAE,CAAC;QAC3E,OAAO;IACT,CAAC;IACD,qBAAqB,CAAC,GAAG,EAAE;QACzB,MAAM,EAAE,GAAG,QAAQ,CAAC,aAAa,CAAC;QAClC,IAAI,CAAC,CAAC,EAAE,YAAY,WAAW,CAAC,IAAI,EAAE,KAAK,QAAQ,CAAC,IAAI;YAAE,OAAO;QACjE,EAAE,CAAC,YAAY,CAAC,0BAA0B,EAAE,EAAE,CAAC,CAAC;QAChD,MAAM,KAAK,GAAG,GAAG,EAAE;YACjB,EAAE,CAAC,eAAe,CAAC,0BAA0B,CAAC,CAAC;YAC/C,EAAE,CAAC,mBAAmB,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;YACtC,QAAQ,CAAC,mBAAmB,CAAC,aAAa,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;QAC3D,CAAC,CAAC;QACF,EAAE,CAAC,gBAAgB,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;QACnC,QAAQ,CAAC,gBAAgB,CAAC,aAAa,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;IACxD,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,qBAAqB,CACnC,OAAgC;IAEhC,OAAO,CAAC,KAAK,EAAE,EAAE;QACf,OAAO,EAAE,CAAC,KAAK,CAAC,CAAC;QACjB,uBAAuB,CAAC,KAAK,CAAC,CAAC;IACjC,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Mirrors native `inert` onto the page background while a modal Radix overlay
3
+ * (Dialog, AlertDialog, DropdownMenu, Select, Sheet, modal Popover) is open.
4
+ *
5
+ * Why this exists (#259): those primitives call the `aria-hidden` package's
6
+ * `hideOthers()` on open, which marks every background sibling
7
+ * `aria-hidden="true"` (plus a `data-aria-hidden` counter) but leaves it
8
+ * keyboard-focusable. That trips axe's `aria-hidden-focus` rule
9
+ * (WCAG 4.1.2 / 2.4.3) on every consuming app. Radix's pinned version uses
10
+ * `hideOthers()`, not `inertOthers()`, so we add `inert` ourselves.
11
+ *
12
+ * Scope: only direct children of `document.body` are inerted — those are the
13
+ * real page-background roots (app root, portal-less content). This matches
14
+ * Radix's default body-level portals: `hideOthers()` marks the portal's
15
+ * body-level siblings (the background) plus the overlay's in-portal sibling
16
+ * (the backdrop). The backdrop lives *inside* the portal (not a body child), so
17
+ * it is left untouched — inerting it would block click-outside-to-close.
18
+ *
19
+ * Known limitation: an app that both mounts into a non-body container AND
20
+ * configures Radix to portal inside that same container would have its
21
+ * background marked at a nested level, not as a body child, and would fall
22
+ * outside this scope. DS overlays use the default (body) portal, so this does
23
+ * not affect them.
24
+ *
25
+ * We only ever clear `inert` on elements we set it on (tracked in a WeakSet), so
26
+ * a consumer's own `inert` is never clobbered.
27
+ */
28
+ /**
29
+ * Installs a single document-wide observer that keeps `inert` in sync with the
30
+ * `data-aria-hidden` marker Radix applies. Idempotent — safe to call from every
31
+ * C4Provider mount; only the first call installs anything.
32
+ */
33
+ export declare function installAriaHiddenInert(): void;
34
+ //# sourceMappingURL=inert-aria-hidden.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inert-aria-hidden.d.ts","sourceRoot":"","sources":["../../../src/lib/inert-aria-hidden.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAUH;;;;GAIG;AACH,wBAAgB,sBAAsB,IAAI,IAAI,CAqC7C"}
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Mirrors native `inert` onto the page background while a modal Radix overlay
3
+ * (Dialog, AlertDialog, DropdownMenu, Select, Sheet, modal Popover) is open.
4
+ *
5
+ * Why this exists (#259): those primitives call the `aria-hidden` package's
6
+ * `hideOthers()` on open, which marks every background sibling
7
+ * `aria-hidden="true"` (plus a `data-aria-hidden` counter) but leaves it
8
+ * keyboard-focusable. That trips axe's `aria-hidden-focus` rule
9
+ * (WCAG 4.1.2 / 2.4.3) on every consuming app. Radix's pinned version uses
10
+ * `hideOthers()`, not `inertOthers()`, so we add `inert` ourselves.
11
+ *
12
+ * Scope: only direct children of `document.body` are inerted — those are the
13
+ * real page-background roots (app root, portal-less content). This matches
14
+ * Radix's default body-level portals: `hideOthers()` marks the portal's
15
+ * body-level siblings (the background) plus the overlay's in-portal sibling
16
+ * (the backdrop). The backdrop lives *inside* the portal (not a body child), so
17
+ * it is left untouched — inerting it would block click-outside-to-close.
18
+ *
19
+ * Known limitation: an app that both mounts into a non-body container AND
20
+ * configures Radix to portal inside that same container would have its
21
+ * background marked at a nested level, not as a body child, and would fall
22
+ * outside this scope. DS overlays use the default (body) portal, so this does
23
+ * not affect them.
24
+ *
25
+ * We only ever clear `inert` on elements we set it on (tracked in a WeakSet), so
26
+ * a consumer's own `inert` is never clobbered.
27
+ */
28
+ const HIDDEN_SELECTOR = '[data-aria-hidden][aria-hidden="true"]';
29
+ let installed = false;
30
+ function isBackgroundRoot(el) {
31
+ return el.parentElement === document.body && el instanceof HTMLElement;
32
+ }
33
+ /**
34
+ * Installs a single document-wide observer that keeps `inert` in sync with the
35
+ * `data-aria-hidden` marker Radix applies. Idempotent — safe to call from every
36
+ * C4Provider mount; only the first call installs anything.
37
+ */
38
+ export function installAriaHiddenInert() {
39
+ if (typeof document === "undefined" || installed)
40
+ return;
41
+ installed = true;
42
+ const owned = new WeakSet();
43
+ const sync = (el) => {
44
+ if (!isBackgroundRoot(el))
45
+ return;
46
+ const shouldInert = el.matches(HIDDEN_SELECTOR);
47
+ if (shouldInert && !el.inert) {
48
+ el.inert = true;
49
+ owned.add(el);
50
+ }
51
+ else if (!shouldInert && owned.has(el)) {
52
+ el.inert = false;
53
+ owned.delete(el);
54
+ }
55
+ };
56
+ // Cover state that already exists at install time (an overlay may open before
57
+ // the first provider mounts, or the provider itself lives inside the overlay).
58
+ document.body.querySelectorAll(HIDDEN_SELECTOR).forEach(sync);
59
+ const observer = new MutationObserver((records) => {
60
+ for (const record of records)
61
+ sync(record.target);
62
+ });
63
+ // Watch only the marker attributes anywhere under body (cheap — the filter
64
+ // scopes callbacks to two attributes). This is the primary path: Radix
65
+ // toggles `aria-hidden`/`data-aria-hidden` on the background *after* the
66
+ // portal is inserted, so the attribute mutation always fires. Any background
67
+ // already marked at install time is handled by the scan above. Clearing the
68
+ // marker on close removes `inert` here; the FocusRestoredOnClose regression
69
+ // story guards that this lands before Radix restores focus to the trigger.
70
+ observer.observe(document.body, {
71
+ subtree: true,
72
+ attributes: true,
73
+ attributeFilter: ["aria-hidden", "data-aria-hidden"],
74
+ });
75
+ }
76
+ //# sourceMappingURL=inert-aria-hidden.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inert-aria-hidden.js","sourceRoot":"","sources":["../../../src/lib/inert-aria-hidden.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,MAAM,eAAe,GAAG,wCAAwC,CAAC;AAEjE,IAAI,SAAS,GAAG,KAAK,CAAC;AAEtB,SAAS,gBAAgB,CAAC,EAAW;IACnC,OAAO,EAAE,CAAC,aAAa,KAAK,QAAQ,CAAC,IAAI,IAAI,EAAE,YAAY,WAAW,CAAC;AACzE,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,sBAAsB;IACpC,IAAI,OAAO,QAAQ,KAAK,WAAW,IAAI,SAAS;QAAE,OAAO;IACzD,SAAS,GAAG,IAAI,CAAC;IAEjB,MAAM,KAAK,GAAG,IAAI,OAAO,EAAe,CAAC;IAEzC,MAAM,IAAI,GAAG,CAAC,EAAW,EAAE,EAAE;QAC3B,IAAI,CAAC,gBAAgB,CAAC,EAAE,CAAC;YAAE,OAAO;QAClC,MAAM,WAAW,GAAG,EAAE,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;QAChD,IAAI,WAAW,IAAI,CAAC,EAAE,CAAC,KAAK,EAAE,CAAC;YAC7B,EAAE,CAAC,KAAK,GAAG,IAAI,CAAC;YAChB,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChB,CAAC;aAAM,IAAI,CAAC,WAAW,IAAI,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;YACzC,EAAE,CAAC,KAAK,GAAG,KAAK,CAAC;YACjB,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;QACnB,CAAC;IACH,CAAC,CAAC;IAEF,8EAA8E;IAC9E,+EAA+E;IAC/E,QAAQ,CAAC,IAAI,CAAC,gBAAgB,CAAC,eAAe,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAE9D,MAAM,QAAQ,GAAG,IAAI,gBAAgB,CAAC,CAAC,OAAO,EAAE,EAAE;QAChD,KAAK,MAAM,MAAM,IAAI,OAAO;YAAE,IAAI,CAAC,MAAM,CAAC,MAAiB,CAAC,CAAC;IAC/D,CAAC,CAAC,CAAC;IACH,2EAA2E;IAC3E,uEAAuE;IACvE,yEAAyE;IACzE,6EAA6E;IAC7E,4EAA4E;IAC5E,4EAA4E;IAC5E,2EAA2E;IAC3E,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,EAAE;QAC9B,OAAO,EAAE,IAAI;QACb,UAAU,EAAE,IAAI;QAChB,eAAe,EAAE,CAAC,aAAa,EAAE,kBAAkB,CAAC;KACrD,CAAC,CAAC;AACL,CAAC"}