@verdify/ui 0.1.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/LICENSE +12 -0
- package/README.md +117 -0
- package/dist/components/accordion/accordion.d.ts +66 -0
- package/dist/components/accordion/accordion.d.ts.map +1 -0
- package/dist/components/accordion/accordion.js +97 -0
- package/dist/components/accordion/accordion.js.map +1 -0
- package/dist/components/accordion/accordion.variants.d.ts +9 -0
- package/dist/components/accordion/accordion.variants.d.ts.map +1 -0
- package/dist/components/accordion/accordion.variants.js +54 -0
- package/dist/components/accordion/accordion.variants.js.map +1 -0
- package/dist/components/accordion/index.d.ts +3 -0
- package/dist/components/accordion/index.d.ts.map +1 -0
- package/dist/components/accordion/index.js +25 -0
- package/dist/components/accordion/index.js.map +1 -0
- package/dist/components/agent-badge/agent-badge.d.ts +56 -0
- package/dist/components/agent-badge/agent-badge.d.ts.map +1 -0
- package/dist/components/agent-badge/agent-badge.js +35 -0
- package/dist/components/agent-badge/agent-badge.js.map +1 -0
- package/dist/components/agent-badge/agent-badge.variants.d.ts +7 -0
- package/dist/components/agent-badge/agent-badge.variants.d.ts.map +1 -0
- package/dist/components/agent-badge/agent-badge.variants.js +35 -0
- package/dist/components/agent-badge/agent-badge.variants.js.map +1 -0
- package/dist/components/agent-badge/index.d.ts +3 -0
- package/dist/components/agent-badge/index.d.ts.map +1 -0
- package/dist/components/agent-badge/index.js +11 -0
- package/dist/components/agent-badge/index.js.map +1 -0
- package/dist/components/alert/alert.d.ts +94 -0
- package/dist/components/alert/alert.d.ts.map +1 -0
- package/dist/components/alert/alert.js +105 -0
- package/dist/components/alert/alert.js.map +1 -0
- package/dist/components/alert/alert.variants.d.ts +15 -0
- package/dist/components/alert/alert.variants.d.ts.map +1 -0
- package/dist/components/alert/alert.variants.js +74 -0
- package/dist/components/alert/alert.variants.js.map +1 -0
- package/dist/components/alert/index.d.ts +3 -0
- package/dist/components/alert/index.d.ts.map +1 -0
- package/dist/components/alert/index.js +37 -0
- package/dist/components/alert/index.js.map +1 -0
- package/dist/components/avatar/avatar.d.ts +56 -0
- package/dist/components/avatar/avatar.d.ts.map +1 -0
- package/dist/components/avatar/avatar.js +107 -0
- package/dist/components/avatar/avatar.js.map +1 -0
- package/dist/components/avatar/avatar.variants.d.ts +11 -0
- package/dist/components/avatar/avatar.variants.d.ts.map +1 -0
- package/dist/components/avatar/avatar.variants.js +48 -0
- package/dist/components/avatar/avatar.variants.js.map +1 -0
- package/dist/components/avatar/index.d.ts +3 -0
- package/dist/components/avatar/index.d.ts.map +1 -0
- package/dist/components/avatar/index.js +15 -0
- package/dist/components/avatar/index.js.map +1 -0
- package/dist/components/badge/badge.d.ts +30 -0
- package/dist/components/badge/badge.d.ts.map +1 -0
- package/dist/components/badge/badge.js +33 -0
- package/dist/components/badge/badge.js.map +1 -0
- package/dist/components/badge/badge.variants.d.ts +7 -0
- package/dist/components/badge/badge.variants.d.ts.map +1 -0
- package/dist/components/badge/badge.variants.js +33 -0
- package/dist/components/badge/badge.variants.js.map +1 -0
- package/dist/components/badge/index.d.ts +3 -0
- package/dist/components/badge/index.d.ts.map +1 -0
- package/dist/components/badge/index.js +8 -0
- package/dist/components/badge/index.js.map +1 -0
- package/dist/components/breadcrumb/breadcrumb.d.ts +90 -0
- package/dist/components/breadcrumb/breadcrumb.d.ts.map +1 -0
- package/dist/components/breadcrumb/breadcrumb.js +143 -0
- package/dist/components/breadcrumb/breadcrumb.js.map +1 -0
- package/dist/components/breadcrumb/breadcrumb.variants.d.ts +10 -0
- package/dist/components/breadcrumb/breadcrumb.variants.d.ts.map +1 -0
- package/dist/components/breadcrumb/breadcrumb.variants.js +41 -0
- package/dist/components/breadcrumb/breadcrumb.variants.js.map +1 -0
- package/dist/components/breadcrumb/index.d.ts +3 -0
- package/dist/components/breadcrumb/index.d.ts.map +1 -0
- package/dist/components/breadcrumb/index.js +35 -0
- package/dist/components/breadcrumb/index.js.map +1 -0
- package/dist/components/button/button.d.ts +10 -0
- package/dist/components/button/button.d.ts.map +1 -0
- package/dist/components/button/button.js +42 -0
- package/dist/components/button/button.js.map +1 -0
- package/dist/components/button/button.variants.d.ts +6 -0
- package/dist/components/button/button.variants.d.ts.map +1 -0
- package/dist/components/button/button.variants.js +45 -0
- package/dist/components/button/button.variants.js.map +1 -0
- package/dist/components/button/index.d.ts +3 -0
- package/dist/components/button/index.d.ts.map +1 -0
- package/dist/components/button/index.js +7 -0
- package/dist/components/button/index.js.map +1 -0
- package/dist/components/card/card.d.ts +59 -0
- package/dist/components/card/card.d.ts.map +1 -0
- package/dist/components/card/card.js +101 -0
- package/dist/components/card/card.js.map +1 -0
- package/dist/components/card/card.variants.d.ts +13 -0
- package/dist/components/card/card.variants.d.ts.map +1 -0
- package/dist/components/card/card.variants.js +64 -0
- package/dist/components/card/card.variants.js.map +1 -0
- package/dist/components/card/index.d.ts +3 -0
- package/dist/components/card/index.d.ts.map +1 -0
- package/dist/components/card/index.js +35 -0
- package/dist/components/card/index.js.map +1 -0
- package/dist/components/checkbox/checkbox.d.ts +20 -0
- package/dist/components/checkbox/checkbox.d.ts.map +1 -0
- package/dist/components/checkbox/checkbox.js +102 -0
- package/dist/components/checkbox/checkbox.js.map +1 -0
- package/dist/components/checkbox/checkbox.variants.d.ts +15 -0
- package/dist/components/checkbox/checkbox.variants.d.ts.map +1 -0
- package/dist/components/checkbox/checkbox.variants.js +70 -0
- package/dist/components/checkbox/checkbox.variants.js.map +1 -0
- package/dist/components/checkbox/index.d.ts +3 -0
- package/dist/components/checkbox/index.d.ts.map +1 -0
- package/dist/components/checkbox/index.js +11 -0
- package/dist/components/checkbox/index.js.map +1 -0
- package/dist/components/command-palette/command-palette.d.ts +76 -0
- package/dist/components/command-palette/command-palette.d.ts.map +1 -0
- package/dist/components/command-palette/command-palette.js +271 -0
- package/dist/components/command-palette/command-palette.js.map +1 -0
- package/dist/components/command-palette/command-palette.variants.d.ts +18 -0
- package/dist/components/command-palette/command-palette.variants.d.ts.map +1 -0
- package/dist/components/command-palette/command-palette.variants.js +62 -0
- package/dist/components/command-palette/command-palette.variants.js.map +1 -0
- package/dist/components/command-palette/index.d.ts +3 -0
- package/dist/components/command-palette/index.d.ts.map +1 -0
- package/dist/components/command-palette/index.js +35 -0
- package/dist/components/command-palette/index.js.map +1 -0
- package/dist/components/consent-toggle/consent-toggle.d.ts +107 -0
- package/dist/components/consent-toggle/consent-toggle.d.ts.map +1 -0
- package/dist/components/consent-toggle/consent-toggle.js +68 -0
- package/dist/components/consent-toggle/consent-toggle.js.map +1 -0
- package/dist/components/consent-toggle/consent-toggle.variants.d.ts +10 -0
- package/dist/components/consent-toggle/consent-toggle.variants.d.ts.map +1 -0
- package/dist/components/consent-toggle/consent-toggle.variants.js +29 -0
- package/dist/components/consent-toggle/consent-toggle.variants.js.map +1 -0
- package/dist/components/consent-toggle/index.d.ts +3 -0
- package/dist/components/consent-toggle/index.d.ts.map +1 -0
- package/dist/components/consent-toggle/index.js +19 -0
- package/dist/components/consent-toggle/index.js.map +1 -0
- package/dist/components/credential-card/credential-card.d.ts +144 -0
- package/dist/components/credential-card/credential-card.d.ts.map +1 -0
- package/dist/components/credential-card/credential-card.js +117 -0
- package/dist/components/credential-card/credential-card.js.map +1 -0
- package/dist/components/credential-card/credential-card.variants.d.ts +15 -0
- package/dist/components/credential-card/credential-card.variants.d.ts.map +1 -0
- package/dist/components/credential-card/credential-card.variants.js +48 -0
- package/dist/components/credential-card/credential-card.variants.js.map +1 -0
- package/dist/components/credential-card/index.d.ts +3 -0
- package/dist/components/credential-card/index.d.ts.map +1 -0
- package/dist/components/credential-card/index.js +29 -0
- package/dist/components/credential-card/index.js.map +1 -0
- package/dist/components/data-grid/data-grid.d.ts +247 -0
- package/dist/components/data-grid/data-grid.d.ts.map +1 -0
- package/dist/components/data-grid/data-grid.js +529 -0
- package/dist/components/data-grid/data-grid.js.map +1 -0
- package/dist/components/data-grid/data-grid.variants.d.ts +29 -0
- package/dist/components/data-grid/data-grid.variants.d.ts.map +1 -0
- package/dist/components/data-grid/data-grid.variants.js +110 -0
- package/dist/components/data-grid/data-grid.variants.js.map +1 -0
- package/dist/components/data-grid/index.d.ts +3 -0
- package/dist/components/data-grid/index.d.ts.map +1 -0
- package/dist/components/data-grid/index.js +59 -0
- package/dist/components/data-grid/index.js.map +1 -0
- package/dist/components/dialog/dialog.d.ts +98 -0
- package/dist/components/dialog/dialog.d.ts.map +1 -0
- package/dist/components/dialog/dialog.js +121 -0
- package/dist/components/dialog/dialog.js.map +1 -0
- package/dist/components/dialog/dialog.variants.d.ts +14 -0
- package/dist/components/dialog/dialog.variants.d.ts.map +1 -0
- package/dist/components/dialog/dialog.variants.js +71 -0
- package/dist/components/dialog/dialog.variants.js.map +1 -0
- package/dist/components/dialog/index.d.ts +3 -0
- package/dist/components/dialog/index.d.ts.map +1 -0
- package/dist/components/dialog/index.js +31 -0
- package/dist/components/dialog/index.js.map +1 -0
- package/dist/components/identity-chip/identity-chip.d.ts +121 -0
- package/dist/components/identity-chip/identity-chip.d.ts.map +1 -0
- package/dist/components/identity-chip/identity-chip.js +203 -0
- package/dist/components/identity-chip/identity-chip.js.map +1 -0
- package/dist/components/identity-chip/identity-chip.variants.d.ts +11 -0
- package/dist/components/identity-chip/identity-chip.variants.d.ts.map +1 -0
- package/dist/components/identity-chip/identity-chip.variants.js +61 -0
- package/dist/components/identity-chip/identity-chip.variants.js.map +1 -0
- package/dist/components/identity-chip/index.d.ts +3 -0
- package/dist/components/identity-chip/index.d.ts.map +1 -0
- package/dist/components/identity-chip/index.js +21 -0
- package/dist/components/identity-chip/index.js.map +1 -0
- package/dist/components/input/index.d.ts +3 -0
- package/dist/components/input/index.d.ts.map +1 -0
- package/dist/components/input/index.js +11 -0
- package/dist/components/input/index.js.map +1 -0
- package/dist/components/input/input.d.ts +17 -0
- package/dist/components/input/input.d.ts.map +1 -0
- package/dist/components/input/input.js +71 -0
- package/dist/components/input/input.js.map +1 -0
- package/dist/components/input/input.variants.d.ts +11 -0
- package/dist/components/input/input.variants.d.ts.map +1 -0
- package/dist/components/input/input.variants.js +64 -0
- package/dist/components/input/input.variants.js.map +1 -0
- package/dist/components/label/index.d.ts +3 -0
- package/dist/components/label/index.d.ts.map +1 -0
- package/dist/components/label/index.js +13 -0
- package/dist/components/label/index.js.map +1 -0
- package/dist/components/label/label.d.ts +16 -0
- package/dist/components/label/label.d.ts.map +1 -0
- package/dist/components/label/label.js +27 -0
- package/dist/components/label/label.js.map +1 -0
- package/dist/components/label/label.variants.d.ts +8 -0
- package/dist/components/label/label.variants.d.ts.map +1 -0
- package/dist/components/label/label.variants.js +27 -0
- package/dist/components/label/label.variants.js.map +1 -0
- package/dist/components/menu/index.d.ts +3 -0
- package/dist/components/menu/index.d.ts.map +1 -0
- package/dist/components/menu/index.js +43 -0
- package/dist/components/menu/index.js.map +1 -0
- package/dist/components/menu/menu.d.ts +115 -0
- package/dist/components/menu/menu.d.ts.map +1 -0
- package/dist/components/menu/menu.js +130 -0
- package/dist/components/menu/menu.js.map +1 -0
- package/dist/components/menu/menu.variants.d.ts +13 -0
- package/dist/components/menu/menu.variants.d.ts.map +1 -0
- package/dist/components/menu/menu.variants.js +56 -0
- package/dist/components/menu/menu.variants.js.map +1 -0
- package/dist/components/pagination/index.d.ts +3 -0
- package/dist/components/pagination/index.d.ts.map +1 -0
- package/dist/components/pagination/index.js +37 -0
- package/dist/components/pagination/index.js.map +1 -0
- package/dist/components/pagination/pagination.d.ts +118 -0
- package/dist/components/pagination/pagination.d.ts.map +1 -0
- package/dist/components/pagination/pagination.js +204 -0
- package/dist/components/pagination/pagination.js.map +1 -0
- package/dist/components/pagination/pagination.variants.d.ts +13 -0
- package/dist/components/pagination/pagination.variants.d.ts.map +1 -0
- package/dist/components/pagination/pagination.variants.js +63 -0
- package/dist/components/pagination/pagination.variants.js.map +1 -0
- package/dist/components/popover/index.d.ts +3 -0
- package/dist/components/popover/index.d.ts.map +1 -0
- package/dist/components/popover/index.js +39 -0
- package/dist/components/popover/index.js.map +1 -0
- package/dist/components/popover/popover.d.ts +92 -0
- package/dist/components/popover/popover.d.ts.map +1 -0
- package/dist/components/popover/popover.js +135 -0
- package/dist/components/popover/popover.js.map +1 -0
- package/dist/components/popover/popover.variants.d.ts +9 -0
- package/dist/components/popover/popover.variants.d.ts.map +1 -0
- package/dist/components/popover/popover.variants.js +19 -0
- package/dist/components/popover/popover.variants.js.map +1 -0
- package/dist/components/progress/index.d.ts +3 -0
- package/dist/components/progress/index.d.ts.map +1 -0
- package/dist/components/progress/index.js +23 -0
- package/dist/components/progress/index.js.map +1 -0
- package/dist/components/progress/progress.d.ts +71 -0
- package/dist/components/progress/progress.d.ts.map +1 -0
- package/dist/components/progress/progress.js +91 -0
- package/dist/components/progress/progress.js.map +1 -0
- package/dist/components/progress/progress.variants.d.ts +14 -0
- package/dist/components/progress/progress.variants.d.ts.map +1 -0
- package/dist/components/progress/progress.variants.js +37 -0
- package/dist/components/progress/progress.variants.js.map +1 -0
- package/dist/components/radio/index.d.ts +3 -0
- package/dist/components/radio/index.d.ts.map +1 -0
- package/dist/components/radio/index.js +22 -0
- package/dist/components/radio/index.js.map +1 -0
- package/dist/components/radio/radio.d.ts +23 -0
- package/dist/components/radio/radio.d.ts.map +1 -0
- package/dist/components/radio/radio.js +183 -0
- package/dist/components/radio/radio.js.map +1 -0
- package/dist/components/radio/radio.variants.d.ts +17 -0
- package/dist/components/radio/radio.variants.d.ts.map +1 -0
- package/dist/components/radio/radio.variants.js +60 -0
- package/dist/components/radio/radio.variants.js.map +1 -0
- package/dist/components/select/index.d.ts +3 -0
- package/dist/components/select/index.d.ts.map +1 -0
- package/dist/components/select/index.js +9 -0
- package/dist/components/select/index.js.map +1 -0
- package/dist/components/select/select.d.ts +27 -0
- package/dist/components/select/select.d.ts.map +1 -0
- package/dist/components/select/select.js +145 -0
- package/dist/components/select/select.js.map +1 -0
- package/dist/components/select/select.variants.d.ts +18 -0
- package/dist/components/select/select.variants.d.ts.map +1 -0
- package/dist/components/select/select.variants.js +102 -0
- package/dist/components/select/select.variants.js.map +1 -0
- package/dist/components/separator/index.d.ts +3 -0
- package/dist/components/separator/index.d.ts.map +1 -0
- package/dist/components/separator/index.js +15 -0
- package/dist/components/separator/index.js.map +1 -0
- package/dist/components/separator/separator.d.ts +23 -0
- package/dist/components/separator/separator.d.ts.map +1 -0
- package/dist/components/separator/separator.js +61 -0
- package/dist/components/separator/separator.js.map +1 -0
- package/dist/components/separator/separator.variants.d.ts +13 -0
- package/dist/components/separator/separator.variants.d.ts.map +1 -0
- package/dist/components/separator/separator.variants.js +46 -0
- package/dist/components/separator/separator.variants.js.map +1 -0
- package/dist/components/sheet/index.d.ts +3 -0
- package/dist/components/sheet/index.d.ts.map +1 -0
- package/dist/components/sheet/index.js +31 -0
- package/dist/components/sheet/index.js.map +1 -0
- package/dist/components/sheet/sheet.d.ts +102 -0
- package/dist/components/sheet/sheet.d.ts.map +1 -0
- package/dist/components/sheet/sheet.js +120 -0
- package/dist/components/sheet/sheet.js.map +1 -0
- package/dist/components/sheet/sheet.variants.d.ts +15 -0
- package/dist/components/sheet/sheet.variants.d.ts.map +1 -0
- package/dist/components/sheet/sheet.variants.js +97 -0
- package/dist/components/sheet/sheet.variants.js.map +1 -0
- package/dist/components/sidebar/index.d.ts +3 -0
- package/dist/components/sidebar/index.d.ts.map +1 -0
- package/dist/components/sidebar/index.js +43 -0
- package/dist/components/sidebar/index.js.map +1 -0
- package/dist/components/sidebar/sidebar.d.ts +114 -0
- package/dist/components/sidebar/sidebar.d.ts.map +1 -0
- package/dist/components/sidebar/sidebar.js +202 -0
- package/dist/components/sidebar/sidebar.js.map +1 -0
- package/dist/components/sidebar/sidebar.variants.d.ts +19 -0
- package/dist/components/sidebar/sidebar.variants.d.ts.map +1 -0
- package/dist/components/sidebar/sidebar.variants.js +93 -0
- package/dist/components/sidebar/sidebar.variants.js.map +1 -0
- package/dist/components/skeleton/index.d.ts +3 -0
- package/dist/components/skeleton/index.d.ts.map +1 -0
- package/dist/components/skeleton/index.js +15 -0
- package/dist/components/skeleton/index.js.map +1 -0
- package/dist/components/skeleton/skeleton.d.ts +42 -0
- package/dist/components/skeleton/skeleton.d.ts.map +1 -0
- package/dist/components/skeleton/skeleton.js +54 -0
- package/dist/components/skeleton/skeleton.js.map +1 -0
- package/dist/components/skeleton/skeleton.variants.d.ts +9 -0
- package/dist/components/skeleton/skeleton.variants.d.ts.map +1 -0
- package/dist/components/skeleton/skeleton.variants.js +31 -0
- package/dist/components/skeleton/skeleton.variants.js.map +1 -0
- package/dist/components/spinner/index.d.ts +3 -0
- package/dist/components/spinner/index.d.ts.map +1 -0
- package/dist/components/spinner/index.js +13 -0
- package/dist/components/spinner/index.js.map +1 -0
- package/dist/components/spinner/spinner.d.ts +41 -0
- package/dist/components/spinner/spinner.d.ts.map +1 -0
- package/dist/components/spinner/spinner.js +48 -0
- package/dist/components/spinner/spinner.js.map +1 -0
- package/dist/components/spinner/spinner.variants.d.ts +8 -0
- package/dist/components/spinner/spinner.variants.d.ts.map +1 -0
- package/dist/components/spinner/spinner.variants.js +32 -0
- package/dist/components/spinner/spinner.variants.js.map +1 -0
- package/dist/components/switch/index.d.ts +3 -0
- package/dist/components/switch/index.d.ts.map +1 -0
- package/dist/components/switch/index.js +15 -0
- package/dist/components/switch/index.js.map +1 -0
- package/dist/components/switch/switch.d.ts +20 -0
- package/dist/components/switch/switch.d.ts.map +1 -0
- package/dist/components/switch/switch.js +107 -0
- package/dist/components/switch/switch.js.map +1 -0
- package/dist/components/switch/switch.variants.d.ts +14 -0
- package/dist/components/switch/switch.variants.d.ts.map +1 -0
- package/dist/components/switch/switch.variants.js +69 -0
- package/dist/components/switch/switch.variants.js.map +1 -0
- package/dist/components/table/index.d.ts +3 -0
- package/dist/components/table/index.d.ts.map +1 -0
- package/dist/components/table/index.js +51 -0
- package/dist/components/table/index.js.map +1 -0
- package/dist/components/table/table.d.ts +173 -0
- package/dist/components/table/table.d.ts.map +1 -0
- package/dist/components/table/table.js +172 -0
- package/dist/components/table/table.js.map +1 -0
- package/dist/components/table/table.variants.d.ts +39 -0
- package/dist/components/table/table.variants.d.ts.map +1 -0
- package/dist/components/table/table.variants.js +124 -0
- package/dist/components/table/table.variants.js.map +1 -0
- package/dist/components/tabs/index.d.ts +3 -0
- package/dist/components/tabs/index.d.ts.map +1 -0
- package/dist/components/tabs/index.js +21 -0
- package/dist/components/tabs/index.js.map +1 -0
- package/dist/components/tabs/tabs.d.ts +66 -0
- package/dist/components/tabs/tabs.d.ts.map +1 -0
- package/dist/components/tabs/tabs.js +81 -0
- package/dist/components/tabs/tabs.js.map +1 -0
- package/dist/components/tabs/tabs.variants.d.ts +15 -0
- package/dist/components/tabs/tabs.variants.d.ts.map +1 -0
- package/dist/components/tabs/tabs.variants.js +98 -0
- package/dist/components/tabs/tabs.variants.js.map +1 -0
- package/dist/components/textarea/index.d.ts +3 -0
- package/dist/components/textarea/index.d.ts.map +1 -0
- package/dist/components/textarea/index.js +7 -0
- package/dist/components/textarea/index.js.map +1 -0
- package/dist/components/textarea/textarea.d.ts +18 -0
- package/dist/components/textarea/textarea.d.ts.map +1 -0
- package/dist/components/textarea/textarea.js +136 -0
- package/dist/components/textarea/textarea.js.map +1 -0
- package/dist/components/textarea/textarea.variants.d.ts +6 -0
- package/dist/components/textarea/textarea.variants.d.ts.map +1 -0
- package/dist/components/textarea/textarea.variants.js +53 -0
- package/dist/components/textarea/textarea.variants.js.map +1 -0
- package/dist/components/toast/index.d.ts +3 -0
- package/dist/components/toast/index.d.ts.map +1 -0
- package/dist/components/toast/index.js +43 -0
- package/dist/components/toast/index.js.map +1 -0
- package/dist/components/toast/toast.d.ts +140 -0
- package/dist/components/toast/toast.d.ts.map +1 -0
- package/dist/components/toast/toast.js +123 -0
- package/dist/components/toast/toast.js.map +1 -0
- package/dist/components/toast/toast.variants.d.ts +16 -0
- package/dist/components/toast/toast.variants.d.ts.map +1 -0
- package/dist/components/toast/toast.variants.js +77 -0
- package/dist/components/toast/toast.variants.js.map +1 -0
- package/dist/components/tooltip/index.d.ts +3 -0
- package/dist/components/tooltip/index.d.ts.map +1 -0
- package/dist/components/tooltip/index.js +16 -0
- package/dist/components/tooltip/index.js.map +1 -0
- package/dist/components/tooltip/tooltip.d.ts +81 -0
- package/dist/components/tooltip/tooltip.d.ts.map +1 -0
- package/dist/components/tooltip/tooltip.js +44 -0
- package/dist/components/tooltip/tooltip.js.map +1 -0
- package/dist/components/tooltip/tooltip.variants.d.ts +3 -0
- package/dist/components/tooltip/tooltip.variants.d.ts.map +1 -0
- package/dist/components/tooltip/tooltip.variants.js +7 -0
- package/dist/components/tooltip/tooltip.variants.js.map +1 -0
- package/dist/components/trust-score/index.d.ts +3 -0
- package/dist/components/trust-score/index.d.ts.map +1 -0
- package/dist/components/trust-score/index.js +11 -0
- package/dist/components/trust-score/index.js.map +1 -0
- package/dist/components/trust-score/trust-score.d.ts +100 -0
- package/dist/components/trust-score/trust-score.d.ts.map +1 -0
- package/dist/components/trust-score/trust-score.js +146 -0
- package/dist/components/trust-score/trust-score.js.map +1 -0
- package/dist/components/trust-score/trust-score.variants.d.ts +16 -0
- package/dist/components/trust-score/trust-score.variants.d.ts.map +1 -0
- package/dist/components/trust-score/trust-score.variants.js +50 -0
- package/dist/components/trust-score/trust-score.variants.js.map +1 -0
- package/dist/components/verified-badge/index.d.ts +3 -0
- package/dist/components/verified-badge/index.d.ts.map +1 -0
- package/dist/components/verified-badge/index.js +15 -0
- package/dist/components/verified-badge/index.js.map +1 -0
- package/dist/components/verified-badge/verified-badge.d.ts +55 -0
- package/dist/components/verified-badge/verified-badge.d.ts.map +1 -0
- package/dist/components/verified-badge/verified-badge.js +67 -0
- package/dist/components/verified-badge/verified-badge.js.map +1 -0
- package/dist/components/verified-badge/verified-badge.variants.d.ts +11 -0
- package/dist/components/verified-badge/verified-badge.variants.d.ts.map +1 -0
- package/dist/components/verified-badge/verified-badge.variants.js +45 -0
- package/dist/components/verified-badge/verified-badge.variants.js.map +1 -0
- package/dist/index.d.ts +39 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +322 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/cn.d.ts +3 -0
- package/dist/lib/cn.d.ts.map +1 -0
- package/dist/lib/cn.js +24 -0
- package/dist/lib/cn.js.map +1 -0
- package/package.json +74 -0
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import { Slot } from "radix-ui";
|
|
5
|
+
import { cn } from "../../lib/cn";
|
|
6
|
+
import {
|
|
7
|
+
sidebarRailVariants,
|
|
8
|
+
sidebarHeaderClass,
|
|
9
|
+
sidebarGroupClass,
|
|
10
|
+
sidebarGroupLabelClass,
|
|
11
|
+
sidebarListClass,
|
|
12
|
+
sidebarItemVariants,
|
|
13
|
+
sidebarItemIconClass,
|
|
14
|
+
sidebarItemLabelClass,
|
|
15
|
+
sidebarItemTrailingClass,
|
|
16
|
+
sidebarFooterClass,
|
|
17
|
+
sidebarCollapseToggleClass,
|
|
18
|
+
sidebarCollapseIconClass
|
|
19
|
+
} from "./sidebar.variants";
|
|
20
|
+
const SidebarContext = React.createContext(null);
|
|
21
|
+
function useSidebar() {
|
|
22
|
+
const ctx = React.useContext(SidebarContext);
|
|
23
|
+
if (!ctx) {
|
|
24
|
+
throw new Error("Sidebar slots must be rendered inside <Sidebar>.");
|
|
25
|
+
}
|
|
26
|
+
return ctx;
|
|
27
|
+
}
|
|
28
|
+
const Sidebar = React.forwardRef(function Sidebar2({ className, side = "inline-start", defaultCollapsed = false, collapsed: collapsedProp, onCollapsedChange, children, ...props }, ref) {
|
|
29
|
+
const isControlled = collapsedProp !== void 0;
|
|
30
|
+
const [uncontrolled, setUncontrolled] = React.useState(defaultCollapsed);
|
|
31
|
+
const collapsed = isControlled ? collapsedProp : uncontrolled;
|
|
32
|
+
const toggle = React.useCallback(() => {
|
|
33
|
+
const next = !collapsed;
|
|
34
|
+
if (!isControlled) setUncontrolled(next);
|
|
35
|
+
onCollapsedChange?.(next);
|
|
36
|
+
}, [collapsed, isControlled, onCollapsedChange]);
|
|
37
|
+
const registry = React.useRef(/* @__PURE__ */ new Set());
|
|
38
|
+
const register = React.useCallback((entry) => {
|
|
39
|
+
registry.current.add(entry);
|
|
40
|
+
return () => {
|
|
41
|
+
registry.current.delete(entry);
|
|
42
|
+
};
|
|
43
|
+
}, []);
|
|
44
|
+
const order = React.useCallback(() => {
|
|
45
|
+
return Array.from(registry.current).filter((e) => !e.disabled).map((e) => e.el).sort(
|
|
46
|
+
(a, b) => a.compareDocumentPosition(b) & Node.DOCUMENT_POSITION_FOLLOWING ? -1 : 1
|
|
47
|
+
);
|
|
48
|
+
}, []);
|
|
49
|
+
const ctx = React.useMemo(
|
|
50
|
+
() => ({ side, collapsed, toggle, register, order }),
|
|
51
|
+
[side, collapsed, toggle, register, order]
|
|
52
|
+
);
|
|
53
|
+
const onKeyDown = (event) => {
|
|
54
|
+
const items = order();
|
|
55
|
+
if (items.length === 0) return;
|
|
56
|
+
const active = document.activeElement;
|
|
57
|
+
const currentIndex = active ? items.indexOf(active) : -1;
|
|
58
|
+
switch (event.key) {
|
|
59
|
+
case "ArrowDown": {
|
|
60
|
+
event.preventDefault();
|
|
61
|
+
const next = currentIndex < 0 ? 0 : (currentIndex + 1) % items.length;
|
|
62
|
+
items[next]?.focus();
|
|
63
|
+
break;
|
|
64
|
+
}
|
|
65
|
+
case "ArrowUp": {
|
|
66
|
+
event.preventDefault();
|
|
67
|
+
const prev = currentIndex < 0 ? items.length - 1 : (currentIndex - 1 + items.length) % items.length;
|
|
68
|
+
items[prev]?.focus();
|
|
69
|
+
break;
|
|
70
|
+
}
|
|
71
|
+
case "Home": {
|
|
72
|
+
event.preventDefault();
|
|
73
|
+
items[0]?.focus();
|
|
74
|
+
break;
|
|
75
|
+
}
|
|
76
|
+
case "End": {
|
|
77
|
+
event.preventDefault();
|
|
78
|
+
items[items.length - 1]?.focus();
|
|
79
|
+
break;
|
|
80
|
+
}
|
|
81
|
+
// Space on a focused item follows the link without scrolling the rail (spec §6). It is
|
|
82
|
+
// ignored on the toggle here — the toggle handles its own Space (native button activation).
|
|
83
|
+
case " ": {
|
|
84
|
+
if (active?.dataset.sidebarItem === "true") {
|
|
85
|
+
event.preventDefault();
|
|
86
|
+
active.click();
|
|
87
|
+
}
|
|
88
|
+
break;
|
|
89
|
+
}
|
|
90
|
+
default:
|
|
91
|
+
break;
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
return /* @__PURE__ */ jsx(SidebarContext.Provider, { value: ctx, children: /* @__PURE__ */ jsx(
|
|
95
|
+
"nav",
|
|
96
|
+
{
|
|
97
|
+
ref,
|
|
98
|
+
"data-collapsed": collapsed || void 0,
|
|
99
|
+
className: cn(sidebarRailVariants({ side }), className),
|
|
100
|
+
onKeyDown,
|
|
101
|
+
...props,
|
|
102
|
+
children
|
|
103
|
+
}
|
|
104
|
+
) });
|
|
105
|
+
});
|
|
106
|
+
const SidebarHeader = React.forwardRef(
|
|
107
|
+
function SidebarHeader2({ className, ...props }, ref) {
|
|
108
|
+
return /* @__PURE__ */ jsx("div", { ref, className: cn(sidebarHeaderClass, className), ...props });
|
|
109
|
+
}
|
|
110
|
+
);
|
|
111
|
+
const SidebarGroup = React.forwardRef(
|
|
112
|
+
function SidebarGroup2({ className, label, children, ...props }, ref) {
|
|
113
|
+
const { collapsed } = useSidebar();
|
|
114
|
+
const headingId = React.useId();
|
|
115
|
+
return /* @__PURE__ */ jsxs(
|
|
116
|
+
"div",
|
|
117
|
+
{
|
|
118
|
+
ref,
|
|
119
|
+
role: "group",
|
|
120
|
+
"aria-labelledby": label ? headingId : void 0,
|
|
121
|
+
className: cn(sidebarGroupClass, className),
|
|
122
|
+
...props,
|
|
123
|
+
children: [
|
|
124
|
+
label ? /* @__PURE__ */ jsx("div", { id: headingId, className: cn(sidebarGroupLabelClass, collapsed && "sr-only"), children: label }) : null,
|
|
125
|
+
/* @__PURE__ */ jsx("ul", { className: sidebarListClass, children })
|
|
126
|
+
]
|
|
127
|
+
}
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
);
|
|
131
|
+
const SidebarItem = React.forwardRef(function SidebarItem2({ className, icon, trailing, children, current = false, disabled = false, asChild = false, href, ...props }, ref) {
|
|
132
|
+
const { collapsed, register } = useSidebar();
|
|
133
|
+
const innerRef = React.useRef(null);
|
|
134
|
+
React.useImperativeHandle(ref, () => innerRef.current);
|
|
135
|
+
React.useEffect(() => {
|
|
136
|
+
const el = innerRef.current;
|
|
137
|
+
if (!el) return;
|
|
138
|
+
return register({ el, disabled });
|
|
139
|
+
}, [register, disabled]);
|
|
140
|
+
const Comp = asChild ? Slot.Root : "a";
|
|
141
|
+
return /* @__PURE__ */ jsx("li", { children: /* @__PURE__ */ jsxs(
|
|
142
|
+
Comp,
|
|
143
|
+
{
|
|
144
|
+
ref: innerRef,
|
|
145
|
+
"aria-current": current ? "page" : void 0,
|
|
146
|
+
href: disabled ? void 0 : href,
|
|
147
|
+
"aria-disabled": disabled || void 0,
|
|
148
|
+
tabIndex: disabled ? -1 : void 0,
|
|
149
|
+
"data-sidebar-item": "true",
|
|
150
|
+
className: cn(sidebarItemVariants(), className),
|
|
151
|
+
...props,
|
|
152
|
+
children: [
|
|
153
|
+
icon ? /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: sidebarItemIconClass, children: icon }) : null,
|
|
154
|
+
/* @__PURE__ */ jsx("span", { className: cn(sidebarItemLabelClass, collapsed && "sr-only"), children }),
|
|
155
|
+
trailing && !collapsed ? /* @__PURE__ */ jsx("span", { className: sidebarItemTrailingClass, children: trailing }) : null
|
|
156
|
+
]
|
|
157
|
+
}
|
|
158
|
+
) });
|
|
159
|
+
});
|
|
160
|
+
const SidebarFooter = React.forwardRef(
|
|
161
|
+
function SidebarFooter2({ className, children, ...props }, ref) {
|
|
162
|
+
return /* @__PURE__ */ jsx("div", { ref, className: cn(sidebarFooterClass, className), ...props, children: /* @__PURE__ */ jsx("ul", { className: sidebarListClass, children }) });
|
|
163
|
+
}
|
|
164
|
+
);
|
|
165
|
+
const SidebarCollapseToggle = React.forwardRef(
|
|
166
|
+
function SidebarCollapseToggle2({ className, collapseLabel = "Collapse sidebar", expandLabel = "Expand sidebar", ...props }, ref) {
|
|
167
|
+
const { collapsed, toggle } = useSidebar();
|
|
168
|
+
return /* @__PURE__ */ jsx(
|
|
169
|
+
"button",
|
|
170
|
+
{
|
|
171
|
+
ref,
|
|
172
|
+
type: "button",
|
|
173
|
+
"aria-expanded": !collapsed,
|
|
174
|
+
"aria-label": collapsed ? expandLabel : collapseLabel,
|
|
175
|
+
onClick: toggle,
|
|
176
|
+
className: cn(sidebarCollapseToggleClass(), className),
|
|
177
|
+
...props,
|
|
178
|
+
children: /* @__PURE__ */ jsx(ChevronIcon, { collapsed })
|
|
179
|
+
}
|
|
180
|
+
);
|
|
181
|
+
}
|
|
182
|
+
);
|
|
183
|
+
function ChevronIcon({ collapsed }) {
|
|
184
|
+
return /* @__PURE__ */ jsx(
|
|
185
|
+
"span",
|
|
186
|
+
{
|
|
187
|
+
"data-testid": "sidebar-collapse-icon",
|
|
188
|
+
"aria-hidden": "true",
|
|
189
|
+
className: cn(sidebarCollapseIconClass, collapsed && "rotate-180"),
|
|
190
|
+
children: /* @__PURE__ */ jsx("svg", { viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", "aria-hidden": "true", focusable: "false", children: /* @__PURE__ */ jsx("path", { d: "M10 4L6 8l4 4", strokeLinecap: "round", strokeLinejoin: "round" }) })
|
|
191
|
+
}
|
|
192
|
+
);
|
|
193
|
+
}
|
|
194
|
+
export {
|
|
195
|
+
Sidebar,
|
|
196
|
+
SidebarCollapseToggle,
|
|
197
|
+
SidebarFooter,
|
|
198
|
+
SidebarGroup,
|
|
199
|
+
SidebarHeader,
|
|
200
|
+
SidebarItem
|
|
201
|
+
};
|
|
202
|
+
//# sourceMappingURL=sidebar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/sidebar/sidebar.tsx"],"sourcesContent":["\"use client\";\n\nimport * as React from \"react\";\nimport { Slot } from \"radix-ui\";\nimport { cn } from \"../../lib/cn\";\nimport {\n sidebarRailVariants,\n sidebarHeaderClass,\n sidebarGroupClass,\n sidebarGroupLabelClass,\n sidebarListClass,\n sidebarItemVariants,\n sidebarItemIconClass,\n sidebarItemLabelClass,\n sidebarItemTrailingClass,\n sidebarFooterClass,\n sidebarCollapseToggleClass,\n sidebarCollapseIconClass,\n type SidebarRailVariantProps,\n} from \"./sidebar.variants\";\n\ntype SidebarSide = NonNullable<SidebarRailVariantProps[\"side\"]>;\n\n// The rail context carries the presentation/state axes set ONCE on the root down to every slot\n// (mirrors the Tabs/Sheet root-context precedent): the docked `side`, the live `collapsed` state\n// (so an item can visually hide its label while keeping it in the a11y tree), and the toggle's\n// handler. Items also register their DOM ref here so the rail can run roving arrow-key focus over\n// the ENABLED items in DOM order — the spec §6 keyboard model has no Radix primitive to lean on\n// (it is a list of native <a> links), so it is hand-composed here, the same way Separator's labeled\n// anatomy is hand-rolled when no primitive expresses the spec.\ntype SidebarRegistration = { el: HTMLElement; disabled: boolean };\ntype SidebarContextValue = {\n side: SidebarSide;\n collapsed: boolean;\n toggle: () => void;\n register: (entry: SidebarRegistration) => () => void;\n order: () => HTMLElement[];\n};\nconst SidebarContext = React.createContext<SidebarContextValue | null>(null);\n\nfunction useSidebar(): SidebarContextValue {\n const ctx = React.useContext(SidebarContext);\n if (!ctx) {\n throw new Error(\"Sidebar slots must be rendered inside <Sidebar>.\");\n }\n return ctx;\n}\n\nexport interface SidebarProps extends Omit<React.ComponentPropsWithoutRef<\"nav\">, \"onChange\"> {\n /** The docked edge (spec §3). `inline-start` (default) or `inline-end` — logical, mirrors under RTL. */\n side?: SidebarSide;\n /**\n * The rail starts collapsed when uncontrolled (spec §3 `collapsed`): a narrow rail of icons only.\n * For a controlled rail set `collapsed` + `onCollapsedChange` instead.\n */\n defaultCollapsed?: boolean;\n /** Controlled collapsed state (spec §3). When set, the rail is controlled — pair with `onCollapsedChange`. */\n collapsed?: boolean;\n /** Notified when the collapse-toggle flips the rail width (spec §3/§4). */\n onCollapsedChange?: (collapsed: boolean) => void;\n /**\n * The landmark's accessible name (spec §7), so multiple `navigation` landmarks on a page are\n * distinguishable — for example \"Primary\". Use `aria-labelledby` pointing at a visible heading\n * (e.g. the `SidebarHeader`) instead when the rail has a visible title.\n */\n \"aria-label\"?: string;\n}\n\n/**\n * A Sidebar is the primary navigation rail down one edge of an app shell: it lists the destinations\n * a person or an agent moves between and marks where they are now (spec §1). It is the `navigation`\n * landmark wrapping a list of real `<a href>` links. Reach for a Menu for a short transient list of\n * actions, Tabs when panels are peers within one page, and Breadcrumb for depth within a destination.\n *\n * The rail is a NEUTRAL surface — it does not wear the brand (spec §3): the current item takes the\n * primary ACTION accent (where you are), never a status color; a verified meaning belongs to\n * VerifiedBadge, never to a navigation item (brand != state). On narrow/touch viewports the rail\n * leaves the layout and opens as a modal drawer — use the Sheet `side=inline-start` pattern\n * (./sheet.md) for that; this component covers the DOCKED rail.\n *\n * It owns the collapse state and the roving arrow-key focus over its items, so it is `'use client'`.\n */\nexport const Sidebar = React.forwardRef<HTMLElement, SidebarProps>(function Sidebar(\n { className, side = \"inline-start\", defaultCollapsed = false, collapsed: collapsedProp, onCollapsedChange, children, ...props },\n ref,\n) {\n const isControlled = collapsedProp !== undefined;\n const [uncontrolled, setUncontrolled] = React.useState(defaultCollapsed);\n const collapsed = isControlled ? collapsedProp : uncontrolled;\n\n const toggle = React.useCallback(() => {\n const next = !collapsed;\n if (!isControlled) setUncontrolled(next);\n onCollapsedChange?.(next);\n }, [collapsed, isControlled, onCollapsedChange]);\n\n // Items register their live DOM ref + disabled flag here; `order()` returns the enabled items in\n // current DOM order so the arrow-key handler can move focus and wrap at the ends (spec §6).\n const registry = React.useRef<Set<SidebarRegistration>>(new Set());\n const register = React.useCallback((entry: SidebarRegistration) => {\n registry.current.add(entry);\n return () => {\n registry.current.delete(entry);\n };\n }, []);\n const order = React.useCallback(() => {\n return Array.from(registry.current)\n .filter((e) => !e.disabled)\n .map((e) => e.el)\n // sort by DOM order so footer items follow group items regardless of registration order\n .sort((a, b) =>\n a.compareDocumentPosition(b) & Node.DOCUMENT_POSITION_FOLLOWING ? -1 : 1,\n );\n }, []);\n\n const ctx = React.useMemo<SidebarContextValue>(\n () => ({ side, collapsed, toggle, register, order }),\n [side, collapsed, toggle, register, order],\n );\n\n // Down/Up move to the next/previous ENABLED item, wrapping; Home/End jump to the first/last\n // enabled item. Disabled items are not registered as targets, so they are skipped for free. The\n // rail never moves focus on its own — only on the user's keypress (spec §6/§7). Enter follows the\n // focused link (native); Space on an item follows it without scrolling the rail (preventDefault).\n const onKeyDown = (event: React.KeyboardEvent<HTMLElement>) => {\n const items = order();\n if (items.length === 0) return;\n const active = document.activeElement as HTMLElement | null;\n const currentIndex = active ? items.indexOf(active) : -1;\n switch (event.key) {\n case \"ArrowDown\": {\n event.preventDefault();\n const next = currentIndex < 0 ? 0 : (currentIndex + 1) % items.length;\n items[next]?.focus();\n break;\n }\n case \"ArrowUp\": {\n event.preventDefault();\n const prev = currentIndex < 0 ? items.length - 1 : (currentIndex - 1 + items.length) % items.length;\n items[prev]?.focus();\n break;\n }\n case \"Home\": {\n event.preventDefault();\n items[0]?.focus();\n break;\n }\n case \"End\": {\n event.preventDefault();\n items[items.length - 1]?.focus();\n break;\n }\n // Space on a focused item follows the link without scrolling the rail (spec §6). It is\n // ignored on the toggle here — the toggle handles its own Space (native button activation).\n case \" \": {\n if (active?.dataset.sidebarItem === \"true\") {\n event.preventDefault();\n active.click();\n }\n break;\n }\n default:\n break;\n }\n };\n\n return (\n <SidebarContext.Provider value={ctx}>\n {/* the navigation landmark, named so a screen reader can jump to and skip the rail (spec §7) */}\n {/* The rail WIDTH is a layout concern the app sets via `className` (the token set has no\n sidebar-width scale, and a rail's width is shell-specific) — the component exposes the\n collapsed state via `data-collapsed` and the `transition-[width]` base motion so the\n caller animates between its own two widths. The collapsed rail hides labels (icons only)\n through each slot's `sr-only`, independent of the exact width. */}\n <nav\n ref={ref}\n data-collapsed={collapsed || undefined}\n className={cn(sidebarRailVariants({ side }), className)}\n onKeyDown={onKeyDown}\n {...props}\n >\n {children}\n </nav>\n </SidebarContext.Provider>\n );\n});\n\nexport type SidebarHeaderProps = React.ComponentPropsWithoutRef<\"div\">;\n\n/**\n * The top slot for a product mark or workspace switcher (spec §2). It is NOT a navigation item and\n * is skipped by item arrow movement. Give it an `id` and point the rail's `aria-labelledby` at it to\n * name the landmark from a visible heading.\n */\nexport const SidebarHeader = React.forwardRef<HTMLDivElement, SidebarHeaderProps>(\n function SidebarHeader({ className, ...props }, ref) {\n return <div ref={ref} className={cn(sidebarHeaderClass, className)} {...props} />;\n },\n);\n\nexport interface SidebarGroupProps extends React.ComponentPropsWithoutRef<\"div\"> {\n /** The cluster's visible heading (spec §2 group). It also names the group for assistive tech. */\n label?: React.ReactNode;\n}\n\n/**\n * A labeled cluster of items (spec §2 group). Use groups only when the labels earn their space;\n * restraint over volume keeps the rail scannable. The heading names the group via `aria-labelledby`,\n * so its items read as a related set (1.3.1 Info and Relationships). The items live in a `<ul>` so\n * they expose the list relationship. In the collapsed rail the heading is hidden (icons only) but the\n * group keeps its accessible name.\n */\nexport const SidebarGroup = React.forwardRef<HTMLDivElement, SidebarGroupProps>(\n function SidebarGroup({ className, label, children, ...props }, ref) {\n const { collapsed } = useSidebar();\n const headingId = React.useId();\n return (\n <div\n ref={ref}\n role=\"group\"\n aria-labelledby={label ? headingId : undefined}\n className={cn(sidebarGroupClass, className)}\n {...props}\n >\n {label ? (\n <div id={headingId} className={cn(sidebarGroupLabelClass, collapsed && \"sr-only\")}>\n {label}\n </div>\n ) : null}\n <ul className={sidebarListClass}>{children}</ul>\n </div>\n );\n },\n);\n\nexport interface SidebarItemProps extends Omit<React.ComponentPropsWithoutRef<\"a\">, \"color\"> {\n /** The destination (spec §7). Items are real links; omit it only on a disabled item. */\n href?: string;\n /** The leading icon (spec §2): decorative, sized by `--size-icon-md`. The item names itself by its label text. */\n icon?: React.ReactNode;\n /** A trailing count or status (spec §2): text or an `aria-label`, never color alone (spec §7). */\n trailing?: React.ReactNode;\n /**\n * This is the item for the page you are on (spec §4 Current). It sets `aria-current=\"page\"`, lifts\n * its label to the primary text color, and shows the brand action indicator bar — where you are,\n * never a status color. Exactly one item in the rail is current.\n */\n current?: boolean;\n /**\n * The item is present but not operable (spec §4 Disabled): it is skipped by arrow movement and the\n * tab order and drops its `href`, while its label stays readable to assistive technology.\n */\n disabled?: boolean;\n /**\n * Project the item styling onto a caller-supplied anchor (a framework router `<Link>` rendered as an\n * `<a>`) via Radix Slot, instead of the default native `<a>` (spec §2). Slot runs\n * `React.Children.only` — pass exactly one anchor child holding the icon + label.\n */\n asChild?: boolean;\n}\n\n/**\n * One navigation item (spec §2 item, §4 states): a native `<a href>` link holding a leading icon, a\n * label, and an optional trailing count or status. It exposes the link role and is operable without\n * extra wiring; it gets the visible focus ring, the restrained ghost hover fill, and the target-size\n * floor. The current item is a link, not a button — it still navigates (spec §7). In the collapsed\n * rail the label is visually hidden but kept in the accessibility tree, so the item never loses its\n * accessible name (spec §4 Collapsed / §7).\n */\nexport const SidebarItem = React.forwardRef<HTMLAnchorElement, SidebarItemProps>(function SidebarItem(\n { className, icon, trailing, children, current = false, disabled = false, asChild = false, href, ...props },\n ref,\n) {\n const { collapsed, register } = useSidebar();\n const innerRef = React.useRef<HTMLAnchorElement | null>(null);\n React.useImperativeHandle(ref, () => innerRef.current as HTMLAnchorElement);\n\n // register this item with the rail (for roving arrow-key focus) while it is mounted; a disabled\n // item registers as disabled so the rail skips it as a target (spec §6).\n React.useEffect(() => {\n const el = innerRef.current;\n if (!el) return;\n return register({ el, disabled });\n }, [register, disabled]);\n\n const Comp = asChild ? Slot.Root : \"a\";\n return (\n <li>\n <Comp\n ref={innerRef}\n // the only item carrying aria-current; exactly one per rail (spec §4/§7)\n aria-current={current ? \"page\" : undefined}\n // a disabled item drops its href (cannot navigate), leaves the tab order, and is marked\n // aria-disabled so AT still reads its label (spec §4/§7); an <a> has no native disabled\n href={disabled ? undefined : href}\n aria-disabled={disabled || undefined}\n tabIndex={disabled ? -1 : undefined}\n data-sidebar-item=\"true\"\n className={cn(sidebarItemVariants(), className)}\n {...props}\n >\n {icon ? (\n <span aria-hidden=\"true\" className={sidebarItemIconClass}>\n {icon}\n </span>\n ) : null}\n {/* the label stays in the a11y tree when collapsed (sr-only), so the link keeps its name\n without depending on a tooltip being open (spec §4 Collapsed / §7) */}\n <span className={cn(sidebarItemLabelClass, collapsed && \"sr-only\")}>{children}</span>\n {trailing && !collapsed ? <span className={sidebarItemTrailingClass}>{trailing}</span> : null}\n </Comp>\n </li>\n );\n});\n\nexport type SidebarFooterProps = React.ComponentPropsWithoutRef<\"div\">;\n\n/**\n * A bottom slot for an account or settings entry (spec §2). Its items follow the same item rules as\n * the rest of the list and join the rail's roving arrow-key order. Wrap its items in a `<ul>` so they\n * keep the list relationship.\n */\nexport const SidebarFooter = React.forwardRef<HTMLDivElement, SidebarFooterProps>(\n function SidebarFooter({ className, children, ...props }, ref) {\n return (\n <div ref={ref} className={cn(sidebarFooterClass, className)} {...props}>\n <ul className={sidebarListClass}>{children}</ul>\n </div>\n );\n },\n);\n\nexport interface SidebarCollapseToggleProps\n extends Omit<React.ComponentPropsWithoutRef<\"button\">, \"onClick\" | \"children\"> {\n /** The accessible name when expanded (icon-only). Defaults to \"Collapse sidebar\" (spec §7). */\n collapseLabel?: string;\n /** The accessible name when collapsed (icon-only). Defaults to \"Expand sidebar\" (spec §7). */\n expandLabel?: string;\n}\n\n/**\n * The control that switches the rail between expanded and collapsed (spec §2/§4/§6/§7). It is a\n * native `<button>`, NOT an item, reachable in the rail's tab order. It sets `aria-expanded` to\n * reflect the rail width and names its action with `aria-label` (\"Collapse sidebar\" / \"Expand\n * sidebar\"); its glyph is `aria-hidden`. Toggling it does not move focus off the toggle, so a\n * keyboard user keeps their place when switching the rail's width (spec §6). Render it only on a\n * collapsible rail.\n */\nexport const SidebarCollapseToggle = React.forwardRef<HTMLButtonElement, SidebarCollapseToggleProps>(\n function SidebarCollapseToggle(\n { className, collapseLabel = \"Collapse sidebar\", expandLabel = \"Expand sidebar\", ...props },\n ref,\n ) {\n const { collapsed, toggle } = useSidebar();\n return (\n <button\n ref={ref}\n type=\"button\"\n // aria-expanded reflects the rail width; the action is named for the icon-only control (spec §7)\n aria-expanded={!collapsed}\n aria-label={collapsed ? expandLabel : collapseLabel}\n onClick={toggle}\n className={cn(sidebarCollapseToggleClass(), className)}\n {...props}\n >\n <ChevronIcon collapsed={collapsed} />\n </button>\n );\n },\n);\n\n// The toggle glyph — inline SVG (no icon dep), --size-icon-md, rotates to mirror the rail width.\n// Decorative: aria-hidden; aria-expanded carries the state, not the glyph (spec §2/§7).\nfunction ChevronIcon({ collapsed }: { collapsed: boolean }) {\n return (\n <span\n data-testid=\"sidebar-collapse-icon\"\n aria-hidden=\"true\"\n className={cn(sidebarCollapseIconClass, collapsed && \"rotate-180\")}\n >\n <svg viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\" aria-hidden=\"true\" focusable=\"false\">\n <path d=\"M10 4L6 8l4 4\" strokeLinecap=\"round\" strokeLinejoin=\"round\" />\n </svg>\n </span>\n );\n}\n"],"mappings":"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","names":["Sidebar","SidebarHeader","SidebarGroup","SidebarItem","SidebarFooter","SidebarCollapseToggle"]}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type VariantProps } from "class-variance-authority";
|
|
2
|
+
export declare const sidebarRailVariants: (props?: ({
|
|
3
|
+
side?: "inline-end" | "inline-start" | null | undefined;
|
|
4
|
+
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
5
|
+
export type SidebarRailVariantProps = VariantProps<typeof sidebarRailVariants>;
|
|
6
|
+
export declare const sidebarHeaderClass = "flex items-center gap-(--space-2) px-(--space-2) py-(--space-2) border-b border-surface-border-muted";
|
|
7
|
+
export declare const sidebarGroupClass = "flex flex-col gap-(--space-1) py-(--space-2)";
|
|
8
|
+
export declare const sidebarGroupLabelClass = "px-(--space-2) py-(--space-1) text-caption text-text-muted select-none";
|
|
9
|
+
export declare const sidebarListClass = "flex flex-col gap-(--space-1) m-0 p-0 list-none";
|
|
10
|
+
export declare const sidebarItemVariants: (props?: ({} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
11
|
+
export type SidebarItemVariantProps = VariantProps<typeof sidebarItemVariants>;
|
|
12
|
+
export declare const sidebarItemIconClass = "inline-flex h-(--size-icon-md) w-(--size-icon-md) shrink-0 items-center justify-center text-action-ghost-fg";
|
|
13
|
+
export declare const sidebarItemLabelClass = "min-w-0 flex-1 truncate";
|
|
14
|
+
export declare const sidebarItemTrailingClass = "ms-auto inline-flex items-center text-caption text-text-secondary";
|
|
15
|
+
export declare const sidebarFooterClass = "mt-auto flex flex-col gap-(--space-1) pt-(--space-2) border-t border-surface-border-muted";
|
|
16
|
+
export declare const sidebarCollapseToggleClass: (props?: ({} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
17
|
+
export type SidebarCollapseToggleVariantProps = VariantProps<typeof sidebarCollapseToggleClass>;
|
|
18
|
+
export declare const sidebarCollapseIconClass = "inline-flex h-(--size-icon-md) w-(--size-icon-md) shrink-0 items-center justify-center transition-transform duration-(--motion-duration-base) ease-(--motion-easing-verdify) motion-reduce:duration-(--motion-duration-instant)";
|
|
19
|
+
//# sourceMappingURL=sidebar.variants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sidebar.variants.d.ts","sourceRoot":"","sources":["../../../src/components/sidebar/sidebar.variants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAgBlE,eAAO,MAAM,mBAAmB;;8EAsB/B,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG,YAAY,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAK/E,eAAO,MAAM,kBAAkB,yGACyE,CAAC;AAIzG,eAAO,MAAM,iBAAiB,iDAAiD,CAAC;AAIhF,eAAO,MAAM,sBAAsB,2EACuC,CAAC;AAI3E,eAAO,MAAM,gBAAgB,oDAAoD,CAAC;AAsBlF,eAAO,MAAM,mBAAmB,2FA8B/B,CAAC;AAEF,MAAM,MAAM,uBAAuB,GAAG,YAAY,CAAC,OAAO,mBAAmB,CAAC,CAAC;AAM/E,eAAO,MAAM,oBAAoB,gHAC8E,CAAC;AAKhH,eAAO,MAAM,qBAAqB,4BAA4B,CAAC;AAI/D,eAAO,MAAM,wBAAwB,sEACgC,CAAC;AAItE,eAAO,MAAM,kBAAkB,8FAC8D,CAAC;AAM9F,eAAO,MAAM,0BAA0B,2FAatC,CAAC;AAEF,MAAM,MAAM,iCAAiC,GAAG,YAAY,CAAC,OAAO,0BAA0B,CAAC,CAAC;AAIhG,eAAO,MAAM,wBAAwB,oOAC8L,CAAC"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { cva } from "class-variance-authority";
|
|
2
|
+
const sidebarRailVariants = cva(
|
|
3
|
+
[
|
|
4
|
+
// surface + elevation + column layout with the rail insets
|
|
5
|
+
"flex flex-col gap-(--space-2) bg-surface-raised shadow-sm",
|
|
6
|
+
"p-(--space-2)",
|
|
7
|
+
// the expand/collapse width transition — base duration + verdify easing, instant under
|
|
8
|
+
// reduced motion (NEVER the deliberate verified-check theatre, G-U3)
|
|
9
|
+
"transition-[width] duration-(--motion-duration-base) ease-(--motion-easing-verdify)",
|
|
10
|
+
"motion-reduce:duration-(--motion-duration-instant)"
|
|
11
|
+
],
|
|
12
|
+
{
|
|
13
|
+
variants: {
|
|
14
|
+
// SIDE axis (spec §3): the rail docks at a logical edge and carries its border on the edge
|
|
15
|
+
// that faces the content area — inline-end when docked inline-start, inline-start when docked
|
|
16
|
+
// inline-end. Logical properties only (border-e / border-s), so it mirrors under dir="rtl".
|
|
17
|
+
side: {
|
|
18
|
+
"inline-start": "border-e border-surface-border",
|
|
19
|
+
"inline-end": "border-s border-surface-border"
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
defaultVariants: { side: "inline-start" }
|
|
23
|
+
}
|
|
24
|
+
);
|
|
25
|
+
const sidebarHeaderClass = "flex items-center gap-(--space-2) px-(--space-2) py-(--space-2) border-b border-surface-border-muted";
|
|
26
|
+
const sidebarGroupClass = "flex flex-col gap-(--space-1) py-(--space-2)";
|
|
27
|
+
const sidebarGroupLabelClass = "px-(--space-2) py-(--space-1) text-caption text-text-muted select-none";
|
|
28
|
+
const sidebarListClass = "flex flex-col gap-(--space-1) m-0 p-0 list-none";
|
|
29
|
+
const sidebarItemVariants = cva(
|
|
30
|
+
[
|
|
31
|
+
// shape + the icon-to-label gap + logical inline padding so it mirrors under RTL; the leading
|
|
32
|
+
// indicator bar is a left/start accent rendered via a logical inline-start border that is
|
|
33
|
+
// transparent at rest and painted in the action alias when current
|
|
34
|
+
"relative flex items-center gap-(--space-3) rounded-(--radius-md) px-(--space-3)",
|
|
35
|
+
"border-s-2 border-transparent",
|
|
36
|
+
// type ROLE + resting label color, no fill, pointer cursor
|
|
37
|
+
"text-label text-text-secondary no-underline cursor-pointer select-none",
|
|
38
|
+
// hover: the restrained ghost-action fill (the only fill a resting item paints)
|
|
39
|
+
"hover:bg-action-ghost-bg-hover",
|
|
40
|
+
// CURRENT: the leading indicator BAR is painted in the brand action alias and the label lifts to
|
|
41
|
+
// the primary text color. This is the action(primary) alias (where you are), NEVER status-verified
|
|
42
|
+
// (brand != state, G-U2). The indicator bar SHAPE + aria-current carry the state alongside the
|
|
43
|
+
// color, so it survives a color-blind read; the rail itself stays a neutral surface (no brand fill).
|
|
44
|
+
"aria-[current=page]:border-s-action-primary-bg aria-[current=page]:text-text-primary",
|
|
45
|
+
// motion: fast + verdify easing, instant under reduced motion (NEVER the check theatre, G-U3)
|
|
46
|
+
"transition-[color,background-color,border-color] duration-(--motion-duration-fast) ease-(--motion-easing-verdify)",
|
|
47
|
+
"motion-reduce:duration-(--motion-duration-instant)",
|
|
48
|
+
// target-size floor — 44px touch / 40px pointer, on every item (spec §7, 2.5.8), never a fixed
|
|
49
|
+
// height below the floor
|
|
50
|
+
"min-h-(--size-target-mobile) sm:min-h-(--size-target-desktop)",
|
|
51
|
+
// focus ring — identical on every state, never removed; persists expanded and collapsed
|
|
52
|
+
"outline-none",
|
|
53
|
+
"focus-visible:ring-2 focus-visible:ring-border-focus focus-visible:ring-offset-2",
|
|
54
|
+
// disabled (non-operable) item — DEC-C: dim via the disabled TOKEN, never opacity. aria-disabled
|
|
55
|
+
// drives it because an <a> has no native disabled; the component also strips href + tabindex.
|
|
56
|
+
"aria-disabled:pointer-events-none aria-disabled:text-text-disabled"
|
|
57
|
+
],
|
|
58
|
+
{ variants: {}, defaultVariants: {} }
|
|
59
|
+
);
|
|
60
|
+
const sidebarItemIconClass = "inline-flex h-(--size-icon-md) w-(--size-icon-md) shrink-0 items-center justify-center text-action-ghost-fg";
|
|
61
|
+
const sidebarItemLabelClass = "min-w-0 flex-1 truncate";
|
|
62
|
+
const sidebarItemTrailingClass = "ms-auto inline-flex items-center text-caption text-text-secondary";
|
|
63
|
+
const sidebarFooterClass = "mt-auto flex flex-col gap-(--space-1) pt-(--space-2) border-t border-surface-border-muted";
|
|
64
|
+
const sidebarCollapseToggleClass = cva(
|
|
65
|
+
[
|
|
66
|
+
"inline-flex items-center justify-center gap-(--space-2) rounded-(--radius-md) px-(--space-2)",
|
|
67
|
+
"text-action-ghost-fg cursor-pointer select-none",
|
|
68
|
+
"hover:bg-action-ghost-bg-hover",
|
|
69
|
+
"transition-[color,background-color] duration-(--motion-duration-fast) ease-(--motion-easing-verdify)",
|
|
70
|
+
"motion-reduce:duration-(--motion-duration-instant)",
|
|
71
|
+
"min-h-(--size-target-mobile) sm:min-h-(--size-target-desktop)",
|
|
72
|
+
"outline-none",
|
|
73
|
+
"focus-visible:ring-2 focus-visible:ring-border-focus focus-visible:ring-offset-2",
|
|
74
|
+
"disabled:pointer-events-none disabled:text-text-disabled"
|
|
75
|
+
],
|
|
76
|
+
{ variants: {}, defaultVariants: {} }
|
|
77
|
+
);
|
|
78
|
+
const sidebarCollapseIconClass = "inline-flex h-(--size-icon-md) w-(--size-icon-md) shrink-0 items-center justify-center transition-transform duration-(--motion-duration-base) ease-(--motion-easing-verdify) motion-reduce:duration-(--motion-duration-instant)";
|
|
79
|
+
export {
|
|
80
|
+
sidebarCollapseIconClass,
|
|
81
|
+
sidebarCollapseToggleClass,
|
|
82
|
+
sidebarFooterClass,
|
|
83
|
+
sidebarGroupClass,
|
|
84
|
+
sidebarGroupLabelClass,
|
|
85
|
+
sidebarHeaderClass,
|
|
86
|
+
sidebarItemIconClass,
|
|
87
|
+
sidebarItemLabelClass,
|
|
88
|
+
sidebarItemTrailingClass,
|
|
89
|
+
sidebarItemVariants,
|
|
90
|
+
sidebarListClass,
|
|
91
|
+
sidebarRailVariants
|
|
92
|
+
};
|
|
93
|
+
//# sourceMappingURL=sidebar.variants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/sidebar/sidebar.variants.ts"],"sourcesContent":["import { cva, type VariantProps } from \"class-variance-authority\";\n\n// A Sidebar is the primary navigation rail down one edge of an app shell (spec §1). It is a\n// NEUTRAL surface (spec §3): the rail does not wear the brand. The only accent is on the CURRENT\n// item, which takes the primary ACTION (brand) alias — where you are — never a status color: a\n// current item reports your location, not a verification result, so it binds nothing from the\n// status tier (brand != state, G-U2). A verified meaning belongs to VerifiedBadge. The rail\n// paints from the surface, text, action(primary + ghost), and border aliases only (spec §5).\n\n// The nav landmark wrapping the rail. The raised neutral surface against the page canvas, an edge\n// against the content area (a logical inline-end border when docked inline-start, inline-start when\n// docked inline-end — G-U6, so it mirrors under dir=\"rtl\"), the sm elevation where it floats above\n// content, and the expand/collapse WIDTH transition. Motion is the BASE token transition on the\n// verdify easing, collapsing to the instant endpoint under reduced motion — never the 350ms\n// VerifiedBadge-only theatre duration (toggling the rail is a plain transition, not theatre — spec\n// §4 Collapsed, G-U3). The rail is NEVER tinted with the brand or a status fill (spec §3/§8).\nexport const sidebarRailVariants = cva(\n [\n // surface + elevation + column layout with the rail insets\n \"flex flex-col gap-(--space-2) bg-surface-raised shadow-sm\",\n \"p-(--space-2)\",\n // the expand/collapse width transition — base duration + verdify easing, instant under\n // reduced motion (NEVER the deliberate verified-check theatre, G-U3)\n \"transition-[width] duration-(--motion-duration-base) ease-(--motion-easing-verdify)\",\n \"motion-reduce:duration-(--motion-duration-instant)\",\n ],\n {\n variants: {\n // SIDE axis (spec §3): the rail docks at a logical edge and carries its border on the edge\n // that faces the content area — inline-end when docked inline-start, inline-start when docked\n // inline-end. Logical properties only (border-e / border-s), so it mirrors under dir=\"rtl\".\n side: {\n \"inline-start\": \"border-e border-surface-border\",\n \"inline-end\": \"border-s border-surface-border\",\n },\n },\n defaultVariants: { side: \"inline-start\" },\n },\n);\n\nexport type SidebarRailVariantProps = VariantProps<typeof sidebarRailVariants>;\n\n// The header slot (spec §2): the top slot for a product mark or workspace switcher. It is NOT a\n// navigation item and is skipped by item arrow movement. A separator from the list below it via a\n// muted hairline (spec §5, surface-border-muted). Plain structural slot — no variant axis.\nexport const sidebarHeaderClass =\n \"flex items-center gap-(--space-2) px-(--space-2) py-(--space-2) border-b border-surface-border-muted\";\n\n// A labeled cluster of items (spec §2 group). Restraint over volume keeps the rail scannable, so a\n// group is plain structure; its dividers use the muted hairline (spec §5). No variant axis.\nexport const sidebarGroupClass = \"flex flex-col gap-(--space-1) py-(--space-2)\";\n\n// The group heading (spec §2/§5): the cluster label in the MUTED text color at the CAPTION type\n// role. Decorative-weight wayfinding, not a navigation item.\nexport const sidebarGroupLabelClass =\n \"px-(--space-2) py-(--space-1) text-caption text-text-muted select-none\";\n\n// The item list (the <ul>): a flush column of items. The list carries no text color — each item\n// sets its own. The roving arrow-key handler is wired by the component on this element.\nexport const sidebarListClass = \"flex flex-col gap-(--space-1) m-0 p-0 list-none\";\n\n// One navigation item (spec §2 item, §4 states). A native <a href> link.\n//\n// RESTING (default): the LABEL in the SECONDARY text color and the icon in the GHOST action fg, on\n// the rail surface with NO fill (spec §4 Default).\n// HOVER: a restrained ghost-action hover fill; the cursor is a pointer (spec §4 Hover). The only\n// fill a resting item ever paints.\n// CURRENT (aria-current=page): the leading INDICATOR BAR is painted in the primary ACTION (brand)\n// alias — where you are — and the label lifts to the PRIMARY text color. This spec offers two\n// indicator treatments (spec §5: an indicator \"bar OR fill\"); this component uses the restrained\n// BAR (a logical inline-start border accent) so the rail never wears a brand SURFACE (spec §3/§8).\n// The current state is never carried by color alone: the indicator bar shape AND aria-current also\n// encode it, so it survives a contrast or color-blind reading (spec §4 Current / 1.4.1, brand !=\n// state — NEVER status-verified).\n// FOCUS: the visible 2px focus ring, part of the base on every state, never removed; it persists in\n// both the expanded and collapsed rail (spec §4 Focus / 2.4.7).\n// DISABLED (aria-disabled): dims via the disabled TOKEN (DEC-C), never a blanket opacity; the\n// component also strips href + tabindex and skips it in arrow movement, while the label stays\n// readable to AT (spec §4 Disabled / §7).\n// Motion is the fast token transition on the verdify easing, instant under reduced motion — never\n// the 350ms VerifiedBadge-only theatre duration (G-U3).\nexport const sidebarItemVariants = cva(\n [\n // shape + the icon-to-label gap + logical inline padding so it mirrors under RTL; the leading\n // indicator bar is a left/start accent rendered via a logical inline-start border that is\n // transparent at rest and painted in the action alias when current\n \"relative flex items-center gap-(--space-3) rounded-(--radius-md) px-(--space-3)\",\n \"border-s-2 border-transparent\",\n // type ROLE + resting label color, no fill, pointer cursor\n \"text-label text-text-secondary no-underline cursor-pointer select-none\",\n // hover: the restrained ghost-action fill (the only fill a resting item paints)\n \"hover:bg-action-ghost-bg-hover\",\n // CURRENT: the leading indicator BAR is painted in the brand action alias and the label lifts to\n // the primary text color. This is the action(primary) alias (where you are), NEVER status-verified\n // (brand != state, G-U2). The indicator bar SHAPE + aria-current carry the state alongside the\n // color, so it survives a color-blind read; the rail itself stays a neutral surface (no brand fill).\n \"aria-[current=page]:border-s-action-primary-bg aria-[current=page]:text-text-primary\",\n // motion: fast + verdify easing, instant under reduced motion (NEVER the check theatre, G-U3)\n \"transition-[color,background-color,border-color] duration-(--motion-duration-fast) ease-(--motion-easing-verdify)\",\n \"motion-reduce:duration-(--motion-duration-instant)\",\n // target-size floor — 44px touch / 40px pointer, on every item (spec §7, 2.5.8), never a fixed\n // height below the floor\n \"min-h-(--size-target-mobile) sm:min-h-(--size-target-desktop)\",\n // focus ring — identical on every state, never removed; persists expanded and collapsed\n \"outline-none\",\n \"focus-visible:ring-2 focus-visible:ring-border-focus focus-visible:ring-offset-2\",\n // disabled (non-operable) item — DEC-C: dim via the disabled TOKEN, never opacity. aria-disabled\n // drives it because an <a> has no native disabled; the component also strips href + tabindex.\n \"aria-disabled:pointer-events-none aria-disabled:text-text-disabled\",\n ],\n { variants: {}, defaultVariants: {} },\n);\n\nexport type SidebarItemVariantProps = VariantProps<typeof sidebarItemVariants>;\n\n// The leading item icon (spec §5): the md icon role, decorative (the item names itself by its label\n// text, not the glyph). At rest it is the GHOST action fg; it inherits the disabled token when the\n// item is disabled (aria-disabled on the parent link). When the item is current it lifts with the\n// label to the primary text color. shrink-0 so it never collapses when labels are hidden.\nexport const sidebarItemIconClass =\n \"inline-flex h-(--size-icon-md) w-(--size-icon-md) shrink-0 items-center justify-center text-action-ghost-fg\";\n\n// The item label text (spec §5): the part hidden in the collapsed rail. When collapsed the label is\n// visually hidden but stays in the accessibility tree (sr-only), so the link keeps its accessible\n// name without depending on a tooltip being open (spec §4 Collapsed / §7).\nexport const sidebarItemLabelClass = \"min-w-0 flex-1 truncate\";\n\n// A trailing count or status on an item (spec §2): text or an aria-label, never color alone (spec\n// §7). Plain secondary caption text, hidden with the label when collapsed.\nexport const sidebarItemTrailingClass =\n \"ms-auto inline-flex items-center text-caption text-text-secondary\";\n\n// The footer slot (spec §2): a bottom slot for an account or settings entry; its items follow the\n// same item rules. Pushed to the bottom; separated from the list above by the muted hairline.\nexport const sidebarFooterClass =\n \"mt-auto flex flex-col gap-(--space-1) pt-(--space-2) border-t border-surface-border-muted\";\n\n// The collapse-toggle (spec §2/§4/§6/§7): a native <button>, NOT an item, reachable in the rail's\n// tab order. It carries the ghost-action glyph and the same neutral hover fill, focus ring, and\n// target-size floor as an item. Its glyph is decorative (aria-hidden); aria-expanded + aria-label\n// carry the action. Same fast motion, never the deliberate theatre.\nexport const sidebarCollapseToggleClass = cva(\n [\n \"inline-flex items-center justify-center gap-(--space-2) rounded-(--radius-md) px-(--space-2)\",\n \"text-action-ghost-fg cursor-pointer select-none\",\n \"hover:bg-action-ghost-bg-hover\",\n \"transition-[color,background-color] duration-(--motion-duration-fast) ease-(--motion-easing-verdify)\",\n \"motion-reduce:duration-(--motion-duration-instant)\",\n \"min-h-(--size-target-mobile) sm:min-h-(--size-target-desktop)\",\n \"outline-none\",\n \"focus-visible:ring-2 focus-visible:ring-border-focus focus-visible:ring-offset-2\",\n \"disabled:pointer-events-none disabled:text-text-disabled\",\n ],\n { variants: {}, defaultVariants: {} },\n);\n\nexport type SidebarCollapseToggleVariantProps = VariantProps<typeof sidebarCollapseToggleClass>;\n\n// The collapse-toggle glyph (spec §5): the md icon role, decorative. It rotates to mirror the rail\n// width (collapsed vs expanded) as a reinforcement; aria-expanded carries the state, not the glyph.\nexport const sidebarCollapseIconClass =\n \"inline-flex h-(--size-icon-md) w-(--size-icon-md) shrink-0 items-center justify-center transition-transform duration-(--motion-duration-base) ease-(--motion-easing-verdify) motion-reduce:duration-(--motion-duration-instant)\";\n"],"mappings":"AAAA,SAAS,WAA8B;AAgBhC,MAAM,sBAAsB;AAAA,EACjC;AAAA;AAAA,IAEE;AAAA,IACA;AAAA;AAAA;AAAA,IAGA;AAAA,IACA;AAAA,EACF;AAAA,EACA;AAAA,IACE,UAAU;AAAA;AAAA;AAAA;AAAA,MAIR,MAAM;AAAA,QACJ,gBAAgB;AAAA,QAChB,cAAc;AAAA,MAChB;AAAA,IACF;AAAA,IACA,iBAAiB,EAAE,MAAM,eAAe;AAAA,EAC1C;AACF;AAOO,MAAM,qBACX;AAIK,MAAM,oBAAoB;AAI1B,MAAM,yBACX;AAIK,MAAM,mBAAmB;AAsBzB,MAAM,sBAAsB;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA,IAIE;AAAA,IACA;AAAA;AAAA,IAEA;AAAA;AAAA,IAEA;AAAA;AAAA;AAAA;AAAA;AAAA,IAKA;AAAA;AAAA,IAEA;AAAA,IACA;AAAA;AAAA;AAAA,IAGA;AAAA;AAAA,IAEA;AAAA,IACA;AAAA;AAAA;AAAA,IAGA;AAAA,EACF;AAAA,EACA,EAAE,UAAU,CAAC,GAAG,iBAAiB,CAAC,EAAE;AACtC;AAQO,MAAM,uBACX;AAKK,MAAM,wBAAwB;AAI9B,MAAM,2BACX;AAIK,MAAM,qBACX;AAMK,MAAM,6BAA6B;AAAA,EACxC;AAAA,IACE;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,EAAE,UAAU,CAAC,GAAG,iBAAiB,CAAC,EAAE;AACtC;AAMO,MAAM,2BACX;","names":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/skeleton/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,KAAK,aAAa,EAAE,KAAK,eAAe,EAAE,MAAM,YAAY,CAAC;AAChF,OAAO,EACL,gBAAgB,EAChB,kBAAkB,EAClB,iBAAiB,EACjB,oBAAoB,EACpB,KAAK,oBAAoB,GAC1B,MAAM,qBAAqB,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Skeleton } from "./skeleton";
|
|
2
|
+
import {
|
|
3
|
+
skeletonVariants,
|
|
4
|
+
skeletonShapeClass,
|
|
5
|
+
skeletonLineClass,
|
|
6
|
+
skeletonShimmerClass
|
|
7
|
+
} from "./skeleton.variants";
|
|
8
|
+
export {
|
|
9
|
+
Skeleton,
|
|
10
|
+
skeletonLineClass,
|
|
11
|
+
skeletonShapeClass,
|
|
12
|
+
skeletonShimmerClass,
|
|
13
|
+
skeletonVariants
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/skeleton/index.ts"],"sourcesContent":["export { Skeleton, type SkeletonProps, type SkeletonVariant } from \"./skeleton\";\nexport {\n skeletonVariants,\n skeletonShapeClass,\n skeletonLineClass,\n skeletonShimmerClass,\n type SkeletonVariantProps,\n} from \"./skeleton.variants\";\n"],"mappings":"AAAA,SAAS,gBAA0D;AACnE;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAEK;","names":[]}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import * as React from "react";
|
|
2
|
+
import { type SkeletonVariantProps } from "./skeleton.variants";
|
|
3
|
+
/** The shape of the placeholder (spec §3). Defaults to `text`. */
|
|
4
|
+
export type SkeletonVariant = NonNullable<SkeletonVariantProps["variant"]>;
|
|
5
|
+
export interface SkeletonProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
6
|
+
/**
|
|
7
|
+
* The shape of the placeholder (spec §3) — `text` (default), `block`, `circle`,
|
|
8
|
+
* or `group`. Variant is the footprint of the incoming content, not decoration.
|
|
9
|
+
* Every variant paints from neutral surface roles only; a skeleton is a wait, never
|
|
10
|
+
* the brand color and never a status color.
|
|
11
|
+
*/
|
|
12
|
+
variant?: SkeletonVariant;
|
|
13
|
+
/**
|
|
14
|
+
* For the `text` variant only: how many placeholder lines to stack (spec §2/§3),
|
|
15
|
+
* default `1`. Match the line count to the real content; the last line of a
|
|
16
|
+
* multi-line block is rendered shorter to mirror a real paragraph's ragged final
|
|
17
|
+
* line.
|
|
18
|
+
*/
|
|
19
|
+
lines?: number;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* A Skeleton is a placeholder that holds the SHAPE of content while it loads, so the
|
|
23
|
+
* layout does not jump when the real content arrives (spec §1). Use it for a known,
|
|
24
|
+
* bounded wait — a card, a row, an avatar, a block of text — where you can predict the
|
|
25
|
+
* shape of what is coming.
|
|
26
|
+
*
|
|
27
|
+
* It is a neutral, decorative placeholder. It carries `aria-hidden="true"` so a screen
|
|
28
|
+
* reader skips the placeholder shapes entirely (spec §7); the loading meaning is NOT
|
|
29
|
+
* carried by the skeleton itself. The container the skeleton sits in owns the wait: set
|
|
30
|
+
* `aria-busy="true"` and expose a polite status message ("Loading") on THAT region while
|
|
31
|
+
* loading, then clear it and let the real content's own semantics take over once
|
|
32
|
+
* resolved. Do not put `aria-busy` or a live-region announcement on the skeleton, where
|
|
33
|
+
* it would be ignored.
|
|
34
|
+
*
|
|
35
|
+
* It is non-interactive (spec §4/§6): it takes no focus, binds no keys, is never a tab
|
|
36
|
+
* stop, and renders no focus ring or target-size floor. It never carries the brand color
|
|
37
|
+
* (Sovereign Violet) or a status color (for example Verified Green) — a skeleton is a
|
|
38
|
+
* wait, not a state, and the deliberate verified "check" motion is reserved for the
|
|
39
|
+
* verified moment and never spent on a placeholder (brand != state, spec §1/§3/§8).
|
|
40
|
+
*/
|
|
41
|
+
export declare const Skeleton: React.ForwardRefExoticComponent<SkeletonProps & React.RefAttributes<HTMLDivElement>>;
|
|
42
|
+
//# sourceMappingURL=skeleton.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skeleton.d.ts","sourceRoot":"","sources":["../../../src/components/skeleton/skeleton.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,EAKL,KAAK,oBAAoB,EAC1B,MAAM,qBAAqB,CAAC;AAE7B,kEAAkE;AAClE,MAAM,MAAM,eAAe,GAAG,WAAW,CAAC,oBAAoB,CAAC,SAAS,CAAC,CAAC,CAAC;AAE3E,MAAM,WAAW,aAAc,SAAQ,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC;IACzE;;;;;OAKG;IACH,OAAO,CAAC,EAAE,eAAe,CAAC;IAC1B;;;;;OAKG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAWD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,QAAQ,sFA4CpB,CAAC"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
import { cn } from "../../lib/cn";
|
|
4
|
+
import {
|
|
5
|
+
skeletonVariants,
|
|
6
|
+
skeletonShapeClass,
|
|
7
|
+
skeletonLineClass,
|
|
8
|
+
skeletonShimmerClass
|
|
9
|
+
} from "./skeleton.variants";
|
|
10
|
+
function Shimmer() {
|
|
11
|
+
return /* @__PURE__ */ jsx("span", { "data-testid": "skeleton-shimmer", "aria-hidden": "true", className: skeletonShimmerClass });
|
|
12
|
+
}
|
|
13
|
+
const Skeleton = React.forwardRef(
|
|
14
|
+
function Skeleton2({ className, variant = "text", lines = 1, children, ...props }, ref) {
|
|
15
|
+
const count = Math.max(1, lines);
|
|
16
|
+
return (
|
|
17
|
+
// the skeleton is decorative — aria-hidden so a screen reader skips it entirely;
|
|
18
|
+
// no role, no tabIndex, no live region (spec §7). The wait is announced by the
|
|
19
|
+
// consumer's container, never here.
|
|
20
|
+
/* @__PURE__ */ jsxs(
|
|
21
|
+
"div",
|
|
22
|
+
{
|
|
23
|
+
ref,
|
|
24
|
+
"aria-hidden": "true",
|
|
25
|
+
className: cn(skeletonVariants({ variant }), className),
|
|
26
|
+
...props,
|
|
27
|
+
children: [
|
|
28
|
+
variant === "text" && // a layout column of leaf line-shapes; the last of many is shorter to mirror
|
|
29
|
+
// a real paragraph's ragged final line (spec §2/§3).
|
|
30
|
+
Array.from({ length: count }, (_, i) => /* @__PURE__ */ jsx(
|
|
31
|
+
"span",
|
|
32
|
+
{
|
|
33
|
+
"data-testid": "skeleton-line",
|
|
34
|
+
className: cn(
|
|
35
|
+
skeletonShapeClass,
|
|
36
|
+
skeletonLineClass,
|
|
37
|
+
count > 1 && i === count - 1 ? "w-3/5" : "w-full"
|
|
38
|
+
),
|
|
39
|
+
children: /* @__PURE__ */ jsx(Shimmer, {})
|
|
40
|
+
},
|
|
41
|
+
i
|
|
42
|
+
)),
|
|
43
|
+
(variant === "block" || variant === "circle") && /* @__PURE__ */ jsx("span", { className: cn(skeletonShapeClass, "absolute inset-0 rounded-[inherit]"), children: /* @__PURE__ */ jsx(Shimmer, {}) }),
|
|
44
|
+
variant === "group" && children
|
|
45
|
+
]
|
|
46
|
+
}
|
|
47
|
+
)
|
|
48
|
+
);
|
|
49
|
+
}
|
|
50
|
+
);
|
|
51
|
+
export {
|
|
52
|
+
Skeleton
|
|
53
|
+
};
|
|
54
|
+
//# sourceMappingURL=skeleton.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/skeleton/skeleton.tsx"],"sourcesContent":["import * as React from \"react\";\nimport { cn } from \"../../lib/cn\";\nimport {\n skeletonVariants,\n skeletonShapeClass,\n skeletonLineClass,\n skeletonShimmerClass,\n type SkeletonVariantProps,\n} from \"./skeleton.variants\";\n\n/** The shape of the placeholder (spec §3). Defaults to `text`. */\nexport type SkeletonVariant = NonNullable<SkeletonVariantProps[\"variant\"]>;\n\nexport interface SkeletonProps extends React.HTMLAttributes<HTMLDivElement> {\n /**\n * The shape of the placeholder (spec §3) — `text` (default), `block`, `circle`,\n * or `group`. Variant is the footprint of the incoming content, not decoration.\n * Every variant paints from neutral surface roles only; a skeleton is a wait, never\n * the brand color and never a status color.\n */\n variant?: SkeletonVariant;\n /**\n * For the `text` variant only: how many placeholder lines to stack (spec §2/§3),\n * default `1`. Match the line count to the real content; the last line of a\n * multi-line block is rendered shorter to mirror a real paragraph's ragged final\n * line.\n */\n lines?: number;\n}\n\n/**\n * The decorative shimmer band (spec §2/§4): the lighter raised-surface sweep, read\n * against a leaf shape's input-surface fill, animated on the ambient duration and\n * removed under reduced motion. Always paired with a leaf shape, never on its own.\n */\nfunction Shimmer() {\n return <span data-testid=\"skeleton-shimmer\" aria-hidden=\"true\" className={skeletonShimmerClass} />;\n}\n\n/**\n * A Skeleton is a placeholder that holds the SHAPE of content while it loads, so the\n * layout does not jump when the real content arrives (spec §1). Use it for a known,\n * bounded wait — a card, a row, an avatar, a block of text — where you can predict the\n * shape of what is coming.\n *\n * It is a neutral, decorative placeholder. It carries `aria-hidden=\"true\"` so a screen\n * reader skips the placeholder shapes entirely (spec §7); the loading meaning is NOT\n * carried by the skeleton itself. The container the skeleton sits in owns the wait: set\n * `aria-busy=\"true\"` and expose a polite status message (\"Loading\") on THAT region while\n * loading, then clear it and let the real content's own semantics take over once\n * resolved. Do not put `aria-busy` or a live-region announcement on the skeleton, where\n * it would be ignored.\n *\n * It is non-interactive (spec §4/§6): it takes no focus, binds no keys, is never a tab\n * stop, and renders no focus ring or target-size floor. It never carries the brand color\n * (Sovereign Violet) or a status color (for example Verified Green) — a skeleton is a\n * wait, not a state, and the deliberate verified \"check\" motion is reserved for the\n * verified moment and never spent on a placeholder (brand != state, spec §1/§3/§8).\n */\nexport const Skeleton = React.forwardRef<HTMLDivElement, SkeletonProps>(\n function Skeleton({ className, variant = \"text\", lines = 1, children, ...props }, ref) {\n const count = Math.max(1, lines);\n return (\n // the skeleton is decorative — aria-hidden so a screen reader skips it entirely;\n // no role, no tabIndex, no live region (spec §7). The wait is announced by the\n // consumer's container, never here.\n <div\n ref={ref}\n aria-hidden=\"true\"\n className={cn(skeletonVariants({ variant }), className)}\n {...props}\n >\n {variant === \"text\" &&\n // a layout column of leaf line-shapes; the last of many is shorter to mirror\n // a real paragraph's ragged final line (spec §2/§3).\n Array.from({ length: count }, (_, i) => (\n <span\n key={i}\n data-testid=\"skeleton-line\"\n className={cn(\n skeletonShapeClass,\n skeletonLineClass,\n count > 1 && i === count - 1 ? \"w-3/5\" : \"w-full\",\n )}\n >\n <Shimmer />\n </span>\n ))}\n\n {/* block / circle: the root IS the leaf shape, so the fill + shimmer sit on it.\n The corner radius came from the variant on the root (spec §3/§5). */}\n {(variant === \"block\" || variant === \"circle\") && (\n <span className={cn(skeletonShapeClass, \"absolute inset-0 rounded-[inherit]\")}>\n <Shimmer />\n </span>\n )}\n\n {/* a composed silhouette: pure layout — its children carry the fill + shimmer,\n so the placeholder reads as the thing it replaces (spec §2/§3). */}\n {variant === \"group\" && children}\n </div>\n );\n },\n);\n"],"mappings":"AAoCS,cA8BH,YA9BG;AApCT,YAAY,WAAW;AACvB,SAAS,UAAU;AACnB;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAEK;AA2BP,SAAS,UAAU;AACjB,SAAO,oBAAC,UAAK,eAAY,oBAAmB,eAAY,QAAO,WAAW,sBAAsB;AAClG;AAsBO,MAAM,WAAW,MAAM;AAAA,EAC5B,SAASA,UAAS,EAAE,WAAW,UAAU,QAAQ,QAAQ,GAAG,UAAU,GAAG,MAAM,GAAG,KAAK;AACrF,UAAM,QAAQ,KAAK,IAAI,GAAG,KAAK;AAC/B;AAAA;AAAA;AAAA;AAAA,MAIE;AAAA,QAAC;AAAA;AAAA,UACC;AAAA,UACA,eAAY;AAAA,UACZ,WAAW,GAAG,iBAAiB,EAAE,QAAQ,CAAC,GAAG,SAAS;AAAA,UACrD,GAAG;AAAA,UAEH;AAAA,wBAAY;AAAA;AAAA,YAGX,MAAM,KAAK,EAAE,QAAQ,MAAM,GAAG,CAAC,GAAG,MAChC;AAAA,cAAC;AAAA;AAAA,gBAEC,eAAY;AAAA,gBACZ,WAAW;AAAA,kBACT;AAAA,kBACA;AAAA,kBACA,QAAQ,KAAK,MAAM,QAAQ,IAAI,UAAU;AAAA,gBAC3C;AAAA,gBAEA,8BAAC,WAAQ;AAAA;AAAA,cARJ;AAAA,YASP,CACD;AAAA,aAID,YAAY,WAAW,YAAY,aACnC,oBAAC,UAAK,WAAW,GAAG,oBAAoB,oCAAoC,GAC1E,8BAAC,WAAQ,GACX;AAAA,YAKD,YAAY,WAAW;AAAA;AAAA;AAAA,MAC1B;AAAA;AAAA,EAEJ;AACF;","names":["Skeleton"]}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type VariantProps } from "class-variance-authority";
|
|
2
|
+
export declare const skeletonVariants: (props?: ({
|
|
3
|
+
variant?: "text" | "group" | "circle" | "block" | null | undefined;
|
|
4
|
+
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
5
|
+
export declare const skeletonShapeClass = "relative block overflow-hidden bg-surface-input";
|
|
6
|
+
export declare const skeletonLineClass = "h-(--space-4) rounded-(--radius-sm)";
|
|
7
|
+
export declare const skeletonShimmerClass: string;
|
|
8
|
+
export type SkeletonVariantProps = VariantProps<typeof skeletonVariants>;
|
|
9
|
+
//# sourceMappingURL=skeleton.variants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skeleton.variants.d.ts","sourceRoot":"","sources":["../../../src/components/skeleton/skeleton.variants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAelE,eAAO,MAAM,gBAAgB;;8EAmB3B,CAAC;AAKH,eAAO,MAAM,kBAAkB,oDAAoD,CAAC;AAKpF,eAAO,MAAM,iBAAiB,wCAAwC,CAAC;AAcvE,eAAO,MAAM,oBAAoB,QAGT,CAAC;AAEzB,MAAM,MAAM,oBAAoB,GAAG,YAAY,CAAC,OAAO,gBAAgB,CAAC,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { cva } from "class-variance-authority";
|
|
2
|
+
const skeletonVariants = cva("block", {
|
|
3
|
+
variants: {
|
|
4
|
+
// STRUCTURAL axis = spec §3: the shape of the placeholder, not decoration.
|
|
5
|
+
variant: {
|
|
6
|
+
// one or more placeholder lines for incoming text. The root is a layout column
|
|
7
|
+
// (no fill / no shimmer); each line is a leaf shape at the small corner radius.
|
|
8
|
+
text: "flex flex-col gap-(--space-2)",
|
|
9
|
+
// a rectangular placeholder (image / chart / thumbnail / media). The root IS the
|
|
10
|
+
// leaf shape: input-surface fill + shimmer + the larger corner radius (spec §3/§5).
|
|
11
|
+
block: "rounded-(--radius-md)",
|
|
12
|
+
// a round placeholder for an avatar or icon — full radius (spec §3/§5).
|
|
13
|
+
circle: "rounded-(--radius-full)",
|
|
14
|
+
// a composed silhouette (card, list row) built from the shapes above, when the
|
|
15
|
+
// whole unit loads as one. Pure layout: no fill, no shimmer — its children carry
|
|
16
|
+
// both, so the placeholder reads as the thing it replaces (spec §2/§3).
|
|
17
|
+
group: "flex flex-col gap-(--space-2)"
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
defaultVariants: { variant: "text" }
|
|
21
|
+
});
|
|
22
|
+
const skeletonShapeClass = "relative block overflow-hidden bg-surface-input";
|
|
23
|
+
const skeletonLineClass = "h-(--space-4) rounded-(--radius-sm)";
|
|
24
|
+
const skeletonShimmerClass = "absolute inset-0 bg-surface-raised animate-pulse [animation-duration:var(--motion-duration-ambient)] ease-(--motion-easing-ambient) motion-reduce:hidden";
|
|
25
|
+
export {
|
|
26
|
+
skeletonLineClass,
|
|
27
|
+
skeletonShapeClass,
|
|
28
|
+
skeletonShimmerClass,
|
|
29
|
+
skeletonVariants
|
|
30
|
+
};
|
|
31
|
+
//# sourceMappingURL=skeleton.variants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../src/components/skeleton/skeleton.variants.ts"],"sourcesContent":["import { cva, type VariantProps } from \"class-variance-authority\";\n\n// A Skeleton is a placeholder that holds the SHAPE of content while it loads, so the\n// layout does not jump when the real content arrives (spec §1). It is a neutral,\n// decorative placeholder: it never carries the brand color (Sovereign Violet) and\n// never carries a status color (for example Verified Green) — a skeleton is a WAIT,\n// not a state, so it binds nothing from the action tier or the status tier\n// (brand != state, spec §1/§3/§8).\n//\n// The model: a LEAF shape (`block`, `circle`, and each line of a `text` block) is the\n// element that carries the neutral input-surface FILL plus one decorative shimmer band\n// (see `skeletonShapeClass` / `skeletonShimmerClass`). A COMPOSING container (a `text`\n// block of lines, or a `group`) carries NO fill and NO shimmer — it is pure layout that\n// stacks its child shapes at the --space-2 gap. Variant therefore differs only by shape\n// (corner radius / composition), never by color (spec §3/§5).\nexport const skeletonVariants = cva(\"block\", {\n variants: {\n // STRUCTURAL axis = spec §3: the shape of the placeholder, not decoration.\n variant: {\n // one or more placeholder lines for incoming text. The root is a layout column\n // (no fill / no shimmer); each line is a leaf shape at the small corner radius.\n text: \"flex flex-col gap-(--space-2)\",\n // a rectangular placeholder (image / chart / thumbnail / media). The root IS the\n // leaf shape: input-surface fill + shimmer + the larger corner radius (spec §3/§5).\n block: \"rounded-(--radius-md)\",\n // a round placeholder for an avatar or icon — full radius (spec §3/§5).\n circle: \"rounded-(--radius-full)\",\n // a composed silhouette (card, list row) built from the shapes above, when the\n // whole unit loads as one. Pure layout: no fill, no shimmer — its children carry\n // both, so the placeholder reads as the thing it replaces (spec §2/§3).\n group: \"flex flex-col gap-(--space-2)\",\n },\n },\n defaultVariants: { variant: \"text\" },\n});\n\n// A LEAF shape's fill (spec §5): the neutral input surface, clipped so the shimmer band\n// sweeping inside it never bleeds out. This fill stays legible on its own, so removing\n// the shimmer under reduced motion loses nothing.\nexport const skeletonShapeClass = \"relative block overflow-hidden bg-surface-input\";\n\n// Each text line is a leaf shape at the small corner radius (spec §3/§5). Height tracks\n// a body line; width is full, except the LAST line of a multi-line block, which is\n// shorter to mirror a real paragraph's ragged final line (spec §2/§3 — applied in tsx).\nexport const skeletonLineClass = \"h-(--space-4) rounded-(--radius-sm)\";\n\n// The optional ambient shimmer (spec §2/§4): a decorative aria-hidden band in the\n// lighter RAISED surface role, read against the input-surface fill. It sweeps on the\n// AMBIENT duration with the ambient (steady) easing — a continuous wait indicator, like\n// the loading spinner — NOT the 350ms verified-check theatre duration, which is reserved\n// for the verified moment and is never spent on a placeholder (spec §4/§5).\n//\n// `animate-pulse` is the built-in ambient keyframe (the spinner reuses the built-in\n// `animate-spin` the same way); its duration is driven onto the ambient token via the\n// arbitrary `animation-duration` PROPERTY — a keyword arbitrary property, not a raw\n// value, so the token-binding gate does not flag it. Under prefers-reduced-motion the\n// band is removed entirely (`motion-reduce:hidden`); no information is carried by the\n// shimmer alone, so the static input-surface shape remains legible (spec §4/§7).\nexport const skeletonShimmerClass =\n \"absolute inset-0 bg-surface-raised animate-pulse \" +\n \"[animation-duration:var(--motion-duration-ambient)] ease-(--motion-easing-ambient) \" +\n \"motion-reduce:hidden\";\n\nexport type SkeletonVariantProps = VariantProps<typeof skeletonVariants>;\n"],"mappings":"AAAA,SAAS,WAA8B;AAehC,MAAM,mBAAmB,IAAI,SAAS;AAAA,EAC3C,UAAU;AAAA;AAAA,IAER,SAAS;AAAA;AAAA;AAAA,MAGP,MAAM;AAAA;AAAA;AAAA,MAGN,OAAO;AAAA;AAAA,MAEP,QAAQ;AAAA;AAAA;AAAA;AAAA,MAIR,OAAO;AAAA,IACT;AAAA,EACF;AAAA,EACA,iBAAiB,EAAE,SAAS,OAAO;AACrC,CAAC;AAKM,MAAM,qBAAqB;AAK3B,MAAM,oBAAoB;AAc1B,MAAM,uBACX;","names":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/spinner/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,KAAK,YAAY,EAAE,MAAM,WAAW,CAAC;AACvD,OAAO,EACL,wBAAwB,EACxB,gBAAgB,EAChB,iBAAiB,EACjB,KAAK,4BAA4B,GAClC,MAAM,oBAAoB,CAAC"}
|