@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
|
@@ -2,50 +2,196 @@ import { StoryObj, Meta } from "@storybook/react-vite";
|
|
|
2
2
|
import { within, expect } from "storybook/test";
|
|
3
3
|
|
|
4
4
|
import Badge from "./badge";
|
|
5
|
+
import "./badge.scss";
|
|
5
6
|
|
|
6
7
|
const meta: Meta<typeof Badge> = {
|
|
7
8
|
title: "FP.REACT Components/Badge",
|
|
8
9
|
component: Badge,
|
|
9
|
-
tags: ["beta"],
|
|
10
|
+
tags: ["beta", "accessible"],
|
|
10
11
|
args: {
|
|
11
|
-
children: "
|
|
12
|
+
children: "5",
|
|
12
13
|
},
|
|
13
|
-
} as
|
|
14
|
+
} as Meta;
|
|
14
15
|
|
|
15
16
|
export default meta;
|
|
16
17
|
type Story = StoryObj<typeof Badge>;
|
|
17
18
|
|
|
18
|
-
|
|
19
|
-
|
|
19
|
+
/**
|
|
20
|
+
* Default badge story - demonstrates basic usage with notification count
|
|
21
|
+
*/
|
|
22
|
+
export const Default: Story = {
|
|
23
|
+
args: {
|
|
24
|
+
children: "5",
|
|
25
|
+
"aria-label": "5 unread notifications",
|
|
26
|
+
},
|
|
20
27
|
play: async ({ canvasElement }) => {
|
|
21
28
|
const canvas = within(canvasElement);
|
|
22
|
-
expect(canvas.getByText(
|
|
29
|
+
expect(canvas.getByText("5")).toBeInTheDocument();
|
|
30
|
+
expect(canvas.getByRole("status")).toHaveAttribute(
|
|
31
|
+
"aria-label",
|
|
32
|
+
"5 unread notifications"
|
|
33
|
+
);
|
|
23
34
|
},
|
|
24
35
|
};
|
|
25
36
|
|
|
26
|
-
|
|
37
|
+
/**
|
|
38
|
+
* Badge within text content - shows typical usage alongside other content
|
|
39
|
+
*/
|
|
40
|
+
export const WithinText: Story = {
|
|
41
|
+
render: () => {
|
|
42
|
+
return (
|
|
43
|
+
<p>
|
|
44
|
+
Messages
|
|
45
|
+
<Badge aria-label="3 unread messages">3</Badge>
|
|
46
|
+
</p>
|
|
47
|
+
);
|
|
48
|
+
},
|
|
49
|
+
play: async ({ canvasElement }) => {
|
|
50
|
+
const canvas = within(canvasElement);
|
|
51
|
+
expect(canvas.getByText(/messages/i)).toBeInTheDocument();
|
|
52
|
+
expect(canvas.getByText("3")).toBeInTheDocument();
|
|
53
|
+
},
|
|
54
|
+
} as Story;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Rounded variant badge - circular style for compact display
|
|
58
|
+
*/
|
|
59
|
+
export const RoundedVariant: Story = {
|
|
27
60
|
args: {
|
|
28
|
-
|
|
61
|
+
variant: "rounded",
|
|
62
|
+
children: "99+",
|
|
63
|
+
"aria-label": "More than 99 notifications",
|
|
29
64
|
},
|
|
30
|
-
render: () => {
|
|
65
|
+
render: (args) => {
|
|
31
66
|
return (
|
|
32
67
|
<p>
|
|
33
|
-
|
|
34
|
-
<Badge
|
|
68
|
+
Notifications
|
|
69
|
+
<Badge {...args} />
|
|
35
70
|
</p>
|
|
36
71
|
);
|
|
37
72
|
},
|
|
38
73
|
play: async ({ canvasElement }) => {
|
|
39
74
|
const canvas = within(canvasElement);
|
|
40
|
-
|
|
75
|
+
const badge = canvas.getByRole("status");
|
|
76
|
+
expect(badge).toHaveAttribute("data-badge", "rounded");
|
|
77
|
+
expect(canvas.getByText("99+")).toBeInTheDocument();
|
|
78
|
+
},
|
|
79
|
+
} as Story;
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Multiple badges - demonstrates using multiple badges in the same context
|
|
83
|
+
*/
|
|
84
|
+
export const MultipleBadges: Story = {
|
|
85
|
+
render: () => {
|
|
86
|
+
return (
|
|
87
|
+
<div style={{ display: "flex", gap: "1rem", flexDirection: "column" }}>
|
|
88
|
+
<p>
|
|
89
|
+
Inbox
|
|
90
|
+
<Badge variant="rounded" aria-label="12 unread emails">
|
|
91
|
+
122
|
|
92
|
+
</Badge>
|
|
93
|
+
</p>
|
|
94
|
+
<p>
|
|
95
|
+
Inbox
|
|
96
|
+
<Badge variant="rounded" aria-label="12 unread emails">
|
|
97
|
+
12
|
|
98
|
+
</Badge>
|
|
99
|
+
</p>
|
|
100
|
+
<p>
|
|
101
|
+
Tasks
|
|
102
|
+
<Badge variant="rounded" aria-label="5 pending tasks">
|
|
103
|
+
5
|
|
104
|
+
</Badge>
|
|
105
|
+
</p>
|
|
106
|
+
<p>
|
|
107
|
+
Alerts
|
|
108
|
+
<Badge variant="rounded" aria-label="1 new alert">
|
|
109
|
+
1
|
|
110
|
+
</Badge>
|
|
111
|
+
</p>
|
|
112
|
+
</div>
|
|
113
|
+
);
|
|
41
114
|
},
|
|
42
115
|
} as Story;
|
|
43
116
|
|
|
44
|
-
|
|
117
|
+
/**
|
|
118
|
+
* Rounded badges with fixed circular shape - demonstrates perfect circles with ellipsis truncation
|
|
119
|
+
* All rounded badges maintain a fixed size (1.5625rem), with content truncated using ellipsis if too long
|
|
120
|
+
*/
|
|
121
|
+
export const RoundedCircles: Story = {
|
|
45
122
|
render: () => {
|
|
123
|
+
return (
|
|
124
|
+
<div style={{ display: "flex", gap: "1.5rem", flexDirection: "column" }}>
|
|
125
|
+
<p>
|
|
126
|
+
Single digit (perfect circle)
|
|
127
|
+
<Badge variant="rounded" aria-label="1 notification">
|
|
128
|
+
1
|
|
129
|
+
</Badge>
|
|
130
|
+
</p>
|
|
131
|
+
<p>
|
|
132
|
+
Single digit (perfect circle)
|
|
133
|
+
<Badge variant="rounded" aria-label="9 notifications">
|
|
134
|
+
9
|
|
135
|
+
</Badge>
|
|
136
|
+
</p>
|
|
137
|
+
<p>
|
|
138
|
+
Double digits (perfect circle)
|
|
139
|
+
<Badge variant="rounded" aria-label="12 notifications">
|
|
140
|
+
12
|
|
141
|
+
</Badge>
|
|
142
|
+
</p>
|
|
143
|
+
<p>
|
|
144
|
+
Double digits (perfect circle)
|
|
145
|
+
<Badge variant="rounded" aria-label="99 notifications">
|
|
146
|
+
99
|
|
147
|
+
</Badge>
|
|
148
|
+
</p>
|
|
149
|
+
<p>
|
|
150
|
+
✅ Good: Formatted by developer
|
|
151
|
+
<Badge variant="rounded" aria-label="More than 99 notifications">
|
|
152
|
+
99+
|
|
153
|
+
</Badge>
|
|
154
|
+
</p>
|
|
155
|
+
<p>
|
|
156
|
+
⚠️ Will truncate: Too many characters
|
|
157
|
+
<Badge variant="rounded" aria-label="More than 999 notifications">
|
|
158
|
+
999+
|
|
159
|
+
</Badge>
|
|
160
|
+
</p>
|
|
161
|
+
<p>
|
|
162
|
+
⚠️ Will truncate: Text content
|
|
163
|
+
<Badge variant="rounded" aria-label="New feature available">
|
|
164
|
+
NEW
|
|
165
|
+
</Badge>
|
|
166
|
+
</p>
|
|
167
|
+
<p>
|
|
168
|
+
⚠️ Will truncate: Very long text
|
|
169
|
+
<Badge variant="rounded" aria-label="Multiple notifications">
|
|
170
|
+
Multiple
|
|
171
|
+
</Badge>
|
|
172
|
+
</p>
|
|
173
|
+
</div>
|
|
174
|
+
);
|
|
175
|
+
},
|
|
176
|
+
} as Story;
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Custom styled badge - demonstrates custom styling with inline styles
|
|
180
|
+
*/
|
|
181
|
+
export const CustomStyling: Story = {
|
|
182
|
+
args: {
|
|
183
|
+
children: "NEW",
|
|
184
|
+
"aria-label": "New feature",
|
|
185
|
+
styles: {
|
|
186
|
+
backgroundColor: "#10b981",
|
|
187
|
+
color: "white",
|
|
188
|
+
},
|
|
189
|
+
},
|
|
190
|
+
render: (args) => {
|
|
46
191
|
return (
|
|
47
192
|
<p>
|
|
48
|
-
|
|
193
|
+
Feature Release
|
|
194
|
+
<Badge {...args} />
|
|
49
195
|
</p>
|
|
50
196
|
);
|
|
51
197
|
},
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { render, screen } from "@testing-library/react";
|
|
3
|
+
import { Badge } from "./badge";
|
|
4
|
+
|
|
5
|
+
describe("Badge", () => {
|
|
6
|
+
it("renders a badge element with the correct content", () => {
|
|
7
|
+
render(<Badge aria-label="5 notifications">5</Badge>);
|
|
8
|
+
const badge = screen.getByText("5");
|
|
9
|
+
expect(badge).toBeInTheDocument();
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
it("renders as a sup element by default", () => {
|
|
13
|
+
render(<Badge aria-label="notification badge">3</Badge>);
|
|
14
|
+
const badge = screen.getByRole("status");
|
|
15
|
+
expect(badge.tagName).toBe("SUP");
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it("has role='status' by default for accessibility", () => {
|
|
19
|
+
render(<Badge aria-label="badge">12</Badge>);
|
|
20
|
+
const badge = screen.getByRole("status");
|
|
21
|
+
expect(badge).toHaveAttribute("role", "status");
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it("applies aria-label for screen reader accessibility", () => {
|
|
25
|
+
render(<Badge aria-label="3 unread messages">3</Badge>);
|
|
26
|
+
const badge = screen.getByRole("status");
|
|
27
|
+
expect(badge).toHaveAttribute("aria-label", "3 unread messages");
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
it("renders with nested span element for styling", () => {
|
|
31
|
+
render(<Badge aria-label="badge">5</Badge>);
|
|
32
|
+
const badge = screen.getByRole("status");
|
|
33
|
+
const span = badge.querySelector("span");
|
|
34
|
+
expect(span).toBeInTheDocument();
|
|
35
|
+
expect(span?.textContent).toBe("5");
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it("applies custom id when provided", () => {
|
|
39
|
+
render(
|
|
40
|
+
<Badge id="notification-badge" aria-label="notification">
|
|
41
|
+
10
|
|
42
|
+
</Badge>
|
|
43
|
+
);
|
|
44
|
+
const badge = screen.getByRole("status");
|
|
45
|
+
expect(badge).toHaveAttribute("id", "notification-badge");
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it("applies custom className when provided via classes prop", () => {
|
|
49
|
+
render(
|
|
50
|
+
<Badge classes="custom-badge-class" aria-label="badge">
|
|
51
|
+
7
|
|
52
|
+
</Badge>
|
|
53
|
+
);
|
|
54
|
+
const badge = screen.getByRole("status");
|
|
55
|
+
expect(badge).toHaveClass("custom-badge-class");
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it("applies custom inline styles when provided", () => {
|
|
59
|
+
render(
|
|
60
|
+
<Badge styles={{ backgroundColor: "red", fontSize: "1rem" }} aria-label="badge">
|
|
61
|
+
99+
|
|
62
|
+
</Badge>
|
|
63
|
+
);
|
|
64
|
+
const badge = screen.getByRole("status");
|
|
65
|
+
expect(badge).toHaveAttribute("style");
|
|
66
|
+
expect(badge).toHaveStyle({
|
|
67
|
+
fontSize: "1rem",
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
describe("variant prop", () => {
|
|
72
|
+
it("applies data-badge='rounded' when variant is 'rounded'", () => {
|
|
73
|
+
render(
|
|
74
|
+
<Badge variant="rounded" aria-label="rounded badge">
|
|
75
|
+
5
|
|
76
|
+
</Badge>
|
|
77
|
+
);
|
|
78
|
+
const badge = screen.getByRole("status");
|
|
79
|
+
expect(badge).toHaveAttribute("data-badge", "rounded");
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
it("does not apply data-badge attribute when variant is undefined", () => {
|
|
83
|
+
render(<Badge aria-label="default badge">3</Badge>);
|
|
84
|
+
const badge = screen.getByRole("status");
|
|
85
|
+
expect(badge).not.toHaveAttribute("data-badge");
|
|
86
|
+
});
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
describe("children rendering", () => {
|
|
90
|
+
it("renders numeric children correctly", () => {
|
|
91
|
+
render(<Badge aria-label="count">123</Badge>);
|
|
92
|
+
expect(screen.getByText("123")).toBeInTheDocument();
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it("renders string children correctly", () => {
|
|
96
|
+
render(<Badge aria-label="new badge">NEW</Badge>);
|
|
97
|
+
expect(screen.getByText("NEW")).toBeInTheDocument();
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
it("renders React element children correctly", () => {
|
|
101
|
+
render(
|
|
102
|
+
<Badge aria-label="icon badge">
|
|
103
|
+
<span data-testid="custom-icon">★</span>
|
|
104
|
+
</Badge>
|
|
105
|
+
);
|
|
106
|
+
expect(screen.getByTestId("custom-icon")).toBeInTheDocument();
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
describe("accessibility", () => {
|
|
111
|
+
it("is accessible with proper aria-label", () => {
|
|
112
|
+
render(<Badge aria-label="12 items in cart">12</Badge>);
|
|
113
|
+
const badge = screen.getByRole("status", { name: "12 items in cart" });
|
|
114
|
+
expect(badge).toBeInTheDocument();
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
it("can override role attribute if needed", () => {
|
|
118
|
+
render(
|
|
119
|
+
<Badge role="note" aria-label="information">
|
|
120
|
+
i
|
|
121
|
+
</Badge>
|
|
122
|
+
);
|
|
123
|
+
// role="note" should be applied via props spread
|
|
124
|
+
const badge = screen.getByText("i").closest("sup");
|
|
125
|
+
expect(badge).toHaveAttribute("role", "note");
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
it("supports additional ARIA attributes", () => {
|
|
129
|
+
render(
|
|
130
|
+
<Badge aria-label="badge" aria-live="polite" aria-atomic="true">
|
|
131
|
+
5
|
|
132
|
+
</Badge>
|
|
133
|
+
);
|
|
134
|
+
const badge = screen.getByRole("status");
|
|
135
|
+
expect(badge).toHaveAttribute("aria-live", "polite");
|
|
136
|
+
expect(badge).toHaveAttribute("aria-atomic", "true");
|
|
137
|
+
});
|
|
138
|
+
});
|
|
139
|
+
|
|
140
|
+
describe("integration", () => {
|
|
141
|
+
it("renders correctly within text content", () => {
|
|
142
|
+
render(
|
|
143
|
+
<p>
|
|
144
|
+
Messages
|
|
145
|
+
<Badge aria-label="3 unread">3</Badge>
|
|
146
|
+
</p>
|
|
147
|
+
);
|
|
148
|
+
expect(screen.getByText("Messages")).toBeInTheDocument();
|
|
149
|
+
expect(screen.getByText("3")).toBeInTheDocument();
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
it("renders multiple badges independently", () => {
|
|
153
|
+
render(
|
|
154
|
+
<div>
|
|
155
|
+
<Badge aria-label="first badge">1</Badge>
|
|
156
|
+
<Badge aria-label="second badge">2</Badge>
|
|
157
|
+
<Badge aria-label="third badge" variant="rounded">
|
|
158
|
+
3
|
|
159
|
+
</Badge>
|
|
160
|
+
</div>
|
|
161
|
+
);
|
|
162
|
+
const badges = screen.getAllByRole("status");
|
|
163
|
+
expect(badges).toHaveLength(3);
|
|
164
|
+
expect(badges[2]).toHaveAttribute("data-badge", "rounded");
|
|
165
|
+
});
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
describe("props spreading", () => {
|
|
169
|
+
it("forwards additional props to the UI component", () => {
|
|
170
|
+
render(
|
|
171
|
+
<Badge data-testid="custom-badge" data-custom="value" aria-label="badge">
|
|
172
|
+
5
|
|
173
|
+
</Badge>
|
|
174
|
+
);
|
|
175
|
+
const badge = screen.getByTestId("custom-badge");
|
|
176
|
+
expect(badge).toHaveAttribute("data-custom", "value");
|
|
177
|
+
});
|
|
178
|
+
});
|
|
179
|
+
});
|
|
@@ -1,17 +1,110 @@
|
|
|
1
1
|
import UI from '#components/ui'
|
|
2
2
|
import React from 'react'
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Props for the Badge component
|
|
6
|
+
*
|
|
7
|
+
* @property {React.ReactNode} children - Content to display inside the badge (typically numbers or short text)
|
|
8
|
+
* @property {string} [id] - Optional HTML id attribute for the badge element
|
|
9
|
+
* @property {React.CSSProperties} [styles] - Inline styles to apply to the badge
|
|
10
|
+
* @property {string} [classes] - CSS class names to apply to the badge
|
|
11
|
+
* @property {'rounded'} [variant] - Visual variant of the badge. Use 'rounded' for circular badges (fixed size with ellipsis for overflow)
|
|
12
|
+
* @property {string} [aria-label] - Accessible label for screen readers. Required for icon-only or number-only badges
|
|
13
|
+
* @property {'status' | 'note'} [role] - ARIA role for the badge. Defaults to 'status' for dynamic content
|
|
14
|
+
*/
|
|
4
15
|
export type BadgeProps = {
|
|
5
|
-
|
|
16
|
+
/**
|
|
17
|
+
* Content to display inside the badge (typically numbers or short text)
|
|
18
|
+
*/
|
|
19
|
+
children?: React.ReactNode
|
|
20
|
+
/**
|
|
21
|
+
* Visual variant of the badge
|
|
22
|
+
* - 'rounded': Circular badge style
|
|
23
|
+
*/
|
|
24
|
+
variant?: 'rounded'
|
|
6
25
|
} & React.ComponentProps<typeof UI>
|
|
7
26
|
|
|
8
|
-
|
|
27
|
+
/**
|
|
28
|
+
* Badge - A small label component for displaying status, counts, or notifications
|
|
29
|
+
*
|
|
30
|
+
* The Badge component is used to display supplementary information alongside other content,
|
|
31
|
+
* such as notification counts, status indicators, or labels. It renders as a semantic `<sup>`
|
|
32
|
+
* element with a nested `<span>` required for the component's styling architecture.
|
|
33
|
+
*
|
|
34
|
+
* ## Styling Architecture
|
|
35
|
+
*
|
|
36
|
+
* The Badge uses a nested structure (`<sup><span>content</span></sup>`) which is required
|
|
37
|
+
* for the SCSS styling system. The outer `<sup>` element provides positioning context,
|
|
38
|
+
* while the inner `<span>` receives the visual styling (background, padding, border-radius).
|
|
39
|
+
*
|
|
40
|
+
* ## Rounded Variant Behavior
|
|
41
|
+
*
|
|
42
|
+
* The `rounded` variant creates a perfect circular badge with fixed dimensions (1.5625rem).
|
|
43
|
+
* Content that exceeds the available space will be truncated with an ellipsis (...).
|
|
44
|
+
* **Best practice**: Format large numbers yourself (e.g., pass "99+" instead of "999").
|
|
45
|
+
*
|
|
46
|
+
* ## Accessibility Considerations
|
|
47
|
+
*
|
|
48
|
+
* - **Semantic HTML**: Uses `<sup>` (superscript) element for proper positioning context
|
|
49
|
+
* - **ARIA Role**: Defaults to `role="status"` for dynamic badges (e.g., unread counts)
|
|
50
|
+
* - **Accessible Names**: For icon-only or number-only badges, provide an `aria-label`
|
|
51
|
+
* to give context (e.g., "3 unread messages" instead of just "3")
|
|
52
|
+
* - **Live Regions**: The `role="status"` makes badges announce updates to screen readers
|
|
53
|
+
*
|
|
54
|
+
* @param {BadgeProps} props - Component props
|
|
55
|
+
* @returns {React.ReactElement} A Badge component
|
|
56
|
+
*
|
|
57
|
+
* @example
|
|
58
|
+
* // Basic badge with notification count
|
|
59
|
+
* <p>
|
|
60
|
+
* Messages
|
|
61
|
+
* <Badge aria-label="3 unread messages">3</Badge>
|
|
62
|
+
* </p>
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* // Rounded badge variant (perfect circle)
|
|
66
|
+
* <p>
|
|
67
|
+
* Notifications
|
|
68
|
+
* <Badge variant="rounded" aria-label="99 or more notifications">99+</Badge>
|
|
69
|
+
* </p>
|
|
70
|
+
*
|
|
71
|
+
* @example
|
|
72
|
+
* // Status badge with custom styling
|
|
73
|
+
* <p>
|
|
74
|
+
* Active Users
|
|
75
|
+
* <Badge styles={{ backgroundColor: 'green', color: 'white' }}>21</Badge>
|
|
76
|
+
* </p>
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* // ✅ GOOD: Accessible badge with descriptive label and formatted content
|
|
80
|
+
* <Badge variant="rounded" aria-label="12 items in cart">12</Badge>
|
|
81
|
+
*
|
|
82
|
+
* @example
|
|
83
|
+
* // ✅ GOOD: Large numbers formatted by developer
|
|
84
|
+
* <Badge variant="rounded" aria-label="More than 99 notifications">99+</Badge>
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* // ❌ BAD: Number-only badge without context for screen readers
|
|
88
|
+
* <Badge>12</Badge>
|
|
89
|
+
*/
|
|
90
|
+
export const Badge = ({ id, styles, classes, children, variant, ...props }: BadgeProps) => {
|
|
91
|
+
// Build data-badge attribute for variant styling
|
|
92
|
+
const dataBadge = variant ? variant : undefined
|
|
93
|
+
|
|
9
94
|
return (
|
|
10
|
-
<UI
|
|
95
|
+
<UI
|
|
96
|
+
as="sup"
|
|
97
|
+
id={id}
|
|
98
|
+
styles={styles}
|
|
99
|
+
className={classes}
|
|
100
|
+
data-badge={dataBadge}
|
|
101
|
+
role="status"
|
|
102
|
+
{...props}
|
|
103
|
+
>
|
|
11
104
|
<UI as="span">{children}</UI>
|
|
12
105
|
</UI>
|
|
13
106
|
)
|
|
14
107
|
}
|
|
15
108
|
|
|
16
|
-
export default Badge
|
|
17
109
|
Badge.displayName = 'Badge'
|
|
110
|
+
export default Badge
|