@teamofsilicons/silicon-ui 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -3
- package/check.mjs +14 -5
- package/components/activity-heatmap/activity-heatmap.module.css +4 -4
- package/components/alert/alert.module.css +1 -1
- package/components/announcement-bar/announcement-bar.module.css +6 -6
- package/components/avatar/avatar.d.ts +2 -2
- package/components/avatar/avatar.js +1 -1
- package/components/avatar/avatar.module.css +5 -2
- package/components/avatar-group/avatar-group.module.css +4 -4
- package/components/badge/badge.module.css +4 -4
- package/components/bar-chart/bar-chart.module.css +4 -4
- package/components/billing-toggle/billing-toggle.module.css +10 -10
- package/components/bottom-sheet/bottom-sheet.module.css +4 -5
- package/components/breadcrumb/breadcrumb.d.ts +8 -2
- package/components/breadcrumb/breadcrumb.js +21 -9
- package/components/breadcrumb/breadcrumb.module.css +7 -3
- package/components/brush-chart/brush-chart.module.css +9 -9
- package/components/button/button.d.ts +7 -2
- package/components/button/button.js +3 -1
- package/components/button/button.module.css +10 -1
- package/components/button-group/button-group.module.css +6 -6
- package/components/calendar/calendar.module.css +7 -7
- package/components/card/card.module.css +2 -2
- package/components/card-stack/card-stack.module.css +2 -3
- package/components/carousel/carousel.module.css +2 -2
- package/components/chat-thread/chat-thread.module.css +41 -41
- package/components/checkbox/checkbox.module.css +1 -1
- package/components/chip-group/chip-group.module.css +2 -2
- package/components/code-block/code-block.module.css +7 -14
- package/components/color-picker/color-picker.module.css +20 -21
- package/components/combobox/combobox.module.css +2 -2
- package/components/command-palette/command-palette.module.css +18 -18
- package/components/comment-thread/comment-thread.module.css +35 -35
- package/components/confirm-morph/confirm-morph.module.css +9 -9
- package/components/context-menu/context-menu.module.css +3 -3
- package/components/countdown/countdown.module.css +4 -4
- package/components/date-picker/date-picker.module.css +6 -6
- package/components/date-range-picker/date-range-picker.module.css +21 -21
- package/components/dialog/dialog.module.css +2 -2
- package/components/donut-chart/donut-chart.module.css +4 -4
- package/components/drawer/drawer.module.css +5 -5
- package/components/dropdown-menu/dropdown-menu.d.ts +71 -1
- package/components/dropdown-menu/dropdown-menu.js +100 -6
- package/components/dropdown-menu/dropdown-menu.module.css +15 -5
- package/components/elastic-slider/elastic-slider.module.css +4 -4
- package/components/expandable-card/expandable-card.module.css +1 -1
- package/components/expanding-button-group/expanding-button-group.module.css +1 -1
- package/components/expanding-search/expanding-search.module.css +9 -9
- package/components/file-dropzone/file-dropzone.module.css +21 -21
- package/components/file-upload/file-upload.module.css +7 -7
- package/components/filter-toolbar/filter-toolbar.module.css +9 -9
- package/components/floating-button-group/floating-button-group.module.css +6 -6
- package/components/gauge/gauge.module.css +2 -2
- package/components/hover-card/hover-card.module.css +2 -2
- package/components/image-compare/image-compare.module.css +4 -4
- package/components/inline-edit/inline-edit.module.css +12 -12
- package/components/json-viewer/json-viewer.module.css +12 -12
- package/components/line-chart/line-chart.module.css +8 -8
- package/components/mention-input/mention-input.module.css +8 -8
- package/components/metric-card/metric-card.module.css +1 -1
- package/components/money-input/money-input.module.css +9 -9
- package/components/morph-select/morph-select.module.css +13 -13
- package/components/multi-select/multi-select.module.css +6 -6
- package/components/nav-list/nav-list.d.ts +64 -0
- package/components/nav-list/nav-list.js +103 -0
- package/components/nav-list/nav-list.module.css +25 -0
- package/components/notification-center/notification-center.module.css +27 -27
- package/components/number-field/number-field.module.css +2 -2
- package/components/otp-input/otp-input.module.css +4 -4
- package/components/password-field/password-field.module.css +1 -1
- package/components/password-strength/password-strength.module.css +7 -7
- package/components/phone-input/phone-input.module.css +19 -19
- package/components/popover/popover.module.css +2 -2
- package/components/progress/progress.module.css +1 -1
- package/components/radio-cards/radio-cards.module.css +8 -8
- package/components/radio-group/radio-group.module.css +1 -1
- package/components/resizable-panels/resizable-panels.module.css +5 -5
- package/components/rich-text-editor/rich-text-editor.module.css +12 -12
- package/components/ridgeline/ridgeline.module.css +7 -7
- package/components/scroll-area/scroll-area.module.css +8 -8
- package/components/segmented-control/segmented-control.d.ts +3 -1
- package/components/segmented-control/segmented-control.js +2 -2
- package/components/segmented-control/segmented-control.module.css +7 -4
- package/components/select/select.module.css +5 -5
- package/components/shortcut-recorder/shortcut-recorder.module.css +15 -15
- package/components/signature-pad/signature-pad.module.css +11 -11
- package/components/slider/slider.module.css +4 -4
- package/components/slope-chart/slope-chart.module.css +7 -7
- package/components/sortable-data-table/sortable-data-table.module.css +4 -4
- package/components/split-button/split-button.module.css +5 -5
- package/components/stepper/stepper.module.css +3 -3
- package/components/streamgraph/streamgraph.module.css +7 -7
- package/components/swipe-actions/swipe-actions.module.css +5 -5
- package/components/switch/switch.module.css +1 -1
- package/components/tabs/tabs.d.ts +9 -2
- package/components/tabs/tabs.js +4 -2
- package/components/tabs/tabs.module.css +7 -2
- package/components/tag-input/tag-input.module.css +4 -4
- package/components/time-picker/time-picker.module.css +3 -3
- package/components/timeline/timeline.module.css +3 -3
- package/components/toast/toast.module.css +5 -5
- package/components/toast-stack/toast-stack.module.css +5 -5
- package/components/tooltip/tooltip.module.css +1 -1
- package/components/tree-view/tree-view.module.css +7 -7
- package/components/treemap/treemap.module.css +13 -13
- package/components/usage-meter/usage-meter.module.css +5 -5
- package/components/user-menu/user-menu.module.css +22 -22
- package/components/waffle-chart/waffle-chart.module.css +7 -7
- package/components.json +416 -1
- package/eslint.js +35 -3
- package/package.json +1 -1
- package/styles.css +44 -4
|
@@ -26,5 +26,5 @@
|
|
|
26
26
|
.option strong, .option small { display: block; }
|
|
27
27
|
.option strong { color: var(--text-secondary); font-size: var(--text-sm); font-weight: 500; transition: color var(--duration-standard) var(--ease-standard); }
|
|
28
28
|
.option:has(input:checked) strong { color: var(--foreground); }
|
|
29
|
-
.option small { margin-top:
|
|
29
|
+
.option small { margin-top: var(--space-hair); color: var(--text-muted); font-size: var(--text-xs); }
|
|
30
30
|
@media (prefers-reduced-motion: reduce) { .option, .mark, .mark::after, .option strong { transition: none; } .option:active .mark { transform: none; } }
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
|
|
15
15
|
/* The divider is a one pixel line with a 13px grab area, and a grip that forms while it is hovered, focused, or dragged. */
|
|
16
16
|
.handle { position: relative; z-index: 2; flex: 0 0 1px; background: var(--border); cursor: col-resize; touch-action: none; outline: none; -webkit-tap-highlight-color: transparent; transition: background-color var(--duration-fast) var(--ease-standard); }
|
|
17
|
-
.handle::before { position: absolute; inset: 0 -
|
|
17
|
+
.handle::before { position: absolute; inset: 0 calc(var(--space-related) * -1); content: ""; }
|
|
18
18
|
.handle[data-collapsed] { background: transparent; cursor: pointer; }
|
|
19
19
|
.grip { position: absolute; top: 50%; left: 50%; width: 4px; height: 32px; border-radius: var(--radius-full); corner-shape: round; background: var(--border-strong); opacity: 0; pointer-events: none; transform: translate(-50%, -50%) scaleY(.6); transition: opacity var(--duration-fast) var(--ease-standard), background-color var(--duration-fast) var(--ease-standard), transform var(--duration-spring) var(--ease-spring); }
|
|
20
20
|
@media (hover: hover) and (pointer: fine) {
|
|
@@ -28,10 +28,10 @@
|
|
|
28
28
|
.handle[data-collapsed]:focus-visible .restore { border-color: var(--border-strong); color: var(--foreground); }
|
|
29
29
|
|
|
30
30
|
/* Once a neighbour is hidden, a tab on the divider points the way it will come back. */
|
|
31
|
-
.restore { position: absolute; top: 50%; display: grid; width: 18px; height: 40px; margin-top: -
|
|
32
|
-
.restore[data-side="before"] { left:
|
|
33
|
-
.restore[data-side="after"] { right:
|
|
34
|
-
.handle[data-collapsed]::before { inset: 0 -
|
|
31
|
+
.restore { position: absolute; top: 50%; display: grid; width: 18px; height: 40px; margin-top: calc(var(--space-comfort) * -1); place-items: center; border: 1px solid var(--border); border-radius: var(--radius-full); corner-shape: round; background: var(--surface); box-shadow: var(--shadow-resting); color: var(--text-secondary); pointer-events: none; transition: border-color var(--duration-fast) var(--ease-standard), color var(--duration-fast) var(--ease-standard); }
|
|
32
|
+
.restore[data-side="before"] { left: var(--space-tight); transform-origin: 0 50%; }
|
|
33
|
+
.restore[data-side="after"] { right: var(--space-tight); transform-origin: 100% 50%; }
|
|
34
|
+
.handle[data-collapsed]::before { inset: 0 calc(var(--space-block) * -1); }
|
|
35
35
|
.handle[data-collapsed="before"]::before { left: 0; }
|
|
36
36
|
.handle[data-collapsed="after"]::before { right: 0; }
|
|
37
37
|
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
/* The writing surface. Everything inside is plain semantic HTML, styled here so pasted and typed content look the same. */
|
|
11
11
|
.editor {
|
|
12
12
|
min-height: 8rem;
|
|
13
|
-
padding:
|
|
13
|
+
padding: var(--space-hair) 0;
|
|
14
14
|
outline: none;
|
|
15
15
|
color: var(--foreground);
|
|
16
16
|
font-size: var(--text-base);
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
font-size: .86em;
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
-
.editor blockquote { padding-left:
|
|
51
|
+
.editor blockquote { padding-left: var(--space-inset); border-left: 2px solid var(--border-strong); color: var(--text-secondary); }
|
|
52
52
|
|
|
53
53
|
.editor ul,
|
|
54
54
|
.editor ol { margin-block: 0; padding-left: 1.45em; }
|
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
.editor ol > li::marker { font-variant-numeric: tabular-nums; }
|
|
64
64
|
|
|
65
65
|
.editor pre {
|
|
66
|
-
padding:
|
|
66
|
+
padding: var(--space-group) var(--space-inset);
|
|
67
67
|
overflow-x: auto;
|
|
68
68
|
border: 1px solid var(--border-subtle);
|
|
69
69
|
border-radius: var(--radius-control);
|
|
@@ -91,7 +91,7 @@
|
|
|
91
91
|
/* Floating toolbar. One surface whose size springs between its two faces. */
|
|
92
92
|
.toolbar {
|
|
93
93
|
position: absolute;
|
|
94
|
-
z-index:
|
|
94
|
+
z-index: var(--layer-popover);
|
|
95
95
|
translate: -50% -100%;
|
|
96
96
|
overflow: hidden;
|
|
97
97
|
border: 1px solid var(--border);
|
|
@@ -104,11 +104,11 @@
|
|
|
104
104
|
.face[inert] { pointer-events: none; }
|
|
105
105
|
|
|
106
106
|
.row,
|
|
107
|
-
.linkRow { display: flex; align-items: center; gap:
|
|
108
|
-
.blockTools { display: flex; align-items: center; gap:
|
|
107
|
+
.linkRow { display: flex; align-items: center; gap: var(--space-hair); padding: var(--space-tight); }
|
|
108
|
+
.blockTools { display: flex; align-items: center; gap: var(--space-hair); }
|
|
109
109
|
/* Narrow editors keep the inline marks; block types stay one slash away. */
|
|
110
110
|
@container (max-width: 330px) { .blockTools { display: none; } }
|
|
111
|
-
.divider { width: 1px; height: 18px; margin: 0
|
|
111
|
+
.divider { width: 1px; height: 18px; margin: 0 var(--space-tight); background: var(--border); }
|
|
112
112
|
|
|
113
113
|
.tool {
|
|
114
114
|
display: grid;
|
|
@@ -134,7 +134,7 @@
|
|
|
134
134
|
width: min(15rem, 60vw);
|
|
135
135
|
height: 32px;
|
|
136
136
|
min-width: 0;
|
|
137
|
-
padding: 0
|
|
137
|
+
padding: 0 var(--space-related);
|
|
138
138
|
border: 0;
|
|
139
139
|
background: transparent;
|
|
140
140
|
color: var(--foreground);
|
|
@@ -163,7 +163,7 @@
|
|
|
163
163
|
/* Slash menu. */
|
|
164
164
|
.slash {
|
|
165
165
|
position: absolute;
|
|
166
|
-
z-index:
|
|
166
|
+
z-index: var(--layer-dropdown);
|
|
167
167
|
width: 240px;
|
|
168
168
|
max-width: calc(100% - 8px);
|
|
169
169
|
overflow-x: hidden;
|
|
@@ -176,7 +176,7 @@
|
|
|
176
176
|
box-shadow: var(--shadow-floating);
|
|
177
177
|
}
|
|
178
178
|
.slash[data-above] { translate: 0 -100%; }
|
|
179
|
-
.slashBody { padding:
|
|
179
|
+
.slashBody { padding: var(--space-related); }
|
|
180
180
|
.slashList { position: relative; display: grid; margin: 0; padding: 0; list-style: none; }
|
|
181
181
|
.slashHighlight { position: absolute; top: 0; right: 0; left: 0; border-radius: var(--radius-control); background: color-mix(in oklab, var(--foreground) 6.5%, transparent); pointer-events: none; }
|
|
182
182
|
.slashOption {
|
|
@@ -184,8 +184,8 @@
|
|
|
184
184
|
display: flex;
|
|
185
185
|
height: 34px;
|
|
186
186
|
align-items: center;
|
|
187
|
-
gap:
|
|
188
|
-
padding: 0
|
|
187
|
+
gap: var(--space-group);
|
|
188
|
+
padding: 0 var(--space-group);
|
|
189
189
|
border-radius: var(--radius-control);
|
|
190
190
|
color: var(--text-secondary);
|
|
191
191
|
cursor: pointer;
|
|
@@ -35,19 +35,19 @@
|
|
|
35
35
|
|
|
36
36
|
.message { position: absolute; inset: 0; display: grid; place-items: center; margin: 0; color: var(--text-muted); font-size: var(--text-sm); pointer-events: none; }
|
|
37
37
|
|
|
38
|
-
.tooltip { position: absolute; top: 0; left: 0; z-index: 2; display: grid; min-width: 170px; max-width: min(240px, 100%); gap:
|
|
38
|
+
.tooltip { position: absolute; top: 0; left: 0; z-index: 2; display: grid; min-width: 170px; max-width: min(240px, 100%); gap: var(--space-hair); padding: var(--space-group) var(--space-group); border: 1px solid var(--border); border-radius: var(--radius-control); background: var(--surface-raised); box-shadow: var(--shadow-floating); opacity: 0; pointer-events: none; scale: .96; transition: opacity var(--duration-fast) var(--ease-standard), scale var(--duration-fast) var(--ease-standard); }
|
|
39
39
|
.plot[data-active] .tooltip { opacity: 1; scale: 1; }
|
|
40
|
-
.tipTitle { margin: 0 0
|
|
41
|
-
.tipValue, .tipRow { display: flex; align-items: baseline; justify-content: space-between; gap:
|
|
40
|
+
.tipTitle { margin: 0 0 var(--space-hair); color: var(--text-secondary); font-size: var(--text-xs); line-height: var(--leading-body); }
|
|
41
|
+
.tipValue, .tipRow { display: flex; align-items: baseline; justify-content: space-between; gap: var(--space-group); margin: 0; font-variant-numeric: tabular-nums; white-space: nowrap; }
|
|
42
42
|
.tipValue { color: var(--foreground); font-size: var(--text-sm); font-weight: 500; line-height: 1.4; }
|
|
43
43
|
.tipRow { color: var(--foreground); font-size: var(--text-xs); line-height: var(--leading-body); }
|
|
44
44
|
.tipKey { color: var(--text-muted); font-weight: 400; }
|
|
45
45
|
.tipValue .tipKey { font-size: var(--text-xs); }
|
|
46
|
-
.tipNote { margin:
|
|
46
|
+
.tipNote { margin: var(--space-tight) 0 0; color: var(--text-muted); font-size: var(--text-xs); line-height: var(--leading-body); font-variant-numeric: tabular-nums; }
|
|
47
47
|
|
|
48
|
-
.scale { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap:
|
|
49
|
-
.scaleLabel { margin-right:
|
|
50
|
-
.steps { display: inline-flex; gap:
|
|
48
|
+
.scale { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: var(--space-related); margin-top: var(--space-group); color: var(--text-muted); font-size: var(--text-xs); line-height: var(--leading-body); font-variant-numeric: tabular-nums; }
|
|
49
|
+
.scaleLabel { margin-right: var(--space-tight); color: var(--text-secondary); }
|
|
50
|
+
.steps { display: inline-flex; gap: var(--space-hair); }
|
|
51
51
|
.step { width: 18px; height: 10px; border-radius: var(--radius-detail); background: var(--ridge); }
|
|
52
52
|
|
|
53
53
|
.srOnly { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
|
|
@@ -40,10 +40,10 @@
|
|
|
40
40
|
touch-action: none;
|
|
41
41
|
transition: opacity var(--duration-considered) var(--ease-standard);
|
|
42
42
|
}
|
|
43
|
-
.track[data-axis="y"] { top:
|
|
44
|
-
.track[data-axis="x"] { right:
|
|
45
|
-
.root[data-orientation="both"] > .track[data-axis="y"] { bottom:
|
|
46
|
-
.root[data-orientation="both"] > .track[data-axis="x"] { right:
|
|
43
|
+
.track[data-axis="y"] { top: var(--space-tight); right: 1px; bottom: var(--space-tight); width: 11px; }
|
|
44
|
+
.track[data-axis="x"] { right: var(--space-tight); bottom: 1px; left: var(--space-tight); height: 11px; }
|
|
45
|
+
.root[data-orientation="both"] > .track[data-axis="y"] { bottom: var(--space-group); }
|
|
46
|
+
.root[data-orientation="both"] > .track[data-axis="x"] { right: var(--space-group); }
|
|
47
47
|
.track[data-hidden] { display: none; }
|
|
48
48
|
|
|
49
49
|
.thumb { position: absolute; top: 0; left: 0; will-change: transform; }
|
|
@@ -56,8 +56,8 @@
|
|
|
56
56
|
background: color-mix(in oklab, var(--foreground) 30%, transparent);
|
|
57
57
|
transition: width var(--duration-fast) var(--ease-standard), height var(--duration-fast) var(--ease-standard), background-color var(--duration-fast) var(--ease-standard);
|
|
58
58
|
}
|
|
59
|
-
.track[data-axis="y"] .thumb::after { top: 0; right:
|
|
60
|
-
.track[data-axis="x"] .thumb::after { right: 0; bottom:
|
|
59
|
+
.track[data-axis="y"] .thumb::after { top: 0; right: var(--space-tight); bottom: 0; width: 5px; }
|
|
60
|
+
.track[data-axis="x"] .thumb::after { right: 0; bottom: var(--space-tight); left: 0; height: 5px; }
|
|
61
61
|
|
|
62
62
|
/* Visible while scrolling, while the pointer is over the area, and always when asked. Appearing is quick; leaving lingers. */
|
|
63
63
|
.root[data-scrolling] > .track,
|
|
@@ -69,9 +69,9 @@
|
|
|
69
69
|
.track:hover .thumb::after,
|
|
70
70
|
.root[data-dragging] .thumb::after { background: color-mix(in oklab, var(--foreground) 46%, transparent); }
|
|
71
71
|
.track[data-axis="y"]:hover .thumb::after,
|
|
72
|
-
.root[data-dragging="y"] .track[data-axis="y"] .thumb::after { width: 7px; right:
|
|
72
|
+
.root[data-dragging="y"] .track[data-axis="y"] .thumb::after { width: 7px; right: var(--space-hair); }
|
|
73
73
|
.track[data-axis="x"]:hover .thumb::after,
|
|
74
|
-
.root[data-dragging="x"] .track[data-axis="x"] .thumb::after { height: 7px; bottom:
|
|
74
|
+
.root[data-dragging="x"] .track[data-axis="x"] .thumb::after { height: 7px; bottom: var(--space-hair); }
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
@media (prefers-reduced-motion: reduce) {
|
|
@@ -11,6 +11,8 @@ export interface SegmentedControlProps {
|
|
|
11
11
|
label?: string;
|
|
12
12
|
/** Called when the pointer or focus reaches an option, before it is chosen. Use it to start loading what that option shows. */
|
|
13
13
|
onOptionIntent?: (value: string) => void;
|
|
14
|
+
/** `sm` (default) or `xs`, a compact 24px control for dense UI such as an Edit/Read toggle in a toolbar. */
|
|
15
|
+
size?: "sm" | "xs";
|
|
14
16
|
className?: string;
|
|
15
17
|
}
|
|
16
|
-
export default function SegmentedControl({ options, value, onValueChange, label, onOptionIntent, className }: SegmentedControlProps): import("react").JSX.Element;
|
|
18
|
+
export default function SegmentedControl({ options, value, onValueChange, label, onOptionIntent, size, className }: SegmentedControlProps): import("react").JSX.Element;
|
|
@@ -4,7 +4,7 @@ import { useEffect, useId, useLayoutEffect, useRef } from "react";
|
|
|
4
4
|
import { LayoutGroup, motion, useReducedMotion } from "motion/react";
|
|
5
5
|
import { motionTokens } from "../../lib/motion-tokens.js";
|
|
6
6
|
import styles from "./segmented-control.module.css";
|
|
7
|
-
export default function SegmentedControl({ options, value, onValueChange, label, onOptionIntent, className }) {
|
|
7
|
+
export default function SegmentedControl({ options, value, onValueChange, label, onOptionIntent, size = "sm", className }) {
|
|
8
8
|
const id = useId();
|
|
9
9
|
const reduced = useReducedMotion();
|
|
10
10
|
const track = useRef(null);
|
|
@@ -52,5 +52,5 @@ export default function SegmentedControl({ options, value, onValueChange, label,
|
|
|
52
52
|
onValueChange(options[target].value);
|
|
53
53
|
track.current?.querySelector(`[data-value="${CSS.escape(options[target].value)}"]`)?.focus({ preventScroll: true });
|
|
54
54
|
};
|
|
55
|
-
return _jsx("div", { className: `${styles.root} ${className ?? ""}`, role: "group", "aria-label": label, children: _jsx(LayoutGroup, { id: id, children: _jsx(motion.div, { ref: track, layoutScroll: true, className: styles.track, children: options.map((option, index) => _jsxs("button", { id: `${id}-${option.value}`, className: styles.button, type: "button", "data-value": option.value, "aria-pressed": value === option.value, tabIndex: index === selectedIndex ? 0 : -1, onClick: () => onValueChange(option.value), onKeyDown: onKeyDown, onPointerEnter: onOptionIntent ? () => onOptionIntent(option.value) : undefined, onFocus: onOptionIntent ? () => onOptionIntent(option.value) : undefined, children: [value === option.value && _jsx(motion.span, { className: styles.selection, layoutId: "selection", layoutDependency: value, transition: reduced ? { duration: 0 } : motionTokens.spring.morph, "aria-hidden": "true" }), _jsxs("span", { className: styles.label, children: [option.label, option.accessory] })] }, option.value)) }) }) });
|
|
55
|
+
return _jsx("div", { className: `${styles.root} ${className ?? ""}`, role: "group", "aria-label": label, "data-size": size, children: _jsx(LayoutGroup, { id: id, children: _jsx(motion.div, { ref: track, layoutScroll: true, className: styles.track, children: options.map((option, index) => _jsxs("button", { id: `${id}-${option.value}`, className: styles.button, type: "button", "data-value": option.value, "aria-pressed": value === option.value, tabIndex: index === selectedIndex ? 0 : -1, onClick: () => onValueChange(option.value), onKeyDown: onKeyDown, onPointerEnter: onOptionIntent ? () => onOptionIntent(option.value) : undefined, onFocus: onOptionIntent ? () => onOptionIntent(option.value) : undefined, children: [value === option.value && _jsx(motion.span, { className: styles.selection, layoutId: "selection", layoutDependency: value, transition: reduced ? { duration: 0 } : motionTokens.spring.morph, "aria-hidden": "true" }), _jsxs("span", { className: styles.label, children: [option.label, option.accessory] })] }, option.value)) }) }) });
|
|
56
56
|
}
|
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
/* The frame can shrink below its content inside flex and grid parents; the track then scrolls inside it. */
|
|
2
2
|
.root { display: inline-flex; min-width: 0; max-width: 100%; flex-shrink: 1; border: 1px solid var(--border); border-radius: var(--radius-control); background: var(--surface-muted); }
|
|
3
3
|
/* The track owns the stacking context so the gliding highlight passes under every label, not over earlier ones. */
|
|
4
|
-
.track { --fade-start: 0px; --fade-end: 0px; isolation: isolate; display: flex; min-width: 0; gap:
|
|
4
|
+
.track { --fade-start: 0px; --fade-end: 0px; isolation: isolate; display: flex; min-width: 0; gap: var(--space-hair); overflow-x: auto; overscroll-behavior-x: contain; padding: var(--space-tight); border-radius: inherit; corner-shape: inherit; scrollbar-width: none; -webkit-mask-image: linear-gradient(to right, transparent, #000 var(--fade-start), #000 calc(100% - var(--fade-end)), transparent); mask-image: linear-gradient(to right, transparent, #000 var(--fade-start), #000 calc(100% - var(--fade-end)), transparent); }
|
|
5
5
|
.track::-webkit-scrollbar { display: none; }
|
|
6
6
|
.track[data-fade-start] { --fade-start: 20px; }
|
|
7
7
|
.track[data-fade-end] { --fade-end: 20px; }
|
|
8
8
|
/* Items never scale or change weight; only the highlight travels and the label color follows it. */
|
|
9
|
-
.button { position: relative; flex: 0 0 auto; min-height: var(--control-height-sm); border: 0; border-radius: calc(var(--radius-control) -
|
|
9
|
+
.button { position: relative; flex: 0 0 auto; min-height: var(--control-height-sm); border: 0; border-radius: calc(var(--radius-control) - var(--space-tight)); padding: 0 var(--space-group); background: transparent; color: var(--text-muted); font: inherit; font-size: var(--text-sm); font-weight: 500; white-space: nowrap; cursor: pointer; -webkit-tap-highlight-color: transparent; transition: color var(--duration-fast) var(--ease-standard); }
|
|
10
10
|
@media (hover: hover) and (pointer: fine) { .button:hover { color: var(--foreground); } }
|
|
11
11
|
.button:active, .button[aria-pressed="true"] { color: var(--foreground); }
|
|
12
12
|
.selection { position: absolute; z-index: -1; inset: 0; border: 1px solid var(--border); border-radius: inherit; corner-shape: inherit; background: var(--surface); box-shadow: var(--shadow-resting); }
|
|
13
|
-
.label { position: relative; z-index: 1; display: inline-flex; align-items: center; gap:
|
|
14
|
-
|
|
13
|
+
.label { position: relative; z-index: 1; display: inline-flex; align-items: center; gap: var(--space-related); }
|
|
14
|
+
/* Compact: 24px segments in a thinner track, at the small type step. */
|
|
15
|
+
.root[data-size="xs"] .track { padding: var(--space-hair); }
|
|
16
|
+
.root[data-size="xs"] .button { min-height: var(--control-height-xs); padding: 0 var(--space-related); font-size: var(--text-xs); }
|
|
17
|
+
@media (max-width: 380px) { .button { padding: 0 var(--space-group); } }
|
|
15
18
|
@media (prefers-reduced-motion: reduce) { .button { transition: none; } }
|
|
@@ -14,17 +14,17 @@
|
|
|
14
14
|
.trigger[data-state="open"] .chevron { transform: rotate(180deg); }
|
|
15
15
|
.hint { color: var(--text-muted); font-size: var(--text-xs); }
|
|
16
16
|
/* Radix holds the animation until the menu is positioned, so it always grows from the trigger edge. */
|
|
17
|
-
.content { --menu-x: 0px; --menu-y: -6px; box-sizing: border-box; z-index:
|
|
17
|
+
.content { --menu-x: 0px; --menu-y: -6px; box-sizing: border-box; z-index: var(--layer-dropdown); width: var(--radix-select-trigger-width); min-width: var(--radix-select-trigger-width); max-width: min(24rem, calc(100vw - 20px)); max-height: min(320px, var(--radix-select-content-available-height)); overflow: hidden; border: 1px solid var(--border); border-radius: calc(var(--radius-control) + var(--space-hair)); padding: var(--space-related); background: var(--surface-raised); color: var(--foreground); box-shadow: var(--shadow-floating); transform-origin: var(--radix-select-content-transform-origin); animation: select-in var(--duration-standard) var(--ease-enter) both; }
|
|
18
18
|
.content[data-side="top"] { --menu-y: 6px; }
|
|
19
19
|
.content[data-side="left"] { --menu-x: 6px; --menu-y: 0px; }
|
|
20
20
|
.content[data-side="right"] { --menu-x: -6px; --menu-y: 0px; }
|
|
21
21
|
.content[data-state="closed"] { animation: select-out var(--duration-instant) var(--ease-standard) both; }
|
|
22
|
-
.viewport { position: relative; padding:
|
|
22
|
+
.viewport { position: relative; padding: var(--space-hair) 0; }
|
|
23
23
|
/* One highlight glides between options for the pointer and jumps instantly for the keyboard (lib/menu-highlight). */
|
|
24
|
-
.highlight { position: absolute; top: 0; right: 0; left: 0; border-radius: calc(var(--radius-control) -
|
|
25
|
-
.item { position: relative; display: flex; align-items: center; min-height: 36px; border-radius: calc(var(--radius-control) -
|
|
24
|
+
.highlight { position: absolute; top: 0; right: 0; left: 0; border-radius: calc(var(--radius-control) - var(--space-tight)); background: var(--surface-muted); opacity: 0; pointer-events: none; }
|
|
25
|
+
.item { position: relative; display: flex; align-items: center; min-height: 36px; border-radius: calc(var(--radius-control) - var(--space-tight)); padding: 0 var(--space-block) 0 var(--space-group); color: var(--foreground); font-size: var(--text-sm); cursor: default; outline: none; user-select: none; transition: background-color var(--duration-instant) var(--ease-standard), color var(--duration-instant) var(--ease-standard); }
|
|
26
26
|
.item[data-disabled] { opacity: .45; }
|
|
27
|
-
.indicator { position: absolute; right:
|
|
27
|
+
.indicator { position: absolute; right: var(--space-group); display: inline-flex; align-items: center; color: var(--foreground); animation: indicator-in var(--duration-standard) var(--ease-enter) 40ms both; }
|
|
28
28
|
.scrollButton { display: grid; height: 28px; place-items: center; color: var(--text-muted); }
|
|
29
29
|
@keyframes select-in { from { opacity: 0; transform: translate(var(--menu-x), var(--menu-y)) scale(.97); } }
|
|
30
30
|
@keyframes select-out { to { opacity: 0; transform: translate(calc(var(--menu-x) / 2), calc(var(--menu-y) / 2)) scale(.98); } }
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/* ---------------------------------------------- Kbd ---------------------------------------------- */
|
|
2
2
|
|
|
3
3
|
/* A key cap: a one pixel edge with a slightly heavier bottom, so it reads as a key without a shadow. Held, it drops a pixel and takes the accent. */
|
|
4
|
-
.kbd { display: inline-grid; min-width: 26px; height: 26px; box-sizing: border-box; place-items: center; padding: 0
|
|
5
|
-
.kbd[data-size="sm"] { min-width: 22px; height: 22px; padding: 0
|
|
4
|
+
.kbd { display: inline-grid; min-width: 26px; height: 26px; box-sizing: border-box; place-items: center; padding: 0 var(--space-related) 1px; border: 1px solid var(--border-strong); border-bottom-width: 2px; border-radius: var(--radius-detail); corner-shape: var(--corner-shape); background: var(--surface-raised); color: var(--foreground); font-family: var(--font-body); font-size: var(--text-xs); font-weight: 500; line-height: 1; letter-spacing: 0; font-variant-numeric: tabular-nums; white-space: nowrap; transition: transform var(--duration-spring) var(--ease-spring), border-color var(--duration-fast) var(--ease-standard), background-color var(--duration-fast) var(--ease-standard), color var(--duration-fast) var(--ease-standard), border-bottom-width var(--duration-fast) var(--ease-standard); }
|
|
5
|
+
.kbd[data-size="sm"] { min-width: 22px; height: 22px; padding: 0 var(--space-tight) 1px; border-radius: var(--radius-detail); corner-shape: var(--corner-shape); font-size: var(--text-xs); }
|
|
6
6
|
.kbd[data-pressed] { transform: translateY(1px); border-color: color-mix(in oklab, var(--accent) 55%, var(--border-strong)); border-bottom-width: 1px; background: var(--accent-subtle); color: var(--accent-strong); transition-duration: 90ms; }
|
|
7
7
|
.kbd[data-tone="warning"] { border-color: color-mix(in oklab, var(--warning) 55%, var(--border-strong)); background: color-mix(in oklab, var(--warning) 12%, var(--surface-raised)); color: var(--foreground); }
|
|
8
|
-
.keys { display: inline-flex; flex: none; align-items: center; gap:
|
|
8
|
+
.keys { display: inline-flex; flex: none; align-items: center; gap: var(--space-tight); }
|
|
9
9
|
|
|
10
10
|
/* ---------------------------------------------- Recorder ---------------------------------------------- */
|
|
11
11
|
|
|
@@ -19,27 +19,27 @@
|
|
|
19
19
|
.control[data-state="conflict"] { border-color: var(--warning); }
|
|
20
20
|
.field[data-disabled] .control { opacity: .5; background: var(--surface-muted); }
|
|
21
21
|
|
|
22
|
-
.recorder { display: flex; min-width: 0; height: 100%; flex: 1; align-items: center; padding: 0
|
|
22
|
+
.recorder { display: flex; min-width: 0; height: 100%; flex: 1; align-items: center; padding: 0 var(--space-related) 0 var(--space-related); border: 0; border-radius: var(--radius-control); corner-shape: var(--corner-shape); background: transparent; color: var(--foreground); cursor: pointer; font: inherit; text-align: left; -webkit-tap-highlight-color: transparent; touch-action: manipulation; outline: none; }
|
|
23
23
|
.recorder:disabled { cursor: not-allowed; }
|
|
24
|
-
.row { position: relative; display: flex; min-width: 0; align-items: center; gap:
|
|
24
|
+
.row { position: relative; display: flex; min-width: 0; align-items: center; gap: var(--space-tight); }
|
|
25
25
|
.chipSlot { display: inline-flex; }
|
|
26
|
-
.placeholder { padding-left:
|
|
26
|
+
.placeholder { padding-left: var(--space-tight); color: var(--text-muted); font-size: var(--text-sm); white-space: nowrap; }
|
|
27
27
|
.placeholder[data-recording] { color: var(--text-secondary); }
|
|
28
28
|
/* A recording light: steady in reduced motion, a slow breath otherwise. */
|
|
29
|
-
.dot { width: 7px; height: 7px; flex: none; margin: 0
|
|
29
|
+
.dot { width: 7px; height: 7px; flex: none; margin: 0 var(--space-related) 0 var(--space-tight); border-radius: 50%; corner-shape: round; background: var(--accent); animation: breathe 1.4s var(--ease-in-out) infinite; }
|
|
30
30
|
.dot[data-reduced] { animation: none; }
|
|
31
31
|
@keyframes breathe { 50% { opacity: .35; } }
|
|
32
32
|
|
|
33
|
-
.actions { display: flex; flex: none; align-items: center; gap:
|
|
34
|
-
.action { display: grid; width: 32px; height: 32px; place-items: center; padding: 0; border: 0; border-radius: calc(var(--radius-control) -
|
|
33
|
+
.actions { display: flex; flex: none; align-items: center; gap: var(--space-hair); padding-right: var(--space-tight); }
|
|
34
|
+
.action { display: grid; width: 32px; height: 32px; place-items: center; padding: 0; border: 0; border-radius: calc(var(--radius-control) - var(--space-tight)); corner-shape: var(--corner-shape); background: transparent; color: var(--text-muted); cursor: pointer; -webkit-tap-highlight-color: transparent; transition: background-color var(--duration-fast) var(--ease-standard), color var(--duration-fast) var(--ease-standard); }
|
|
35
35
|
@media (hover: hover) and (pointer: fine) { .action:hover { background: var(--surface-muted); color: var(--foreground); } }
|
|
36
36
|
.action:active, .action:focus-visible { background: var(--surface-muted); color: var(--foreground); outline: none; }
|
|
37
37
|
|
|
38
38
|
.messageSlot { position: relative; overflow: hidden; }
|
|
39
|
-
.message { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap:
|
|
39
|
+
.message { display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: var(--space-hair) var(--space-group); padding-top: var(--space-related); font-size: var(--text-xs); line-height: var(--leading-body); }
|
|
40
40
|
.message[data-tone="hint"] { color: var(--text-muted); }
|
|
41
41
|
.message[data-tone="warning"] { color: var(--text-secondary); }
|
|
42
|
-
.message[data-tone="warning"] .messageText::before { content: ""; display: inline-block; width: 6px; height: 6px; margin: 0
|
|
42
|
+
.message[data-tone="warning"] .messageText::before { content: ""; display: inline-block; width: 6px; height: 6px; margin: 0 var(--space-related) 1px 1px; border-radius: 50%; corner-shape: round; background: var(--warning); vertical-align: middle; }
|
|
43
43
|
.strong { color: var(--foreground); font-weight: 500; }
|
|
44
44
|
.messageActions { display: inline-flex; gap: var(--space-group); }
|
|
45
45
|
.link { padding: 0; border: 0; background: none; color: var(--foreground); cursor: pointer; font: inherit; font-weight: 500; text-decoration: underline; text-decoration-color: var(--border-strong); text-underline-offset: 3px; transition: text-decoration-color var(--duration-fast) var(--ease-standard), color var(--duration-fast) var(--ease-standard); }
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
/* ---------------------------------------------- Cheatsheet ---------------------------------------------- */
|
|
51
51
|
|
|
52
52
|
.list { container-type: inline-size; display: grid; min-width: 0; gap: var(--space-group); font-family: var(--font-body); letter-spacing: var(--tracking-body); }
|
|
53
|
-
.searchRow { display: flex; height: var(--control-height-sm); box-sizing: border-box; align-items: center; gap: var(--space-related); padding: 0
|
|
53
|
+
.searchRow { display: flex; height: var(--control-height-sm); box-sizing: border-box; align-items: center; gap: var(--space-related); padding: 0 var(--space-related) 0 var(--space-group); border: 1px solid var(--border); border-radius: var(--radius-control); corner-shape: var(--corner-shape); background: var(--surface); transition: border-color var(--duration-fast) var(--ease-standard); }
|
|
54
54
|
.searchRow:focus-within { border-color: var(--foreground); }
|
|
55
55
|
.searchIcon { flex: none; color: var(--text-muted); }
|
|
56
56
|
.search { min-width: 0; height: 100%; flex: 1; padding: 0; border: 0; background: transparent; color: var(--foreground); font: inherit; font-size: var(--text-sm); outline: none; -webkit-appearance: none; appearance: none; }
|
|
@@ -62,12 +62,12 @@
|
|
|
62
62
|
|
|
63
63
|
.groups { display: grid; align-items: start; gap: 0 var(--space-section); }
|
|
64
64
|
@container (min-width: 520px) { .groups { grid-template-columns: 1fr 1fr; } }
|
|
65
|
-
.group { overflow: hidden; margin-inline: -
|
|
65
|
+
.group { overflow: hidden; margin-inline: calc(var(--space-related) * -1); padding-inline: var(--space-related); }
|
|
66
66
|
.groupLabel { margin: 0; padding: var(--space-group) 0 var(--space-tight); color: var(--text-muted); font-size: var(--text-xs); font-weight: 400; }
|
|
67
67
|
.rows { display: grid; margin: 0; padding: 0; list-style: none; }
|
|
68
|
-
.item { overflow: hidden; margin-inline: -
|
|
68
|
+
.item { overflow: hidden; margin-inline: calc(var(--space-related) * -1); }
|
|
69
69
|
/* Rows fade when a held modifier is not in them, and light when their whole combination is down. */
|
|
70
|
-
.itemInner { display: flex; min-height: 36px; align-items: center; justify-content: space-between; gap: var(--space-group); padding: 0
|
|
70
|
+
.itemInner { display: flex; min-height: 36px; align-items: center; justify-content: space-between; gap: var(--space-group); padding: 0 var(--space-related); border-radius: var(--radius-detail); corner-shape: var(--corner-shape); transition: opacity var(--duration-standard) var(--ease-standard), background-color var(--duration-fast) var(--ease-standard); }
|
|
71
71
|
.item + .item .itemInner { box-shadow: inset 0 1px 0 var(--border-subtle); }
|
|
72
72
|
.item[data-dim] .itemInner { opacity: .38; }
|
|
73
73
|
.item[data-match] .itemInner { background: var(--accent-subtle); box-shadow: none; }
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
--ink-black: var(--foreground);
|
|
3
3
|
--ink-blue: oklch(46% .17 262);
|
|
4
4
|
--ink-violet: oklch(49% .2 292);
|
|
5
|
-
display: grid; gap:
|
|
5
|
+
display: grid; gap: var(--space-group); width: 100%; min-width: 0; font-family: var(--font-body); letter-spacing: var(--tracking-body);
|
|
6
6
|
}
|
|
7
7
|
:global(:root[data-theme="dark"]) .root { --ink-blue: oklch(76% .12 258); --ink-violet: oklch(77% .13 295); }
|
|
8
8
|
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
.guide { position: absolute; inset: 0; pointer-events: none; }
|
|
18
18
|
.baseline { position: absolute; left: 7%; right: 7%; top: 72%; border-top: 1.5px dashed var(--border-strong); }
|
|
19
19
|
.mark { position: absolute; left: 7%; top: 72%; color: var(--text-muted); translate: 0 calc(-100% - 6px); }
|
|
20
|
-
.signer { position: absolute; left: 7%; top: calc(72% +
|
|
20
|
+
.signer { position: absolute; left: 7%; top: calc(72% + var(--space-related)); color: var(--text-muted); font-size: var(--text-xs); line-height: var(--leading-body); }
|
|
21
21
|
.hint {
|
|
22
22
|
position: absolute; left: 50%; top: 72%; translate: -50% calc(-100% - 8px); color: var(--text-muted);
|
|
23
23
|
font-size: var(--text-lg); line-height: var(--leading-body); white-space: nowrap;
|
|
@@ -37,15 +37,15 @@
|
|
|
37
37
|
background: var(--foreground); opacity: .5;
|
|
38
38
|
}
|
|
39
39
|
.sweep::after {
|
|
40
|
-
content: ""; position: absolute; top: 0; bottom: 0; left: -
|
|
40
|
+
content: ""; position: absolute; top: 0; bottom: 0; left: calc(var(--space-block) * -1); width: 28px;
|
|
41
41
|
background: linear-gradient(to right, transparent, color-mix(in oklab, var(--foreground) 5%, transparent));
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
-
.toolbar { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap:
|
|
45
|
-
.group { display: flex; align-items: center; gap:
|
|
46
|
-
.divider { width: 1px; height: 20px; margin: 0
|
|
44
|
+
.toolbar { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: var(--space-related); }
|
|
45
|
+
.group { display: flex; align-items: center; gap: var(--space-hair); }
|
|
46
|
+
.divider { width: 1px; height: 20px; margin: 0 var(--space-related); background: var(--border); }
|
|
47
47
|
|
|
48
|
-
.choice { display: flex; align-items: center; gap:
|
|
48
|
+
.choice { display: flex; align-items: center; gap: var(--space-hair); }
|
|
49
49
|
.option {
|
|
50
50
|
position: relative; display: grid; place-items: center; width: 36px; height: 36px; padding: 0; border: 0; border-radius: var(--radius-full); corner-shape: round;
|
|
51
51
|
background: transparent; color: var(--foreground); cursor: pointer; -webkit-tap-highlight-color: transparent;
|
|
@@ -66,16 +66,16 @@
|
|
|
66
66
|
.iconButton[aria-pressed="true"] { background: var(--surface-muted); color: var(--foreground); }
|
|
67
67
|
.swap { display: grid; place-items: center; }
|
|
68
68
|
|
|
69
|
-
.exports { display: flex; align-items: center; justify-content: flex-end; gap:
|
|
70
|
-
.exportLabel { margin-right:
|
|
69
|
+
.exports { display: flex; align-items: center; justify-content: flex-end; gap: var(--space-related); }
|
|
70
|
+
.exportLabel { margin-right: var(--space-tight); color: var(--text-muted); font-size: var(--text-xs); }
|
|
71
71
|
.export {
|
|
72
|
-
display: grid; min-width: 76px; height: var(--control-height-sm); padding: 0
|
|
72
|
+
display: grid; min-width: 76px; height: var(--control-height-sm); padding: 0 var(--space-group); border: 1px solid var(--border); border-radius: var(--radius-control); corner-shape: var(--corner-shape);
|
|
73
73
|
background: var(--surface); color: var(--foreground); font: inherit; font-size: var(--text-sm); cursor: pointer; -webkit-tap-highlight-color: transparent;
|
|
74
74
|
transition: background-color var(--duration-fast) var(--ease-standard), transform var(--duration-instant) var(--ease-standard);
|
|
75
75
|
}
|
|
76
76
|
.export:active:not(:disabled) { transform: scale(.97); }
|
|
77
77
|
.export:disabled { color: var(--text-muted); cursor: default; }
|
|
78
|
-
.exportContent { display: inline-flex; grid-area: 1 / 1; align-items: center; justify-content: center; gap:
|
|
78
|
+
.exportContent { display: inline-flex; grid-area: 1 / 1; align-items: center; justify-content: center; gap: var(--space-related); }
|
|
79
79
|
|
|
80
80
|
.srOnly { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
|
|
81
81
|
|
|
@@ -13,19 +13,19 @@
|
|
|
13
13
|
.track { position: absolute; top: 50%; right: calc(var(--slider-thumb) / 2); left: calc(var(--slider-thumb) / 2); height: var(--slider-track); margin-top: calc(var(--slider-track) / -2); border-radius: var(--radius-full); corner-shape: round; background: var(--control-track); }
|
|
14
14
|
/* The fill spans the track and is revealed by a clip that follows the thumbs on the same frame. Ticks inside it are the "on" set, cut exactly at the thumb. */
|
|
15
15
|
.fill { position: absolute; inset: 0; border-radius: inherit; corner-shape: inherit; background: var(--control-fill); }
|
|
16
|
-
.tick { position: absolute; top: 50%; width: 4px; height: 4px; margin: -
|
|
16
|
+
.tick { position: absolute; top: 50%; width: 4px; height: 4px; margin: calc(var(--space-hair) * -1) 0 0 calc(var(--space-hair) * -1); border-radius: var(--radius-full); corner-shape: round; background: color-mix(in oklab, var(--foreground) 30%, transparent); }
|
|
17
17
|
.fill .tick { background: color-mix(in oklab, var(--control-glyph) 60%, transparent); }
|
|
18
18
|
.thumbs { position: absolute; inset: 0 calc(var(--slider-thumb) / 2); container-type: inline-size; pointer-events: none; }
|
|
19
19
|
/* Each layer is as wide as the track and slides by a percentage of itself; it only ever overflows to the left, which never scrolls. */
|
|
20
20
|
.thumbLayer { position: absolute; inset: 0; }
|
|
21
21
|
/* Centering uses the translate property, so Motion's scale on transform composes with it instead of replacing it. */
|
|
22
22
|
.thumb { position: absolute; top: 50%; right: 0; box-sizing: border-box; width: var(--slider-thumb); height: var(--slider-thumb); translate: 50% -50%; border: 0; border-radius: var(--radius-full); corner-shape: round; background: var(--control-thumb); box-shadow: var(--control-thumb-shadow); pointer-events: auto; cursor: grab; transition: box-shadow var(--duration-fast) var(--ease-standard); }
|
|
23
|
-
.thumb::after { content: ""; position: absolute; inset: -
|
|
23
|
+
.thumb::after { content: ""; position: absolute; inset: calc(var(--space-group) * -1); border-radius: inherit; corner-shape: inherit; }
|
|
24
24
|
.root[data-dragging], .root[data-dragging] .control, .root[data-dragging] .thumb { cursor: grabbing; }
|
|
25
25
|
/* The bubble centers on the thumb until it would pass the component's edge, then holds there. --at is the thumb position in percent of
|
|
26
26
|
the track, written each frame, and cqw measures the track, so the clamp needs no JavaScript measuring. It floats higher on touch so a fingertip never hides it. */
|
|
27
|
-
.bubbleAnchor { --edge: calc(var(--slider-thumb) / 2); --x: calc(var(--at, 0) * 1cqw); position: absolute; right: 0; bottom: calc(50% + var(--slider-thumb) / 2 +
|
|
28
|
-
@media (pointer: coarse) { .bubbleAnchor { bottom: calc(50% + var(--slider-thumb) / 2 +
|
|
27
|
+
.bubbleAnchor { --edge: calc(var(--slider-thumb) / 2); --x: calc(var(--at, 0) * 1cqw); position: absolute; right: 0; bottom: calc(50% + var(--slider-thumb) / 2 + var(--space-related)); display: flex; translate: clamp(calc(100% - var(--edge) - var(--x)), 50%, calc(100cqw + var(--edge) - var(--x))) 0; pointer-events: none; }
|
|
28
|
+
@media (pointer: coarse) { .bubbleAnchor { bottom: calc(50% + var(--slider-thumb) / 2 + var(--space-comfort)); } }
|
|
29
29
|
.bubble { display: inline-flex; min-height: 1.75rem; align-items: center; padding: 0 var(--space-group); border: 1px solid color-mix(in oklab, var(--background) 14%, var(--foreground)); border-radius: var(--radius-full); corner-shape: round; background: var(--foreground); color: var(--background); box-shadow: var(--shadow-raised); font-size: var(--text-sm); font-weight: 500; white-space: nowrap; transform-origin: 50% 100%; }
|
|
30
30
|
/* Mark labels sit on their ticks; one at a limit keeps its outer edge inside the component. */
|
|
31
31
|
.marks { position: relative; grid-area: 2 / 2; height: 1.25rem; margin: calc(var(--space-tight) * -1) calc(var(--slider-thumb) / 2) 0; color: var(--text-muted); font-size: var(--text-xs); font-variant-numeric: tabular-nums; }
|
|
@@ -21,27 +21,27 @@
|
|
|
21
21
|
|
|
22
22
|
.labels { transition: opacity var(--duration-standard) var(--ease-standard); }
|
|
23
23
|
.labels[data-dim] { opacity: .3; }
|
|
24
|
-
.start, .end { position: absolute; top: 0; display: flex; height: 20px; align-items: center; gap:
|
|
24
|
+
.start, .end { position: absolute; top: 0; display: flex; height: 20px; align-items: center; gap: var(--space-related); margin-top: calc(var(--space-group) * -1); font-size: var(--text-sm); line-height: 20px; white-space: nowrap; pointer-events: none; }
|
|
25
25
|
.start { justify-content: flex-end; max-width: 100%; }
|
|
26
26
|
/* On a phone the labels step down a size so the longest names fit beside the first column instead of running off the edge. */
|
|
27
|
-
.stage[data-narrow] .start, .stage[data-narrow] .end { gap:
|
|
27
|
+
.stage[data-narrow] .start, .stage[data-narrow] .end { gap: var(--space-related); font-size: var(--text-xs); }
|
|
28
28
|
.name { min-width: 0; overflow: hidden; color: var(--text-secondary); text-overflow: ellipsis; }
|
|
29
29
|
.value { color: var(--foreground); font-variant-numeric: tabular-nums; }
|
|
30
30
|
.labels[data-on] .name, .labels[data-accent] .name { color: var(--foreground); }
|
|
31
31
|
/* Only the story item is medium; the item in focus changes color, not weight, so its label never shifts sideways. */
|
|
32
32
|
.labels[data-accent] .value { font-weight: 500; }
|
|
33
33
|
|
|
34
|
-
.rank { display: inline-flex; min-width: 30px; align-items: center; gap:
|
|
34
|
+
.rank { display: inline-flex; min-width: 30px; align-items: center; gap: var(--space-hair); color: var(--text-muted); font-size: var(--text-xs); font-variant-numeric: tabular-nums; }
|
|
35
35
|
.rank[data-move="up"] { color: var(--text-secondary); }
|
|
36
36
|
.rankSwap { position: relative; display: inline-flex; overflow: hidden; }
|
|
37
37
|
|
|
38
|
-
.tooltip { position: absolute; top: 0; left: 0; z-index: 2; display: grid; min-width: 168px; max-width: min(240px, 100%); gap:
|
|
38
|
+
.tooltip { position: absolute; top: 0; left: 0; z-index: 2; display: grid; min-width: 168px; max-width: min(240px, 100%); gap: var(--space-tight); padding: var(--space-group) var(--space-group); border: 1px solid var(--border); border-radius: var(--radius-control); background: var(--surface-raised); box-shadow: var(--shadow-floating); opacity: 0; pointer-events: none; scale: .96; transition: opacity var(--duration-fast) var(--ease-standard), scale var(--duration-fast) var(--ease-standard); }
|
|
39
39
|
.stage[data-active] .tooltip { opacity: 1; scale: 1; }
|
|
40
|
-
.tipTitle { margin: 0 0
|
|
41
|
-
.tipRow { display: flex; align-items: center; justify-content: space-between; gap:
|
|
40
|
+
.tipTitle { margin: 0 0 var(--space-hair); color: var(--foreground); font-size: var(--text-sm); font-weight: 500; line-height: var(--leading-body); white-space: nowrap; }
|
|
41
|
+
.tipRow { display: flex; align-items: center; justify-content: space-between; gap: var(--space-group); margin: 0; font-size: var(--text-sm); line-height: 1.3; }
|
|
42
42
|
.tipName { color: var(--text-secondary); }
|
|
43
43
|
.tipValue { color: var(--foreground); font-weight: 500; font-variant-numeric: tabular-nums; }
|
|
44
|
-
.tipMeta { margin:
|
|
44
|
+
.tipMeta { margin: var(--space-hair) 0 0; color: var(--text-muted); font-size: var(--text-xs); line-height: var(--leading-body); font-variant-numeric: tabular-nums; }
|
|
45
45
|
|
|
46
46
|
.message { display: grid; min-height: 160px; place-items: center; margin: 0; color: var(--text-muted); font-size: var(--text-sm); }
|
|
47
47
|
.srOnly { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
|
|
22
22
|
.sortButton { display: flex; width: 100%; height: 44px; align-items: center; justify-content: flex-start; border: 0; padding: 0 var(--space-inset); background: transparent; color: inherit; font: inherit; letter-spacing: inherit; cursor: pointer; -webkit-tap-highlight-color: transparent; }
|
|
23
23
|
.table th[data-numeric] .sortButton { justify-content: flex-end; }
|
|
24
|
-
.sortInner { display: inline-flex; align-items: center; gap:
|
|
24
|
+
.sortInner { display: inline-flex; align-items: center; gap: var(--space-related); border-radius: var(--radius-control); transition: color var(--duration-fast) var(--ease-standard); }
|
|
25
25
|
/* Right-aligned columns lead with the arrow so the label lines up with the digits below it. */
|
|
26
26
|
.table th[data-numeric] .sortInner { flex-direction: row-reverse; }
|
|
27
27
|
.sortIcon { position: relative; display: grid; width: 16px; height: 16px; flex: none; place-items: center; }
|
|
@@ -79,15 +79,15 @@
|
|
|
79
79
|
.table th.selectCell .selectHit { height: 32px; }
|
|
80
80
|
/* Once the strip scrolls, a fade off the pinned cell hides the word sliding under it. */
|
|
81
81
|
.table th.selectCell::after { position: absolute; top: 0; bottom: 0; left: 100%; width: 36px; background: linear-gradient(to right, var(--surface) 45%, transparent); content: ""; opacity: 0; pointer-events: none; animation: stripFade linear both; animation-timeline: scroll(nearest inline); animation-range: 0 24px; }
|
|
82
|
-
.table th .sortButton, .table[data-selectable] th[data-primary] .sortButton { width: auto; height: 32px; border-radius: var(--radius-control); padding: 0
|
|
82
|
+
.table th .sortButton, .table[data-selectable] th[data-primary] .sortButton { width: auto; height: 32px; border-radius: var(--radius-control); padding: 0 var(--space-group); transition: background-color var(--duration-standard) var(--ease-standard), color var(--duration-standard) var(--ease-standard); }
|
|
83
83
|
.table th[data-sorted] .sortButton { background: var(--surface-muted); }
|
|
84
84
|
.table th[data-numeric] .sortInner { flex-direction: row; }
|
|
85
85
|
.sortButton:focus-visible { --focus-outline-offset: 1px; }
|
|
86
86
|
.table tbody { display: block; width: 100%; }
|
|
87
87
|
/* Rows fold into two lines: the first column with its number, then the remaining details. */
|
|
88
|
-
.table tbody tr { --row-fill: var(--surface); position: relative; display: flex; width: 100%; min-height: 64px; box-sizing: border-box; flex-wrap: wrap; align-items: baseline; align-content: center; gap:
|
|
88
|
+
.table tbody tr { --row-fill: var(--surface); position: relative; display: flex; width: 100%; min-height: 64px; box-sizing: border-box; flex-wrap: wrap; align-items: baseline; align-content: center; gap: var(--space-hair) var(--space-related); padding: var(--space-group) var(--space-inset); border-bottom: 1px solid var(--border-subtle); background-color: var(--row-fill); transition: background-color var(--duration-standard) var(--ease-standard); }
|
|
89
89
|
.table tbody tr::after { order: 1; flex-basis: 100%; content: ""; }
|
|
90
|
-
.table[data-selectable] tbody tr { padding-left:
|
|
90
|
+
.table[data-selectable] tbody tr { padding-left: var(--space-page); }
|
|
91
91
|
.table[data-selectable] tbody tr[data-selected] { --row-fill: color-mix(in oklab, var(--accent) 8%, var(--surface)); }
|
|
92
92
|
.table tbody tr:last-child { border-bottom: 0; }
|
|
93
93
|
.table td { order: 2; display: block; min-width: 0; height: auto; border: 0; padding: 0; background: transparent; color: var(--text-secondary); font-size: var(--text-xs); text-align: left; }
|
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
.group { display: inline-flex; align-items: stretch; border: 1px solid var(--foreground); border-radius: var(--radius-control); corner-shape: var(--corner-shape); background: var(--foreground); transition: transform var(--duration-spring) var(--ease-spring); }
|
|
3
3
|
.group:has(> .primary:active:not(:disabled)) { transform: scale(.97); transition-duration: var(--duration-instant); transition-timing-function: var(--ease-standard); }
|
|
4
4
|
.primary, .trigger { border: 0; background: var(--foreground); color: var(--background); font: inherit; cursor: pointer; -webkit-tap-highlight-color: transparent; transition: background-color var(--duration-fast) var(--ease-standard), color var(--duration-fast) var(--ease-standard), opacity var(--duration-fast) var(--ease-standard); }
|
|
5
|
-
.primary { position: relative; display: inline-grid; min-height: var(--control-height-md); place-items: center; padding: 0 var(--space-inset); border-radius: calc(var(--radius-control) -
|
|
5
|
+
.primary { position: relative; display: inline-grid; min-height: var(--control-height-md); place-items: center; padding: 0 var(--space-inset); border-radius: calc(var(--radius-control) - var(--space-hair)) 0 0 calc(var(--radius-control) - var(--space-hair)); corner-shape: var(--corner-shape); font-size: var(--text-sm); font-weight: 500; }
|
|
6
6
|
/* TextMorph springs the label's width, so the main half grows and shrinks with its text. */
|
|
7
7
|
.primarySlot { display: inline-flex; min-width: 0; align-items: center; }
|
|
8
8
|
.primaryContent { display: inline-flex; flex: none; align-items: center; gap: var(--space-related); white-space: nowrap; }
|
|
9
9
|
.mainIcon { display: inline-grid; flex: none; place-items: center; }
|
|
10
10
|
.iconPhase { grid-area: 1 / 1; display: inline-flex; align-items: center; justify-content: center; }
|
|
11
|
-
.trigger { display: grid; width: 38px; min-height: var(--control-height-md); place-items: center; border-left: 1px solid color-mix(in oklab, var(--background) 18%, var(--foreground)); border-radius: 0 calc(var(--radius-control) -
|
|
11
|
+
.trigger { display: grid; width: 38px; min-height: var(--control-height-md); place-items: center; border-left: 1px solid color-mix(in oklab, var(--background) 18%, var(--foreground)); border-radius: 0 calc(var(--radius-control) - var(--space-hair)) calc(var(--radius-control) - var(--space-hair)) 0; corner-shape: var(--corner-shape); }
|
|
12
12
|
.chevron { transition: transform var(--duration-spring) var(--ease-spring); }
|
|
13
13
|
.trigger[data-state="open"] .chevron { transform: rotate(180deg); }
|
|
14
14
|
@media (hover: hover) and (pointer: fine) {
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
.srOnly { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }
|
|
27
27
|
/* The menu grows from the trigger edge: offset toward the trigger, scale from the Radix origin, fade quickly; it leaves faster than it arrives.
|
|
28
28
|
Transitions instead of keyframes, so a close that interrupts the open reverses from where the menu is instead of snapping to rest first. */
|
|
29
|
-
.menu { --menu-x: 0px; --menu-y: -5px; position: relative; z-index:
|
|
29
|
+
.menu { --menu-x: 0px; --menu-y: -5px; position: relative; z-index: var(--layer-dropdown); min-width: min(12rem, var(--radix-dropdown-menu-content-available-width)); max-width: var(--radix-dropdown-menu-content-available-width); padding: var(--space-tight); border: 1px solid var(--border); border-radius: var(--radius-container); corner-shape: var(--corner-shape); background: var(--surface-raised); color: var(--foreground); box-shadow: var(--shadow-floating); transform-origin: var(--radix-dropdown-menu-content-transform-origin); transition: opacity var(--duration-fast) var(--ease-enter), transform var(--duration-spring) var(--ease-spring); }
|
|
30
30
|
.menu[data-side="top"] { --menu-y: 5px; }
|
|
31
31
|
.menu[data-side="left"] { --menu-x: 5px; --menu-y: 0px; }
|
|
32
32
|
.menu[data-side="right"] { --menu-x: -5px; --menu-y: 0px; }
|
|
@@ -36,10 +36,10 @@
|
|
|
36
36
|
}
|
|
37
37
|
/* Radix unmounts when the exit animation ends, so a no-op keyframe times the exit while the transition does the visual work. */
|
|
38
38
|
.menu[data-state="closed"] { opacity: 0; transform: translate(calc(var(--menu-x) * .5), calc(var(--menu-y) * .5)) scale(.985); transition: opacity 130ms var(--ease-standard), transform 130ms var(--ease-standard); animation: menu-exit 130ms linear both; pointer-events: none; }
|
|
39
|
-
.highlight { position: absolute; top: 0; right:
|
|
39
|
+
.highlight { position: absolute; top: 0; right: var(--space-tight); left: var(--space-tight); border-radius: calc(var(--radius-container) - var(--space-related)); background: var(--surface-muted); opacity: 0; pointer-events: none; transition: background-color var(--duration-fast) var(--ease-standard); }
|
|
40
40
|
.highlight[data-tone="danger"] { background: color-mix(in oklab, var(--danger) 8%, var(--surface)); }
|
|
41
41
|
/* One highlight glides between items for the pointer and jumps instantly for the keyboard (lib/menu-highlight). */
|
|
42
|
-
.item { position: relative; display: flex; min-height: var(--control-height-sm); align-items: center; gap:
|
|
42
|
+
.item { position: relative; display: flex; min-height: var(--control-height-sm); align-items: center; gap: var(--space-group); padding: 0 var(--space-group); border-radius: calc(var(--radius-container) - var(--space-related)); corner-shape: var(--corner-shape); font-size: var(--text-sm); cursor: pointer; outline: none; transition: opacity var(--duration-standard) var(--ease-enter) calc(min(var(--i, 0), 4) * 35ms), transform var(--duration-standard) var(--ease-enter) calc(min(var(--i, 0), 4) * 35ms); }
|
|
43
43
|
.item[data-disabled] { cursor: default; opacity: .45; }
|
|
44
44
|
.destructive { color: var(--danger); }
|
|
45
45
|
@keyframes menu-exit { to { --menu-exit: 1; } }
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
.connector { position: absolute; overflow: hidden; border-radius: var(--radius-full); corner-shape: round; background: var(--border); pointer-events: none; }
|
|
32
32
|
.horizontal .connector { top: calc(var(--marker) / 2 - 1px); inset-inline: calc(var(--marker) + var(--halo) + var(--space-tight)) calc(var(--halo) + var(--space-tight)); height: 2px; }
|
|
33
33
|
/* Both ends keep a clear gap from the markers, and from the current step's ring. */
|
|
34
|
-
.vertical .connector { top: calc(var(--marker) + var(--halo) +
|
|
34
|
+
.vertical .connector { top: calc(var(--marker) + var(--halo) + var(--space-hair)); bottom: calc(var(--halo) + var(--space-hair)); inset-inline-start: calc(var(--marker) / 2 - 1px); width: 2px; }
|
|
35
35
|
.fill { position: absolute; inset: 0; border-radius: inherit; corner-shape: inherit; background: var(--accent); }
|
|
36
36
|
.horizontal .fill { transform-origin: left center; }
|
|
37
37
|
.horizontal .fill:dir(rtl) { transform-origin: right center; }
|
|
@@ -39,14 +39,14 @@
|
|
|
39
39
|
|
|
40
40
|
.text { display: grid; min-width: 0; }
|
|
41
41
|
/* Centers the first line of the label on the marker. */
|
|
42
|
-
.vertical .text { padding-top:
|
|
42
|
+
.vertical .text { padding-top: var(--space-tight); }
|
|
43
43
|
.label { display: block; color: var(--text-muted); font-size: var(--text-sm); font-weight: 500; line-height: 1.25rem; overflow-wrap: break-word; transition: color var(--duration-standard) var(--ease-standard); }
|
|
44
44
|
.item[data-status="complete"] .label { color: var(--text-secondary); }
|
|
45
45
|
.item[data-status="current"] .label, .item[data-status="error"] .label { color: var(--foreground); }
|
|
46
46
|
/* Changing text pops out of flow against this box while it leaves, so it must be the positioned parent. */
|
|
47
47
|
.slot { display: block; }
|
|
48
48
|
.slotInner { position: relative; display: block; }
|
|
49
|
-
.description, .error { display: block; padding-top:
|
|
49
|
+
.description, .error { display: block; padding-top: var(--space-hair); font-size: var(--text-xs); font-weight: 400; line-height: var(--leading-body); overflow-wrap: break-word; }
|
|
50
50
|
.description { color: var(--text-muted); }
|
|
51
51
|
.error { color: var(--danger); }
|
|
52
52
|
|