@fpkit/acss 0.5.12 → 0.6.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/README.md +89 -0
- package/libs/chunk-2NRIP6RB.cjs +17 -0
- package/libs/chunk-2NRIP6RB.cjs.map +1 -0
- package/libs/chunk-33PNJ4LO.cjs +15 -0
- package/libs/chunk-33PNJ4LO.cjs.map +1 -0
- package/libs/chunk-4BZKFPEC.cjs +17 -0
- package/libs/chunk-4BZKFPEC.cjs.map +1 -0
- package/libs/{chunk-O6QZBB6G.js → chunk-5QD3DWFI.js} +5 -5
- package/libs/chunk-5QD3DWFI.js.map +1 -0
- package/libs/chunk-6SAHIYCZ.js +7 -0
- package/libs/chunk-6SAHIYCZ.js.map +1 -0
- package/libs/{chunk-KKLTUJFB.cjs → chunk-6WTC4JXH.cjs} +5 -5
- package/libs/chunk-6WTC4JXH.cjs.map +1 -0
- package/libs/chunk-75QHTLFO.js +7 -0
- package/libs/chunk-75QHTLFO.js.map +1 -0
- package/libs/{chunk-YWOYVRFT.js → chunk-7XPFW7CB.js} +3 -3
- package/libs/chunk-BFK62VX5.js +5 -0
- package/libs/chunk-BFK62VX5.js.map +1 -0
- package/libs/{chunk-ICCKQ2GC.cjs → chunk-DKTHCQ5P.cjs} +4 -4
- package/libs/{chunk-6TE5QEVE.cjs → chunk-E2AJURUW.cjs} +3 -3
- package/libs/chunk-E2AJURUW.cjs.map +1 -0
- package/libs/chunk-ENTCUJ3A.cjs +13 -0
- package/libs/chunk-ENTCUJ3A.cjs.map +1 -0
- package/libs/chunk-F5EYMVQM.js +10 -0
- package/libs/chunk-F5EYMVQM.js.map +1 -0
- package/libs/chunk-FVROL3V5.js +9 -0
- package/libs/chunk-FVROL3V5.js.map +1 -0
- package/libs/chunk-GT77BX4L.cjs +17 -0
- package/libs/chunk-GT77BX4L.cjs.map +1 -0
- package/libs/chunk-GUJSMQ3V.cjs +16 -0
- package/libs/chunk-GUJSMQ3V.cjs.map +1 -0
- package/libs/chunk-HHLNOC5T.js +7 -0
- package/libs/chunk-HHLNOC5T.js.map +1 -0
- package/libs/chunk-HRRHPLER.js +8 -0
- package/libs/chunk-HRRHPLER.js.map +1 -0
- package/libs/chunk-IEB64SWY.js +8 -0
- package/libs/chunk-IEB64SWY.js.map +1 -0
- package/libs/{chunk-LIQJ7ZZR.js → chunk-IQ76HGVP.js} +2 -2
- package/libs/chunk-IRLFZ3OL.js +9 -0
- package/libs/chunk-IRLFZ3OL.js.map +1 -0
- package/libs/chunk-KK47SYZI.js +8 -0
- package/libs/chunk-KK47SYZI.js.map +1 -0
- package/libs/chunk-O3JIHC5M.cjs +15 -0
- package/libs/chunk-O3JIHC5M.cjs.map +1 -0
- package/libs/chunk-O5XAJ7BY.cjs +18 -0
- package/libs/chunk-O5XAJ7BY.cjs.map +1 -0
- package/libs/chunk-OVWLQYMK.js +10 -0
- package/libs/chunk-OVWLQYMK.js.map +1 -0
- package/libs/chunk-PNWIRCG3.cjs +7 -0
- package/libs/chunk-PNWIRCG3.cjs.map +1 -0
- package/libs/chunk-QVW6W76L.cjs +18 -0
- package/libs/chunk-QVW6W76L.cjs.map +1 -0
- package/libs/chunk-T4T6GWYQ.cjs +17 -0
- package/libs/chunk-T4T6GWYQ.cjs.map +1 -0
- package/libs/chunk-TON2YGMD.cjs +9 -0
- package/libs/chunk-TON2YGMD.cjs.map +1 -0
- package/libs/chunk-UEPAWMDF.js +8 -0
- package/libs/chunk-UEPAWMDF.js.map +1 -0
- package/libs/{chunk-LT5KZ2QW.cjs → chunk-US2I5GI7.cjs} +3 -3
- package/libs/{chunk-E3XP6BEX.cjs → chunk-W2UIN7EV.cjs} +3 -3
- package/libs/chunk-W5TKWBFC.cjs +18 -0
- package/libs/chunk-W5TKWBFC.cjs.map +1 -0
- package/libs/chunk-WXBFBWYF.cjs +16 -0
- package/libs/chunk-WXBFBWYF.cjs.map +1 -0
- package/libs/chunk-X3JCTEPD.js +11 -0
- package/libs/chunk-X3JCTEPD.js.map +1 -0
- package/libs/chunk-X5LGFCWG.js +9 -0
- package/libs/chunk-X5LGFCWG.js.map +1 -0
- package/libs/{chunk-5M57K4SW.js → chunk-Y2PFDELK.js} +2 -2
- package/libs/chunk-ZFJ4U45S.js +10 -0
- package/libs/chunk-ZFJ4U45S.js.map +1 -0
- package/libs/{component-props-a8a2f97e.d.ts → component-props-67d978a2.d.ts} +4 -4
- 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 +275 -36
- package/libs/components/breadcrumbs/breadcrumb.d.ts +275 -36
- package/libs/components/breadcrumbs/breadcrumb.js +3 -3
- package/libs/components/button.cjs +6 -4
- package/libs/components/button.d.cts +97 -4
- package/libs/components/button.d.ts +97 -4
- package/libs/components/button.js +4 -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 +278 -34
- package/libs/components/card.d.ts +278 -34
- 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 +9 -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 +7 -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 +16 -7
- package/libs/components/form/fields.d.ts +16 -7
- package/libs/components/form/fields.js +2 -2
- package/libs/components/form/inputs.cjs +6 -4
- package/libs/components/form/inputs.d.cts +50 -2
- package/libs/components/form/inputs.d.ts +50 -2
- package/libs/components/form/inputs.js +4 -2
- package/libs/components/form/textarea.cjs +5 -4
- package/libs/components/form/textarea.d.cts +32 -23
- package/libs/components/form/textarea.d.ts +32 -23
- package/libs/components/form/textarea.js +3 -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 +183 -39
- package/libs/components/icons/icon.d.ts +183 -39
- 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.css +1 -1
- package/libs/components/link/link.css.map +1 -1
- package/libs/components/link/link.d.cts +3 -19
- package/libs/components/link/link.d.ts +3 -19
- package/libs/components/link/link.js +2 -2
- package/libs/components/link/link.min.css +2 -2
- package/libs/components/list/list.cjs +5 -5
- package/libs/components/list/list.css +1 -0
- package/libs/components/list/list.css.map +1 -0
- package/libs/components/list/list.d.cts +120 -33
- package/libs/components/list/list.d.ts +120 -33
- package/libs/components/list/list.js +2 -2
- package/libs/components/list/list.min.css +3 -0
- package/libs/components/modal.cjs +6 -4
- package/libs/components/modal.d.cts +8 -8
- package/libs/components/modal.d.ts +8 -8
- package/libs/components/modal.js +5 -3
- package/libs/components/nav/nav.cjs +7 -7
- package/libs/components/nav/nav.css +1 -1
- package/libs/components/nav/nav.css.map +1 -1
- package/libs/components/nav/nav.d.cts +550 -34
- package/libs/components/nav/nav.d.ts +550 -34
- package/libs/components/nav/nav.js +3 -3
- package/libs/components/nav/nav.min.css +2 -2
- package/libs/components/popover/popover.d.cts +5 -5
- package/libs/components/popover/popover.d.ts +5 -5
- package/libs/components/tables/table.cjs +5 -5
- package/libs/components/tables/table.d.cts +8 -8
- package/libs/components/tables/table.d.ts +8 -8
- package/libs/components/tables/table.js +2 -2
- package/libs/components/tag/tag.css +1 -1
- package/libs/components/tag/tag.css.map +1 -1
- package/libs/components/tag/tag.min.css +2 -2
- package/libs/components/text/text.cjs +5 -5
- package/libs/components/text/text.d.cts +5 -5
- package/libs/components/text/text.d.ts +5 -5
- package/libs/components/text/text.js +2 -2
- package/libs/form.types-d25ebfac.d.ts +233 -0
- package/libs/heading-7446cb46.d.ts +250 -0
- package/libs/hooks.cjs +12 -0
- package/libs/hooks.d.cts +140 -1
- package/libs/hooks.d.ts +140 -1
- package/libs/hooks.js +4 -0
- package/libs/icons.cjs +3 -3
- package/libs/icons.d.cts +2 -2
- package/libs/icons.d.ts +2 -2
- package/libs/icons.js +2 -2
- package/libs/index.cjs +117 -94
- 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 +834 -61
- package/libs/index.d.ts +834 -61
- package/libs/index.js +36 -22
- package/libs/index.js.map +1 -1
- package/libs/link-5192f411.d.ts +323 -0
- package/libs/list.types-d26de310.d.ts +245 -0
- package/libs/ui-d01b50d4.d.ts +289 -0
- package/package.json +4 -87
- 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 +110 -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 +430 -170
- package/src/components/buttons/README.mdx +102 -1
- package/src/components/buttons/button.scss +34 -31
- package/src/components/buttons/button.stories.tsx +141 -0
- package/src/components/buttons/button.tsx +82 -52
- 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-a11y-review.md +653 -0
- 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/form/README.mdx +725 -43
- package/src/components/form/WCAG-REVIEW.md +654 -0
- package/src/components/form/fields.tsx +10 -1
- package/src/components/form/form.stories.tsx +604 -23
- package/src/components/form/form.tsx +204 -63
- package/src/components/form/form.types.ts +378 -0
- package/src/components/form/input.stories.tsx +71 -3
- package/src/components/form/inputs.tsx +159 -67
- package/src/components/form/select.tsx +122 -66
- package/src/components/form/textarea.tsx +120 -73
- package/src/components/fp.tsx +86 -11
- 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/link/README.mdx +923 -0
- package/src/components/link/link.scss +79 -26
- package/src/components/link/link.stories.tsx +383 -30
- package/src/components/link/link.test.tsx +677 -0
- package/src/components/link/link.tsx +163 -57
- package/src/components/link/link.types.ts +261 -0
- package/src/components/list/README.mdx +764 -0
- package/src/components/list/list.scss +285 -0
- package/src/components/list/list.stories.tsx +514 -27
- package/src/components/list/list.test.tsx +554 -0
- package/src/components/list/list.tsx +153 -51
- package/src/components/list/list.types.ts +255 -0
- package/src/components/nav/ACCESSIBILITY.md +649 -0
- package/src/components/nav/README.mdx +782 -0
- package/src/components/nav/nav.scss +32 -1
- package/src/components/nav/nav.stories.tsx +44 -6
- package/src/components/nav/nav.tsx +302 -51
- package/src/components/nav/nav.types.ts +308 -0
- package/src/components/tag/README.mdx +426 -0
- package/src/components/tag/tag.scss +101 -27
- package/src/components/tag/tag.stories.tsx +384 -10
- package/src/components/tag/tag.test.tsx +210 -0
- package/src/components/tag/tag.tsx +106 -9
- package/src/components/tag/tag.types.ts +107 -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 +274 -18
- package/src/components/word-count/README.md +240 -0
- package/src/hooks/use-disabled-state.test.tsx +536 -0
- package/src/hooks/use-disabled-state.ts +246 -0
- package/src/hooks/useDisabledState.md +393 -0
- package/src/hooks.ts +7 -0
- package/src/index.scss +2 -0
- package/src/index.ts +12 -3
- package/src/sass/_globals.scss +2 -7
- package/src/sass/_properties.scss +1 -0
- package/src/styles/alert/alert.css +92 -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 +691 -128
- package/src/styles/index.css.map +1 -1
- package/src/styles/link/link.css +45 -28
- package/src/styles/link/link.css.map +1 -1
- package/src/styles/list/list.css +214 -0
- package/src/styles/list/list.css.map +1 -0
- package/src/styles/nav/nav.css +21 -1
- package/src/styles/nav/nav.css.map +1 -1
- package/src/styles/tag/tag.css +113 -35
- package/src/styles/tag/tag.css.map +1 -1
- package/src/styles/utilities/_disabled.scss +58 -0
- package/src/test/setup.d.ts +9 -0
- package/src/test/setup.ts +53 -1
- package/src/types/shared.ts +43 -6
- package/src/utils/accessibility.ts +109 -0
- package/libs/chunk-5ZM4XL44.js +0 -8
- package/libs/chunk-5ZM4XL44.js.map +0 -1
- package/libs/chunk-6BVXFW7U.cjs +0 -15
- package/libs/chunk-6BVXFW7U.cjs.map +0 -1
- 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-BHRQBJRY.js +0 -8
- package/libs/chunk-BHRQBJRY.js.map +0 -1
- package/libs/chunk-BIP2NY53.js +0 -8
- package/libs/chunk-BIP2NY53.js.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-DV56L5YX.cjs +0 -18
- package/libs/chunk-DV56L5YX.cjs.map +0 -1
- package/libs/chunk-ECLD37WN.cjs +0 -16
- package/libs/chunk-ECLD37WN.cjs.map +0 -1
- package/libs/chunk-EQ67LF46.js +0 -9
- package/libs/chunk-EQ67LF46.js.map +0 -1
- package/libs/chunk-HYBZBN4G.js +0 -8
- package/libs/chunk-HYBZBN4G.js.map +0 -1
- package/libs/chunk-IYUN2EW3.cjs +0 -15
- package/libs/chunk-IYUN2EW3.cjs.map +0 -1
- package/libs/chunk-KKLTUJFB.cjs.map +0 -1
- package/libs/chunk-LHVJKDMA.cjs +0 -15
- package/libs/chunk-LHVJKDMA.cjs.map +0 -1
- package/libs/chunk-LL7HTLMS.cjs +0 -15
- package/libs/chunk-LL7HTLMS.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-NHYXGV3L.js +0 -8
- package/libs/chunk-NHYXGV3L.js.map +0 -1
- package/libs/chunk-O6QZBB6G.js.map +0 -1
- package/libs/chunk-P7TTEYCD.js +0 -7
- package/libs/chunk-P7TTEYCD.js.map +0 -1
- package/libs/chunk-PPOOBUOS.js +0 -8
- package/libs/chunk-PPOOBUOS.js.map +0 -1
- package/libs/chunk-QCMV4VQZ.js +0 -8
- package/libs/chunk-QCMV4VQZ.js.map +0 -1
- package/libs/chunk-QVV34QEH.cjs +0 -32
- package/libs/chunk-QVV34QEH.cjs.map +0 -1
- package/libs/chunk-S7BABR7Z.cjs +0 -13
- package/libs/chunk-S7BABR7Z.cjs.map +0 -1
- package/libs/chunk-SXVZSWX6.js +0 -11
- package/libs/chunk-SXVZSWX6.js.map +0 -1
- package/libs/chunk-X3EVB7VS.cjs +0 -15
- package/libs/chunk-X3EVB7VS.cjs.map +0 -1
- package/libs/inputs-f3a216db.d.ts +0 -45
- 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-YWOYVRFT.js.map → chunk-7XPFW7CB.js.map} +0 -0
- /package/libs/{chunk-ICCKQ2GC.cjs.map → chunk-DKTHCQ5P.cjs.map} +0 -0
- /package/libs/{chunk-LIQJ7ZZR.js.map → chunk-IQ76HGVP.js.map} +0 -0
- /package/libs/{chunk-LT5KZ2QW.cjs.map → chunk-US2I5GI7.cjs.map} +0 -0
- /package/libs/{chunk-E3XP6BEX.cjs.map → chunk-W2UIN7EV.cjs.map} +0 -0
- /package/libs/{chunk-5M57K4SW.js.map → chunk-Y2PFDELK.js.map} +0 -0
|
@@ -1,20 +1,39 @@
|
|
|
1
1
|
import { StoryObj, Meta } from "@storybook/react-vite";
|
|
2
|
-
// import { within, userEvent, screen } from "storybook/test";
|
|
3
|
-
|
|
4
2
|
import Card from "./card";
|
|
5
|
-
// import './card.scss'
|
|
6
3
|
|
|
7
4
|
const content =
|
|
8
5
|
"Enim aliquip excepteur veniam esse culpa. Et exercitation incididunt occaecat incididunt proident consectetur. Voluptate elit reprehenderit nulla reprehenderit excepteur tempor adipisicing officia eiusmod est id aute. Nisi do et nulla fugiat enim id pariatur ex. Culpa aliquip excepteur velit fugiat qui magna deserunt adipisicing dolore quis. Esse proident qui consectetur Lorem id fugiat elit amet proident enim deserunt dolore sit.";
|
|
9
6
|
|
|
10
7
|
const meta: Meta<typeof Card> = {
|
|
11
8
|
title: "FP.REACT Components/Card",
|
|
12
|
-
tags: ["rc"],
|
|
9
|
+
tags: ["rc", "autodocs"],
|
|
13
10
|
component: Card,
|
|
14
11
|
args: {
|
|
15
12
|
children: <p>{content}</p>,
|
|
16
13
|
},
|
|
17
|
-
|
|
14
|
+
argTypes: {
|
|
15
|
+
as: {
|
|
16
|
+
control: 'select',
|
|
17
|
+
options: ['div', 'article', 'section', 'aside'],
|
|
18
|
+
description: 'HTML element to render',
|
|
19
|
+
},
|
|
20
|
+
interactive: {
|
|
21
|
+
control: 'boolean',
|
|
22
|
+
description: 'Enable keyboard navigation and button semantics',
|
|
23
|
+
},
|
|
24
|
+
role: {
|
|
25
|
+
control: 'text',
|
|
26
|
+
description: 'ARIA role attribute',
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
parameters: {
|
|
30
|
+
docs: {
|
|
31
|
+
description: {
|
|
32
|
+
component: 'A flexible, accessible card component with compound component pattern. Supports polymorphic rendering, interactive variants, and WCAG 2.1 AA compliance.',
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
},
|
|
36
|
+
} as Meta<typeof Card>;
|
|
18
37
|
|
|
19
38
|
export default meta;
|
|
20
39
|
type Story = StoryObj<typeof Card>;
|
|
@@ -145,3 +164,146 @@ export const FlexibleContent: Story = {
|
|
|
145
164
|
</div>
|
|
146
165
|
),
|
|
147
166
|
} as Story;
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Interactive Card - Demonstrates clickable card with keyboard navigation
|
|
170
|
+
*/
|
|
171
|
+
export const InteractiveCard: Story = {
|
|
172
|
+
args: {
|
|
173
|
+
interactive: true,
|
|
174
|
+
'aria-label': 'View product details',
|
|
175
|
+
},
|
|
176
|
+
render: (args) => (
|
|
177
|
+
<Card
|
|
178
|
+
{...args}
|
|
179
|
+
onClick={() => alert('Card clicked!')}
|
|
180
|
+
style={{ cursor: 'pointer' }}
|
|
181
|
+
>
|
|
182
|
+
<Card.Title>Interactive Product Card</Card.Title>
|
|
183
|
+
<Card.Content>
|
|
184
|
+
<p>
|
|
185
|
+
This card is fully interactive! Click anywhere or use your keyboard
|
|
186
|
+
(Tab to focus, Enter or Space to activate) to trigger the action.
|
|
187
|
+
</p>
|
|
188
|
+
<p style={{ fontSize: '0.875rem', color: '#666', marginTop: '0.5rem' }}>
|
|
189
|
+
Try it: Tab to focus this card, then press Enter or Space.
|
|
190
|
+
</p>
|
|
191
|
+
</Card.Content>
|
|
192
|
+
<Card.Footer>
|
|
193
|
+
<span style={{ color: '#007bff', fontWeight: 'bold' }}>
|
|
194
|
+
Click to learn more →
|
|
195
|
+
</span>
|
|
196
|
+
</Card.Footer>
|
|
197
|
+
</Card>
|
|
198
|
+
),
|
|
199
|
+
parameters: {
|
|
200
|
+
docs: {
|
|
201
|
+
description: {
|
|
202
|
+
story: 'Interactive cards support full keyboard navigation (Enter/Space keys) and automatically receive proper ARIA attributes for accessibility.',
|
|
203
|
+
},
|
|
204
|
+
},
|
|
205
|
+
},
|
|
206
|
+
} as Story;
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Accessible Card with ARIA - Demonstrates proper ARIA labeling
|
|
210
|
+
*/
|
|
211
|
+
export const AccessibleCard: Story = {
|
|
212
|
+
render: () => (
|
|
213
|
+
<Card as="article" aria-labelledby="product-title">
|
|
214
|
+
<Card.Title id="product-title">Featured Product</Card.Title>
|
|
215
|
+
<Card.Content as="div">
|
|
216
|
+
<p>
|
|
217
|
+
This card uses <code>aria-labelledby</code> to connect the title with
|
|
218
|
+
the card container, providing an accessible name for screen readers.
|
|
219
|
+
</p>
|
|
220
|
+
<p style={{ fontSize: '0.875rem', color: '#666', marginTop: '0.5rem' }}>
|
|
221
|
+
Screen readers will announce: "Featured Product, article"
|
|
222
|
+
</p>
|
|
223
|
+
</Card.Content>
|
|
224
|
+
<Card.Footer>
|
|
225
|
+
<button>Add to Cart</button>
|
|
226
|
+
</Card.Footer>
|
|
227
|
+
</Card>
|
|
228
|
+
),
|
|
229
|
+
parameters: {
|
|
230
|
+
docs: {
|
|
231
|
+
description: {
|
|
232
|
+
story: 'Demonstrates best practices for accessible cards using aria-labelledby to provide context to assistive technologies.',
|
|
233
|
+
},
|
|
234
|
+
},
|
|
235
|
+
},
|
|
236
|
+
} as Story;
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* Polymorphic Card - Shows different HTML elements
|
|
240
|
+
*/
|
|
241
|
+
export const PolymorphicElements: Story = {
|
|
242
|
+
render: () => (
|
|
243
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: '1rem' }}>
|
|
244
|
+
<Card as="article">
|
|
245
|
+
<Card.Title as="h2">Article Card</Card.Title>
|
|
246
|
+
<Card.Content>
|
|
247
|
+
Renders as <code><article></code> element for standalone content
|
|
248
|
+
</Card.Content>
|
|
249
|
+
</Card>
|
|
250
|
+
|
|
251
|
+
<Card as="section">
|
|
252
|
+
<Card.Title as="h2">Section Card</Card.Title>
|
|
253
|
+
<Card.Content>
|
|
254
|
+
Renders as <code><section></code> element for thematic grouping
|
|
255
|
+
</Card.Content>
|
|
256
|
+
</Card>
|
|
257
|
+
|
|
258
|
+
<Card as="aside">
|
|
259
|
+
<Card.Title as="h3">Aside Card</Card.Title>
|
|
260
|
+
<Card.Content>
|
|
261
|
+
Renders as <code><aside></code> element for tangential content
|
|
262
|
+
</Card.Content>
|
|
263
|
+
</Card>
|
|
264
|
+
</div>
|
|
265
|
+
),
|
|
266
|
+
parameters: {
|
|
267
|
+
docs: {
|
|
268
|
+
description: {
|
|
269
|
+
story: 'The Card component supports polymorphic rendering via the `as` prop, allowing you to use semantic HTML elements while maintaining consistent styling.',
|
|
270
|
+
},
|
|
271
|
+
},
|
|
272
|
+
},
|
|
273
|
+
} as Story;
|
|
274
|
+
|
|
275
|
+
/**
|
|
276
|
+
* Custom Heading Levels - Demonstrates heading hierarchy
|
|
277
|
+
*/
|
|
278
|
+
export const CustomHeadingLevels: Story = {
|
|
279
|
+
render: () => (
|
|
280
|
+
<div style={{ display: 'flex', flexDirection: 'column', gap: '1rem' }}>
|
|
281
|
+
<Card>
|
|
282
|
+
<Card.Title as="h1">Level 1 Heading</Card.Title>
|
|
283
|
+
<Card.Content>Main page title level</Card.Content>
|
|
284
|
+
</Card>
|
|
285
|
+
|
|
286
|
+
<Card>
|
|
287
|
+
<Card.Title as="h2">Level 2 Heading</Card.Title>
|
|
288
|
+
<Card.Content>Section title level</Card.Content>
|
|
289
|
+
</Card>
|
|
290
|
+
|
|
291
|
+
<Card>
|
|
292
|
+
<Card.Title as="h3">Level 3 Heading (Default)</Card.Title>
|
|
293
|
+
<Card.Content>Subsection title level - this is the default</Card.Content>
|
|
294
|
+
</Card>
|
|
295
|
+
|
|
296
|
+
<Card>
|
|
297
|
+
<Card.Title as="h4">Level 4 Heading</Card.Title>
|
|
298
|
+
<Card.Content>Component title level</Card.Content>
|
|
299
|
+
</Card>
|
|
300
|
+
</div>
|
|
301
|
+
),
|
|
302
|
+
parameters: {
|
|
303
|
+
docs: {
|
|
304
|
+
description: {
|
|
305
|
+
story: 'Card.Title supports all heading levels (h1-h6) to maintain proper document outline and heading hierarchy.',
|
|
306
|
+
},
|
|
307
|
+
},
|
|
308
|
+
},
|
|
309
|
+
} as Story;
|
|
@@ -1,30 +1,370 @@
|
|
|
1
|
+
import React from 'react'
|
|
1
2
|
import { render, screen } from '@testing-library/react'
|
|
3
|
+
import userEvent from '@testing-library/user-event'
|
|
2
4
|
import { Card } from './card'
|
|
3
5
|
|
|
4
6
|
describe('Card', () => {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
7
|
+
describe('Basic Rendering', () => {
|
|
8
|
+
it('renders children', () => {
|
|
9
|
+
render(<Card>Hello World</Card>)
|
|
10
|
+
expect(screen.getByText('Hello World')).toBeInTheDocument()
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
it('renders with custom styles', () => {
|
|
14
|
+
const style = { backgroundColor: '#000' }
|
|
15
|
+
render(
|
|
16
|
+
<Card data-testid="card" styles={style}>
|
|
17
|
+
Hello World
|
|
18
|
+
</Card>,
|
|
19
|
+
)
|
|
20
|
+
const card = screen.getByTestId('card')
|
|
21
|
+
expect(card).toHaveStyle(style)
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
it('renders with custom element using as prop', () => {
|
|
25
|
+
render(
|
|
26
|
+
<Card data-testid="card" as="section">
|
|
27
|
+
Hello World
|
|
28
|
+
</Card>,
|
|
29
|
+
)
|
|
30
|
+
const card = screen.getByTestId('card')
|
|
31
|
+
expect(card.tagName.toLowerCase()).toBe('section')
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
it('renders with default div element', () => {
|
|
35
|
+
render(<Card data-testid="card">Content</Card>)
|
|
36
|
+
const card = screen.getByTestId('card')
|
|
37
|
+
expect(card.tagName.toLowerCase()).toBe('div')
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
it('applies custom classes', () => {
|
|
41
|
+
render(
|
|
42
|
+
<Card data-testid="card" classes="custom-class">
|
|
43
|
+
Content
|
|
44
|
+
</Card>,
|
|
45
|
+
)
|
|
46
|
+
const card = screen.getByTestId('card')
|
|
47
|
+
expect(card).toHaveClass('custom-class')
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
it('applies default shadow class', () => {
|
|
51
|
+
render(<Card data-testid="card">Content</Card>)
|
|
52
|
+
const card = screen.getByTestId('card')
|
|
53
|
+
expect(card).toHaveClass('shadow')
|
|
54
|
+
})
|
|
8
55
|
})
|
|
9
56
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
57
|
+
describe('Compound Components', () => {
|
|
58
|
+
it('renders Card.Title component', () => {
|
|
59
|
+
render(
|
|
60
|
+
<Card>
|
|
61
|
+
<Card.Title>Test Title</Card.Title>
|
|
62
|
+
</Card>,
|
|
63
|
+
)
|
|
64
|
+
expect(screen.getByText('Test Title')).toBeInTheDocument()
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
it('renders Card.Title as h3 by default', () => {
|
|
68
|
+
render(
|
|
69
|
+
<Card>
|
|
70
|
+
<Card.Title data-testid="title">Test Title</Card.Title>
|
|
71
|
+
</Card>,
|
|
72
|
+
)
|
|
73
|
+
const title = screen.getByTestId('title')
|
|
74
|
+
expect(title.tagName.toLowerCase()).toBe('h3')
|
|
75
|
+
})
|
|
76
|
+
|
|
77
|
+
it('renders Card.Title with custom heading level', () => {
|
|
78
|
+
render(
|
|
79
|
+
<Card>
|
|
80
|
+
<Card.Title data-testid="title" as="h2">
|
|
81
|
+
Test Title
|
|
82
|
+
</Card.Title>
|
|
83
|
+
</Card>,
|
|
84
|
+
)
|
|
85
|
+
const title = screen.getByTestId('title')
|
|
86
|
+
expect(title.tagName.toLowerCase()).toBe('h2')
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
it('renders Card.Content component', () => {
|
|
90
|
+
render(
|
|
91
|
+
<Card>
|
|
92
|
+
<Card.Content>Test Content</Card.Content>
|
|
93
|
+
</Card>,
|
|
94
|
+
)
|
|
95
|
+
expect(screen.getByText('Test Content')).toBeInTheDocument()
|
|
96
|
+
})
|
|
97
|
+
|
|
98
|
+
it('renders Card.Content as article by default', () => {
|
|
99
|
+
render(
|
|
100
|
+
<Card>
|
|
101
|
+
<Card.Content data-testid="content">Test Content</Card.Content>
|
|
102
|
+
</Card>,
|
|
103
|
+
)
|
|
104
|
+
const content = screen.getByTestId('content')
|
|
105
|
+
expect(content.tagName.toLowerCase()).toBe('article')
|
|
106
|
+
})
|
|
107
|
+
|
|
108
|
+
it('renders Card.Content with custom element', () => {
|
|
109
|
+
render(
|
|
110
|
+
<Card>
|
|
111
|
+
<Card.Content data-testid="content" as="div">
|
|
112
|
+
Test Content
|
|
113
|
+
</Card.Content>
|
|
114
|
+
</Card>,
|
|
115
|
+
)
|
|
116
|
+
const content = screen.getByTestId('content')
|
|
117
|
+
expect(content.tagName.toLowerCase()).toBe('div')
|
|
118
|
+
})
|
|
119
|
+
|
|
120
|
+
it('renders Card.Footer component', () => {
|
|
121
|
+
render(
|
|
122
|
+
<Card>
|
|
123
|
+
<Card.Footer>Test Footer</Card.Footer>
|
|
124
|
+
</Card>,
|
|
125
|
+
)
|
|
126
|
+
expect(screen.getByText('Test Footer')).toBeInTheDocument()
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
it('renders Card.Footer with custom element', () => {
|
|
130
|
+
render(
|
|
131
|
+
<Card>
|
|
132
|
+
<Card.Footer data-testid="footer" as="footer">
|
|
133
|
+
Test Footer
|
|
134
|
+
</Card.Footer>
|
|
135
|
+
</Card>,
|
|
136
|
+
)
|
|
137
|
+
const footer = screen.getByTestId('footer')
|
|
138
|
+
expect(footer.tagName.toLowerCase()).toBe('footer')
|
|
139
|
+
})
|
|
140
|
+
|
|
141
|
+
it('renders complete card structure', () => {
|
|
142
|
+
render(
|
|
143
|
+
<Card>
|
|
144
|
+
<Card.Title>Title</Card.Title>
|
|
145
|
+
<Card.Content>Content</Card.Content>
|
|
146
|
+
<Card.Footer>Footer</Card.Footer>
|
|
147
|
+
</Card>,
|
|
148
|
+
)
|
|
149
|
+
expect(screen.getByText('Title')).toBeInTheDocument()
|
|
150
|
+
expect(screen.getByText('Content')).toBeInTheDocument()
|
|
151
|
+
expect(screen.getByText('Footer')).toBeInTheDocument()
|
|
152
|
+
})
|
|
153
|
+
|
|
154
|
+
it('applies custom className to sub-components', () => {
|
|
155
|
+
render(
|
|
156
|
+
<Card>
|
|
157
|
+
<Card.Title data-testid="title" className="custom-title">
|
|
158
|
+
Title
|
|
159
|
+
</Card.Title>
|
|
160
|
+
<Card.Content data-testid="content" className="custom-content">
|
|
161
|
+
Content
|
|
162
|
+
</Card.Content>
|
|
163
|
+
<Card.Footer data-testid="footer" className="custom-footer">
|
|
164
|
+
Footer
|
|
165
|
+
</Card.Footer>
|
|
166
|
+
</Card>,
|
|
167
|
+
)
|
|
168
|
+
expect(screen.getByTestId('title')).toHaveClass('card-title', 'custom-title')
|
|
169
|
+
expect(screen.getByTestId('content')).toHaveClass('card-content', 'custom-content')
|
|
170
|
+
expect(screen.getByTestId('footer')).toHaveClass('card-footer', 'custom-footer')
|
|
171
|
+
})
|
|
19
172
|
})
|
|
20
173
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
174
|
+
describe('Accessibility', () => {
|
|
175
|
+
it('accepts aria-label prop', () => {
|
|
176
|
+
render(
|
|
177
|
+
<Card data-testid="card" aria-label="Product card">
|
|
178
|
+
Content
|
|
179
|
+
</Card>,
|
|
180
|
+
)
|
|
181
|
+
const card = screen.getByTestId('card')
|
|
182
|
+
expect(card).toHaveAttribute('aria-label', 'Product card')
|
|
183
|
+
})
|
|
184
|
+
|
|
185
|
+
it('accepts aria-labelledby prop', () => {
|
|
186
|
+
render(
|
|
187
|
+
<Card data-testid="card" aria-labelledby="card-title">
|
|
188
|
+
<Card.Title id="card-title">Title</Card.Title>
|
|
189
|
+
</Card>,
|
|
190
|
+
)
|
|
191
|
+
const card = screen.getByTestId('card')
|
|
192
|
+
expect(card).toHaveAttribute('aria-labelledby', 'card-title')
|
|
193
|
+
})
|
|
194
|
+
|
|
195
|
+
it('accepts aria-describedby prop', () => {
|
|
196
|
+
render(
|
|
197
|
+
<Card data-testid="card" aria-describedby="card-desc">
|
|
198
|
+
Content
|
|
199
|
+
</Card>,
|
|
200
|
+
)
|
|
201
|
+
const card = screen.getByTestId('card')
|
|
202
|
+
expect(card).toHaveAttribute('aria-describedby', 'card-desc')
|
|
203
|
+
})
|
|
204
|
+
|
|
205
|
+
it('accepts custom role', () => {
|
|
206
|
+
render(
|
|
207
|
+
<Card data-testid="card" role="article">
|
|
208
|
+
Content
|
|
209
|
+
</Card>,
|
|
210
|
+
)
|
|
211
|
+
const card = screen.getByTestId('card')
|
|
212
|
+
expect(card).toHaveAttribute('role', 'article')
|
|
213
|
+
})
|
|
214
|
+
})
|
|
215
|
+
|
|
216
|
+
describe('Interactive Card', () => {
|
|
217
|
+
it('applies interactive attributes when interactive is true', () => {
|
|
218
|
+
const handleClick = vi.fn()
|
|
219
|
+
render(
|
|
220
|
+
<Card data-testid="card" interactive onClick={handleClick}>
|
|
221
|
+
Content
|
|
222
|
+
</Card>,
|
|
223
|
+
)
|
|
224
|
+
const card = screen.getByTestId('card')
|
|
225
|
+
expect(card).toHaveAttribute('role', 'button')
|
|
226
|
+
expect(card).toHaveAttribute('tabIndex', '0')
|
|
227
|
+
expect(card).toHaveAttribute('data-card', 'interactive')
|
|
228
|
+
})
|
|
229
|
+
|
|
230
|
+
it('calls onClick when clicked', async () => {
|
|
231
|
+
const handleClick = vi.fn()
|
|
232
|
+
const user = userEvent.setup()
|
|
233
|
+
render(
|
|
234
|
+
<Card data-testid="card" interactive onClick={handleClick}>
|
|
235
|
+
Content
|
|
236
|
+
</Card>,
|
|
237
|
+
)
|
|
238
|
+
const card = screen.getByTestId('card')
|
|
239
|
+
await user.click(card)
|
|
240
|
+
expect(handleClick).toHaveBeenCalledTimes(1)
|
|
241
|
+
})
|
|
242
|
+
|
|
243
|
+
it('calls onClick when Enter key is pressed', async () => {
|
|
244
|
+
const handleClick = vi.fn()
|
|
245
|
+
const user = userEvent.setup()
|
|
246
|
+
render(
|
|
247
|
+
<Card data-testid="card" interactive onClick={handleClick}>
|
|
248
|
+
Content
|
|
249
|
+
</Card>,
|
|
250
|
+
)
|
|
251
|
+
const card = screen.getByTestId('card')
|
|
252
|
+
card.focus()
|
|
253
|
+
await user.keyboard('{Enter}')
|
|
254
|
+
expect(handleClick).toHaveBeenCalledTimes(1)
|
|
255
|
+
})
|
|
256
|
+
|
|
257
|
+
it('calls onClick when Space key is pressed', async () => {
|
|
258
|
+
const handleClick = vi.fn()
|
|
259
|
+
const user = userEvent.setup()
|
|
260
|
+
render(
|
|
261
|
+
<Card data-testid="card" interactive onClick={handleClick}>
|
|
262
|
+
Content
|
|
263
|
+
</Card>,
|
|
264
|
+
)
|
|
265
|
+
const card = screen.getByTestId('card')
|
|
266
|
+
card.focus()
|
|
267
|
+
await user.keyboard(' ')
|
|
268
|
+
expect(handleClick).toHaveBeenCalledTimes(1)
|
|
269
|
+
})
|
|
270
|
+
|
|
271
|
+
it('does not call onClick for other keys', async () => {
|
|
272
|
+
const handleClick = vi.fn()
|
|
273
|
+
const user = userEvent.setup()
|
|
274
|
+
render(
|
|
275
|
+
<Card data-testid="card" interactive onClick={handleClick}>
|
|
276
|
+
Content
|
|
277
|
+
</Card>,
|
|
278
|
+
)
|
|
279
|
+
const card = screen.getByTestId('card')
|
|
280
|
+
card.focus()
|
|
281
|
+
await user.keyboard('a')
|
|
282
|
+
expect(handleClick).not.toHaveBeenCalled()
|
|
283
|
+
})
|
|
284
|
+
|
|
285
|
+
it('allows custom tabIndex', () => {
|
|
286
|
+
render(
|
|
287
|
+
<Card data-testid="card" interactive tabIndex={-1}>
|
|
288
|
+
Content
|
|
289
|
+
</Card>,
|
|
290
|
+
)
|
|
291
|
+
const card = screen.getByTestId('card')
|
|
292
|
+
expect(card).toHaveAttribute('tabIndex', '-1')
|
|
293
|
+
})
|
|
294
|
+
|
|
295
|
+
it('allows custom role override for interactive cards', () => {
|
|
296
|
+
render(
|
|
297
|
+
<Card data-testid="card" interactive role="link">
|
|
298
|
+
Content
|
|
299
|
+
</Card>,
|
|
300
|
+
)
|
|
301
|
+
const card = screen.getByTestId('card')
|
|
302
|
+
expect(card).toHaveAttribute('role', 'link')
|
|
303
|
+
})
|
|
304
|
+
|
|
305
|
+
it('is keyboard focusable when interactive', () => {
|
|
306
|
+
render(
|
|
307
|
+
<Card data-testid="card" interactive>
|
|
308
|
+
Content
|
|
309
|
+
</Card>,
|
|
310
|
+
)
|
|
311
|
+
const card = screen.getByTestId('card')
|
|
312
|
+
expect(card).toHaveAttribute('tabIndex', '0')
|
|
313
|
+
})
|
|
314
|
+
})
|
|
315
|
+
|
|
316
|
+
describe('Non-Interactive with onClick', () => {
|
|
317
|
+
it('allows onClick without interactive prop', async () => {
|
|
318
|
+
const handleClick = vi.fn()
|
|
319
|
+
const user = userEvent.setup()
|
|
320
|
+
render(
|
|
321
|
+
<Card data-testid="card" onClick={handleClick}>
|
|
322
|
+
Content
|
|
323
|
+
</Card>,
|
|
324
|
+
)
|
|
325
|
+
const card = screen.getByTestId('card')
|
|
326
|
+
await user.click(card)
|
|
327
|
+
expect(handleClick).toHaveBeenCalledTimes(1)
|
|
328
|
+
})
|
|
329
|
+
|
|
330
|
+
it('does not add role="button" without interactive', () => {
|
|
331
|
+
const handleClick = vi.fn()
|
|
332
|
+
render(
|
|
333
|
+
<Card data-testid="card" onClick={handleClick}>
|
|
334
|
+
Content
|
|
335
|
+
</Card>,
|
|
336
|
+
)
|
|
337
|
+
const card = screen.getByTestId('card')
|
|
338
|
+
expect(card).not.toHaveAttribute('role')
|
|
339
|
+
})
|
|
340
|
+
|
|
341
|
+
it('does not add tabIndex without interactive', () => {
|
|
342
|
+
const handleClick = vi.fn()
|
|
343
|
+
render(
|
|
344
|
+
<Card data-testid="card" onClick={handleClick}>
|
|
345
|
+
Content
|
|
346
|
+
</Card>,
|
|
347
|
+
)
|
|
348
|
+
const card = screen.getByTestId('card')
|
|
349
|
+
expect(card).not.toHaveAttribute('tabIndex')
|
|
350
|
+
})
|
|
351
|
+
})
|
|
352
|
+
|
|
353
|
+
describe('Display Names', () => {
|
|
354
|
+
it('has correct display name for Card', () => {
|
|
355
|
+
expect(Card.displayName).toBe('Card')
|
|
356
|
+
})
|
|
357
|
+
|
|
358
|
+
it('has correct display name for Card.Title', () => {
|
|
359
|
+
expect(Card.Title.displayName).toBe('Card.Title')
|
|
360
|
+
})
|
|
361
|
+
|
|
362
|
+
it('has correct display name for Card.Content', () => {
|
|
363
|
+
expect(Card.Content.displayName).toBe('Card.Content')
|
|
364
|
+
})
|
|
365
|
+
|
|
366
|
+
it('has correct display name for Card.Footer', () => {
|
|
367
|
+
expect(Card.Footer.displayName).toBe('Card.Footer')
|
|
368
|
+
})
|
|
29
369
|
})
|
|
30
370
|
})
|