@fpkit/acss 0.5.12 → 0.5.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +89 -0
- package/libs/{chunk-DV56L5YX.cjs → chunk-2LTJ7HHX.cjs} +4 -4
- package/libs/{chunk-EQ67LF46.js → chunk-2Y7W75TT.js} +3 -3
- package/libs/{chunk-KKLTUJFB.cjs → chunk-3MKLDCKQ.cjs} +5 -5
- package/libs/chunk-3MKLDCKQ.cjs.map +1 -0
- package/libs/{chunk-X3EVB7VS.cjs → chunk-5S4ORA4C.cjs} +3 -3
- package/libs/{chunk-O6QZBB6G.js → chunk-772NRB75.js} +5 -5
- package/libs/chunk-772NRB75.js.map +1 -0
- package/libs/{chunk-6BVXFW7U.cjs → chunk-AHDJGCG5.cjs} +3 -3
- package/libs/{chunk-E3XP6BEX.cjs → chunk-B7F5FS6D.cjs} +3 -3
- package/libs/chunk-D4YLRWAO.cjs +18 -0
- package/libs/chunk-D4YLRWAO.cjs.map +1 -0
- package/libs/chunk-ETFLFC2S.js +10 -0
- package/libs/chunk-ETFLFC2S.js.map +1 -0
- package/libs/chunk-GZ4QFPRY.js +9 -0
- package/libs/chunk-GZ4QFPRY.js.map +1 -0
- package/libs/{chunk-LHVJKDMA.cjs → chunk-J32EZPYD.cjs} +3 -3
- package/libs/chunk-JJ43O4Y5.js +8 -0
- package/libs/chunk-JJ43O4Y5.js.map +1 -0
- package/libs/chunk-KUKIVRC2.js +7 -0
- package/libs/chunk-KUKIVRC2.js.map +1 -0
- package/libs/chunk-L75OQKEI.cjs +13 -0
- package/libs/chunk-L75OQKEI.cjs.map +1 -0
- package/libs/{chunk-LL7HTLMS.cjs → chunk-M5RRNTVX.cjs} +3 -3
- package/libs/{chunk-LIQJ7ZZR.js → chunk-NGTJDDFO.js} +2 -2
- package/libs/chunk-OK5QEIMD.cjs +17 -0
- package/libs/chunk-OK5QEIMD.cjs.map +1 -0
- package/libs/chunk-P2DC76ZZ.cjs +18 -0
- package/libs/chunk-P2DC76ZZ.cjs.map +1 -0
- package/libs/chunk-PQ2K3BM6.cjs +17 -0
- package/libs/chunk-PQ2K3BM6.cjs.map +1 -0
- package/libs/{chunk-QCMV4VQZ.js → chunk-QLZWHAMK.js} +2 -2
- package/libs/{chunk-BIP2NY53.js → chunk-RIVUMPOG.js} +2 -2
- package/libs/{chunk-ICCKQ2GC.cjs → chunk-ROZI23GS.cjs} +4 -4
- package/libs/{chunk-NHYXGV3L.js → chunk-SMYRLO3E.js} +2 -2
- package/libs/{chunk-5ZM4XL44.js → chunk-TYRCEX2L.js} +2 -2
- package/libs/chunk-VUH3FXGJ.js +11 -0
- package/libs/chunk-VUH3FXGJ.js.map +1 -0
- package/libs/{chunk-PPOOBUOS.js → chunk-XBA562WW.js} +2 -2
- package/libs/{chunk-QVV34QEH.cjs → chunk-XTQKWY7W.cjs} +3 -3
- package/libs/{chunk-YWOYVRFT.js → chunk-ZANSFMTD.js} +3 -3
- package/libs/components/alert/alert.css +1 -1
- package/libs/components/alert/alert.css.map +1 -1
- package/libs/components/alert/alert.min.css +2 -2
- package/libs/components/badge/badge.css +1 -1
- package/libs/components/badge/badge.css.map +1 -1
- package/libs/components/badge/badge.min.css +2 -2
- package/libs/components/breadcrumbs/breadcrumb.cjs +9 -5
- package/libs/components/breadcrumbs/breadcrumb.d.cts +271 -32
- package/libs/components/breadcrumbs/breadcrumb.d.ts +271 -32
- package/libs/components/breadcrumbs/breadcrumb.js +3 -3
- package/libs/components/button.cjs +4 -4
- package/libs/components/button.d.cts +2 -2
- package/libs/components/button.d.ts +2 -2
- package/libs/components/button.js +2 -2
- package/libs/components/buttons/button.css +1 -1
- package/libs/components/buttons/button.css.map +1 -1
- package/libs/components/buttons/button.min.css +2 -2
- package/libs/components/card.cjs +7 -7
- package/libs/components/card.d.cts +277 -33
- package/libs/components/card.d.ts +277 -33
- package/libs/components/card.js +2 -2
- package/libs/components/cards/card.css +1 -1
- package/libs/components/cards/card.css.map +1 -1
- package/libs/components/cards/card.min.css +2 -2
- package/libs/components/details/details.css +1 -1
- package/libs/components/details/details.css.map +1 -1
- package/libs/components/details/details.min.css +2 -2
- package/libs/components/dialog/dialog.cjs +7 -7
- package/libs/components/dialog/dialog.css +1 -1
- package/libs/components/dialog/dialog.css.map +1 -1
- package/libs/components/dialog/dialog.d.cts +88 -34
- package/libs/components/dialog/dialog.d.ts +88 -34
- package/libs/components/dialog/dialog.js +5 -5
- package/libs/components/dialog/dialog.min.css +2 -2
- package/libs/components/form/fields.cjs +4 -4
- package/libs/components/form/fields.d.cts +2 -2
- package/libs/components/form/fields.d.ts +2 -2
- package/libs/components/form/fields.js +2 -2
- package/libs/components/form/textarea.cjs +4 -4
- package/libs/components/form/textarea.d.cts +2 -2
- package/libs/components/form/textarea.d.ts +2 -2
- package/libs/components/form/textarea.js +2 -2
- package/libs/components/heading/heading.cjs +3 -3
- package/libs/components/heading/heading.d.cts +3 -14
- package/libs/components/heading/heading.d.ts +3 -14
- package/libs/components/heading/heading.js +2 -2
- package/libs/components/icons/icon.cjs +4 -4
- package/libs/components/icons/icon.d.cts +148 -4
- package/libs/components/icons/icon.d.ts +148 -4
- package/libs/components/icons/icon.js +2 -2
- package/libs/components/images/img.css +1 -1
- package/libs/components/images/img.css.map +1 -1
- package/libs/components/images/img.min.css +2 -2
- package/libs/components/link/link.cjs +4 -4
- package/libs/components/link/link.d.cts +2 -2
- package/libs/components/link/link.d.ts +2 -2
- package/libs/components/link/link.js +2 -2
- package/libs/components/list/list.cjs +5 -5
- package/libs/components/list/list.d.cts +3 -3
- package/libs/components/list/list.d.ts +3 -3
- package/libs/components/list/list.js +2 -2
- package/libs/components/modal.cjs +4 -4
- package/libs/components/modal.js +3 -3
- package/libs/components/nav/nav.cjs +7 -7
- package/libs/components/nav/nav.d.cts +2 -2
- package/libs/components/nav/nav.d.ts +2 -2
- package/libs/components/nav/nav.js +3 -3
- package/libs/components/text/text.cjs +5 -5
- package/libs/components/text/text.d.cts +2 -2
- package/libs/components/text/text.d.ts +2 -2
- package/libs/components/text/text.js +2 -2
- package/libs/heading-3648c538.d.ts +250 -0
- package/libs/hooks.cjs +7 -0
- package/libs/hooks.d.cts +5 -0
- package/libs/hooks.d.ts +5 -0
- package/libs/hooks.js +3 -0
- package/libs/icons.cjs +3 -3
- package/libs/icons.d.cts +1 -1
- package/libs/icons.d.ts +1 -1
- package/libs/icons.js +2 -2
- package/libs/index.cjs +112 -91
- package/libs/index.cjs.map +1 -1
- package/libs/index.css +1 -1
- package/libs/index.css.map +1 -1
- package/libs/index.d.cts +515 -31
- package/libs/index.d.ts +515 -31
- package/libs/index.js +31 -19
- package/libs/index.js.map +1 -1
- package/libs/ui-645f95b5.d.ts +285 -0
- package/package.json +2 -83
- package/src/components/README-UI.mdx +416 -0
- package/src/components/alert/ACCESSIBILITY.md +319 -0
- package/src/components/alert/README.mdx +475 -19
- package/src/components/alert/alert.scss +113 -6
- package/src/components/alert/alert.stories.tsx +372 -0
- package/src/components/alert/alert.test.tsx +762 -0
- package/src/components/alert/alert.tsx +331 -66
- package/src/components/alert/views/alert-actions.tsx +13 -0
- package/src/components/alert/views/alert-content.tsx +17 -0
- package/src/components/alert/views/alert-icon.tsx +53 -0
- package/src/components/alert/views/alert-screen-reader-text.tsx +30 -0
- package/src/components/alert/views/alert-title.tsx +23 -0
- package/src/components/alert/views/alert-view.tsx +158 -0
- package/src/components/alert/views/index.ts +12 -0
- package/src/components/badge/badge.mdx +186 -49
- package/src/components/badge/badge.scss +20 -2
- package/src/components/badge/badge.stories.tsx +160 -14
- package/src/components/badge/badge.test.tsx +179 -0
- package/src/components/badge/badge.tsx +97 -4
- package/src/components/breadcrumbs/README.mdx +364 -45
- package/src/components/breadcrumbs/__snapshots__/breadcrumb.test.tsx.snap +152 -0
- package/src/components/breadcrumbs/breadcrumb.stories.tsx +7 -3
- package/src/components/breadcrumbs/breadcrumb.test.tsx +490 -0
- package/src/components/breadcrumbs/breadcrumb.tsx +427 -170
- package/src/components/buttons/button.scss +34 -31
- package/src/components/buttons/button.stories.tsx +35 -0
- package/src/components/cards/README.mdx +657 -0
- package/src/components/cards/card.scss +22 -0
- package/src/components/cards/card.stories.tsx +167 -5
- package/src/components/cards/card.test.tsx +360 -20
- package/src/components/cards/card.tsx +200 -79
- package/src/components/cards/card.types.ts +135 -0
- package/src/components/cards/card.utils.ts +79 -0
- package/src/components/details/ACCESSIBILITY-REVIEW-LIVE.md +1050 -0
- package/src/components/details/ACCESSIBILITY-REVIEW.md +502 -0
- package/src/components/details/README.mdx +437 -69
- package/src/components/details/details.scss +16 -7
- package/src/components/details/details.test.tsx +385 -0
- package/src/components/details/details.tsx +101 -69
- package/src/components/details/details.types.ts +76 -0
- package/src/components/dialog/README.mdx +513 -110
- package/src/components/dialog/dialog-modal.tsx +79 -56
- package/src/components/dialog/dialog.scss +53 -3
- package/src/components/dialog/dialog.stories.tsx +10 -7
- package/src/components/dialog/dialog.test.tsx +450 -0
- package/src/components/dialog/dialog.tsx +69 -59
- package/src/components/dialog/dialog.types.ts +133 -0
- package/src/components/dialog/views/dialog-footer.tsx +54 -11
- package/src/components/dialog/views/dialog-header.tsx +20 -15
- package/src/components/heading/heading.stories.tsx +44 -4
- package/src/components/heading/heading.tsx +89 -23
- package/src/components/icons/README.mdx +332 -0
- package/src/components/icons/icon.stories.tsx +74 -1
- package/src/components/icons/icon.tsx +89 -1
- package/src/components/icons/types.ts +47 -0
- package/src/components/images/README.mdx +340 -24
- package/src/components/images/img.scss +19 -3
- package/src/components/images/img.stories.tsx +424 -15
- package/src/components/images/img.test.tsx +354 -25
- package/src/components/images/img.tsx +186 -63
- package/src/components/images/img.types.ts +211 -0
- package/src/components/title/MIGRATION.md +199 -0
- package/src/components/title/README.md +326 -0
- package/src/components/title/README.mdx +452 -0
- package/src/components/title/title.stories.tsx +393 -0
- package/src/components/title/title.test.tsx +251 -0
- package/src/components/title/title.tsx +219 -0
- package/src/components/ui.stories.tsx +894 -0
- package/src/components/ui.test.tsx +559 -0
- package/src/components/ui.tsx +266 -15
- package/src/components/word-count/README.md +240 -0
- package/src/hooks.ts +1 -0
- package/src/index.ts +10 -2
- package/src/sass/_properties.scss +1 -0
- package/src/styles/alert/alert.css +94 -4
- package/src/styles/alert/alert.css.map +1 -1
- package/src/styles/badge/badge.css +20 -2
- package/src/styles/badge/badge.css.map +1 -1
- package/src/styles/buttons/button.css +31 -31
- package/src/styles/buttons/button.css.map +1 -1
- package/src/styles/cards/card.css +16 -0
- package/src/styles/cards/card.css.map +1 -1
- package/src/styles/details/details.css +19 -8
- package/src/styles/details/details.css.map +1 -1
- package/src/styles/dialog/dialog.css +43 -2
- package/src/styles/dialog/dialog.css.map +1 -1
- package/src/styles/images/img.css +15 -3
- package/src/styles/images/img.css.map +1 -1
- package/src/styles/index.css +240 -51
- package/src/styles/index.css.map +1 -1
- package/src/test/setup.d.ts +9 -0
- package/src/test/setup.ts +53 -1
- package/libs/chunk-6TE5QEVE.cjs +0 -13
- package/libs/chunk-6TE5QEVE.cjs.map +0 -1
- package/libs/chunk-7K76RW2A.cjs +0 -18
- package/libs/chunk-7K76RW2A.cjs.map +0 -1
- package/libs/chunk-BSPKFLO4.js +0 -8
- package/libs/chunk-BSPKFLO4.js.map +0 -1
- package/libs/chunk-BV5CLH44.cjs +0 -18
- package/libs/chunk-BV5CLH44.cjs.map +0 -1
- package/libs/chunk-DKGJHKGW.js +0 -9
- package/libs/chunk-DKGJHKGW.js.map +0 -1
- package/libs/chunk-ECLD37WN.cjs +0 -16
- package/libs/chunk-ECLD37WN.cjs.map +0 -1
- package/libs/chunk-HYBZBN4G.js +0 -8
- package/libs/chunk-HYBZBN4G.js.map +0 -1
- package/libs/chunk-KKLTUJFB.cjs.map +0 -1
- package/libs/chunk-M5QL5TAE.cjs +0 -14
- package/libs/chunk-M5QL5TAE.cjs.map +0 -1
- package/libs/chunk-NE6YXTMC.js +0 -7
- package/libs/chunk-NE6YXTMC.js.map +0 -1
- package/libs/chunk-O6QZBB6G.js.map +0 -1
- package/libs/chunk-SXVZSWX6.js +0 -11
- package/libs/chunk-SXVZSWX6.js.map +0 -1
- package/libs/ui-9a6f9f8d.d.ts +0 -24
- package/src/components/cards/README.md +0 -80
- package/src/components/dialog/hooks/useClickOutside.ts +0 -33
- /package/libs/{chunk-DV56L5YX.cjs.map → chunk-2LTJ7HHX.cjs.map} +0 -0
- /package/libs/{chunk-EQ67LF46.js.map → chunk-2Y7W75TT.js.map} +0 -0
- /package/libs/{chunk-X3EVB7VS.cjs.map → chunk-5S4ORA4C.cjs.map} +0 -0
- /package/libs/{chunk-6BVXFW7U.cjs.map → chunk-AHDJGCG5.cjs.map} +0 -0
- /package/libs/{chunk-E3XP6BEX.cjs.map → chunk-B7F5FS6D.cjs.map} +0 -0
- /package/libs/{chunk-LHVJKDMA.cjs.map → chunk-J32EZPYD.cjs.map} +0 -0
- /package/libs/{chunk-LL7HTLMS.cjs.map → chunk-M5RRNTVX.cjs.map} +0 -0
- /package/libs/{chunk-LIQJ7ZZR.js.map → chunk-NGTJDDFO.js.map} +0 -0
- /package/libs/{chunk-QCMV4VQZ.js.map → chunk-QLZWHAMK.js.map} +0 -0
- /package/libs/{chunk-BIP2NY53.js.map → chunk-RIVUMPOG.js.map} +0 -0
- /package/libs/{chunk-ICCKQ2GC.cjs.map → chunk-ROZI23GS.cjs.map} +0 -0
- /package/libs/{chunk-NHYXGV3L.js.map → chunk-SMYRLO3E.js.map} +0 -0
- /package/libs/{chunk-5ZM4XL44.js.map → chunk-TYRCEX2L.js.map} +0 -0
- /package/libs/{chunk-PPOOBUOS.js.map → chunk-XBA562WW.js.map} +0 -0
- /package/libs/{chunk-QVV34QEH.cjs.map → chunk-XTQKWY7W.cjs.map} +0 -0
- /package/libs/{chunk-YWOYVRFT.js.map → chunk-ZANSFMTD.js.map} +0 -0
|
@@ -1,61 +1,57 @@
|
|
|
1
|
-
|
|
2
|
-
import React from "react";
|
|
1
|
+
import React, { useState, useRef, useCallback, useEffect } from "react";
|
|
3
2
|
import Dialog from "./dialog";
|
|
4
3
|
import Button from "#components/buttons/button.jsx";
|
|
4
|
+
import type { DialogModalProps } from "./dialog.types";
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
*
|
|
7
|
+
* DialogModal - A wrapper component that manages dialog state and provides a trigger button.
|
|
8
8
|
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* A modal dialog component that provides an accessible overlay with an optional trigger button.
|
|
25
|
-
* Extends the base Dialog component with additional button control functionality.
|
|
9
|
+
* This is an **uncontrolled** component wrapper around the controlled Dialog component.
|
|
10
|
+
* It manages the dialog's open/closed state internally and provides a button to trigger it.
|
|
11
|
+
*
|
|
12
|
+
* **Use this when:**
|
|
13
|
+
* - You want a simple dialog with a trigger button
|
|
14
|
+
* - You don't need to control the dialog state externally
|
|
15
|
+
* - You want automatic focus restoration to the trigger button
|
|
16
|
+
*
|
|
17
|
+
* **Use the base Dialog component instead when:**
|
|
18
|
+
* - You need to control dialog state from parent component
|
|
19
|
+
* - You have a custom trigger mechanism
|
|
20
|
+
* - You need to open dialog programmatically from multiple places
|
|
26
21
|
*
|
|
27
22
|
* @component
|
|
28
|
-
* @param {
|
|
29
|
-
* @param {
|
|
30
|
-
* @param {
|
|
31
|
-
* @param {string} [props.dialogTitle] - Title displayed in dialog header
|
|
32
|
-
* @param {string} [props.dialogLabel] - Accessible label for the dialog
|
|
23
|
+
* @param {DialogModalProps} props - Component props
|
|
24
|
+
* @param {string} props.dialogTitle - Title displayed in dialog header
|
|
25
|
+
* @param {ReactNode} props.children - Content to display inside the dialog
|
|
33
26
|
* @param {string} [props.btnLabel="Open Dialog"] - Text label for the trigger button
|
|
34
|
-
* @param {"sm" | "md" | "lg"} [props.btnSize="
|
|
35
|
-
* @param {() => void} [props.btnOnClick] - Callback when trigger button is clicked
|
|
36
|
-
* @param {
|
|
37
|
-
* @param {() => void} [props.
|
|
38
|
-
* @param {
|
|
39
|
-
* @param {string} [props.
|
|
40
|
-
* @param {string} [props.
|
|
41
|
-
* @param {
|
|
42
|
-
* @
|
|
27
|
+
* @param {"sm" | "md" | "lg"} [props.btnSize="sm"] - Size variant for the trigger button
|
|
28
|
+
* @param {() => void} [props.btnOnClick] - Callback fired when trigger button is clicked (before opening)
|
|
29
|
+
* @param {boolean} [props.isAlertDialog=false] - If true, renders as non-modal inline alert
|
|
30
|
+
* @param {() => void} [props.onClose] - Callback fired when dialog is closed
|
|
31
|
+
* @param {() => void | Promise<void>} [props.onConfirm] - Callback when confirm button is clicked
|
|
32
|
+
* @param {string} [props.confirmLabel="Confirm"] - Text label for confirm button
|
|
33
|
+
* @param {string} [props.cancelLabel="Cancel"] - Text label for cancel button
|
|
34
|
+
* @param {boolean} [props.hideFooter=false] - If true, hides the footer with action buttons
|
|
35
|
+
* @param {string} [props.className] - Additional CSS classes for the dialog
|
|
36
|
+
* @param {string} [props.dialogLabel] - Optional aria-label for the dialog
|
|
37
|
+
* @returns {JSX.Element} A dialog with trigger button and automatic state management
|
|
43
38
|
*
|
|
44
39
|
* @example
|
|
45
|
-
* ```
|
|
40
|
+
* ```tsx
|
|
46
41
|
* <DialogModal
|
|
47
|
-
* dialogTitle="Confirm
|
|
48
|
-
* btnLabel="
|
|
49
|
-
* btnSize="
|
|
50
|
-
*
|
|
42
|
+
* dialogTitle="Confirm Delete"
|
|
43
|
+
* btnLabel="Delete Item"
|
|
44
|
+
* btnSize="md"
|
|
45
|
+
* onConfirm={async () => await deleteItem()}
|
|
46
|
+
* confirmLabel="Delete"
|
|
47
|
+
* cancelLabel="Cancel"
|
|
51
48
|
* >
|
|
52
|
-
*
|
|
49
|
+
* Are you sure you want to delete this item? This action cannot be undone.
|
|
53
50
|
* </DialogModal>
|
|
54
51
|
* ```
|
|
55
52
|
*/
|
|
56
|
-
|
|
57
53
|
export const DialogModal: React.FC<DialogModalProps> = ({
|
|
58
|
-
isAlertDialog,
|
|
54
|
+
isAlertDialog = false,
|
|
59
55
|
onClose,
|
|
60
56
|
dialogTitle,
|
|
61
57
|
dialogLabel,
|
|
@@ -67,21 +63,48 @@ export const DialogModal: React.FC<DialogModalProps> = ({
|
|
|
67
63
|
confirmLabel = "Confirm",
|
|
68
64
|
cancelLabel = "Cancel",
|
|
69
65
|
className,
|
|
66
|
+
hideFooter = false,
|
|
70
67
|
btnProps,
|
|
71
68
|
}) => {
|
|
72
|
-
const [isOpen, setIsOpen] =
|
|
69
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
70
|
+
const lastFocusedElement = useRef<HTMLElement | null>(null);
|
|
73
71
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
72
|
+
// Handle dialog state changes
|
|
73
|
+
const handleOpenChange = useCallback(
|
|
74
|
+
(open: boolean) => {
|
|
75
|
+
setIsOpen(open);
|
|
76
|
+
// If closing, call the onClose callback
|
|
77
|
+
if (!open && onClose) {
|
|
78
|
+
onClose();
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
[onClose]
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
// Handle trigger button click
|
|
85
|
+
const handleButtonClick = useCallback(() => {
|
|
86
|
+
// Store the currently focused element (should be the trigger button)
|
|
87
|
+
lastFocusedElement.current = document.activeElement as HTMLElement;
|
|
79
88
|
setIsOpen(true);
|
|
80
|
-
|
|
81
|
-
|
|
89
|
+
// Call optional pre-open callback
|
|
90
|
+
if (btnOnClick) {
|
|
91
|
+
btnOnClick();
|
|
92
|
+
}
|
|
93
|
+
}, [btnOnClick]);
|
|
94
|
+
|
|
95
|
+
// Restore focus to trigger button when dialog closes
|
|
96
|
+
useEffect(() => {
|
|
97
|
+
if (!isOpen && lastFocusedElement.current) {
|
|
98
|
+
// Small delay to ensure dialog has fully closed
|
|
99
|
+
const timeoutId = setTimeout(() => {
|
|
100
|
+
lastFocusedElement.current?.focus();
|
|
101
|
+
}, 100);
|
|
102
|
+
return () => clearTimeout(timeoutId);
|
|
103
|
+
}
|
|
104
|
+
}, [isOpen]);
|
|
82
105
|
|
|
83
|
-
const
|
|
84
|
-
type: "button" as
|
|
106
|
+
const triggerButtonProps = {
|
|
107
|
+
type: "button" as const,
|
|
85
108
|
onClick: handleButtonClick,
|
|
86
109
|
"data-btn": btnSize,
|
|
87
110
|
...btnProps,
|
|
@@ -89,18 +112,18 @@ export const DialogModal: React.FC<DialogModalProps> = ({
|
|
|
89
112
|
|
|
90
113
|
return (
|
|
91
114
|
<>
|
|
92
|
-
<Button {...
|
|
115
|
+
<Button {...triggerButtonProps}>{btnLabel}</Button>
|
|
93
116
|
<Dialog
|
|
94
|
-
|
|
117
|
+
isOpen={isOpen}
|
|
118
|
+
onOpenChange={handleOpenChange}
|
|
95
119
|
dialogTitle={dialogTitle}
|
|
96
|
-
onClose={handleClose}
|
|
97
|
-
title={dialogTitle}
|
|
98
120
|
dialogLabel={dialogLabel}
|
|
99
121
|
className={className}
|
|
100
122
|
isAlertDialog={isAlertDialog}
|
|
101
123
|
onConfirm={onConfirm}
|
|
102
124
|
confirmLabel={confirmLabel}
|
|
103
125
|
cancelLabel={cancelLabel}
|
|
126
|
+
hideFooter={hideFooter}
|
|
104
127
|
>
|
|
105
128
|
{children}
|
|
106
129
|
</Dialog>
|
|
@@ -13,6 +13,23 @@
|
|
|
13
13
|
--dialog-button-hover-bg: whitesmoke;
|
|
14
14
|
--dialog-display: flex;
|
|
15
15
|
--dialog-flex-direction: column;
|
|
16
|
+
|
|
17
|
+
/* Focus and accessibility */
|
|
18
|
+
--dialog-focus-color: #0066cc;
|
|
19
|
+
--dialog-focus-width: 0.125rem;
|
|
20
|
+
--dialog-focus-offset: 0.125rem;
|
|
21
|
+
--dialog-focus-outline: var(--dialog-focus-width) solid var(--dialog-focus-color);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/* High contrast mode support */
|
|
25
|
+
@media (prefers-contrast: high) {
|
|
26
|
+
:root {
|
|
27
|
+
--dialog-border-color: currentColor;
|
|
28
|
+
--dialog-border-width: 0.125rem;
|
|
29
|
+
--dialog-close-color: currentColor;
|
|
30
|
+
--dialog-button-border: currentColor 0.125rem solid;
|
|
31
|
+
--dialog-focus-width: 0.1875rem;
|
|
32
|
+
}
|
|
16
33
|
}
|
|
17
34
|
|
|
18
35
|
dialog {
|
|
@@ -22,13 +39,20 @@ dialog {
|
|
|
22
39
|
border: var(--dialog-border-color) var(--dialog-border-width) solid;
|
|
23
40
|
border-radius: var(--dialog-border-radius);
|
|
24
41
|
padding: var(--dialog-padding);
|
|
25
|
-
padding-block-start:
|
|
42
|
+
padding-block-start: var(--dialog-padding);
|
|
43
|
+
|
|
44
|
+
/* Focus visible for keyboard navigation */
|
|
45
|
+
&:focus-visible {
|
|
46
|
+
outline: var(--dialog-focus-outline);
|
|
47
|
+
outline-offset: var(--dialog-focus-offset);
|
|
48
|
+
}
|
|
26
49
|
|
|
27
50
|
&[open] {
|
|
28
51
|
display: var(--dialog-display);
|
|
29
52
|
flex-direction: var(--dialog-flex-direction);
|
|
30
53
|
gap: var(--dialog-gap);
|
|
31
54
|
}
|
|
55
|
+
|
|
32
56
|
section {
|
|
33
57
|
width: 100%;
|
|
34
58
|
display: flex;
|
|
@@ -46,22 +70,38 @@ dialog {
|
|
|
46
70
|
align-items: center;
|
|
47
71
|
width: 100%;
|
|
48
72
|
min-width: 100%;
|
|
73
|
+
|
|
49
74
|
h3 {
|
|
50
75
|
margin-block-start: 0;
|
|
51
76
|
margin-block-end: 0;
|
|
52
77
|
}
|
|
78
|
+
|
|
53
79
|
.dialog-close {
|
|
54
80
|
margin-block-end: 0;
|
|
55
81
|
}
|
|
82
|
+
|
|
56
83
|
button[type="button"] {
|
|
57
84
|
background-color: var(--dialog-button-bg);
|
|
58
85
|
border: var(--dialog-button-border);
|
|
59
86
|
cursor: pointer;
|
|
60
|
-
|
|
61
|
-
&:
|
|
87
|
+
|
|
88
|
+
&:hover {
|
|
62
89
|
border-color: var(--dialog-close-color);
|
|
63
90
|
background-color: var(--dialog-button-hover-bg);
|
|
64
91
|
}
|
|
92
|
+
|
|
93
|
+
/* Keyboard focus indicator */
|
|
94
|
+
&:focus-visible {
|
|
95
|
+
outline: var(--dialog-focus-outline);
|
|
96
|
+
outline-offset: var(--dialog-focus-offset);
|
|
97
|
+
border-color: var(--dialog-focus-color);
|
|
98
|
+
background-color: var(--dialog-button-hover-bg);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/* Remove default focus for mouse users */
|
|
102
|
+
&:focus:not(:focus-visible) {
|
|
103
|
+
outline: none;
|
|
104
|
+
}
|
|
65
105
|
}
|
|
66
106
|
}
|
|
67
107
|
|
|
@@ -73,4 +113,14 @@ dialog {
|
|
|
73
113
|
justify-content: var(--dialog-footer-justify, flex-end);
|
|
74
114
|
gap: var(--dialog-gap);
|
|
75
115
|
width: 100%;
|
|
116
|
+
|
|
117
|
+
/* Focus styles for footer buttons */
|
|
118
|
+
button:focus-visible {
|
|
119
|
+
outline: var(--dialog-focus-outline);
|
|
120
|
+
outline-offset: var(--dialog-focus-offset);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
button:focus:not(:focus-visible) {
|
|
124
|
+
outline: none;
|
|
125
|
+
}
|
|
76
126
|
}
|
|
@@ -15,8 +15,8 @@ const buttonDecorator = [
|
|
|
15
15
|
<button onClick={() => setIsOpen(true)}>Open Dialog</button>
|
|
16
16
|
<Story
|
|
17
17
|
args={{
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
isOpen: isOpen,
|
|
19
|
+
onOpenChange: setIsOpen,
|
|
20
20
|
dialogTitle: "Dialog Button",
|
|
21
21
|
children: content,
|
|
22
22
|
}}
|
|
@@ -67,18 +67,20 @@ type Story = StoryObj<typeof Dialog>;
|
|
|
67
67
|
export const BasicDialog: Story = {
|
|
68
68
|
args: {
|
|
69
69
|
isAlertDialog: false,
|
|
70
|
-
|
|
70
|
+
isOpen: true,
|
|
71
|
+
onOpenChange: () => {},
|
|
71
72
|
dialogTitle: "Basic Dialog",
|
|
72
73
|
},
|
|
73
74
|
} as Story;
|
|
74
75
|
|
|
75
76
|
/**
|
|
76
|
-
*
|
|
77
|
-
*
|
|
77
|
+
* Non-modal inline alert dialog
|
|
78
|
+
* Uses dialog.show() instead of dialog.showModal()
|
|
78
79
|
*/
|
|
79
80
|
export const NonModalDialog: Story = {
|
|
80
81
|
args: {
|
|
81
|
-
|
|
82
|
+
isOpen: true,
|
|
83
|
+
onOpenChange: () => {},
|
|
82
84
|
isAlertDialog: true,
|
|
83
85
|
dialogTitle: "Non Modal Dialog",
|
|
84
86
|
},
|
|
@@ -95,7 +97,8 @@ export const DialogWithButton: Story = {
|
|
|
95
97
|
export const DialogInteractions: Story = {
|
|
96
98
|
args: {
|
|
97
99
|
isAlertDialog: false,
|
|
98
|
-
|
|
100
|
+
isOpen: true,
|
|
101
|
+
onOpenChange: () => {},
|
|
99
102
|
dialogTitle: "Dialog Interactions",
|
|
100
103
|
},
|
|
101
104
|
play: async ({ canvasElement, step }) => {
|