@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
|
@@ -0,0 +1,416 @@
|
|
|
1
|
+
# UI Component
|
|
2
|
+
|
|
3
|
+
> A polymorphic React component that can render as any HTML element with full TypeScript type safety.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
The **UI component** is a foundational primitive used throughout the fpkit library to create flexible, type-safe components. It implements the polymorphic component pattern, enabling a single component to render as different HTML elements while maintaining complete TypeScript type safety for element-specific props.
|
|
8
|
+
|
|
9
|
+
This component serves as the building block for 25+ components across fpkit, including Button, Badge, Tag, Heading, Text, and more.
|
|
10
|
+
|
|
11
|
+
## Features
|
|
12
|
+
|
|
13
|
+
- **Polymorphic Rendering** - Render as any valid HTML element using the `as` prop
|
|
14
|
+
- **Full Type Safety** - TypeScript infers correct props based on the chosen element
|
|
15
|
+
- **Style Merging** - Intelligent merging of `defaultStyles` and `styles` props
|
|
16
|
+
- **Ref Forwarding** - Properly typed ref support for all element types
|
|
17
|
+
- **Prop Spreading** - All native element props are forwarded with type checking
|
|
18
|
+
- **Zero Runtime Overhead** - Thin wrapper with minimal performance cost
|
|
19
|
+
|
|
20
|
+
## Props
|
|
21
|
+
|
|
22
|
+
| Name | Type | Default | Description |
|
|
23
|
+
|------|------|---------|-------------|
|
|
24
|
+
| `as` | `React.ElementType` | `'div'` | The HTML element type to render (e.g., 'button', 'span', 'a') |
|
|
25
|
+
| `styles` | `React.CSSProperties` | `undefined` | Inline styles to apply. Overrides `defaultStyles`. |
|
|
26
|
+
| `classes` | `string` | `undefined` | CSS class names to apply to the element |
|
|
27
|
+
| `defaultStyles` | `React.CSSProperties` | `undefined` | Base styles that can be overridden by `styles` prop |
|
|
28
|
+
| `children` | `React.ReactNode` | `undefined` | Child elements to render inside the component |
|
|
29
|
+
| `ref` | `React.Ref<Element>` | `undefined` | Forwarded ref with proper typing for the element type |
|
|
30
|
+
| `renderStyles` | `boolean` | - | **Deprecated**: Reserved for future use. Currently has no effect. |
|
|
31
|
+
| `...props` | Element-specific | - | All native element props are forwarded (onClick, href, disabled, etc.) |
|
|
32
|
+
|
|
33
|
+
## Usage Examples
|
|
34
|
+
|
|
35
|
+
### Basic Usage
|
|
36
|
+
|
|
37
|
+
By default, the UI component renders as a `div`:
|
|
38
|
+
|
|
39
|
+
```tsx
|
|
40
|
+
import UI from '@fpkit/acss';
|
|
41
|
+
|
|
42
|
+
function Example() {
|
|
43
|
+
return <UI>Hello World</UI>;
|
|
44
|
+
}
|
|
45
|
+
// Renders: <div>Hello World</div>
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
### Polymorphic Rendering
|
|
49
|
+
|
|
50
|
+
Use the `as` prop to render as different HTML elements:
|
|
51
|
+
|
|
52
|
+
```tsx
|
|
53
|
+
// Render as a button
|
|
54
|
+
<UI as="button" onClick={handleClick}>
|
|
55
|
+
Click me
|
|
56
|
+
</UI>
|
|
57
|
+
|
|
58
|
+
// Render as a link with href (TypeScript knows href is valid!)
|
|
59
|
+
<UI as="a" href="/home" target="_blank">
|
|
60
|
+
Go Home
|
|
61
|
+
</UI>
|
|
62
|
+
|
|
63
|
+
// Render as a semantic section
|
|
64
|
+
<UI as="section" aria-label="Main Content">
|
|
65
|
+
<h2>Section Title</h2>
|
|
66
|
+
<p>Section content...</p>
|
|
67
|
+
</UI>
|
|
68
|
+
|
|
69
|
+
// Render as a span
|
|
70
|
+
<UI as="span" style={{ fontWeight: 'bold' }}>
|
|
71
|
+
Bold Text
|
|
72
|
+
</UI>
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### Style Customization
|
|
76
|
+
|
|
77
|
+
The UI component supports both `defaultStyles` (base styles) and `styles` (override styles):
|
|
78
|
+
|
|
79
|
+
```tsx
|
|
80
|
+
// defaultStyles provide a base layer
|
|
81
|
+
<UI
|
|
82
|
+
defaultStyles={{
|
|
83
|
+
padding: '1rem',
|
|
84
|
+
backgroundColor: 'lightblue',
|
|
85
|
+
color: 'blue'
|
|
86
|
+
}}
|
|
87
|
+
>
|
|
88
|
+
Blue text with padding
|
|
89
|
+
</UI>
|
|
90
|
+
|
|
91
|
+
// styles override defaultStyles
|
|
92
|
+
<UI
|
|
93
|
+
defaultStyles={{
|
|
94
|
+
padding: '1rem',
|
|
95
|
+
color: 'blue'
|
|
96
|
+
}}
|
|
97
|
+
styles={{
|
|
98
|
+
color: 'red' // This overrides the blue color
|
|
99
|
+
}}
|
|
100
|
+
>
|
|
101
|
+
Red text with padding (color overridden)
|
|
102
|
+
</UI>
|
|
103
|
+
|
|
104
|
+
// Using CSS custom properties
|
|
105
|
+
<UI
|
|
106
|
+
styles={{
|
|
107
|
+
'--button-bg': '#007bff',
|
|
108
|
+
'--button-color': 'white',
|
|
109
|
+
padding: '0.5rem 1rem',
|
|
110
|
+
backgroundColor: 'var(--button-bg)',
|
|
111
|
+
color: 'var(--button-color)'
|
|
112
|
+
} as React.CSSProperties}
|
|
113
|
+
>
|
|
114
|
+
Themed Button
|
|
115
|
+
</UI>
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Ref Forwarding
|
|
119
|
+
|
|
120
|
+
The UI component properly forwards refs with correct typing:
|
|
121
|
+
|
|
122
|
+
```tsx
|
|
123
|
+
import { useRef, useEffect } from 'react';
|
|
124
|
+
|
|
125
|
+
function FocusExample() {
|
|
126
|
+
const buttonRef = useRef<HTMLButtonElement>(null);
|
|
127
|
+
|
|
128
|
+
useEffect(() => {
|
|
129
|
+
// TypeScript knows this is an HTMLButtonElement
|
|
130
|
+
buttonRef.current?.focus();
|
|
131
|
+
}, []);
|
|
132
|
+
|
|
133
|
+
return (
|
|
134
|
+
<UI as="button" ref={buttonRef}>
|
|
135
|
+
Auto-focused Button
|
|
136
|
+
</UI>
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### Type-Safe Props
|
|
142
|
+
|
|
143
|
+
TypeScript automatically infers the correct props based on the `as` prop:
|
|
144
|
+
|
|
145
|
+
```tsx
|
|
146
|
+
// Button-specific props are available
|
|
147
|
+
<UI as="button" type="submit" disabled>
|
|
148
|
+
Submit
|
|
149
|
+
</UI>
|
|
150
|
+
|
|
151
|
+
// Anchor-specific props are available
|
|
152
|
+
<UI as="a" href="/link" target="_blank" rel="noopener">
|
|
153
|
+
External Link
|
|
154
|
+
</UI>
|
|
155
|
+
|
|
156
|
+
// Form-specific props are available
|
|
157
|
+
<UI as="form" onSubmit={handleSubmit} method="POST">
|
|
158
|
+
<input type="text" />
|
|
159
|
+
</UI>
|
|
160
|
+
|
|
161
|
+
// TypeScript will error on invalid prop combinations!
|
|
162
|
+
// ❌ This will cause a TypeScript error:
|
|
163
|
+
// <UI as="button" href="/link">Invalid</UI>
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### Building Higher-Level Components
|
|
167
|
+
|
|
168
|
+
The UI component is designed to be a primitive for building other components:
|
|
169
|
+
|
|
170
|
+
```tsx
|
|
171
|
+
// Example: Building a Button component
|
|
172
|
+
interface ButtonProps {
|
|
173
|
+
variant?: 'primary' | 'secondary';
|
|
174
|
+
children: React.ReactNode;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
const Button = ({ variant = 'primary', ...props }: ButtonProps) => {
|
|
178
|
+
const variantStyles = {
|
|
179
|
+
primary: {
|
|
180
|
+
backgroundColor: '#007bff',
|
|
181
|
+
color: 'white',
|
|
182
|
+
border: 'none'
|
|
183
|
+
},
|
|
184
|
+
secondary: {
|
|
185
|
+
backgroundColor: 'transparent',
|
|
186
|
+
color: '#007bff',
|
|
187
|
+
border: '1px solid #007bff'
|
|
188
|
+
}
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
return (
|
|
192
|
+
<UI
|
|
193
|
+
as="button"
|
|
194
|
+
defaultStyles={{
|
|
195
|
+
padding: '0.5rem 1rem',
|
|
196
|
+
borderRadius: '0.25rem',
|
|
197
|
+
cursor: 'pointer',
|
|
198
|
+
...variantStyles[variant]
|
|
199
|
+
}}
|
|
200
|
+
{...props}
|
|
201
|
+
/>
|
|
202
|
+
);
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
// Usage
|
|
206
|
+
<Button variant="primary" onClick={handleClick}>
|
|
207
|
+
Primary Button
|
|
208
|
+
</Button>
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
## Technical Details
|
|
212
|
+
|
|
213
|
+
### Type System Architecture
|
|
214
|
+
|
|
215
|
+
The UI component uses a sophisticated type system to achieve polymorphic behavior:
|
|
216
|
+
|
|
217
|
+
```
|
|
218
|
+
FPComponent (function signature)
|
|
219
|
+
↓
|
|
220
|
+
FPProps<C> (merged props with ref)
|
|
221
|
+
↓
|
|
222
|
+
PolymorphicComponentPropWithRef<C, Props>
|
|
223
|
+
↓
|
|
224
|
+
PolymorphicComponentProp<C, Props> (props without ref)
|
|
225
|
+
↓
|
|
226
|
+
PropsWithChildren<Props & AsProp<C>> & Omit<ComponentPropsWithoutRef<C>, ...>
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
**How it works:**
|
|
230
|
+
|
|
231
|
+
1. **Generic Parameter**: The component accepts a generic `C extends React.ElementType` representing the element type
|
|
232
|
+
2. **Prop Inference**: TypeScript uses `React.ComponentPropsWithoutRef<C>` to extract native props for that element
|
|
233
|
+
3. **Prop Merging**: Custom props (`styles`, `classes`, etc.) are merged with native props
|
|
234
|
+
4. **Conflict Resolution**: The `PropsToOmit` type removes conflicting keys to prevent type errors
|
|
235
|
+
5. **Ref Typing**: The `PolymorphicRef` type extracts the correct ref type for the element
|
|
236
|
+
|
|
237
|
+
### Style Merging Behavior
|
|
238
|
+
|
|
239
|
+
The component merges styles using JavaScript object spread:
|
|
240
|
+
|
|
241
|
+
```typescript
|
|
242
|
+
const styleObj: React.CSSProperties = { ...defaultStyles, ...styles };
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
**Precedence:**
|
|
246
|
+
- `defaultStyles` is applied first (base layer)
|
|
247
|
+
- `styles` is applied second (override layer)
|
|
248
|
+
- Properties in `styles` always override matching properties in `defaultStyles`
|
|
249
|
+
|
|
250
|
+
**Example:**
|
|
251
|
+
```tsx
|
|
252
|
+
<UI
|
|
253
|
+
defaultStyles={{ padding: '1rem', color: 'blue', fontSize: '16px' }}
|
|
254
|
+
styles={{ color: 'red' }}
|
|
255
|
+
/>
|
|
256
|
+
// Result: { padding: '1rem', color: 'red', fontSize: '16px' }
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
## Common Patterns
|
|
260
|
+
|
|
261
|
+
### How fpkit Components Use UI
|
|
262
|
+
|
|
263
|
+
Many fpkit components are built on the UI primitive:
|
|
264
|
+
|
|
265
|
+
**Button Component:**
|
|
266
|
+
```tsx
|
|
267
|
+
<UI
|
|
268
|
+
as="button"
|
|
269
|
+
defaultStyles={{ padding: '0.5rem 1rem', borderRadius: '0.25rem' }}
|
|
270
|
+
{...props}
|
|
271
|
+
/>
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
**Badge Component:**
|
|
275
|
+
```tsx
|
|
276
|
+
<UI
|
|
277
|
+
as="span"
|
|
278
|
+
defaultStyles={{
|
|
279
|
+
display: 'inline-block',
|
|
280
|
+
padding: '0.25rem 0.5rem',
|
|
281
|
+
fontSize: '0.75rem',
|
|
282
|
+
borderRadius: '0.25rem'
|
|
283
|
+
}}
|
|
284
|
+
{...props}
|
|
285
|
+
/>
|
|
286
|
+
```
|
|
287
|
+
|
|
288
|
+
**Tag Component:**
|
|
289
|
+
```tsx
|
|
290
|
+
<UI
|
|
291
|
+
as="span"
|
|
292
|
+
defaultStyles={{
|
|
293
|
+
display: 'inline-flex',
|
|
294
|
+
alignItems: 'center',
|
|
295
|
+
gap: '0.25rem'
|
|
296
|
+
}}
|
|
297
|
+
{...props}
|
|
298
|
+
/>
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
## FP vs UI
|
|
302
|
+
|
|
303
|
+
The fpkit codebase contains two similar polymorphic components:
|
|
304
|
+
|
|
305
|
+
| Feature | UI Component | FP Component |
|
|
306
|
+
|---------|-------------|--------------|
|
|
307
|
+
| File | `ui.tsx` | `fp.tsx` |
|
|
308
|
+
| Usage | Used by 25+ components | Standalone usage |
|
|
309
|
+
| `defaultStyles` | ✅ Supported | ✅ Supported |
|
|
310
|
+
| `renderStyles` | ⚠️ Defined but not implemented | ⚠️ Defined but not implemented |
|
|
311
|
+
| Tests | 📝 Being added | ✅ Has tests |
|
|
312
|
+
| Default Element | `div` | `div` |
|
|
313
|
+
|
|
314
|
+
**When to use UI:**
|
|
315
|
+
- When building components within the fpkit library
|
|
316
|
+
- When you need the established patterns used by Button, Badge, etc.
|
|
317
|
+
- When `defaultStyles` merging is important
|
|
318
|
+
|
|
319
|
+
**When to use FP:**
|
|
320
|
+
- For standalone polymorphic rendering
|
|
321
|
+
- When you want a tested primitive
|
|
322
|
+
- For quick prototyping
|
|
323
|
+
|
|
324
|
+
> **Note**: These components may be consolidated in a future version. Check the documentation for updates.
|
|
325
|
+
|
|
326
|
+
## Accessibility Notes
|
|
327
|
+
|
|
328
|
+
The UI component is a low-level primitive that doesn't enforce accessibility features. It's your responsibility to:
|
|
329
|
+
|
|
330
|
+
- **Choose semantic HTML elements** - Use `as="button"` for clickable actions, `as="a"` for navigation, etc.
|
|
331
|
+
- **Avoid generic divs for interactive elements** - Don't use `<UI as="div" onClick={...}>` for buttons
|
|
332
|
+
- **Use proper ARIA attributes** - Add `aria-label`, `role`, etc. when needed
|
|
333
|
+
- **Ensure keyboard accessibility** - Native elements provide this for free (button, a, etc.)
|
|
334
|
+
|
|
335
|
+
**Good examples:**
|
|
336
|
+
```tsx
|
|
337
|
+
// ✅ Semantic button
|
|
338
|
+
<UI as="button" onClick={handleClick}>Click me</UI>
|
|
339
|
+
|
|
340
|
+
// ✅ Semantic navigation link
|
|
341
|
+
<UI as="nav" aria-label="Main navigation">...</UI>
|
|
342
|
+
|
|
343
|
+
// ✅ Semantic article with heading
|
|
344
|
+
<UI as="article">
|
|
345
|
+
<UI as="h2">Article Title</UI>
|
|
346
|
+
</UI>
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
**Bad examples:**
|
|
350
|
+
```tsx
|
|
351
|
+
// ❌ Div used as button (not keyboard accessible)
|
|
352
|
+
<UI as="div" onClick={handleClick}>Click me</UI>
|
|
353
|
+
|
|
354
|
+
// ❌ Span used as link (not accessible)
|
|
355
|
+
<UI as="span" onClick={navigate}>Go to page</UI>
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
## Additional Notes
|
|
359
|
+
|
|
360
|
+
### Performance Considerations
|
|
361
|
+
|
|
362
|
+
The UI component has minimal performance overhead:
|
|
363
|
+
- Single object spread for style merging
|
|
364
|
+
- No hooks or state
|
|
365
|
+
- Thin wrapper around native elements
|
|
366
|
+
- Ref forwarding with no additional rendering
|
|
367
|
+
|
|
368
|
+
### TypeScript IntelliSense
|
|
369
|
+
|
|
370
|
+
One of the biggest benefits of the UI component is enhanced developer experience:
|
|
371
|
+
|
|
372
|
+
- **Autocomplete** - Your IDE will suggest valid props based on the `as` prop
|
|
373
|
+
- **Type Errors** - Invalid prop combinations are caught at compile time
|
|
374
|
+
- **Documentation** - Hover over props to see JSDoc comments
|
|
375
|
+
- **Refactoring** - Change the `as` prop and see prop types update instantly
|
|
376
|
+
|
|
377
|
+
### Gotchas and Best Practices
|
|
378
|
+
|
|
379
|
+
**Style Object Creation:**
|
|
380
|
+
```tsx
|
|
381
|
+
// ❌ Bad: Creates new object on every render
|
|
382
|
+
<UI styles={{ padding: '1rem' }}>Text</UI>
|
|
383
|
+
|
|
384
|
+
// ✅ Good: Memoize style objects
|
|
385
|
+
const styles = useMemo(() => ({ padding: '1rem' }), []);
|
|
386
|
+
<UI styles={styles}>Text</UI>
|
|
387
|
+
|
|
388
|
+
// ✅ Also good: Define outside component if static
|
|
389
|
+
const STATIC_STYLES = { padding: '1rem' };
|
|
390
|
+
<UI styles={STATIC_STYLES}>Text</UI>
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
**Ref Type Safety:**
|
|
394
|
+
```tsx
|
|
395
|
+
// ✅ Good: Ref type matches element
|
|
396
|
+
const buttonRef = useRef<HTMLButtonElement>(null);
|
|
397
|
+
<UI as="button" ref={buttonRef}>Button</UI>
|
|
398
|
+
|
|
399
|
+
// ❌ Bad: Ref type mismatch
|
|
400
|
+
const divRef = useRef<HTMLDivElement>(null);
|
|
401
|
+
<UI as="button" ref={divRef}>Button</UI> // Type error!
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
## Related Components
|
|
405
|
+
|
|
406
|
+
- **FP Component** - Alternative polymorphic primitive
|
|
407
|
+
- **Button** - Interactive button component built with UI
|
|
408
|
+
- **Badge** - Small label component built with UI
|
|
409
|
+
- **Tag** - Dismissible tag component built with UI
|
|
410
|
+
- **Heading** - Semantic heading component built with UI
|
|
411
|
+
|
|
412
|
+
## See Also
|
|
413
|
+
|
|
414
|
+
- [React Polymorphic Components](https://www.benmvp.com/blog/polymorphic-react-components-typescript/)
|
|
415
|
+
- [TypeScript Advanced Types](https://www.typescriptlang.org/docs/handbook/2/types-from-types.html)
|
|
416
|
+
- [React forwardRef](https://react.dev/reference/react/forwardRef)
|