@godxjp/ui 18.15.3 → 19.0.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/dist/app/date-format-labels.d.ts +1 -1
- package/dist/app/time-format-labels.d.ts +1 -1
- package/dist/components/data-display/badge.d.ts +1 -1
- package/dist/components/data-display/card.d.ts +4 -13
- package/dist/components/data-display/card.js +2 -15
- package/dist/components/data-display/data-table.d.ts +3 -8
- package/dist/components/data-display/data-table.js +106 -68
- package/dist/components/data-display/descriptions.js +34 -5
- package/dist/components/data-display/empty-state.js +1 -1
- package/dist/components/data-display/permission-matrix.js +7 -7
- package/dist/components/data-display/popover.js +2 -9
- package/dist/components/data-display/qr-code.d.ts +1 -1
- package/dist/components/data-display/scroll-area.d.ts +3 -1
- package/dist/components/data-display/scroll-area.js +150 -16
- package/dist/components/data-display/table.js +12 -3
- package/dist/components/data-entry/branch-scope-picker.js +4 -4
- package/dist/components/data-entry/calendar.js +15 -24
- package/dist/components/data-entry/cascader.js +67 -71
- package/dist/components/data-entry/checkbox.js +9 -1
- package/dist/components/data-entry/command.d.ts +6 -6
- package/dist/components/data-entry/date-picker.js +28 -15
- package/dist/components/data-entry/date-range-picker.js +10 -10
- package/dist/components/data-entry/form-field.js +7 -3
- package/dist/components/data-entry/index.d.ts +2 -1
- package/dist/components/data-entry/input.js +8 -19
- package/dist/components/data-entry/label.js +4 -2
- package/dist/components/data-entry/month-picker.js +16 -15
- package/dist/components/data-entry/month-range-picker.js +17 -16
- package/dist/components/data-entry/radio.js +6 -1
- package/dist/components/data-entry/search-select.js +29 -29
- package/dist/components/data-entry/select.js +15 -18
- package/dist/components/data-entry/switch.js +7 -1
- package/dist/components/data-entry/textarea.d.ts +56 -0
- package/dist/components/data-entry/textarea.js +103 -40
- package/dist/components/data-entry/time-picker.js +52 -52
- package/dist/components/data-entry/toggle-group.d.ts +1 -0
- package/dist/components/data-entry/toggle.d.ts +1 -1
- package/dist/components/data-entry/transfer.js +14 -15
- package/dist/components/data-entry/tree-select.js +16 -22
- package/dist/components/data-entry/upload-crop-dialog.js +4 -4
- package/dist/components/data-entry/upload.d.ts +1 -1
- package/dist/components/data-entry/upload.js +46 -46
- package/dist/components/feedback/alert.js +7 -14
- package/dist/components/feedback/dialog.d.ts +23 -32
- package/dist/components/feedback/dialog.js +16 -13
- package/dist/components/feedback/sheet.d.ts +1 -1
- package/dist/components/feedback/sheet.js +14 -14
- package/dist/components/feedback/skeleton.js +13 -10
- package/dist/components/feedback/sonner.d.ts +1 -1
- package/dist/components/feedback/sonner.js +17 -8
- package/dist/components/feedback/tooltip.js +1 -1
- package/dist/components/general/activity.d.ts +44 -0
- package/dist/components/general/activity.js +65 -0
- package/dist/components/general/button.d.ts +2 -2
- package/dist/components/general/button.js +11 -24
- package/dist/components/general/index.d.ts +2 -0
- package/dist/components/general/index.js +2 -0
- package/dist/components/layout/app-shell.js +5 -3
- package/dist/components/layout/auth-divider.d.ts +9 -2
- package/dist/components/layout/auth-divider.js +7 -11
- package/dist/components/layout/index.d.ts +1 -0
- package/dist/components/layout/page-container.d.ts +1 -1
- package/dist/components/layout/page-container.js +32 -20
- package/dist/components/layout/resizable.d.ts +12 -12
- package/dist/components/layout/separator.d.ts +1 -0
- package/dist/components/layout/service-role-panel.js +47 -42
- package/dist/components/layout/sidebar.js +13 -1
- package/dist/components/layout/split-pane.d.ts +12 -1
- package/dist/components/layout/split-pane.js +13 -4
- package/dist/components/navigation/app-setting-picker.js +5 -14
- package/dist/components/navigation/dropdown-menu.js +10 -16
- package/dist/components/navigation/menubar.d.ts +3 -6
- package/dist/components/navigation/pagination-utils.d.ts +15 -2
- package/dist/components/navigation/pagination-utils.js +27 -21
- package/dist/components/navigation/pagination.d.ts +4 -4
- package/dist/components/navigation/pagination.js +2 -2
- package/dist/components/navigation/steps.js +31 -67
- package/dist/components/navigation/tabs.js +17 -5
- package/dist/components/query/infinite-query-state.js +2 -2
- package/dist/components/ui/accordion.d.ts +1 -1
- package/dist/components/ui/avatar.d.ts +1 -1
- package/dist/components/ui/avatar.js +29 -10
- package/dist/components/ui/input-otp.d.ts +8 -6
- package/dist/components/ui/rating.js +1 -1
- package/dist/components/ui/separator.d.ts +27 -2
- package/dist/components/ui/separator.js +42 -11
- package/dist/components/ui/toggle-group.d.ts +15 -5
- package/dist/components/ui/toggle-group.js +43 -18
- package/dist/components/ui/toggle.d.ts +66 -5
- package/dist/components/ui/toggle.js +64 -9
- package/dist/i18n/messages/en.json +8 -0
- package/dist/i18n/messages/ja.json +8 -0
- package/dist/i18n/messages/vi.json +8 -0
- package/dist/lib/control-styles.d.ts +14 -0
- package/dist/lib/control-styles.js +2 -0
- package/dist/props/components/data-display.prop.d.ts +85 -3
- package/dist/props/components/data-entry.prop.d.ts +17 -0
- package/dist/props/components/general.prop.d.ts +52 -1
- package/dist/props/components/layout.prop.d.ts +137 -2
- package/dist/props/registry.d.ts +116 -5
- package/dist/props/registry.js +165 -4
- package/dist/props/vocabulary/index.d.ts +2 -2
- package/dist/props/vocabulary/interaction.prop.d.ts +15 -0
- package/dist/props/vocabulary/layout.prop.d.ts +8 -0
- package/dist/styles/alert-layout.css +69 -3
- package/dist/styles/badge-layout.css +2 -2
- package/dist/styles/base.css +6 -0
- package/dist/styles/card-layout.css +27 -7
- package/dist/styles/control.css +1150 -29
- package/dist/styles/data-display-layout.css +185 -11
- package/dist/styles/data-entry-layout.css +352 -1
- package/dist/styles/density.css +2 -2
- package/dist/styles/dialog-layout.css +203 -4
- package/dist/styles/focus-ring.css +155 -0
- package/dist/styles/form-layout.css +50 -5
- package/dist/styles/index.css +1 -0
- package/dist/styles/layout.css +412 -23
- package/dist/styles/motion.css +178 -0
- package/dist/styles/navigation-layout.css +398 -22
- package/dist/styles/shell-layout.css +137 -39
- package/dist/styles/table-layout.css +153 -22
- package/dist/styles/toggle.css +59 -0
- package/dist/tokens/base.css +5 -0
- package/dist/tokens/components/activity.css +64 -0
- package/dist/tokens/components/badge.css +7 -0
- package/dist/tokens/components/card.css +14 -10
- package/dist/tokens/components/chart.css +1 -1
- package/dist/tokens/components/control.css +358 -8
- package/dist/tokens/components/data-display.css +75 -0
- package/dist/tokens/components/data-entry.css +25 -0
- package/dist/tokens/components/descriptions.css +22 -0
- package/dist/tokens/components/feedback.css +143 -4
- package/dist/tokens/components/form.css +16 -0
- package/dist/tokens/components/legal-document.css +5 -1
- package/dist/tokens/components/navigation.css +109 -0
- package/dist/tokens/components/scroll-area.css +21 -0
- package/dist/tokens/components/separator.css +52 -0
- package/dist/tokens/components/shell.css +132 -20
- package/dist/tokens/components/table.css +52 -3
- package/dist/tokens/components/toggle.css +82 -0
- package/dist/tokens/components/upload.css +107 -0
- package/dist/tokens/foundation.css +171 -10
- package/dist/tokens/semantic/layout.css +120 -1
- package/package.json +84 -68
- package/scripts/ui-audit.mjs +51 -2
package/dist/styles/motion.css
CHANGED
|
@@ -50,3 +50,181 @@
|
|
|
50
50
|
}
|
|
51
51
|
}
|
|
52
52
|
}
|
|
53
|
+
|
|
54
|
+
/*
|
|
55
|
+
* AMBIENT MOTION — the `Activity` primitive (gh#313): a continuous, unbounded "something is
|
|
56
|
+
* happening right now, elsewhere" mark. The LOOP counterpart to `.ui-reveal`'s one-shot entrance,
|
|
57
|
+
* living in the same file so the library keeps exactly one place where motion is written.
|
|
58
|
+
*
|
|
59
|
+
* NOT `.ui-skeleton-block` (content is loading — `aria-busy`), NOT the Button spinner (this action
|
|
60
|
+
* is in flight). Every interval, offset, size and colour reads a token, so a service retunes the
|
|
61
|
+
* whole ambient feel from its theme instead of forking a `@keyframes` (cardinal rule #45).
|
|
62
|
+
*
|
|
63
|
+
* REDUCED MOTION IS A DESIGNED FRAME, NOT AN ABSENCE. Under `prefers-reduced-motion: reduce` the
|
|
64
|
+
* loops are dropped and every mark falls back to its BASE rule, which is authored to be a legible
|
|
65
|
+
* resting state: three solid dots (a static ellipsis — the same "…" convention the animation
|
|
66
|
+
* spells out), a solid pulse mark, and a bar segment parked at the reading-start of its track so
|
|
67
|
+
* the bar can never read as "complete". Nothing is hidden, nothing collapses, no box changes size
|
|
68
|
+
* — so there is no layout shift either way (WCAG 2.2 SC 2.3.3 / 2.2.2).
|
|
69
|
+
*/
|
|
70
|
+
@layer components {
|
|
71
|
+
.ui-activity {
|
|
72
|
+
display: inline-flex;
|
|
73
|
+
align-items: center;
|
|
74
|
+
gap: var(--activity-gap);
|
|
75
|
+
font-size: var(--activity-font-size-sm);
|
|
76
|
+
}
|
|
77
|
+
.ui-activity[data-size="xs"] {
|
|
78
|
+
font-size: var(--activity-font-size-xs);
|
|
79
|
+
}
|
|
80
|
+
.ui-activity[data-size="md"] {
|
|
81
|
+
font-size: var(--activity-font-size-md);
|
|
82
|
+
}
|
|
83
|
+
.ui-activity[data-size="lg"] {
|
|
84
|
+
font-size: var(--activity-font-size-lg);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/* The mark row. `block-size` reserves the loop's full travel so a dot at the top of its arc is
|
|
88
|
+
* never clipped and the row never grows mid-cycle. */
|
|
89
|
+
.ui-activity-mark {
|
|
90
|
+
display: inline-flex;
|
|
91
|
+
align-items: flex-end;
|
|
92
|
+
gap: var(--activity-gap);
|
|
93
|
+
block-size: calc(var(--activity-mark-size) + var(--activity-mark-offset));
|
|
94
|
+
color: hsl(var(--activity-color, var(--muted-foreground)));
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/* Tone → mark ink. Two-attribute selectors (0,2,0) outrank the muted base (0,1,0). `muted` has
|
|
98
|
+
* no rule of its own: it IS the base, and therefore the one tone `--activity-color` retints. */
|
|
99
|
+
.ui-activity[data-tone="default"] .ui-activity-mark {
|
|
100
|
+
color: hsl(var(--foreground));
|
|
101
|
+
}
|
|
102
|
+
.ui-activity[data-tone="primary"] .ui-activity-mark {
|
|
103
|
+
color: hsl(var(--primary));
|
|
104
|
+
}
|
|
105
|
+
.ui-activity[data-tone="success"] .ui-activity-mark {
|
|
106
|
+
color: hsl(var(--success));
|
|
107
|
+
}
|
|
108
|
+
.ui-activity[data-tone="warning"] .ui-activity-mark {
|
|
109
|
+
color: hsl(var(--warning));
|
|
110
|
+
}
|
|
111
|
+
.ui-activity[data-tone="destructive"] .ui-activity-mark {
|
|
112
|
+
color: hsl(var(--destructive));
|
|
113
|
+
}
|
|
114
|
+
.ui-activity[data-tone="info"] .ui-activity-mark {
|
|
115
|
+
color: hsl(var(--info));
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/* dots — the ellipsis convention. Resting state (= the reduced-motion frame): three solid dots. */
|
|
119
|
+
.ui-activity-dot {
|
|
120
|
+
inline-size: var(--activity-mark-size);
|
|
121
|
+
block-size: var(--activity-mark-size);
|
|
122
|
+
border-radius: var(--radius-pill);
|
|
123
|
+
background: currentColor;
|
|
124
|
+
opacity: 1;
|
|
125
|
+
animation: ui-activity-bounce var(--activity-interval) var(--ease-standard) infinite;
|
|
126
|
+
}
|
|
127
|
+
/* nth-child, not a physical offset: in RTL the flex row lays the dots end→start, so the cascade
|
|
128
|
+
* follows the reading direction with no `[dir]` rule. */
|
|
129
|
+
.ui-activity-dot:nth-child(2) {
|
|
130
|
+
animation-delay: calc(var(--activity-stagger-step) * 1);
|
|
131
|
+
}
|
|
132
|
+
.ui-activity-dot:nth-child(3) {
|
|
133
|
+
animation-delay: calc(var(--activity-stagger-step) * 2);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/* pulse — a single breathing mark (live / recording). Opacity only: the reference design keeps
|
|
137
|
+
* motion LOW, and an opacity loop degrades to a solid mark instead of a resized box. */
|
|
138
|
+
.ui-activity-pulse {
|
|
139
|
+
inline-size: var(--activity-pulse-mark-size);
|
|
140
|
+
block-size: var(--activity-pulse-mark-size);
|
|
141
|
+
border-radius: var(--radius-pill);
|
|
142
|
+
background: currentColor;
|
|
143
|
+
opacity: 1;
|
|
144
|
+
animation: ui-activity-breathe var(--activity-interval) var(--ease-standard) infinite;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/* bar — an indeterminate sweep (syncing). */
|
|
148
|
+
.ui-activity-bar {
|
|
149
|
+
position: relative;
|
|
150
|
+
overflow: hidden;
|
|
151
|
+
inline-size: var(--activity-bar-width);
|
|
152
|
+
block-size: var(--activity-bar-height);
|
|
153
|
+
border-radius: var(--activity-bar-radius);
|
|
154
|
+
background: hsl(
|
|
155
|
+
var(--activity-color, var(--muted-foreground)) / var(--activity-bar-track-alpha)
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
.ui-activity-bar-segment {
|
|
159
|
+
position: absolute;
|
|
160
|
+
inset-block: 0;
|
|
161
|
+
/* Parked at the reading-start when the animation is dropped: a partial bar, never a full one
|
|
162
|
+
* (a full track would read as "complete", which is the opposite of indeterminate). */
|
|
163
|
+
inset-inline-start: 0;
|
|
164
|
+
inline-size: var(--activity-bar-segment-width);
|
|
165
|
+
border-radius: inherit;
|
|
166
|
+
background: currentColor;
|
|
167
|
+
animation: ui-activity-sweep var(--activity-interval) var(--ease-standard) infinite;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/* The label is a real `Text`; it only needs to stop the mark's travel box stretching the row. */
|
|
171
|
+
.ui-activity-label {
|
|
172
|
+
min-inline-size: 0;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
@keyframes ui-activity-bounce {
|
|
176
|
+
0%,
|
|
177
|
+
70%,
|
|
178
|
+
100% {
|
|
179
|
+
transform: translateY(0);
|
|
180
|
+
opacity: var(--activity-mark-rest-alpha);
|
|
181
|
+
}
|
|
182
|
+
35% {
|
|
183
|
+
transform: translateY(calc(-1 * var(--activity-mark-offset)));
|
|
184
|
+
opacity: 1;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
@keyframes ui-activity-breathe {
|
|
189
|
+
0%,
|
|
190
|
+
100% {
|
|
191
|
+
opacity: var(--activity-mark-rest-alpha);
|
|
192
|
+
}
|
|
193
|
+
50% {
|
|
194
|
+
opacity: 1;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
@keyframes ui-activity-sweep {
|
|
199
|
+
from {
|
|
200
|
+
inset-inline-start: calc(-1 * var(--activity-bar-segment-width));
|
|
201
|
+
}
|
|
202
|
+
to {
|
|
203
|
+
inset-inline-start: 100%;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/* Accessibility: no motion → no loop. Every mark falls back to the legible resting state
|
|
208
|
+
* authored above; the label is visible text either way, so the affordance still says what it
|
|
209
|
+
* means (WCAG 2.2 SC 2.3.3 Animation from Interactions, SC 2.2.2 Pause/Stop/Hide — an
|
|
210
|
+
* indefinite loop runs longer than five seconds and the user cannot pause it). */
|
|
211
|
+
@media (prefers-reduced-motion: reduce) {
|
|
212
|
+
.ui-activity-dot,
|
|
213
|
+
.ui-activity-pulse,
|
|
214
|
+
.ui-activity-bar-segment {
|
|
215
|
+
animation: none;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/* Forced colours: the OS palette replaces the token ink, so the mark must not depend on it. */
|
|
220
|
+
@media (forced-colors: active) {
|
|
221
|
+
.ui-activity-dot,
|
|
222
|
+
.ui-activity-pulse,
|
|
223
|
+
.ui-activity-bar-segment {
|
|
224
|
+
background: CanvasText;
|
|
225
|
+
}
|
|
226
|
+
.ui-activity-bar {
|
|
227
|
+
border: 1px solid CanvasText;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
@@ -42,6 +42,17 @@
|
|
|
42
42
|
--control-padding-x: var(--app-setting-picker-compact-padding-x);
|
|
43
43
|
--control-font-size: var(--app-setting-picker-compact-font-size);
|
|
44
44
|
}
|
|
45
|
+
/* Tabs root — the flex box that stacks the strip above its panel (#319). The strip↔panel gap is
|
|
46
|
+
* a token so a service can retune the tab rhythm to its own grid; `min-inline-size: 0` is NOT a
|
|
47
|
+
* knob but the flexbox shrink idiom that used to ride along as `min-w-0`: without it the strip's
|
|
48
|
+
* intrinsic width forces every ancestor wider instead of letting the strip scroll its own
|
|
49
|
+
* overflow (gh#175). `display:flex` / the vertical column stay on the component — they are
|
|
50
|
+
* structure, not a service-tunable constant. */
|
|
51
|
+
[data-slot="tabs"] {
|
|
52
|
+
min-inline-size: 0;
|
|
53
|
+
gap: var(--tabs-root-gap);
|
|
54
|
+
}
|
|
55
|
+
|
|
45
56
|
[data-slot="tabs-list"] {
|
|
46
57
|
max-inline-size: var(--tabs-list-max-inline-size);
|
|
47
58
|
overflow-x: var(--tabs-list-overflow);
|
|
@@ -88,9 +99,19 @@
|
|
|
88
99
|
}
|
|
89
100
|
}
|
|
90
101
|
|
|
102
|
+
/* Pagination chevrons (#319). The `simple` form draws Prev/Next as size="sm" Buttons whose only
|
|
103
|
+
* content is the glyph, so it must NOT inherit the small-button icon tier — the chevron is the
|
|
104
|
+
* whole control. Pagination lives in styles/layout.css, but this override has to out-specify
|
|
105
|
+
* `.ui-button--sm svg` (0,1,1) from styles/control.css, so it is authored here at (0,2,1); a
|
|
106
|
+
* plain `.ui-pagination svg` rule would lose the cascade and silently shrink both chevrons. */
|
|
107
|
+
.ui-pagination .ui-button svg {
|
|
108
|
+
inline-size: var(--pagination-icon-size);
|
|
109
|
+
block-size: var(--pagination-icon-size);
|
|
110
|
+
}
|
|
111
|
+
|
|
91
112
|
.ui-context-menu-content {
|
|
92
|
-
z-index:
|
|
93
|
-
min-width:
|
|
113
|
+
z-index: var(--overlay-z-index);
|
|
114
|
+
min-width: var(--menu-content-min-width);
|
|
94
115
|
overflow: hidden;
|
|
95
116
|
border-radius: var(--radius-md);
|
|
96
117
|
border: 1px solid hsl(var(--border));
|
|
@@ -111,14 +132,29 @@
|
|
|
111
132
|
.ui-menubar-trigger,
|
|
112
133
|
.ui-menubar-sub-trigger,
|
|
113
134
|
.ui-menubar-checkbox-item,
|
|
114
|
-
.ui-menubar-radio-item
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
135
|
+
.ui-menubar-radio-item,
|
|
136
|
+
.ui-dropdown-menu-item,
|
|
137
|
+
.ui-dropdown-menu-label,
|
|
138
|
+
.ui-dropdown-menu-sub-trigger,
|
|
139
|
+
.ui-dropdown-menu-checkbox-item,
|
|
140
|
+
.ui-dropdown-menu-radio-item,
|
|
141
|
+
.ui-dropdown-menu-shortcut,
|
|
142
|
+
.ui-select-item,
|
|
143
|
+
.ui-select-label {
|
|
144
|
+
border-radius: var(--menu-item-radius);
|
|
145
|
+
padding-inline: var(--menu-item-space-inline);
|
|
146
|
+
height: var(--menu-item-height);
|
|
118
147
|
display: flex;
|
|
119
148
|
align-items: center;
|
|
120
|
-
gap: var(--space-
|
|
121
|
-
font-size: var(--font-size
|
|
149
|
+
gap: var(--menu-item-space-gap);
|
|
150
|
+
font-size: var(--menu-item-font-size);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/* A row marked inset reserves the indicator column so its label lines up with checked siblings. */
|
|
154
|
+
.ui-dropdown-menu-item[data-inset="true"],
|
|
155
|
+
.ui-dropdown-menu-label[data-inset="true"],
|
|
156
|
+
.ui-dropdown-menu-sub-trigger[data-inset="true"] {
|
|
157
|
+
padding-inline-start: var(--menu-item-inset-space-inline-start);
|
|
122
158
|
}
|
|
123
159
|
|
|
124
160
|
.ui-context-menu-item,
|
|
@@ -129,6 +165,10 @@
|
|
|
129
165
|
.ui-menubar-checkbox-item,
|
|
130
166
|
.ui-menubar-radio-item,
|
|
131
167
|
.ui-menubar-sub-trigger,
|
|
168
|
+
.ui-dropdown-menu-item,
|
|
169
|
+
.ui-dropdown-menu-checkbox-item,
|
|
170
|
+
.ui-dropdown-menu-radio-item,
|
|
171
|
+
.ui-dropdown-menu-sub-trigger,
|
|
132
172
|
.ui-navigation-menu-link {
|
|
133
173
|
cursor: pointer;
|
|
134
174
|
outline: none;
|
|
@@ -142,6 +182,8 @@
|
|
|
142
182
|
.ui-context-menu-sub-trigger:hover,
|
|
143
183
|
.ui-menubar-item:hover,
|
|
144
184
|
.ui-menubar-sub-trigger:hover,
|
|
185
|
+
.ui-dropdown-menu-item:hover,
|
|
186
|
+
.ui-dropdown-menu-sub-trigger:hover,
|
|
145
187
|
.ui-navigation-menu-link:hover,
|
|
146
188
|
.ui-navigation-menu-item:hover {
|
|
147
189
|
background: var(--menubar-item-hover-background, hsl(var(--accent)));
|
|
@@ -155,6 +197,11 @@
|
|
|
155
197
|
.ui-menubar-item[data-state="active"],
|
|
156
198
|
.ui-menubar-item[data-state="checked"],
|
|
157
199
|
.ui-menubar-sub-trigger[data-state="open"],
|
|
200
|
+
.ui-dropdown-menu-item[data-state="open"],
|
|
201
|
+
.ui-dropdown-menu-item[data-highlighted],
|
|
202
|
+
.ui-dropdown-menu-checkbox-item[data-highlighted],
|
|
203
|
+
.ui-dropdown-menu-radio-item[data-highlighted],
|
|
204
|
+
.ui-dropdown-menu-sub-trigger[data-state="open"],
|
|
158
205
|
.ui-navigation-menu-link[data-highlighted],
|
|
159
206
|
.ui-navigation-menu-item[data-focus-visible] {
|
|
160
207
|
background: var(--menubar-item-hover-background, hsl(var(--accent)));
|
|
@@ -162,7 +209,8 @@
|
|
|
162
209
|
}
|
|
163
210
|
|
|
164
211
|
.ui-context-menu-item[data-variant="destructive"],
|
|
165
|
-
.ui-menubar-item[data-variant="destructive"]
|
|
212
|
+
.ui-menubar-item[data-variant="destructive"],
|
|
213
|
+
.ui-dropdown-menu-item[data-variant="destructive"] {
|
|
166
214
|
color: hsl(var(--destructive));
|
|
167
215
|
}
|
|
168
216
|
|
|
@@ -173,21 +221,26 @@
|
|
|
173
221
|
}
|
|
174
222
|
|
|
175
223
|
.ui-context-menu-separator,
|
|
176
|
-
.ui-menubar-separator
|
|
177
|
-
|
|
224
|
+
.ui-menubar-separator,
|
|
225
|
+
.ui-dropdown-menu-separator,
|
|
226
|
+
.ui-select-separator {
|
|
227
|
+
margin-block: var(--menu-separator-space-block);
|
|
228
|
+
margin-inline: var(--menu-separator-space-inline);
|
|
178
229
|
height: 1px;
|
|
179
230
|
background: hsl(var(--border));
|
|
180
231
|
}
|
|
181
232
|
|
|
182
233
|
.ui-context-menu-label,
|
|
183
|
-
.ui-menubar-label
|
|
184
|
-
|
|
234
|
+
.ui-menubar-label,
|
|
235
|
+
.ui-dropdown-menu-label {
|
|
236
|
+
min-height: var(--menu-item-height);
|
|
185
237
|
color: hsl(var(--muted-foreground));
|
|
186
238
|
font-weight: var(--font-weight-medium);
|
|
187
239
|
}
|
|
188
240
|
|
|
189
241
|
.ui-context-menu-shortcut,
|
|
190
|
-
.ui-menubar-shortcut
|
|
242
|
+
.ui-menubar-shortcut,
|
|
243
|
+
.ui-dropdown-menu-shortcut {
|
|
191
244
|
margin-inline-start: auto;
|
|
192
245
|
text-align: end;
|
|
193
246
|
color: hsl(var(--muted-foreground));
|
|
@@ -196,6 +249,7 @@
|
|
|
196
249
|
|
|
197
250
|
.ui-context-menu-item-indicator,
|
|
198
251
|
.ui-menubar-item-indicator,
|
|
252
|
+
.ui-dropdown-menu-item-indicator,
|
|
199
253
|
.ui-navigation-menu-item-indicator {
|
|
200
254
|
display: inline-flex;
|
|
201
255
|
width: 1rem;
|
|
@@ -238,10 +292,14 @@
|
|
|
238
292
|
box-shadow: var(--shadow-md), var(--shadow-glow);
|
|
239
293
|
}
|
|
240
294
|
|
|
295
|
+
/* Reads --menu-icon-size, the same knob DropdownMenu's sub-trigger chevron already reads
|
|
296
|
+
* (`.ui-dropdown-menu-sub-trigger-icon`, below). The three menu surfaces share one row rhythm,
|
|
297
|
+
* so the literal `1rem` here meant setting --menu-icon-size resized the dropdown chevron and
|
|
298
|
+
* silently left these two behind. Same resolved value, one owner (gh#326). */
|
|
241
299
|
.ui-context-menu-sub-trigger-icon,
|
|
242
300
|
.ui-menubar-sub-trigger-icon {
|
|
243
|
-
width:
|
|
244
|
-
height:
|
|
301
|
+
width: var(--menu-icon-size);
|
|
302
|
+
height: var(--menu-icon-size);
|
|
245
303
|
margin-inline-start: auto;
|
|
246
304
|
opacity: 0.75;
|
|
247
305
|
}
|
|
@@ -304,8 +362,8 @@
|
|
|
304
362
|
}
|
|
305
363
|
|
|
306
364
|
.ui-navigation-menu-trigger-icon {
|
|
307
|
-
width:
|
|
308
|
-
height:
|
|
365
|
+
width: var(--navigation-menu-trigger-icon-size);
|
|
366
|
+
height: var(--navigation-menu-trigger-icon-size);
|
|
309
367
|
margin-inline-start: var(--space-2);
|
|
310
368
|
opacity: 0.7;
|
|
311
369
|
}
|
|
@@ -390,10 +448,6 @@
|
|
|
390
448
|
outline: none;
|
|
391
449
|
}
|
|
392
450
|
|
|
393
|
-
button.ui-steps-inline-control:focus-visible {
|
|
394
|
-
box-shadow: 0 0 0 var(--focus-ring-width) hsl(var(--focus-ring-color, var(--ring)));
|
|
395
|
-
}
|
|
396
|
-
|
|
397
451
|
/* The step NUMBER carries the emphasis. Both knobs exist because the canonical hosted-identity
|
|
398
452
|
* row marks the step with an accent TINT at normal weight, while the original marked it with
|
|
399
453
|
* bold at the inherited colour — a service picks its own emphasis instead of forking this rule
|
|
@@ -433,4 +487,326 @@
|
|
|
433
487
|
flex: none;
|
|
434
488
|
color: var(--steps-inline-separator-color, hsl(var(--muted-foreground)));
|
|
435
489
|
}
|
|
490
|
+
|
|
491
|
+
/* DROPDOWN MENU — the third Radix menu surface. It was the only one still carrying its whole
|
|
492
|
+
* box as Tailwind literals on the component (#319); it now joins ContextMenu and Menubar on the
|
|
493
|
+
* shared row rhythm above, and scopes the one value that legitimately differs. */
|
|
494
|
+
.ui-dropdown-menu-content,
|
|
495
|
+
.ui-dropdown-menu-sub-content {
|
|
496
|
+
--menu-content-min-width: var(--dropdown-content-min-width);
|
|
497
|
+
|
|
498
|
+
z-index: var(--overlay-z-index);
|
|
499
|
+
min-width: var(--menu-content-min-width);
|
|
500
|
+
border-radius: var(--radius-md);
|
|
501
|
+
border: 1px solid hsl(var(--border));
|
|
502
|
+
background: hsl(var(--popover));
|
|
503
|
+
color: hsl(var(--popover-foreground));
|
|
504
|
+
padding: var(--menu-content-space-inset);
|
|
505
|
+
box-shadow: var(--shadow-md), var(--shadow-glow);
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
.ui-dropdown-menu-content {
|
|
509
|
+
max-height: var(--radix-dropdown-menu-content-available-height);
|
|
510
|
+
overflow-x: hidden;
|
|
511
|
+
overflow-y: auto;
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
.ui-dropdown-menu-sub-content {
|
|
515
|
+
overflow: hidden;
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
/* The checkbox indicator is absolutely placed in the reserved inset column. */
|
|
519
|
+
.ui-dropdown-menu-indicator-slot {
|
|
520
|
+
pointer-events: none;
|
|
521
|
+
position: absolute;
|
|
522
|
+
inset-inline-start: var(--menu-indicator-inset-inline-start);
|
|
523
|
+
display: flex;
|
|
524
|
+
inline-size: var(--menu-indicator-size);
|
|
525
|
+
block-size: var(--menu-indicator-size);
|
|
526
|
+
align-items: center;
|
|
527
|
+
justify-content: center;
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
.ui-dropdown-menu-check,
|
|
531
|
+
.ui-dropdown-menu-sub-trigger-icon {
|
|
532
|
+
inline-size: var(--menu-icon-size);
|
|
533
|
+
block-size: var(--menu-icon-size);
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
.ui-dropdown-menu-sub-trigger-icon {
|
|
537
|
+
margin-inline-start: auto;
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
/* Checkbox and radio rows are inset by construction — they always reserve the marker column. */
|
|
541
|
+
.ui-dropdown-menu-checkbox-item {
|
|
542
|
+
position: relative;
|
|
543
|
+
padding-inline-start: var(--menu-item-inset-space-inline-start);
|
|
544
|
+
padding-inline-end: var(--menu-item-space-inline);
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
.ui-dropdown-menu-item,
|
|
548
|
+
.ui-dropdown-menu-radio-item {
|
|
549
|
+
position: relative;
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
.ui-dropdown-menu-radio-item[data-state="checked"] {
|
|
553
|
+
background: hsl(var(--primary) / 0.1);
|
|
554
|
+
color: hsl(var(--primary));
|
|
555
|
+
font-weight: var(--font-weight-medium);
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
.ui-dropdown-menu-item[data-variant="destructive"][data-highlighted] {
|
|
559
|
+
background: hsl(var(--destructive) / 0.1);
|
|
560
|
+
color: hsl(var(--destructive));
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
.ui-dropdown-menu-item[data-disabled],
|
|
564
|
+
.ui-dropdown-menu-checkbox-item[data-disabled],
|
|
565
|
+
.ui-dropdown-menu-radio-item[data-disabled] {
|
|
566
|
+
pointer-events: none;
|
|
567
|
+
opacity: var(--disabled-opacity);
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
.ui-dropdown-menu-item svg,
|
|
571
|
+
.ui-dropdown-menu-sub-trigger svg {
|
|
572
|
+
pointer-events: none;
|
|
573
|
+
flex-shrink: 0;
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
@layer components {
|
|
578
|
+
/* STEPS — full (non-inline) variant. The inline form keeps its own --steps-inline-* set. */
|
|
579
|
+
.ui-steps-dot {
|
|
580
|
+
display: block;
|
|
581
|
+
inline-size: var(--steps-dot-size);
|
|
582
|
+
block-size: var(--steps-dot-size);
|
|
583
|
+
border-radius: var(--radius-pill);
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
.ui-steps-dot[data-status="finish"],
|
|
587
|
+
.ui-steps-dot[data-status="process"] {
|
|
588
|
+
background: hsl(var(--primary));
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
.ui-steps-dot[data-status="process"] {
|
|
592
|
+
box-shadow: 0 0 0 var(--steps-dot-process-ring-width) hsl(var(--primary) / 0.2);
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
.ui-steps-dot[data-status="error"] {
|
|
596
|
+
background: hsl(var(--destructive));
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
.ui-steps-dot[data-status="wait"] {
|
|
600
|
+
background: hsl(var(--muted-foreground) / 0.3);
|
|
601
|
+
}
|
|
602
|
+
|
|
603
|
+
.ui-steps-marker {
|
|
604
|
+
border-radius: var(--radius-pill);
|
|
605
|
+
border: var(--steps-marker-border-width) solid transparent;
|
|
606
|
+
font-size: var(--steps-marker-font-size);
|
|
607
|
+
font-weight: var(--font-weight-medium);
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
.ui-steps-marker[data-status="finish"] {
|
|
611
|
+
border-color: hsl(var(--primary));
|
|
612
|
+
background: hsl(var(--primary));
|
|
613
|
+
color: hsl(var(--primary-foreground));
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
.ui-steps-marker[data-status="process"] {
|
|
617
|
+
border-color: hsl(var(--primary));
|
|
618
|
+
color: hsl(var(--primary));
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
.ui-steps-marker[data-status="error"] {
|
|
622
|
+
border-color: hsl(var(--destructive));
|
|
623
|
+
background: hsl(var(--destructive));
|
|
624
|
+
color: hsl(var(--destructive-foreground));
|
|
625
|
+
}
|
|
626
|
+
|
|
627
|
+
.ui-steps-marker[data-status="wait"] {
|
|
628
|
+
border-color: hsl(var(--muted-foreground) / 0.3);
|
|
629
|
+
color: hsl(var(--muted-foreground));
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
.ui-steps-marker-icon {
|
|
633
|
+
inline-size: var(--steps-marker-icon-size);
|
|
634
|
+
block-size: var(--steps-marker-icon-size);
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
.ui-steps-wait-icon {
|
|
638
|
+
inline-size: var(--steps-wait-icon-size);
|
|
639
|
+
block-size: var(--steps-wait-icon-size);
|
|
640
|
+
fill: currentColor;
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
.ui-steps-text {
|
|
644
|
+
min-inline-size: 0;
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
.ui-steps-item[data-direction="vertical"] .ui-steps-text {
|
|
648
|
+
padding-block-start: var(--steps-vertical-text-space-block-start);
|
|
649
|
+
text-align: start;
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
.ui-steps-item[data-direction="horizontal"] .ui-steps-text {
|
|
653
|
+
margin-block-start: var(--steps-horizontal-text-space-block-start);
|
|
654
|
+
padding-inline: var(--steps-horizontal-text-space-inline);
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
.ui-steps-item[data-direction="horizontal"][data-title-placement="vertical"] .ui-steps-text {
|
|
658
|
+
margin-block-start: var(--steps-vertical-text-space-block-start);
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
.ui-steps-title {
|
|
662
|
+
font-weight: var(--font-weight-medium);
|
|
663
|
+
font-size: var(--steps-title-font-size);
|
|
664
|
+
}
|
|
665
|
+
|
|
666
|
+
.ui-steps-title[data-compact] {
|
|
667
|
+
font-size: var(--steps-title-font-size-compact);
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
.ui-steps-title[data-status="process"] {
|
|
671
|
+
color: hsl(var(--foreground));
|
|
672
|
+
}
|
|
673
|
+
|
|
674
|
+
.ui-steps-title[data-status="wait"] {
|
|
675
|
+
color: hsl(var(--muted-foreground));
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
.ui-steps-title[data-status="error"] {
|
|
679
|
+
color: hsl(var(--destructive));
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
.ui-steps-subtitle {
|
|
683
|
+
font-size: var(--steps-subtitle-font-size);
|
|
684
|
+
color: hsl(var(--muted-foreground));
|
|
685
|
+
}
|
|
686
|
+
|
|
687
|
+
.ui-steps-description {
|
|
688
|
+
font-size: var(--steps-title-font-size);
|
|
689
|
+
color: hsl(var(--muted-foreground));
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
.ui-steps-description[data-compact] {
|
|
693
|
+
font-size: var(--steps-title-font-size-compact);
|
|
694
|
+
}
|
|
695
|
+
|
|
696
|
+
.ui-steps-list[data-direction="vertical"] {
|
|
697
|
+
flex-direction: column;
|
|
698
|
+
gap: 0;
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
.ui-steps-list[data-direction="horizontal"] {
|
|
702
|
+
flex-direction: row;
|
|
703
|
+
align-items: flex-start;
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
.ui-steps-control {
|
|
707
|
+
display: flex;
|
|
708
|
+
min-inline-size: 0;
|
|
709
|
+
}
|
|
710
|
+
|
|
711
|
+
.ui-steps-control[data-direction="vertical"] {
|
|
712
|
+
flex-direction: row;
|
|
713
|
+
align-items: flex-start;
|
|
714
|
+
gap: var(--steps-vertical-space-gap);
|
|
715
|
+
}
|
|
716
|
+
|
|
717
|
+
.ui-steps-control[data-direction="horizontal"] {
|
|
718
|
+
flex-direction: column;
|
|
719
|
+
align-items: center;
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
.ui-steps-item {
|
|
723
|
+
position: relative;
|
|
724
|
+
display: flex;
|
|
725
|
+
min-inline-size: 0;
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
.ui-steps-item[data-direction="vertical"] {
|
|
729
|
+
flex-direction: row;
|
|
730
|
+
gap: var(--steps-vertical-space-gap);
|
|
731
|
+
padding-block-end: var(--steps-vertical-space-block-end);
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
.ui-steps-item[data-direction="vertical"]:last-child {
|
|
735
|
+
padding-block-end: 0;
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
.ui-steps-item[data-direction="horizontal"] {
|
|
739
|
+
flex-direction: column;
|
|
740
|
+
align-items: center;
|
|
741
|
+
text-align: center;
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
/* The connector spans between two markers, inset by the marker radius at each end so it never
|
|
745
|
+
* runs underneath one. Both ends move together when --steps-connector-inset is retuned. */
|
|
746
|
+
.ui-steps-item[data-direction="horizontal"][data-connector]::after {
|
|
747
|
+
content: "";
|
|
748
|
+
position: absolute;
|
|
749
|
+
inset-block-start: var(--steps-connector-space-block-start);
|
|
750
|
+
inset-inline-start: calc(50% + var(--steps-connector-inset));
|
|
751
|
+
inline-size: calc(100% - var(--steps-connector-inset) * 2);
|
|
752
|
+
block-size: 1px;
|
|
753
|
+
background: hsl(var(--border));
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
/* APP SETTING PICKER — icon-only box + per-kind labelled widths (#319). */
|
|
757
|
+
|
|
758
|
+
/* Structurally icon-only: square to the density-aware --control-height tap target and drop the
|
|
759
|
+
* form-input chrome so it sits among the topbar's ghost icon buttons. The open-state and
|
|
760
|
+
* focus-visible rings from controlTriggerClass are untouched. */
|
|
761
|
+
.ui-app-setting-picker-icon {
|
|
762
|
+
inline-size: var(--control-height);
|
|
763
|
+
justify-content: center;
|
|
764
|
+
border-color: transparent;
|
|
765
|
+
background: transparent;
|
|
766
|
+
padding-inline: 0;
|
|
767
|
+
box-shadow: none;
|
|
768
|
+
}
|
|
769
|
+
|
|
770
|
+
.ui-app-setting-picker-glyph {
|
|
771
|
+
inline-size: var(--app-setting-picker-icon-size);
|
|
772
|
+
block-size: var(--app-setting-picker-icon-size);
|
|
773
|
+
flex-shrink: 0;
|
|
774
|
+
opacity: var(--app-setting-picker-icon-rest-alpha);
|
|
775
|
+
}
|
|
776
|
+
|
|
777
|
+
/* Each kind is sized to the longest value it can show — a timezone name is far wider than a
|
|
778
|
+
* theme name. Below the breakpoint every kind hugs its content instead. */
|
|
779
|
+
@media (min-width: 40rem) {
|
|
780
|
+
.ui-app-setting-picker-trigger[data-kind="locale"] {
|
|
781
|
+
inline-size: var(--app-setting-picker-locale-width);
|
|
782
|
+
}
|
|
783
|
+
|
|
784
|
+
.ui-app-setting-picker-trigger[data-kind="timezone"] {
|
|
785
|
+
inline-size: var(--app-setting-picker-timezone-width);
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
.ui-app-setting-picker-trigger[data-kind="dateFormat"] {
|
|
789
|
+
inline-size: var(--app-setting-picker-date-format-width);
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
.ui-app-setting-picker-trigger[data-kind="timeFormat"] {
|
|
793
|
+
inline-size: var(--app-setting-picker-time-format-width);
|
|
794
|
+
}
|
|
795
|
+
|
|
796
|
+
.ui-app-setting-picker-trigger[data-kind="theme"] {
|
|
797
|
+
inline-size: var(--app-setting-picker-theme-width);
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
.ui-app-setting-picker-trigger[data-kind="brand"] {
|
|
801
|
+
inline-size: var(--app-setting-picker-brand-width);
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
.ui-app-setting-picker-trigger[data-kind="density"] {
|
|
805
|
+
inline-size: var(--app-setting-picker-density-width);
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
.ui-app-setting-picker-trigger[data-kind="fontSize"] {
|
|
809
|
+
inline-size: var(--app-setting-picker-font-size-width);
|
|
810
|
+
}
|
|
811
|
+
}
|
|
436
812
|
}
|