@teamofsilicons/silicon-ui 0.0.0-stage → 0.2.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 +22 -0
- package/README.md +81 -2
- package/check.mjs +236 -0
- package/components/accordion/accordion.d.ts +13 -0
- package/components/accordion/accordion.js +35 -0
- package/components/accordion/accordion.module.css +15 -0
- package/components/action-button/action-button.d.ts +11 -0
- package/components/action-button/action-button.js +57 -0
- package/components/action-button/action-button.module.css +15 -0
- package/components/activity-heatmap/activity-heatmap.d.ts +37 -0
- package/components/activity-heatmap/activity-heatmap.js +303 -0
- package/components/activity-heatmap/activity-heatmap.module.css +83 -0
- package/components/alert/alert.d.ts +13 -0
- package/components/alert/alert.js +79 -0
- package/components/alert/alert.module.css +15 -0
- package/components/animated-counter/animated-counter.d.ts +13 -0
- package/components/animated-counter/animated-counter.js +73 -0
- package/components/animated-counter/animated-counter.module.css +12 -0
- package/components/announcement-bar/announcement-bar.d.ts +53 -0
- package/components/announcement-bar/announcement-bar.js +187 -0
- package/components/announcement-bar/announcement-bar.module.css +60 -0
- package/components/avatar/avatar.d.ts +8 -0
- package/components/avatar/avatar.js +18 -0
- package/components/avatar/avatar.module.css +60 -0
- package/components/avatar-group/avatar-group.d.ts +13 -0
- package/components/avatar-group/avatar-group.js +24 -0
- package/components/avatar-group/avatar-group.module.css +27 -0
- package/components/badge/badge.d.ts +10 -0
- package/components/badge/badge.js +66 -0
- package/components/badge/badge.module.css +52 -0
- package/components/bar-chart/bar-chart.d.ts +32 -0
- package/components/bar-chart/bar-chart.js +327 -0
- package/components/bar-chart/bar-chart.module.css +49 -0
- package/components/billing-toggle/billing-toggle.d.ts +35 -0
- package/components/billing-toggle/billing-toggle.js +83 -0
- package/components/billing-toggle/billing-toggle.module.css +139 -0
- package/components/bottom-sheet/bottom-sheet.d.ts +27 -0
- package/components/bottom-sheet/bottom-sheet.js +386 -0
- package/components/bottom-sheet/bottom-sheet.module.css +69 -0
- package/components/breadcrumb/breadcrumb.d.ts +13 -0
- package/components/breadcrumb/breadcrumb.js +19 -0
- package/components/breadcrumb/breadcrumb.module.css +12 -0
- package/components/brush-chart/brush-chart.d.ts +45 -0
- package/components/brush-chart/brush-chart.js +426 -0
- package/components/brush-chart/brush-chart.module.css +69 -0
- package/components/button/button.d.ts +10 -0
- package/components/button/button.js +97 -0
- package/components/button/button.module.css +39 -0
- package/components/button-group/button-group.d.ts +59 -0
- package/components/button-group/button-group.js +280 -0
- package/components/button-group/button-group.module.css +87 -0
- package/components/button-link/button-link.d.ts +24 -0
- package/components/button-link/button-link.js +11 -0
- package/components/button-link/button-link.module.css +7 -0
- package/components/calendar/calendar.d.ts +22 -0
- package/components/calendar/calendar.js +253 -0
- package/components/calendar/calendar.module.css +51 -0
- package/components/card/card.d.ts +19 -0
- package/components/card/card.js +108 -0
- package/components/card/card.module.css +51 -0
- package/components/card-stack/card-stack.d.ts +34 -0
- package/components/card-stack/card-stack.js +291 -0
- package/components/card-stack/card-stack.module.css +63 -0
- package/components/carousel/carousel.d.ts +28 -0
- package/components/carousel/carousel.js +332 -0
- package/components/carousel/carousel.module.css +42 -0
- package/components/chat-thread/chat-thread.d.ts +135 -0
- package/components/chat-thread/chat-thread.js +406 -0
- package/components/chat-thread/chat-thread.module.css +242 -0
- package/components/checkbox/checkbox.d.ts +7 -0
- package/components/checkbox/checkbox.js +23 -0
- package/components/checkbox/checkbox.module.css +15 -0
- package/components/chip-group/chip-group.d.ts +24 -0
- package/components/chip-group/chip-group.js +196 -0
- package/components/chip-group/chip-group.module.css +38 -0
- package/components/code-block/code-block.d.ts +11 -0
- package/components/code-block/code-block.js +133 -0
- package/components/code-block/code-block.module.css +43 -0
- package/components/color-picker/color-picker.d.ts +40 -0
- package/components/color-picker/color-picker.js +449 -0
- package/components/color-picker/color-picker.module.css +111 -0
- package/components/combobox/combobox.d.ts +19 -0
- package/components/combobox/combobox.js +167 -0
- package/components/combobox/combobox.module.css +28 -0
- package/components/command-palette/command-palette.d.ts +20 -0
- package/components/command-palette/command-palette.js +151 -0
- package/components/command-palette/command-palette.module.css +94 -0
- package/components/comment-thread/comment-thread.d.ts +120 -0
- package/components/comment-thread/comment-thread.js +343 -0
- package/components/comment-thread/comment-thread.module.css +195 -0
- package/components/confirm-morph/confirm-morph.d.ts +65 -0
- package/components/confirm-morph/confirm-morph.js +355 -0
- package/components/confirm-morph/confirm-morph.module.css +146 -0
- package/components/context-menu/context-menu.d.ts +18 -0
- package/components/context-menu/context-menu.js +148 -0
- package/components/context-menu/context-menu.module.css +17 -0
- package/components/copy-button/copy-button.d.ts +10 -0
- package/components/copy-button/copy-button.js +69 -0
- package/components/copy-button/copy-button.module.css +21 -0
- package/components/countdown/countdown.d.ts +31 -0
- package/components/countdown/countdown.js +177 -0
- package/components/countdown/countdown.module.css +49 -0
- package/components/date-picker/date-picker.d.ts +17 -0
- package/components/date-picker/date-picker.js +100 -0
- package/components/date-picker/date-picker.module.css +34 -0
- package/components/date-range-picker/date-range-picker.d.ts +44 -0
- package/components/date-range-picker/date-range-picker.js +534 -0
- package/components/date-range-picker/date-range-picker.module.css +214 -0
- package/components/dialog/dialog.d.ts +11 -0
- package/components/dialog/dialog.js +52 -0
- package/components/dialog/dialog.module.css +36 -0
- package/components/donut-chart/donut-chart.d.ts +46 -0
- package/components/donut-chart/donut-chart.js +382 -0
- package/components/donut-chart/donut-chart.module.css +48 -0
- package/components/drawer/drawer.d.ts +20 -0
- package/components/drawer/drawer.js +111 -0
- package/components/drawer/drawer.module.css +97 -0
- package/components/dropdown-menu/dropdown-menu.d.ts +16 -0
- package/components/dropdown-menu/dropdown-menu.js +39 -0
- package/components/dropdown-menu/dropdown-menu.module.css +38 -0
- package/components/elastic-slider/elastic-slider.d.ts +39 -0
- package/components/elastic-slider/elastic-slider.js +261 -0
- package/components/elastic-slider/elastic-slider.module.css +40 -0
- package/components/empty-state/empty-state.d.ts +12 -0
- package/components/empty-state/empty-state.js +69 -0
- package/components/empty-state/empty-state.module.css +13 -0
- package/components/expandable-card/expandable-card.d.ts +13 -0
- package/components/expandable-card/expandable-card.js +89 -0
- package/components/expandable-card/expandable-card.module.css +22 -0
- package/components/expanding-button-group/expanding-button-group.d.ts +41 -0
- package/components/expanding-button-group/expanding-button-group.js +258 -0
- package/components/expanding-button-group/expanding-button-group.module.css +44 -0
- package/components/expanding-search/expanding-search.d.ts +38 -0
- package/components/expanding-search/expanding-search.js +242 -0
- package/components/expanding-search/expanding-search.module.css +52 -0
- package/components/file-dropzone/file-dropzone.d.ts +44 -0
- package/components/file-dropzone/file-dropzone.js +379 -0
- package/components/file-dropzone/file-dropzone.module.css +115 -0
- package/components/file-upload/file-upload.d.ts +22 -0
- package/components/file-upload/file-upload.js +192 -0
- package/components/file-upload/file-upload.module.css +49 -0
- package/components/filter-toolbar/filter-toolbar.d.ts +48 -0
- package/components/filter-toolbar/filter-toolbar.js +446 -0
- package/components/filter-toolbar/filter-toolbar.module.css +70 -0
- package/components/floating-button-group/floating-button-group.d.ts +51 -0
- package/components/floating-button-group/floating-button-group.js +215 -0
- package/components/floating-button-group/floating-button-group.module.css +74 -0
- package/components/gauge/gauge.d.ts +18 -0
- package/components/gauge/gauge.js +101 -0
- package/components/gauge/gauge.module.css +22 -0
- package/components/hold-to-confirm/hold-to-confirm.d.ts +25 -0
- package/components/hold-to-confirm/hold-to-confirm.js +165 -0
- package/components/hold-to-confirm/hold-to-confirm.module.css +20 -0
- package/components/hover-card/hover-card.d.ts +38 -0
- package/components/hover-card/hover-card.js +145 -0
- package/components/hover-card/hover-card.module.css +20 -0
- package/components/image-compare/image-compare.d.ts +27 -0
- package/components/image-compare/image-compare.js +267 -0
- package/components/image-compare/image-compare.module.css +25 -0
- package/components/in-view-title/in-view-title.d.ts +17 -0
- package/components/in-view-title/in-view-title.js +70 -0
- package/components/in-view-title/in-view-title.module.css +13 -0
- package/components/inline-edit/inline-edit.d.ts +27 -0
- package/components/inline-edit/inline-edit.js +315 -0
- package/components/inline-edit/inline-edit.module.css +73 -0
- package/components/input/input.d.ts +7 -0
- package/components/input/input.js +60 -0
- package/components/input/input.module.css +22 -0
- package/components/json-viewer/json-viewer.d.ts +48 -0
- package/components/json-viewer/json-viewer.js +463 -0
- package/components/json-viewer/json-viewer.module.css +92 -0
- package/components/line-chart/line-chart.d.ts +58 -0
- package/components/line-chart/line-chart.js +383 -0
- package/components/line-chart/line-chart.module.css +60 -0
- package/components/mention-input/mention-input.d.ts +72 -0
- package/components/mention-input/mention-input.js +417 -0
- package/components/mention-input/mention-input.module.css +134 -0
- package/components/metric-card/metric-card.d.ts +8 -0
- package/components/metric-card/metric-card.js +44 -0
- package/components/metric-card/metric-card.module.css +18 -0
- package/components/money-input/money-input.d.ts +48 -0
- package/components/money-input/money-input.js +503 -0
- package/components/money-input/money-input.module.css +77 -0
- package/components/morph-select/morph-select.d.ts +50 -0
- package/components/morph-select/morph-select.js +395 -0
- package/components/morph-select/morph-select.module.css +88 -0
- package/components/multi-select/multi-select.d.ts +18 -0
- package/components/multi-select/multi-select.js +105 -0
- package/components/multi-select/multi-select.module.css +37 -0
- package/components/notification-center/notification-center.d.ts +24 -0
- package/components/notification-center/notification-center.js +146 -0
- package/components/notification-center/notification-center.module.css +79 -0
- package/components/number-field/number-field.d.ts +41 -0
- package/components/number-field/number-field.js +455 -0
- package/components/number-field/number-field.module.css +71 -0
- package/components/otp-input/otp-input.d.ts +13 -0
- package/components/otp-input/otp-input.js +129 -0
- package/components/otp-input/otp-input.module.css +28 -0
- package/components/pagination/pagination.d.ts +7 -0
- package/components/pagination/pagination.js +60 -0
- package/components/pagination/pagination.module.css +16 -0
- package/components/password-field/password-field.d.ts +14 -0
- package/components/password-field/password-field.js +51 -0
- package/components/password-field/password-field.module.css +27 -0
- package/components/password-strength/password-strength.d.ts +107 -0
- package/components/password-strength/password-strength.js +161 -0
- package/components/password-strength/password-strength.module.css +57 -0
- package/components/phone-input/phone-input.d.ts +73 -0
- package/components/phone-input/phone-input.js +612 -0
- package/components/phone-input/phone-input.module.css +98 -0
- package/components/popover/popover.d.ts +6 -0
- package/components/popover/popover.js +19 -0
- package/components/popover/popover.module.css +32 -0
- package/components/progress/progress.d.ts +8 -0
- package/components/progress/progress.js +42 -0
- package/components/progress/progress.module.css +1 -0
- package/components/radio-cards/radio-cards.d.ts +35 -0
- package/components/radio-cards/radio-cards.js +110 -0
- package/components/radio-cards/radio-cards.module.css +84 -0
- package/components/radio-group/radio-group.d.ts +13 -0
- package/components/radio-group/radio-group.js +55 -0
- package/components/radio-group/radio-group.module.css +30 -0
- package/components/resizable-panels/resizable-panels.d.ts +37 -0
- package/components/resizable-panels/resizable-panels.js +338 -0
- package/components/resizable-panels/resizable-panels.module.css +40 -0
- package/components/rich-text-editor/rich-text-editor.d.ts +55 -0
- package/components/rich-text-editor/rich-text-editor.js +1733 -0
- package/components/rich-text-editor/rich-text-editor.module.css +201 -0
- package/components/ridgeline/ridgeline.d.ts +37 -0
- package/components/ridgeline/ridgeline.js +346 -0
- package/components/ridgeline/ridgeline.module.css +58 -0
- package/components/scroll-area/scroll-area.d.ts +40 -0
- package/components/scroll-area/scroll-area.js +153 -0
- package/components/scroll-area/scroll-area.module.css +79 -0
- package/components/search-field/search-field.d.ts +7 -0
- package/components/search-field/search-field.js +20 -0
- package/components/search-field/search-field.module.css +17 -0
- package/components/segmented-control/segmented-control.d.ts +16 -0
- package/components/segmented-control/segmented-control.js +56 -0
- package/components/segmented-control/segmented-control.module.css +15 -0
- package/components/select/select.d.ts +15 -0
- package/components/select/select.js +36 -0
- package/components/select/select.module.css +35 -0
- package/components/shortcut-recorder/shortcut-recorder.d.ts +108 -0
- package/components/shortcut-recorder/shortcut-recorder.js +380 -0
- package/components/shortcut-recorder/shortcut-recorder.module.css +85 -0
- package/components/signature-pad/signature-pad.d.ts +72 -0
- package/components/signature-pad/signature-pad.js +450 -0
- package/components/signature-pad/signature-pad.module.css +84 -0
- package/components/skeleton/skeleton.d.ts +13 -0
- package/components/skeleton/skeleton.js +53 -0
- package/components/skeleton/skeleton.module.css +11 -0
- package/components/slider/slider.d.ts +45 -0
- package/components/slider/slider.js +347 -0
- package/components/slider/slider.module.css +45 -0
- package/components/slope-chart/slope-chart.d.ts +38 -0
- package/components/slope-chart/slope-chart.js +183 -0
- package/components/slope-chart/slope-chart.module.css +51 -0
- package/components/slot-text/slot-text.d.ts +26 -0
- package/components/slot-text/slot-text.js +119 -0
- package/components/slot-text/slot-text.module.css +19 -0
- package/components/sortable-data-table/sortable-data-table.d.ts +38 -0
- package/components/sortable-data-table/sortable-data-table.js +240 -0
- package/components/sortable-data-table/sortable-data-table.module.css +116 -0
- package/components/sparkline/sparkline.d.ts +19 -0
- package/components/sparkline/sparkline.js +239 -0
- package/components/sparkline/sparkline.module.css +26 -0
- package/components/split-button/split-button.d.ts +19 -0
- package/components/split-button/split-button.js +33 -0
- package/components/split-button/split-button.module.css +51 -0
- package/components/stepper/stepper.d.ts +36 -0
- package/components/stepper/stepper.js +108 -0
- package/components/stepper/stepper.module.css +74 -0
- package/components/streamgraph/streamgraph.d.ts +51 -0
- package/components/streamgraph/streamgraph.js +376 -0
- package/components/streamgraph/streamgraph.module.css +55 -0
- package/components/swipe-actions/swipe-actions.d.ts +35 -0
- package/components/swipe-actions/swipe-actions.js +330 -0
- package/components/swipe-actions/swipe-actions.module.css +64 -0
- package/components/switch/switch.d.ts +7 -0
- package/components/switch/switch.js +45 -0
- package/components/switch/switch.module.css +12 -0
- package/components/tabs/tabs.d.ts +8 -0
- package/components/tabs/tabs.js +138 -0
- package/components/tabs/tabs.module.css +27 -0
- package/components/tag-input/tag-input.d.ts +15 -0
- package/components/tag-input/tag-input.js +150 -0
- package/components/tag-input/tag-input.module.css +34 -0
- package/components/text-morph/text-morph.d.ts +13 -0
- package/components/text-morph/text-morph.js +69 -0
- package/components/text-morph/text-morph.module.css +8 -0
- package/components/text-reveal/text-reveal.d.ts +14 -0
- package/components/text-reveal/text-reveal.js +20 -0
- package/components/text-reveal/text-reveal.module.css +13 -0
- package/components/text-shimmer/text-shimmer.d.ts +18 -0
- package/components/text-shimmer/text-shimmer.js +90 -0
- package/components/text-shimmer/text-shimmer.module.css +9 -0
- package/components/textarea/textarea.d.ts +7 -0
- package/components/textarea/textarea.js +56 -0
- package/components/textarea/textarea.module.css +22 -0
- package/components/theme-switch/theme-switch.d.ts +11 -0
- package/components/theme-switch/theme-switch.js +37 -0
- package/components/theme-switch/theme-switch.module.css +31 -0
- package/components/time-picker/time-picker.d.ts +13 -0
- package/components/time-picker/time-picker.js +95 -0
- package/components/time-picker/time-picker.module.css +23 -0
- package/components/timeline/timeline.d.ts +47 -0
- package/components/timeline/timeline.js +171 -0
- package/components/timeline/timeline.module.css +51 -0
- package/components/toast/toast.d.ts +8 -0
- package/components/toast/toast.js +118 -0
- package/components/toast/toast.module.css +100 -0
- package/components/toast-stack/toast-stack.d.ts +57 -0
- package/components/toast-stack/toast-stack.js +399 -0
- package/components/toast-stack/toast-stack.module.css +61 -0
- package/components/tooltip/tooltip.d.ts +8 -0
- package/components/tooltip/tooltip.js +62 -0
- package/components/tooltip/tooltip.module.css +18 -0
- package/components/tree-view/tree-view.d.ts +17 -0
- package/components/tree-view/tree-view.js +147 -0
- package/components/tree-view/tree-view.module.css +22 -0
- package/components/treemap/treemap.d.ts +35 -0
- package/components/treemap/treemap.js +375 -0
- package/components/treemap/treemap.module.css +59 -0
- package/components/usage-meter/usage-meter.d.ts +24 -0
- package/components/usage-meter/usage-meter.js +296 -0
- package/components/usage-meter/usage-meter.module.css +61 -0
- package/components/user-menu/user-menu.d.ts +62 -0
- package/components/user-menu/user-menu.js +316 -0
- package/components/user-menu/user-menu.module.css +97 -0
- package/components/waffle-chart/waffle-chart.d.ts +39 -0
- package/components/waffle-chart/waffle-chart.js +244 -0
- package/components/waffle-chart/waffle-chart.module.css +52 -0
- package/components.json +1330 -0
- package/eslint.js +53 -0
- package/lib/escape.d.ts +19 -0
- package/lib/escape.js +50 -0
- package/lib/media.d.ts +353 -0
- package/lib/media.js +65 -0
- package/lib/menu-highlight.d.ts +28 -0
- package/lib/menu-highlight.js +43 -0
- package/lib/motion-tokens.d.ts +60 -0
- package/lib/motion-tokens.js +25 -0
- package/lib/return-focus.d.ts +9 -0
- package/lib/return-focus.js +53 -0
- package/lib/silicon-provider.d.ts +60 -0
- package/lib/silicon-provider.js +47 -0
- package/lib/use-copy-feedback.d.ts +8 -0
- package/lib/use-copy-feedback.js +36 -0
- package/lib/use-today.d.ts +2 -0
- package/lib/use-today.js +29 -0
- package/package.json +76 -4
- package/styles.css +218 -0
- package/styles.css.d.ts +1 -0
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/** Motion presets are shared by the gallery and future registry consumers. */
|
|
2
|
+
export declare const motionTokens: {
|
|
3
|
+
readonly duration: {
|
|
4
|
+
readonly instant: 0.12;
|
|
5
|
+
readonly fast: 0.16;
|
|
6
|
+
readonly exit: 0.18;
|
|
7
|
+
readonly standard: 0.24;
|
|
8
|
+
readonly considered: 0.48;
|
|
9
|
+
};
|
|
10
|
+
readonly ease: {
|
|
11
|
+
readonly enter: readonly [0.16, 1, 0.3, 1];
|
|
12
|
+
readonly exit: readonly [0.7, 0, 0.84, 0];
|
|
13
|
+
readonly standard: readonly [0.22, 1, 0.36, 1];
|
|
14
|
+
/** For elements that move while already on screen. */
|
|
15
|
+
readonly inOut: readonly [0.65, 0, 0.35, 1];
|
|
16
|
+
};
|
|
17
|
+
readonly spring: {
|
|
18
|
+
readonly responsive: {
|
|
19
|
+
readonly type: "spring";
|
|
20
|
+
readonly stiffness: 520;
|
|
21
|
+
readonly damping: 38;
|
|
22
|
+
};
|
|
23
|
+
readonly gentle: {
|
|
24
|
+
readonly type: "spring";
|
|
25
|
+
readonly stiffness: 340;
|
|
26
|
+
readonly damping: 34;
|
|
27
|
+
};
|
|
28
|
+
/** Presses, toggles, thumbs, and small indicators. Settles fast with a hint of life. */
|
|
29
|
+
readonly snappy: {
|
|
30
|
+
readonly type: "spring";
|
|
31
|
+
readonly visualDuration: 0.26;
|
|
32
|
+
readonly bounce: 0.12;
|
|
33
|
+
};
|
|
34
|
+
/** Panels, height changes, and layout shifts. Critically damped, never overshoots. */
|
|
35
|
+
readonly smooth: {
|
|
36
|
+
readonly type: "spring";
|
|
37
|
+
readonly visualDuration: 0.4;
|
|
38
|
+
readonly bounce: 0;
|
|
39
|
+
};
|
|
40
|
+
/** Shape morphs, shared layout highlights, and width changes that follow new content. */
|
|
41
|
+
readonly morph: {
|
|
42
|
+
readonly type: "spring";
|
|
43
|
+
readonly visualDuration: 0.42;
|
|
44
|
+
readonly bounce: 0.16;
|
|
45
|
+
};
|
|
46
|
+
};
|
|
47
|
+
/** Stagger steps in seconds. Keep total stagger under roughly 0.4s. */
|
|
48
|
+
readonly stagger: {
|
|
49
|
+
readonly char: 0.016;
|
|
50
|
+
readonly word: 0.04;
|
|
51
|
+
readonly line: 0.08;
|
|
52
|
+
readonly item: 0.035;
|
|
53
|
+
};
|
|
54
|
+
/** Blur radii in px for text and content crossfades. Keep blur small and brief. */
|
|
55
|
+
readonly blur: {
|
|
56
|
+
readonly subtle: 2;
|
|
57
|
+
readonly soft: 4;
|
|
58
|
+
readonly text: 8;
|
|
59
|
+
};
|
|
60
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/** Motion presets are shared by the gallery and future registry consumers. */
|
|
2
|
+
export const motionTokens = {
|
|
3
|
+
duration: { instant: 0.12, fast: 0.16, exit: 0.18, standard: 0.24, considered: 0.48 },
|
|
4
|
+
ease: {
|
|
5
|
+
enter: [0.16, 1, 0.3, 1],
|
|
6
|
+
exit: [0.7, 0, 0.84, 0],
|
|
7
|
+
standard: [0.22, 1, 0.36, 1],
|
|
8
|
+
/** For elements that move while already on screen. */
|
|
9
|
+
inOut: [0.65, 0, 0.35, 1],
|
|
10
|
+
},
|
|
11
|
+
spring: {
|
|
12
|
+
responsive: { type: "spring", stiffness: 520, damping: 38 },
|
|
13
|
+
gentle: { type: "spring", stiffness: 340, damping: 34 },
|
|
14
|
+
/** Presses, toggles, thumbs, and small indicators. Settles fast with a hint of life. */
|
|
15
|
+
snappy: { type: "spring", visualDuration: 0.26, bounce: 0.12 },
|
|
16
|
+
/** Panels, height changes, and layout shifts. Critically damped, never overshoots. */
|
|
17
|
+
smooth: { type: "spring", visualDuration: 0.4, bounce: 0 },
|
|
18
|
+
/** Shape morphs, shared layout highlights, and width changes that follow new content. */
|
|
19
|
+
morph: { type: "spring", visualDuration: 0.42, bounce: 0.16 },
|
|
20
|
+
},
|
|
21
|
+
/** Stagger steps in seconds. Keep total stagger under roughly 0.4s. */
|
|
22
|
+
stagger: { char: 0.016, word: 0.04, line: 0.08, item: 0.035 },
|
|
23
|
+
/** Blur radii in px for text and content crossfades. Keep blur small and brief. */
|
|
24
|
+
blur: { subtle: 2, soft: 4, text: 8 },
|
|
25
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export interface ReturnFocusHandlers {
|
|
2
|
+
onOpenAutoFocus: (event: Event) => void;
|
|
3
|
+
onCloseAutoFocus: (event: Event) => void;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* `open`: the layer's open state (null or undefined when the caller cannot know it). `onOpenAutoFocus` /
|
|
7
|
+
* `onCloseAutoFocus`: the caller's own handlers, composed (they run first).
|
|
8
|
+
*/
|
|
9
|
+
export declare function useReturnFocus(open: boolean | null | undefined, onOpenAutoFocus?: (event: Event) => void, onCloseAutoFocus?: (event: Event) => void): ReturnFocusHandlers;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Focus goes back to what opened a layer when it closes (WCAG 2.4.3), however it was opened.
|
|
3
|
+
*
|
|
4
|
+
* Radix's modal Dialog returns focus only to its own <Dialog.Trigger>. Most layers here open from controlled state (a
|
|
5
|
+
* plain button, a menu item, a command, a key), so there is no Trigger and focus fell to <body> when they closed.
|
|
6
|
+
* `useReturnFocus(open)` remembers what had focus when `open` turned true and hands the layer's content an
|
|
7
|
+
* `onCloseAutoFocus` that puts focus back there:
|
|
8
|
+
*
|
|
9
|
+
* - it is captured in an insertion effect, which runs before anything in the layer can take focus (an `autoFocus`
|
|
10
|
+
* field is focused in the layout phase, Radix's FocusScope moves focus in a passive effect); under a bare Radix root,
|
|
11
|
+
* where `open` is unknown, `onOpenAutoFocus` captures it instead;
|
|
12
|
+
* - the caller's own `onCloseAutoFocus` runs first, and one that calls `preventDefault()` keeps its own target;
|
|
13
|
+
* - nothing remembered (focus was on <body>, or the element is gone): Radix's own behaviour, its Trigger if any;
|
|
14
|
+
* - focus already moved on to something outside the layer while it left (a command opened another layer, a link was
|
|
15
|
+
* followed): it stays there.
|
|
16
|
+
*/
|
|
17
|
+
import { useInsertionEffect, useRef } from "react";
|
|
18
|
+
/** What has focus now, unless that is nothing in particular (<body>). */
|
|
19
|
+
function focusedElement() {
|
|
20
|
+
const active = typeof document === "undefined" ? null : document.activeElement;
|
|
21
|
+
return active instanceof HTMLElement && active !== document.body ? active : null;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* `open`: the layer's open state (null or undefined when the caller cannot know it). `onOpenAutoFocus` /
|
|
25
|
+
* `onCloseAutoFocus`: the caller's own handlers, composed (they run first).
|
|
26
|
+
*/
|
|
27
|
+
export function useReturnFocus(open, onOpenAutoFocus, onCloseAutoFocus) {
|
|
28
|
+
const opener = useRef(null);
|
|
29
|
+
useInsertionEffect(() => {
|
|
30
|
+
if (open)
|
|
31
|
+
opener.current = focusedElement();
|
|
32
|
+
}, [open]);
|
|
33
|
+
return {
|
|
34
|
+
onOpenAutoFocus(event) {
|
|
35
|
+
if (open === null || open === undefined)
|
|
36
|
+
opener.current = focusedElement();
|
|
37
|
+
onOpenAutoFocus?.(event);
|
|
38
|
+
},
|
|
39
|
+
onCloseAutoFocus(event) {
|
|
40
|
+
onCloseAutoFocus?.(event);
|
|
41
|
+
const target = opener.current;
|
|
42
|
+
opener.current = null;
|
|
43
|
+
const layer = event.currentTarget instanceof Element ? event.currentTarget : null;
|
|
44
|
+
if (event.defaultPrevented || !target?.isConnected || layer?.contains(target))
|
|
45
|
+
return;
|
|
46
|
+
event.preventDefault();
|
|
47
|
+
const active = document.activeElement;
|
|
48
|
+
if (active && active !== document.body && !layer?.contains(active))
|
|
49
|
+
return;
|
|
50
|
+
target.focus();
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lets an app swap the link and image elements Silicon UI components render.
|
|
3
|
+
*
|
|
4
|
+
* Without a provider, Silicon UI renders a plain `<a>` and `<img>`, so components work in any React app (Vite, Remix, Astro,
|
|
5
|
+
* plain React). Wrap the app once to use your framework's or your own components instead:
|
|
6
|
+
*
|
|
7
|
+
* import Link from "next/link";
|
|
8
|
+
* import Image from "next/image";
|
|
9
|
+
* import { SiliconProvider } from "@/components/silicon-ui/lib/silicon-provider";
|
|
10
|
+
*
|
|
11
|
+
* <SiliconProvider link={Link} image={Image}>{children}</SiliconProvider>
|
|
12
|
+
*
|
|
13
|
+
* Any component that accepts these props works, such as a locale-aware Link from next-intl or a React Router Link
|
|
14
|
+
* wrapped to map `href` to `to`.
|
|
15
|
+
*/
|
|
16
|
+
import { type AnchorHTMLAttributes, type ComponentType, type ImgHTMLAttributes, type ReactNode, type Ref } from "react";
|
|
17
|
+
/** The props Silicon UI passes to a link: an href plus ordinary anchor attributes. */
|
|
18
|
+
export interface SiliconLinkProps extends AnchorHTMLAttributes<HTMLAnchorElement> {
|
|
19
|
+
href: string;
|
|
20
|
+
ref?: Ref<HTMLAnchorElement>;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* The props Silicon UI passes to an image. A subset of next/image's props, so next/image can be passed as is: either `fill`
|
|
24
|
+
* (cover the positioned parent) or `width` and `height`, plus `sizes` and `priority` as hints.
|
|
25
|
+
*/
|
|
26
|
+
export interface SiliconImageProps extends Omit<ImgHTMLAttributes<HTMLImageElement>, "src" | "alt" | "width" | "height" | "loading" | "srcSet"> {
|
|
27
|
+
src: string;
|
|
28
|
+
alt: string;
|
|
29
|
+
width?: number;
|
|
30
|
+
height?: number;
|
|
31
|
+
/** Fills the nearest positioned parent, like next/image's `fill`. */
|
|
32
|
+
fill?: boolean;
|
|
33
|
+
/** Loads the image eagerly with high priority, like next/image's `priority`. */
|
|
34
|
+
priority?: boolean;
|
|
35
|
+
loading?: "eager" | "lazy";
|
|
36
|
+
ref?: Ref<HTMLImageElement>;
|
|
37
|
+
}
|
|
38
|
+
export type SiliconLinkComponent = ComponentType<SiliconLinkProps>;
|
|
39
|
+
export type SiliconImageComponent = ComponentType<SiliconImageProps>;
|
|
40
|
+
/** The default link: a plain anchor. */
|
|
41
|
+
export declare function SiliconAnchor(props: SiliconLinkProps): import("react").JSX.Element;
|
|
42
|
+
/** The default image: a plain, lazily decoded `<img>` that understands `fill` and `priority`. */
|
|
43
|
+
export declare function SiliconImg({ alt, fill, priority, loading, style, ...props }: SiliconImageProps): import("react").JSX.Element;
|
|
44
|
+
export interface SiliconProviderProps {
|
|
45
|
+
/** The link component Silicon UI renders for navigation, such as next/link or your own wrapped Link. Defaults to `<a>`. */
|
|
46
|
+
link?: SiliconLinkComponent;
|
|
47
|
+
/** The image component Silicon UI renders for photos, such as next/image. Defaults to `<img>`. */
|
|
48
|
+
image?: SiliconImageComponent;
|
|
49
|
+
children: ReactNode;
|
|
50
|
+
}
|
|
51
|
+
/** Sets the link and image components for every Silicon UI component inside it. Nested providers inherit what they do not set. */
|
|
52
|
+
export declare function SiliconProvider({ link, image, children }: SiliconProviderProps): import("react").JSX.Element;
|
|
53
|
+
/** The link component from the nearest SiliconProvider, or a plain anchor. */
|
|
54
|
+
export declare const useArcLink: () => SiliconLinkComponent;
|
|
55
|
+
/** The image component from the nearest SiliconProvider, or a plain img. */
|
|
56
|
+
export declare const useArcImage: () => SiliconImageComponent;
|
|
57
|
+
/** What Silicon UI components render for a link: the provider's link component, or a plain anchor. */
|
|
58
|
+
export declare function SiliconLink(props: SiliconLinkProps): import("react").ReactElement<SiliconLinkProps, string | import("react").JSXElementConstructor<any>>;
|
|
59
|
+
/** What Silicon UI components render for an image: the provider's image component, or a plain img. */
|
|
60
|
+
export declare function SiliconImage(props: SiliconImageProps): import("react").ReactElement<SiliconImageProps, string | import("react").JSXElementConstructor<any>>;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
3
|
+
/**
|
|
4
|
+
* Lets an app swap the link and image elements Silicon UI components render.
|
|
5
|
+
*
|
|
6
|
+
* Without a provider, Silicon UI renders a plain `<a>` and `<img>`, so components work in any React app (Vite, Remix, Astro,
|
|
7
|
+
* plain React). Wrap the app once to use your framework's or your own components instead:
|
|
8
|
+
*
|
|
9
|
+
* import Link from "next/link";
|
|
10
|
+
* import Image from "next/image";
|
|
11
|
+
* import { SiliconProvider } from "@/components/silicon-ui/lib/silicon-provider";
|
|
12
|
+
*
|
|
13
|
+
* <SiliconProvider link={Link} image={Image}>{children}</SiliconProvider>
|
|
14
|
+
*
|
|
15
|
+
* Any component that accepts these props works, such as a locale-aware Link from next-intl or a React Router Link
|
|
16
|
+
* wrapped to map `href` to `to`.
|
|
17
|
+
*/
|
|
18
|
+
import { createContext, createElement, useContext, useMemo } from "react";
|
|
19
|
+
/** The default link: a plain anchor. */
|
|
20
|
+
export function SiliconAnchor(props) {
|
|
21
|
+
return _jsx("a", { ...props });
|
|
22
|
+
}
|
|
23
|
+
const fillStyle = { position: "absolute", inset: 0, width: "100%", height: "100%" };
|
|
24
|
+
/** The default image: a plain, lazily decoded `<img>` that understands `fill` and `priority`. */
|
|
25
|
+
export function SiliconImg({ alt, fill, priority, loading, style, ...props }) {
|
|
26
|
+
// eslint-disable-next-line @next/next/no-img-element -- the framework-free default; pass next/image through SiliconProvider instead.
|
|
27
|
+
return _jsx("img", { alt: alt, decoding: "async", ...props, loading: loading ?? (priority ? "eager" : "lazy"), fetchPriority: priority ? "high" : props.fetchPriority, style: fill ? { ...fillStyle, ...style } : style });
|
|
28
|
+
}
|
|
29
|
+
const SiliconContext = createContext({ link: SiliconAnchor, image: SiliconImg });
|
|
30
|
+
/** Sets the link and image components for every Silicon UI component inside it. Nested providers inherit what they do not set. */
|
|
31
|
+
export function SiliconProvider({ link, image, children }) {
|
|
32
|
+
const parent = useContext(SiliconContext);
|
|
33
|
+
const value = useMemo(() => ({ link: link ?? parent.link, image: image ?? parent.image }), [link, image, parent]);
|
|
34
|
+
return _jsx(SiliconContext.Provider, { value: value, children: children });
|
|
35
|
+
}
|
|
36
|
+
/** The link component from the nearest SiliconProvider, or a plain anchor. */
|
|
37
|
+
export const useArcLink = () => useContext(SiliconContext).link;
|
|
38
|
+
/** The image component from the nearest SiliconProvider, or a plain img. */
|
|
39
|
+
export const useArcImage = () => useContext(SiliconContext).image;
|
|
40
|
+
/** What Silicon UI components render for a link: the provider's link component, or a plain anchor. */
|
|
41
|
+
export function SiliconLink(props) {
|
|
42
|
+
return createElement(useArcLink(), props);
|
|
43
|
+
}
|
|
44
|
+
/** What Silicon UI components render for an image: the provider's image component, or a plain img. */
|
|
45
|
+
export function SiliconImage(props) {
|
|
46
|
+
return createElement(useArcImage(), props);
|
|
47
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export type CopyFeedbackState = "idle" | "copied" | "error";
|
|
2
|
+
/** Shared clipboard state for actions that render their own button or menu. */
|
|
3
|
+
export declare function useCopyFeedback(duration?: number): {
|
|
4
|
+
state: CopyFeedbackState;
|
|
5
|
+
activeKey: string | null;
|
|
6
|
+
copy: (value: string, key?: string) => Promise<boolean>;
|
|
7
|
+
reset: () => void;
|
|
8
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
3
|
+
/** Shared clipboard state for actions that render their own button or menu. */
|
|
4
|
+
export function useCopyFeedback(duration = 1900) {
|
|
5
|
+
const [state, setState] = useState("idle");
|
|
6
|
+
const [activeKey, setActiveKey] = useState(null);
|
|
7
|
+
const timeout = useRef(null);
|
|
8
|
+
const reset = useCallback(() => {
|
|
9
|
+
if (timeout.current)
|
|
10
|
+
clearTimeout(timeout.current);
|
|
11
|
+
timeout.current = null;
|
|
12
|
+
setState("idle");
|
|
13
|
+
setActiveKey(null);
|
|
14
|
+
}, []);
|
|
15
|
+
useEffect(() => () => {
|
|
16
|
+
if (timeout.current)
|
|
17
|
+
clearTimeout(timeout.current);
|
|
18
|
+
}, []);
|
|
19
|
+
const copy = useCallback(async (value, key = "default") => {
|
|
20
|
+
if (timeout.current)
|
|
21
|
+
clearTimeout(timeout.current);
|
|
22
|
+
setActiveKey(key);
|
|
23
|
+
try {
|
|
24
|
+
await navigator.clipboard.writeText(value);
|
|
25
|
+
setState("copied");
|
|
26
|
+
timeout.current = setTimeout(reset, duration);
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
setState("error");
|
|
31
|
+
timeout.current = setTimeout(reset, duration);
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
}, [duration, reset]);
|
|
35
|
+
return { state, activeKey, copy, reset };
|
|
36
|
+
}
|
package/lib/use-today.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { useMemo, useSyncExternalStore } from "react";
|
|
2
|
+
/** Shared by calendar and date-range-picker, which both re-export it, so one copy keeps their "today" in step. */
|
|
3
|
+
const dateKey = (date) => `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, "0")}-${String(date.getDate()).padStart(2, "0")}`;
|
|
4
|
+
const fromKey = (key) => {
|
|
5
|
+
const [year = 1970, month = 1, day = 1] = key.split("-").map(Number);
|
|
6
|
+
return new Date(year, month - 1, day);
|
|
7
|
+
};
|
|
8
|
+
/** Today turns over at local midnight; returning to the tab, focusing the window or waking the device reads it again. */
|
|
9
|
+
const subscribeToday = (notify) => {
|
|
10
|
+
let timer = 0;
|
|
11
|
+
const schedule = () => {
|
|
12
|
+
const now = new Date();
|
|
13
|
+
const nextMidnight = new Date(now.getFullYear(), now.getMonth(), now.getDate() + 1);
|
|
14
|
+
timer = window.setTimeout(() => { notify(); schedule(); }, nextMidnight.getTime() - now.getTime() + 1000);
|
|
15
|
+
};
|
|
16
|
+
const onVisible = () => { if (document.visibilityState === "visible")
|
|
17
|
+
notify(); };
|
|
18
|
+
schedule();
|
|
19
|
+
document.addEventListener("visibilitychange", onVisible);
|
|
20
|
+
window.addEventListener("focus", notify);
|
|
21
|
+
return () => { window.clearTimeout(timer); document.removeEventListener("visibilitychange", onVisible); window.removeEventListener("focus", notify); };
|
|
22
|
+
};
|
|
23
|
+
const readToday = () => dateKey(new Date());
|
|
24
|
+
const serverToday = () => "";
|
|
25
|
+
/** The viewer's local date. Undefined on the server and during hydration, so markup never depends on the server clock or time zone; afterwards it follows the real date across midnight. */
|
|
26
|
+
export function useToday() {
|
|
27
|
+
const key = useSyncExternalStore(subscribeToday, readToday, serverToday);
|
|
28
|
+
return useMemo(() => (key ? fromKey(key) : undefined), [key]);
|
|
29
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,78 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@teamofsilicons/silicon-ui",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "React components with calm motion, on the Silicon design tokens. By Team of Silicons.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "Team of Silicons",
|
|
7
|
+
"homepage": "https://ui.teamofsilicons.com",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/teamofsilicons/silicon-ui.git"
|
|
11
|
+
},
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/teamofsilicons/silicon-ui/issues"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"react",
|
|
17
|
+
"components",
|
|
18
|
+
"design-system",
|
|
19
|
+
"ui",
|
|
20
|
+
"motion",
|
|
21
|
+
"radix"
|
|
22
|
+
],
|
|
23
|
+
"type": "module",
|
|
24
|
+
"sideEffects": [
|
|
25
|
+
"**/*.css"
|
|
26
|
+
],
|
|
27
|
+
"bin": {
|
|
28
|
+
"silicon-ui-check": "./check.mjs"
|
|
29
|
+
},
|
|
30
|
+
"exports": {
|
|
31
|
+
"./styles.css": {
|
|
32
|
+
"types": "./styles.css.d.ts",
|
|
33
|
+
"default": "./styles.css"
|
|
34
|
+
},
|
|
35
|
+
"./provider": {
|
|
36
|
+
"types": "./lib/silicon-provider.d.ts",
|
|
37
|
+
"default": "./lib/silicon-provider.js"
|
|
38
|
+
},
|
|
39
|
+
"./motion-tokens": {
|
|
40
|
+
"types": "./lib/motion-tokens.d.ts",
|
|
41
|
+
"default": "./lib/motion-tokens.js"
|
|
42
|
+
},
|
|
43
|
+
"./lib/*": {
|
|
44
|
+
"types": "./lib/*.d.ts",
|
|
45
|
+
"default": "./lib/*.js"
|
|
46
|
+
},
|
|
47
|
+
"./eslint": "./eslint.js",
|
|
48
|
+
"./components.json": "./components.json",
|
|
49
|
+
"./package.json": "./package.json",
|
|
50
|
+
"./*": {
|
|
51
|
+
"types": "./components/*/*.d.ts",
|
|
52
|
+
"default": "./components/*/*.js"
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
"peerDependencies": {
|
|
56
|
+
"react": ">=19",
|
|
57
|
+
"react-dom": ">=19",
|
|
58
|
+
"eslint": ">=9"
|
|
59
|
+
},
|
|
60
|
+
"peerDependenciesMeta": {
|
|
61
|
+
"eslint": {
|
|
62
|
+
"optional": true
|
|
63
|
+
}
|
|
64
|
+
},
|
|
65
|
+
"dependencies": {
|
|
66
|
+
"@radix-ui/react-accordion": "^1.2.20",
|
|
67
|
+
"@radix-ui/react-checkbox": "^1.3.11",
|
|
68
|
+
"@radix-ui/react-dialog": "^1.1.23",
|
|
69
|
+
"@radix-ui/react-dropdown-menu": "^2.1.24",
|
|
70
|
+
"@radix-ui/react-popover": "^1.1.23",
|
|
71
|
+
"@radix-ui/react-select": "^2.3.7",
|
|
72
|
+
"@radix-ui/react-switch": "^1.3.7",
|
|
73
|
+
"@radix-ui/react-tabs": "^1.1.21",
|
|
74
|
+
"@radix-ui/react-tooltip": "^1.2.16",
|
|
75
|
+
"lucide-react": "^1.47.0",
|
|
76
|
+
"motion": "^13.4.0"
|
|
77
|
+
}
|
|
78
|
+
}
|
package/styles.css
ADDED
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
:root {
|
|
2
|
+
color-scheme: light;
|
|
3
|
+
--neutral-0: oklch(100% 0 0);
|
|
4
|
+
--neutral-1: oklch(99% 0 0);
|
|
5
|
+
--neutral-2: oklch(97.8% 0 0);
|
|
6
|
+
--neutral-3: oklch(95.8% 0 0);
|
|
7
|
+
--neutral-4: oklch(91.5% 0 0);
|
|
8
|
+
--neutral-5: oklch(84% 0 0);
|
|
9
|
+
--neutral-6: oklch(72% 0 0);
|
|
10
|
+
--neutral-7: oklch(59% 0 0);
|
|
11
|
+
--neutral-8: oklch(46% 0 0);
|
|
12
|
+
--neutral-9: oklch(34% 0 0);
|
|
13
|
+
--neutral-10: oklch(23% 0 0);
|
|
14
|
+
--neutral-11: oklch(15% 0 0);
|
|
15
|
+
--background: var(--neutral-0);
|
|
16
|
+
--surface: var(--neutral-0);
|
|
17
|
+
--surface-raised: var(--neutral-0);
|
|
18
|
+
--surface-muted: var(--neutral-2);
|
|
19
|
+
--foreground: var(--neutral-11);
|
|
20
|
+
--text-secondary: var(--neutral-8);
|
|
21
|
+
--text-muted: var(--neutral-7);
|
|
22
|
+
--border: oklch(93.5% 0 0);
|
|
23
|
+
--border-subtle: oklch(96.5% 0 0);
|
|
24
|
+
--border-strong: oklch(82% 0 0);
|
|
25
|
+
--accent: oklch(33% 0 0);
|
|
26
|
+
--accent-strong: oklch(24% 0 0);
|
|
27
|
+
--accent-subtle: oklch(33% 0 0 / .1);
|
|
28
|
+
--accent-foreground: var(--background);
|
|
29
|
+
/* Filled primary actions (Button primary, ActionButton). Neutral by default; an app sets its brand colour here. */
|
|
30
|
+
--primary: var(--foreground);
|
|
31
|
+
--primary-foreground: var(--background);
|
|
32
|
+
/* Profile pictures (Avatar, AvatarGroup, UserMenu). Circles by default; an app can choose e.g. 30% and squircle. */
|
|
33
|
+
--avatar-radius: var(--radius-full);
|
|
34
|
+
--avatar-corner-shape: round;
|
|
35
|
+
/* Selection controls (switch, checkbox, radio, slider). --control-on fills a chosen control; --control-glyph is the check or dot drawn on it;
|
|
36
|
+
thumbs stay white in both states so they always read against the track. Tuned per accent below so white thumbs hold on every hue. */
|
|
37
|
+
--control-on: oklch(23% 0 0);
|
|
38
|
+
--control-glyph: oklch(100% 0 0);
|
|
39
|
+
--control-track: oklch(89.5% 0 0);
|
|
40
|
+
--control-track-hover: oklch(86% 0 0);
|
|
41
|
+
--control-thumb: oklch(100% 0 0);
|
|
42
|
+
--control-thumb-on: oklch(100% 0 0);
|
|
43
|
+
--control-thumb-shadow: 0 0 0 .5px oklch(0% 0 0 / .07), 0 1px 2px oklch(0% 0 0 / .14), 0 2px 6px oklch(0% 0 0 / .06);
|
|
44
|
+
--control-on-subtle: color-mix(in oklab, var(--control-on) 10%, transparent);
|
|
45
|
+
/* Slider fills. Same as --control-on except neutral dark, where a mid grey keeps the white thumb distinct. */
|
|
46
|
+
--control-fill: var(--control-on);
|
|
47
|
+
/* Pointer focus draws no ring (product decision). --focus-ring is the halo a few fields drew for any input method, so it stays transparent.
|
|
48
|
+
Keyboard focus uses the outline at the end of this file; tune it with --focus-outline, --focus-outline-width and --focus-outline-offset. */
|
|
49
|
+
--focus-ring: transparent;
|
|
50
|
+
--success: oklch(49% .19 150);
|
|
51
|
+
--warning: oklch(58% .18 75);
|
|
52
|
+
--danger: oklch(54% .21 25);
|
|
53
|
+
--shadow-resting: 0 1px 2px oklch(0% 0 0 / .035);
|
|
54
|
+
--shadow-raised: 0 6px 18px oklch(0% 0 0 / .065), 0 1px 3px oklch(0% 0 0 / .035);
|
|
55
|
+
--shadow-floating: 0 20px 48px oklch(0% 0 0 / .105), 0 3px 10px oklch(0% 0 0 / .045);
|
|
56
|
+
/* Brand gradient: soft lavender to warm peach. Light enough for dark text (--silicon-gradient-foreground, >12:1). */
|
|
57
|
+
--silicon-gradient-from: oklch(90% .045 300);
|
|
58
|
+
--silicon-gradient-to: oklch(92% .045 65);
|
|
59
|
+
--silicon-gradient: linear-gradient(100deg, var(--silicon-gradient-from), var(--silicon-gradient-to));
|
|
60
|
+
--silicon-gradient-foreground: oklch(22% .01 300);
|
|
61
|
+
/* Faint wash for backgrounds and tinted panels. */
|
|
62
|
+
--silicon-gradient-soft: linear-gradient(135deg, oklch(97.5% .016 300), oklch(98% .016 65));
|
|
63
|
+
/* Hairline borders and rules. */
|
|
64
|
+
--silicon-gradient-line: linear-gradient(100deg, oklch(83% .06 300), oklch(86% .06 65));
|
|
65
|
+
/* Text-safe stops for gradient text and small marks (>4.5:1 on the surface). */
|
|
66
|
+
--silicon-gradient-ink: linear-gradient(100deg, oklch(47% .1 300), oklch(50% .09 55));
|
|
67
|
+
/* Space, by role: tight 4 · related 8 · group 12 · inset 16 · comfort 20 · section 24 · block 32 · page 48 · stage 64 · screen 80. */
|
|
68
|
+
--space-tight: 4px; --space-related: 8px; --space-group: 12px; --space-inset: 16px; --space-comfort: 20px;
|
|
69
|
+
--space-section: 24px; --space-block: 32px; --space-page: 48px; --space-stage: 64px; --space-screen: 80px;
|
|
70
|
+
/* Radius, by role: detail for small marks and swatches, control for buttons and fields, container for cards and menus,
|
|
71
|
+
overlay for dialogs and sheets, full for pills and dots. Every corner in every component reads one of these.
|
|
72
|
+
These are the round values (2 / 6 / 8 / 12). Squircle corners use larger radii, set with the corner rule below, so
|
|
73
|
+
both shapes feel equally round. */
|
|
74
|
+
--radius-detail: 2px; --radius-control: 6px; --radius-container: 8px; --radius-overlay: 12px; --radius-full: 999px;
|
|
75
|
+
/* Corner shape. Squircle by default; see the corner rule after the dark theme. */
|
|
76
|
+
--corner-shape: squircle;
|
|
77
|
+
--control-height-sm: 2.25rem; --control-height-md: 2.75rem; --control-height-lg: 3.125rem;
|
|
78
|
+
--font-display: var(--font-geist, "Geist Variable"), sans-serif;
|
|
79
|
+
--font-body: var(--font-inter, "Inter Variable"), sans-serif;
|
|
80
|
+
--text-xs: .75rem; --text-sm: .875rem; --text-base: 1rem; --text-lg: 1.125rem;
|
|
81
|
+
--text-xl: 1.375rem; --text-2xl: 1.75rem; --text-3xl: 2.25rem;
|
|
82
|
+
--text-4xl: 3.25rem; --text-5xl: 4.5rem;
|
|
83
|
+
--tracking-display: -.03em; --tracking-body: -.01em;
|
|
84
|
+
--leading-display: 1.1; --leading-body: 1.4;
|
|
85
|
+
--ease-enter: cubic-bezier(.16,1,.3,1);
|
|
86
|
+
--ease-standard: cubic-bezier(.22,1,.36,1);
|
|
87
|
+
--ease-exit: cubic-bezier(.7,0,.84,0);
|
|
88
|
+
--ease-in-out: cubic-bezier(.65,0,.35,1);
|
|
89
|
+
/* Spring with a gentle settle (bounce .15). Pair with --duration-spring for transform transitions. */
|
|
90
|
+
--ease-spring: linear(0, 0.0258, 0.09, 0.1763, 0.2732, 0.3724, 0.4683, 0.5573, 0.6376, 0.7082, 0.7689, 0.8202, 0.8628, 0.8976, 0.9256, 0.9476, 0.9648, 0.9778, 0.9875, 0.9945, 0.9994, 1.0026, 1.0047, 1.0058, 1.0062, 1.0062, 1.0059, 1.0055, 1.0049, 1.0043, 1.0036, 1.0031, 1.0025, 1.002, 1.0016, 1.0013, 1);
|
|
91
|
+
--duration-instant: 120ms; --duration-fast: 160ms; --duration-standard: 240ms; --duration-considered: 480ms; --duration-spring: 580ms;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
:root[data-theme="dark"] {
|
|
95
|
+
color-scheme: dark;
|
|
96
|
+
--background: oklch(19% 0 0);
|
|
97
|
+
--surface: oklch(21.5% 0 0);
|
|
98
|
+
--surface-raised: oklch(24% 0 0);
|
|
99
|
+
/* Keep muted surfaces and hover states distinct from the base surface in dark mode. */
|
|
100
|
+
--surface-muted: oklch(26% 0 0);
|
|
101
|
+
--foreground: oklch(96% 0 0);
|
|
102
|
+
--text-secondary: oklch(77% 0 0);
|
|
103
|
+
--text-muted: oklch(64% 0 0);
|
|
104
|
+
--border: oklch(29% 0 0);
|
|
105
|
+
--border-subtle: oklch(25% 0 0);
|
|
106
|
+
--border-strong: oklch(40% 0 0);
|
|
107
|
+
--focus-ring: transparent;
|
|
108
|
+
--accent: oklch(80% 0 0);
|
|
109
|
+
--accent-strong: oklch(91% 0 0);
|
|
110
|
+
--accent-subtle: oklch(80% 0 0 / .13);
|
|
111
|
+
/* Neutral dark inverts: a near-white track carries a dark thumb, so on and off never read alike. */
|
|
112
|
+
--control-on: oklch(93% 0 0);
|
|
113
|
+
--control-glyph: oklch(19% 0 0);
|
|
114
|
+
--control-track: oklch(33% 0 0);
|
|
115
|
+
--control-track-hover: oklch(37% 0 0);
|
|
116
|
+
--control-thumb: oklch(97% 0 0);
|
|
117
|
+
--control-thumb-on: oklch(19% 0 0);
|
|
118
|
+
--control-fill: oklch(62% 0 0);
|
|
119
|
+
--control-thumb-shadow: 0 0 0 .5px oklch(0% 0 0 / .3), 0 1px 2px oklch(0% 0 0 / .35), 0 2px 6px oklch(0% 0 0 / .2);
|
|
120
|
+
--success: oklch(78% .18 150);
|
|
121
|
+
--warning: oklch(83% .17 80);
|
|
122
|
+
--danger: oklch(76% .2 25);
|
|
123
|
+
--shadow-resting: 0 1px 2px oklch(0% 0 0 / .18);
|
|
124
|
+
--shadow-raised: 0 8px 22px oklch(0% 0 0 / .22);
|
|
125
|
+
--shadow-floating: 0 22px 55px oklch(0% 0 0 / .34);
|
|
126
|
+
--silicon-gradient-from: oklch(38% .05 300);
|
|
127
|
+
--silicon-gradient-to: oklch(40% .045 60);
|
|
128
|
+
--silicon-gradient-foreground: oklch(96% .005 300);
|
|
129
|
+
--silicon-gradient-soft: linear-gradient(135deg, oklch(23.5% .016 300), oklch(24% .014 65));
|
|
130
|
+
--silicon-gradient-line: linear-gradient(100deg, oklch(48% .06 300), oklch(52% .055 65));
|
|
131
|
+
--silicon-gradient-ink: linear-gradient(100deg, oklch(82% .07 300), oklch(86% .065 70));
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/* Corners are squircles: every rounded corner is drawn as a superellipse, so borders, shadows and focus rings follow the
|
|
135
|
+
same smooth curve. Browsers without corner-shape draw ordinary round corners from the same radius. Set
|
|
136
|
+
data-corners="round" on <html>, or on any element for its subtree, to use round corners instead. */
|
|
137
|
+
:root[data-corners="round"], [data-corners="round"] { --corner-shape: round; }
|
|
138
|
+
:root[data-corners="squircle"], [data-corners="squircle"] { --corner-shape: squircle; }
|
|
139
|
+
*, ::before, ::after { corner-shape: var(--corner-shape); }
|
|
140
|
+
/* A squircle at the same radius reads about 0.55x as round as a circular corner, so squircle radii are about 1.8x the
|
|
141
|
+
round ones: 4 / 11 / 14 / 21 feel like 2 / 6 / 8 / 12. Only browsers that draw squircles get them; the rest keep the
|
|
142
|
+
round values above, so their corners never look oversized. */
|
|
143
|
+
@supports (corner-shape: squircle) {
|
|
144
|
+
:root, [data-corners="squircle"] { --radius-detail: 4px; --radius-control: 11px; --radius-container: 14px; --radius-overlay: 21px; }
|
|
145
|
+
:root[data-corners="round"], [data-corners="round"] { --radius-detail: 2px; --radius-control: 6px; --radius-container: 8px; --radius-overlay: 12px; }
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
:root[data-accent="neutral"] { --accent: oklch(33% 0 0); --accent-strong: oklch(24% 0 0); --accent-subtle: oklch(33% 0 0 / .1); }
|
|
149
|
+
:root[data-accent="violet"] { --accent: #7747ff; --accent-strong: #5528ce; --accent-subtle: rgb(119 71 255 / .13); }
|
|
150
|
+
:root[data-accent="blue"] { --accent: #0562ef; --accent-strong: #074db7; --accent-subtle: rgb(5 98 239 / .12); }
|
|
151
|
+
:root[data-accent="green"] { --accent: #0db879; --accent-strong: #087c54; --accent-subtle: rgb(13 184 121 / .13); --accent-foreground: #102016; }
|
|
152
|
+
:root[data-accent="amber"] { --accent: #f3ad20; --accent-strong: #9c6300; --accent-subtle: rgb(243 173 32 / .16); --accent-foreground: #20190d; }
|
|
153
|
+
:root[data-accent="orange"] { --accent: #f48120; --accent-strong: #aa4700; --accent-subtle: rgb(244 129 32 / .13); --accent-foreground: #17130f; }
|
|
154
|
+
:root[data-accent="coral"] { --accent: #f15f55; --accent-strong: #b92c27; --accent-subtle: rgb(241 95 85 / .14); --accent-foreground: #21110f; }
|
|
155
|
+
:root[data-accent="rose"] { --accent: #ed4e9d; --accent-strong: #ae2570; --accent-subtle: rgb(237 78 157 / .14); --accent-foreground: #250f1b; }
|
|
156
|
+
:root[data-theme="dark"][data-accent="neutral"] { --accent: oklch(80% 0 0); --accent-strong: oklch(91% 0 0); --accent-subtle: oklch(80% 0 0 / .13); }
|
|
157
|
+
:root[data-theme="dark"][data-accent="violet"] { --accent: #a78bff; --accent-strong: #c7b7ff; --accent-subtle: rgb(119 71 255 / .22); }
|
|
158
|
+
:root[data-theme="dark"][data-accent="blue"] { --accent: #6ba3ff; --accent-strong: #a4c7ff; --accent-subtle: rgb(5 98 239 / .22); }
|
|
159
|
+
:root[data-theme="dark"][data-accent="green"] { --accent: #53dca6; --accent-strong: #93efd0; --accent-subtle: rgb(13 184 121 / .2); }
|
|
160
|
+
:root[data-theme="dark"][data-accent="amber"] { --accent: #ffcb62; --accent-strong: #ffe0a1; --accent-subtle: rgb(243 173 32 / .2); }
|
|
161
|
+
:root[data-theme="dark"][data-accent="orange"] { --accent: #ffad5e; --accent-strong: #ffd0a0; --accent-subtle: rgb(244 129 32 / .2); --accent-foreground: #17130f; }
|
|
162
|
+
:root[data-theme="dark"][data-accent="coral"] { --accent: #ff9386; --accent-strong: #ffc1ba; --accent-subtle: rgb(241 95 85 / .2); }
|
|
163
|
+
:root[data-theme="dark"][data-accent="rose"] { --accent: #ff8bc5; --accent-strong: #ffc0df; --accent-subtle: rgb(237 78 157 / .2); }
|
|
164
|
+
|
|
165
|
+
/* Selection control fills per accent. Light: the accent, deepened slightly where a white thumb needs it. Dark: a mid tone instead of the pastel
|
|
166
|
+
text accent, so white thumbs and checks keep contrast without a neon track. Amber keeps a dark glyph because white on yellow washes out. */
|
|
167
|
+
:root[data-accent="neutral"] { --control-on: oklch(23% 0 0); --control-thumb-on: oklch(100% 0 0); --control-glyph: oklch(100% 0 0); }
|
|
168
|
+
:root[data-accent="violet"] { --control-on: #7747ff; --control-thumb-on: #fff; --control-glyph: #fff; }
|
|
169
|
+
:root[data-accent="blue"] { --control-on: #0562ef; --control-thumb-on: #fff; --control-glyph: #fff; }
|
|
170
|
+
:root[data-accent="green"] { --control-on: #10a870; --control-thumb-on: #fff; --control-glyph: #fff; }
|
|
171
|
+
:root[data-accent="amber"] { --control-on: #eda11a; --control-thumb-on: #fff; --control-glyph: #2a1c03; }
|
|
172
|
+
:root[data-accent="orange"] { --control-on: #f07818; --control-thumb-on: #fff; --control-glyph: #fff; }
|
|
173
|
+
:root[data-accent="coral"] { --control-on: #ec564b; --control-thumb-on: #fff; --control-glyph: #fff; }
|
|
174
|
+
:root[data-accent="rose"] { --control-on: #e64494; --control-thumb-on: #fff; --control-glyph: #fff; }
|
|
175
|
+
:root[data-theme="dark"][data-accent="neutral"] { --control-on: oklch(93% 0 0); --control-thumb-on: oklch(19% 0 0); --control-glyph: oklch(19% 0 0); }
|
|
176
|
+
:root[data-theme="dark"][data-accent="violet"] { --control-on: #8a66ff; --control-thumb-on: #fff; --control-glyph: #fff; --control-fill: #8a66ff; }
|
|
177
|
+
:root[data-theme="dark"][data-accent="blue"] { --control-on: #3b82f6; --control-thumb-on: #fff; --control-glyph: #fff; --control-fill: #3b82f6; }
|
|
178
|
+
:root[data-theme="dark"][data-accent="green"] { --control-on: #1fae78; --control-thumb-on: #fff; --control-glyph: #fff; --control-fill: #1fae78; }
|
|
179
|
+
:root[data-theme="dark"][data-accent="amber"] { --control-on: #e8a52a; --control-thumb-on: #fff; --control-glyph: #241803; --control-fill: #e8a52a; }
|
|
180
|
+
:root[data-theme="dark"][data-accent="orange"] { --control-on: #ef873a; --control-thumb-on: #fff; --control-glyph: #fff; --control-fill: #ef873a; }
|
|
181
|
+
:root[data-theme="dark"][data-accent="coral"] { --control-on: #ec6a60; --control-thumb-on: #fff; --control-glyph: #fff; --control-fill: #ec6a60; }
|
|
182
|
+
:root[data-theme="dark"][data-accent="rose"] { --control-on: #e457a0; --control-thumb-on: #fff; --control-glyph: #fff; --control-fill: #e457a0; }
|
|
183
|
+
|
|
184
|
+
/* Chart series palette, shared by every chart. Series 1 is the accent itself; series 2 to 4 rotate its hue at lightness steps
|
|
185
|
+
around it, so they stay distinct for every accent. A neutral accent falls back to a blue. Validated with the dataviz script
|
|
186
|
+
across all eight accents in both themes: every pair (not only neighbours) clears CVD ΔE 9 and normal vision ΔE 17. Browsers
|
|
187
|
+
without relative color get the neutral set. Override --series-1 to --series-4 on any element to rebrand a chart. */
|
|
188
|
+
:root { --series-1: #1f7dcf; --series-2: #7128a5; --series-3: #e58f00; --series-4: #009e84; }
|
|
189
|
+
:root[data-theme="dark"] { --series-1: #55adff; --series-2: #9c37be; --series-3: #e66e00; --series-4: #00a861; }
|
|
190
|
+
@supports (color: oklch(from red clamp(.4, l * sign(max(c - .02, 0)) + .5, .8) c h)) {
|
|
191
|
+
:root {
|
|
192
|
+
--series-1: oklch(from var(--accent) calc(l * sign(max(c - .02, 0)) + .58 * (1 - sign(max(c - .02, 0)))) calc(c * sign(max(c - .02, 0)) + .15 * (1 - sign(max(c - .02, 0)))) calc(h * sign(max(c - .02, 0)) + 250 * (1 - sign(max(c - .02, 0)))));
|
|
193
|
+
--series-2: oklch(from var(--accent) clamp(.45, l * sign(max(c - .02, 0)) + .58 * (1 - sign(max(c - .02, 0))) - 0.25, .76) .19 calc(h * sign(max(c - .02, 0)) + 250 * (1 - sign(max(c - .02, 0))) + 57));
|
|
194
|
+
--series-3: oklch(from var(--accent) clamp(.45, l * sign(max(c - .02, 0)) + .58 * (1 - sign(max(c - .02, 0))) + 0.14, .76) .18 calc(h * sign(max(c - .02, 0)) + 250 * (1 - sign(max(c - .02, 0))) + 184));
|
|
195
|
+
--series-4: oklch(from var(--accent) clamp(.45, l * sign(max(c - .02, 0)) + .58 * (1 - sign(max(c - .02, 0))), .76) .21 calc(h * sign(max(c - .02, 0)) + 250 * (1 - sign(max(c - .02, 0))) + 292));
|
|
196
|
+
}
|
|
197
|
+
:root[data-theme="dark"] {
|
|
198
|
+
--series-1: oklch(from var(--accent) calc(l * sign(max(c - .02, 0)) + .73 * (1 - sign(max(c - .02, 0)))) calc(c * sign(max(c - .02, 0)) + .15 * (1 - sign(max(c - .02, 0)))) calc(h * sign(max(c - .02, 0)) + 250 * (1 - sign(max(c - .02, 0)))));
|
|
199
|
+
--series-2: oklch(from var(--accent) clamp(.485, l * sign(max(c - .02, 0)) + .73 * (1 - sign(max(c - .02, 0))) - 0.19, .665) .21 calc(h * sign(max(c - .02, 0)) + 250 * (1 - sign(max(c - .02, 0))) + 66));
|
|
200
|
+
--series-3: oklch(from var(--accent) clamp(.485, l * sign(max(c - .02, 0)) + .73 * (1 - sign(max(c - .02, 0))) + 0.02, .665) .21 calc(h * sign(max(c - .02, 0)) + 250 * (1 - sign(max(c - .02, 0))) + 175));
|
|
201
|
+
--series-4: oklch(from var(--accent) clamp(.485, l * sign(max(c - .02, 0)) + .73 * (1 - sign(max(c - .02, 0))) - 0.1, .665) .18 calc(h * sign(max(c - .02, 0)) + 250 * (1 - sign(max(c - .02, 0))) + 270));
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/* Focus. Pointer focus never draws a ring (product decision). Keyboard focus (:focus-visible) draws a subtle accent outline, so keyboard users
|
|
206
|
+
can always see where they are (WCAG 2.4.7). Left out of the outline: text fields, which match :focus-visible on a mouse click too and show
|
|
207
|
+
focus with their border and caret; menu items and listbox options, whose highlight fill marks the keyboard position; and tabindex="-1"
|
|
208
|
+
targets (dialog panels, regions) that only receive focus from script.
|
|
209
|
+
Tune it on :root or any element, no !important needed:
|
|
210
|
+
--focus-outline color (default: the accent, softened); set transparent to hide it
|
|
211
|
+
--focus-outline-width default 2px
|
|
212
|
+
--focus-outline-offset default 2px; components inside clipped containers set a negative offset */
|
|
213
|
+
:focus:not(:focus-visible),
|
|
214
|
+
:is(input:not([type="button"], [type="checkbox"], [type="color"], [type="file"], [type="image"], [type="radio"], [type="range"], [type="reset"], [type="submit"]), textarea, [contenteditable]:not([contenteditable="false"]), [role="menuitem"], [role="menuitemcheckbox"], [role="menuitemradio"], [role="option"], [tabindex="-1"]):focus { outline: none !important; }
|
|
215
|
+
:focus-visible:not(input:not([type="button"], [type="checkbox"], [type="color"], [type="file"], [type="image"], [type="radio"], [type="range"], [type="reset"], [type="submit"]), textarea, [contenteditable]:not([contenteditable="false"]), [role="menuitem"], [role="menuitemcheckbox"], [role="menuitemradio"], [role="option"], [tabindex="-1"]) {
|
|
216
|
+
outline: var(--focus-outline-width, 2px) solid var(--focus-outline, color-mix(in oklab, var(--accent-strong) 72%, transparent)) !important;
|
|
217
|
+
outline-offset: var(--focus-outline-offset, 2px) !important;
|
|
218
|
+
}
|
package/styles.css.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|