@fluixi-ui/tokens 0.4.0-alpha.1 → 0.4.0-alpha.11
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/css/accordion.css +81 -3
- package/dist/css/alert.css +52 -23
- package/dist/css/avatar.css +19 -0
- package/dist/css/badge.css +129 -5
- package/dist/css/base.css +3 -1
- package/dist/css/bottom-sheet.css +4 -4
- package/dist/css/breadcrumb.css +1 -1
- package/dist/css/bulk-editor.css +2 -17
- package/dist/css/button.css +76 -16
- package/dist/css/calendar.css +9 -7
- package/dist/css/card.css +5 -1
- package/dist/css/carousel.css +80 -0
- package/dist/css/checkbox-radio.css +55 -1
- package/dist/css/chip.css +175 -0
- package/dist/css/date-field.css +1 -1
- package/dist/css/date-picker.css +2 -2
- package/dist/css/descriptions.css +29 -0
- package/dist/css/drawer.css +4 -4
- package/dist/css/empty.css +40 -0
- package/dist/css/fab.css +48 -0
- package/dist/css/field-variants.css +139 -0
- package/dist/css/file-upload.css +40 -0
- package/dist/css/glow.css +127 -0
- package/dist/css/icon-button.css +42 -0
- package/dist/css/image.css +67 -0
- package/dist/css/input.css +15 -0
- package/dist/css/layout.css +10 -0
- package/dist/css/navigation-menu.css +8 -7
- package/dist/css/number-field.css +3 -3
- package/dist/css/page.css +138 -0
- package/dist/css/pagination.css +3 -3
- package/dist/css/parts/listbox.css +9 -4
- package/dist/css/pin-input.css +40 -0
- package/dist/css/progress.css +56 -0
- package/dist/css/rating.css +59 -0
- package/dist/css/scroll-area.css +44 -0
- package/dist/css/select-combobox.css +19 -4
- package/dist/css/sidenav.css +180 -10
- package/dist/css/slider.css +4 -4
- package/dist/css/speed-dial.css +85 -0
- package/dist/css/splitter.css +81 -0
- package/dist/css/statistic.css +34 -0
- package/dist/css/stepper.css +3 -3
- package/dist/css/surface.css +71 -0
- package/dist/css/switch.css +12 -0
- package/dist/css/table.css +11 -0
- package/dist/css/tabs.css +10 -1
- package/dist/css/tags-input.css +91 -0
- package/dist/css/text.css +124 -0
- package/dist/css/timeline.css +59 -0
- package/dist/css/toggle.css +6 -0
- package/dist/css/tree-view.css +70 -0
- package/dist/lib/css/index.d.ts +10 -12
- package/dist/lib/css/index.d.ts.map +1 -1
- package/dist/lib/css/index.js +21 -7
- package/dist/lib/reference/colors.d.ts.map +1 -1
- package/dist/lib/reference/colors.js +15 -1
- package/dist/preset.css +23 -1
- package/dist/tokens.css +52 -4
- package/dist/tsconfig.lib.tsbuildinfo +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
@layer flx.components {
|
|
2
|
+
/* ----------------------------------------------------------------------------
|
|
3
|
+
* Rating
|
|
4
|
+
*
|
|
5
|
+
* Each item is a star silhouette (mask) painted in the "empty" colour; a
|
|
6
|
+
* ::before overlay paints the "filled" colour, revealed left-to-right via
|
|
7
|
+
* clip-path by the item's data-state (empty / half / full).
|
|
8
|
+
* ------------------------------------------------------------------------- */
|
|
9
|
+
:where([data-rating]) {
|
|
10
|
+
--flx-ui-star: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 2.2l2.9 6.5 7 .6-5.3 4.6 1.6 6.9L12 17.7 5.8 21.4l1.6-6.9L2 9.9l7-.6z'/%3E%3C/svg%3E");
|
|
11
|
+
display: inline-flex;
|
|
12
|
+
align-items: center;
|
|
13
|
+
gap: var(--flx-ui-rating-gap, 2px);
|
|
14
|
+
outline: none;
|
|
15
|
+
}
|
|
16
|
+
:where([data-rating]:not([data-disabled]):not([data-readonly])) {
|
|
17
|
+
cursor: pointer;
|
|
18
|
+
}
|
|
19
|
+
:where([data-rating]:focus-visible) {
|
|
20
|
+
border-radius: var(--flx-ui-radius-sm);
|
|
21
|
+
box-shadow: var(--flx-ui-ctl-ring);
|
|
22
|
+
}
|
|
23
|
+
:where([data-rating][data-disabled]) {
|
|
24
|
+
opacity: var(--flx-ui-opacity-disabled, 0.5);
|
|
25
|
+
cursor: not-allowed;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
:where([data-rating-item]) {
|
|
29
|
+
position: relative;
|
|
30
|
+
display: inline-block;
|
|
31
|
+
width: var(--flx-ui-rating-size, 20px);
|
|
32
|
+
height: var(--flx-ui-rating-size, 20px);
|
|
33
|
+
flex: none;
|
|
34
|
+
background: var(--flx-ui-color-border-strong);
|
|
35
|
+
-webkit-mask: var(--flx-ui-star) center / contain no-repeat;
|
|
36
|
+
mask: var(--flx-ui-star) center / contain no-repeat;
|
|
37
|
+
}
|
|
38
|
+
:where([data-rating-item])::before {
|
|
39
|
+
content: '';
|
|
40
|
+
position: absolute;
|
|
41
|
+
inset: 0;
|
|
42
|
+
background: var(--flx-ui-rating-color, var(--flx-ui-color-primary));
|
|
43
|
+
-webkit-mask: var(--flx-ui-star) center / contain no-repeat;
|
|
44
|
+
mask: var(--flx-ui-star) center / contain no-repeat;
|
|
45
|
+
clip-path: inset(0 100% 0 0);
|
|
46
|
+
transition: clip-path var(--flx-ui-duration-fast) var(--flx-ui-ease-standard);
|
|
47
|
+
}
|
|
48
|
+
:where([data-rating-item][data-state='full'])::before {
|
|
49
|
+
clip-path: inset(0 0 0 0);
|
|
50
|
+
}
|
|
51
|
+
:where([data-rating-item][data-state='half'])::before {
|
|
52
|
+
clip-path: inset(0 50% 0 0);
|
|
53
|
+
}
|
|
54
|
+
@media (prefers-reduced-motion: reduce) {
|
|
55
|
+
:where([data-rating-item])::before {
|
|
56
|
+
transition: none;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
@layer flx.components {
|
|
2
|
+
/* ----------------------------------------------------------------------------
|
|
3
|
+
* Scroll area — a scroll container with slim, theme-aware scrollbars styled over
|
|
4
|
+
* the native scrollbar (Firefox `scrollbar-*` + WebKit `::-webkit-scrollbar`).
|
|
5
|
+
* ------------------------------------------------------------------------- */
|
|
6
|
+
:where([data-scroll-area]) {
|
|
7
|
+
position: relative;
|
|
8
|
+
scrollbar-width: thin;
|
|
9
|
+
scrollbar-color: var(--flx-ui-color-border-strong) transparent;
|
|
10
|
+
overscroll-behavior: contain;
|
|
11
|
+
}
|
|
12
|
+
:where([data-scroll-area][data-orientation='vertical']) {
|
|
13
|
+
overflow-y: auto;
|
|
14
|
+
overflow-x: hidden;
|
|
15
|
+
}
|
|
16
|
+
:where([data-scroll-area][data-orientation='horizontal']) {
|
|
17
|
+
overflow-x: auto;
|
|
18
|
+
overflow-y: hidden;
|
|
19
|
+
}
|
|
20
|
+
:where([data-scroll-area][data-orientation='both']) {
|
|
21
|
+
overflow: auto;
|
|
22
|
+
}
|
|
23
|
+
:where([data-scroll-area])::-webkit-scrollbar {
|
|
24
|
+
width: 10px;
|
|
25
|
+
height: 10px;
|
|
26
|
+
}
|
|
27
|
+
:where([data-scroll-area])::-webkit-scrollbar-track {
|
|
28
|
+
background: transparent;
|
|
29
|
+
}
|
|
30
|
+
:where([data-scroll-area])::-webkit-scrollbar-thumb {
|
|
31
|
+
background: var(--flx-ui-color-border-strong);
|
|
32
|
+
border-radius: var(--flx-ui-radius-full);
|
|
33
|
+
/* Inset the thumb with a transparent border so it reads as a slim pill. */
|
|
34
|
+
border: 2px solid transparent;
|
|
35
|
+
background-clip: content-box;
|
|
36
|
+
}
|
|
37
|
+
:where([data-scroll-area])::-webkit-scrollbar-thumb:hover {
|
|
38
|
+
background: var(--flx-ui-color-fg-muted);
|
|
39
|
+
background-clip: content-box;
|
|
40
|
+
}
|
|
41
|
+
:where([data-scroll-area])::-webkit-scrollbar-corner {
|
|
42
|
+
background: transparent;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
@@ -33,9 +33,13 @@
|
|
|
33
33
|
box-shadow: var(--flx-ui-ctl-ring);
|
|
34
34
|
}
|
|
35
35
|
:where(button[role='combobox'])::after {
|
|
36
|
-
content: '
|
|
37
|
-
|
|
38
|
-
|
|
36
|
+
content: '';
|
|
37
|
+
width: 1.15em;
|
|
38
|
+
height: 1.15em;
|
|
39
|
+
flex: none;
|
|
40
|
+
background: var(--flx-ui-color-fg-muted);
|
|
41
|
+
-webkit-mask: var(--flx-ui-chevron-down) center / contain no-repeat;
|
|
42
|
+
mask: var(--flx-ui-chevron-down) center / contain no-repeat;
|
|
39
43
|
}
|
|
40
44
|
:where([data-select-value][data-placeholder]) {
|
|
41
45
|
color: var(--flx-ui-color-fg-muted);
|
|
@@ -65,12 +69,23 @@
|
|
|
65
69
|
color: var(--flx-ui-color-fg-muted);
|
|
66
70
|
}
|
|
67
71
|
:where([data-combobox-control] > button) {
|
|
72
|
+
display: inline-flex;
|
|
73
|
+
align-items: center;
|
|
74
|
+
justify-content: center;
|
|
68
75
|
border: none;
|
|
69
76
|
background: none;
|
|
70
77
|
cursor: pointer;
|
|
71
78
|
color: var(--flx-ui-color-fg-muted);
|
|
72
79
|
padding: 0 var(--flx-ui-space-1);
|
|
73
|
-
font-size: 0.8em;
|
|
74
80
|
border-radius: var(--flx-ui-radius-sm);
|
|
75
81
|
}
|
|
82
|
+
/* When the trigger has no custom content, show the shared theme chevron. */
|
|
83
|
+
:where([data-combobox-control] > button:empty)::after {
|
|
84
|
+
content: '';
|
|
85
|
+
width: 1.15em;
|
|
86
|
+
height: 1.15em;
|
|
87
|
+
background: currentColor;
|
|
88
|
+
-webkit-mask: var(--flx-ui-chevron-down) center / contain no-repeat;
|
|
89
|
+
mask: var(--flx-ui-chevron-down) center / contain no-repeat;
|
|
90
|
+
}
|
|
76
91
|
}
|
package/dist/css/sidenav.css
CHANGED
|
@@ -3,9 +3,13 @@
|
|
|
3
3
|
* Sidenav (persistent navigation rail)
|
|
4
4
|
* ------------------------------------------------------------------------- */
|
|
5
5
|
:where([data-sidenav]) {
|
|
6
|
+
/* Exposed so a consumer's shell can read the live rail width (it also drives the
|
|
7
|
+
rail's own width, so an in-flow flex/grid sidebar makes the main area adapt
|
|
8
|
+
automatically as this transitions). */
|
|
9
|
+
--flx-ui-sidenav-width: 16rem;
|
|
6
10
|
display: flex;
|
|
7
11
|
flex-direction: column;
|
|
8
|
-
width:
|
|
12
|
+
width: var(--flx-ui-sidenav-width);
|
|
9
13
|
height: 100%;
|
|
10
14
|
background: var(--flx-ui-color-bg);
|
|
11
15
|
color: var(--flx-ui-color-fg);
|
|
@@ -17,8 +21,14 @@
|
|
|
17
21
|
:where([data-sidenav][data-side='right']) {
|
|
18
22
|
border-left: var(--flx-ui-border-width-thin) solid var(--flx-ui-color-border);
|
|
19
23
|
}
|
|
20
|
-
|
|
21
|
-
|
|
24
|
+
/* Compact = icon rail. Hidden = fully off-canvas (zero width, content clipped). */
|
|
25
|
+
:where([data-sidenav][data-state='compact']) {
|
|
26
|
+
--flx-ui-sidenav-width: 3.75rem;
|
|
27
|
+
}
|
|
28
|
+
:where([data-sidenav][data-state='hidden']) {
|
|
29
|
+
--flx-ui-sidenav-width: 0px;
|
|
30
|
+
overflow: hidden;
|
|
31
|
+
border-inline-width: 0;
|
|
22
32
|
}
|
|
23
33
|
|
|
24
34
|
:where([data-sidenav-header]) {
|
|
@@ -65,8 +75,11 @@
|
|
|
65
75
|
transition: background var(--flx-ui-duration-fast) var(--flx-ui-ease-standard),
|
|
66
76
|
color var(--flx-ui-duration-fast) var(--flx-ui-ease-standard);
|
|
67
77
|
}
|
|
68
|
-
|
|
69
|
-
|
|
78
|
+
/* Hover uses an fg-relative tint (not gray-2, which is invisible on the gray-1
|
|
79
|
+
rail) so it stays legible on any surface, light or dark. `:not([data-active])`
|
|
80
|
+
keeps the active pill from being flattened by hover. */
|
|
81
|
+
:where([data-sidenav-link]:hover:not([data-active])) {
|
|
82
|
+
background: color-mix(in oklab, var(--flx-ui-color-fg) 6%, transparent);
|
|
70
83
|
color: var(--flx-ui-color-fg);
|
|
71
84
|
}
|
|
72
85
|
:where([data-sidenav-link][data-active]) {
|
|
@@ -99,6 +112,7 @@
|
|
|
99
112
|
justify-content: center;
|
|
100
113
|
width: 2rem;
|
|
101
114
|
height: 2rem;
|
|
115
|
+
flex-shrink: 0;
|
|
102
116
|
padding: 0;
|
|
103
117
|
background: transparent;
|
|
104
118
|
border: none;
|
|
@@ -106,22 +120,178 @@
|
|
|
106
120
|
color: var(--flx-ui-color-fg-muted);
|
|
107
121
|
cursor: pointer;
|
|
108
122
|
}
|
|
123
|
+
/* A trigger in the header sits at the trailing edge on its own — the consumer
|
|
124
|
+
drops in <SidenavTrigger/> without wiring any layout. On the compact icon rail
|
|
125
|
+
the header centres its contents, so the auto-margin is dropped. */
|
|
126
|
+
:where([data-sidenav-header] [data-sidenav-trigger]) {
|
|
127
|
+
margin-inline-start: auto;
|
|
128
|
+
}
|
|
129
|
+
:where([data-sidenav][data-state='compact']:not([data-mobile]) [data-sidenav-header] [data-sidenav-trigger]) {
|
|
130
|
+
margin-inline-start: 0;
|
|
131
|
+
}
|
|
109
132
|
:where([data-sidenav-trigger]:hover) {
|
|
110
|
-
background: var(--flx-ui-color-
|
|
133
|
+
background: color-mix(in oklab, var(--flx-ui-color-fg) 6%, transparent);
|
|
111
134
|
color: var(--flx-ui-color-fg);
|
|
112
135
|
}
|
|
113
136
|
:where([data-sidenav-trigger]:focus-visible) {
|
|
114
137
|
outline: var(--flx-ui-ctl-ring);
|
|
115
138
|
outline-offset: 2px;
|
|
116
139
|
}
|
|
140
|
+
/* Built-in trigger icon: a chevron pointing in the collapse direction, flipping
|
|
141
|
+
between expanded and compact (and mirrored for a right-side rail). */
|
|
142
|
+
:where([data-sidenav-trigger-icon]) {
|
|
143
|
+
display: block;
|
|
144
|
+
width: 1.15em;
|
|
145
|
+
height: 1.15em;
|
|
146
|
+
background: currentColor;
|
|
147
|
+
mask: var(--flx-ui-chevron-down) center / contain no-repeat;
|
|
148
|
+
-webkit-mask: var(--flx-ui-chevron-down) center / contain no-repeat;
|
|
149
|
+
transform: rotate(90deg);
|
|
150
|
+
transition: transform var(--flx-ui-duration-normal) var(--flx-ui-ease-standard);
|
|
151
|
+
}
|
|
152
|
+
:where([data-sidenav][data-collapsed] [data-sidenav-trigger-icon]),
|
|
153
|
+
:where([data-sidenav][data-side='right'] [data-sidenav-trigger-icon]) {
|
|
154
|
+
transform: rotate(-90deg);
|
|
155
|
+
}
|
|
156
|
+
:where([data-sidenav][data-side='right'][data-collapsed] [data-sidenav-trigger-icon]) {
|
|
157
|
+
transform: rotate(90deg);
|
|
158
|
+
}
|
|
117
159
|
|
|
118
|
-
/*
|
|
119
|
-
|
|
120
|
-
|
|
160
|
+
/* Compact icon rail: collapse each row to its leading icon. Scoped to `compact`
|
|
161
|
+
(not the mobile drawer, which is full-width; `hidden` is clipped anyway).
|
|
162
|
+
Applies to DIRECT rail rows ONLY — a sub's flyout content is portalled OUTSIDE
|
|
163
|
+
[data-sidenav], so these descendant rules never reach it (subitems keep their
|
|
164
|
+
labels in the popup). Three ways an element hides in compact:
|
|
165
|
+
1. [data-sidenav-label] / [data-sidenav-group-label] — the recommended wrapper.
|
|
166
|
+
2. [data-sidenav-hide-compact] — an explicit opt-in marker for ANY element.
|
|
167
|
+
3. auto — any non-leading child of a link / sub-trigger (the first child is the
|
|
168
|
+
icon), so unmarked label text collapses with no extra markup. */
|
|
169
|
+
:where([data-sidenav][data-state='compact']:not([data-mobile]))
|
|
170
|
+
:where([data-sidenav-label], [data-sidenav-group-label], [data-sidenav-hide-compact]) {
|
|
121
171
|
display: none;
|
|
122
172
|
}
|
|
123
|
-
:where([data-sidenav][data-
|
|
173
|
+
:where([data-sidenav][data-state='compact']:not([data-mobile]))
|
|
174
|
+
:where([data-sidenav-link], [data-sidenav-sub-trigger]) > :not(:first-child) {
|
|
175
|
+
display: none;
|
|
176
|
+
}
|
|
177
|
+
:where([data-sidenav][data-state='compact']:not([data-mobile]))
|
|
178
|
+
:where([data-sidenav-link], [data-sidenav-sub-trigger]) {
|
|
124
179
|
justify-content: center;
|
|
180
|
+
gap: 0;
|
|
125
181
|
padding-inline: 0;
|
|
126
182
|
}
|
|
183
|
+
|
|
184
|
+
/* ── Nested items (submenus) ──────────────────────────────────────────────── */
|
|
185
|
+
/* The parent row reuses [data-sidenav-link] styling; add the disclosure chevron. */
|
|
186
|
+
:where([data-sidenav-sub-trigger]) {
|
|
187
|
+
width: 100%;
|
|
188
|
+
border: 0;
|
|
189
|
+
background: transparent;
|
|
190
|
+
font: inherit;
|
|
191
|
+
text-align: start;
|
|
192
|
+
cursor: pointer;
|
|
193
|
+
}
|
|
194
|
+
:where([data-sidenav-sub-trigger])::after {
|
|
195
|
+
content: '';
|
|
196
|
+
margin-inline-start: auto;
|
|
197
|
+
width: 1em;
|
|
198
|
+
height: 1em;
|
|
199
|
+
flex-shrink: 0;
|
|
200
|
+
background: currentColor;
|
|
201
|
+
mask: var(--flx-ui-chevron-down, none) center / contain no-repeat;
|
|
202
|
+
-webkit-mask: var(--flx-ui-chevron-down, none) center / contain no-repeat;
|
|
203
|
+
transition: transform var(--flx-ui-duration-fast) var(--flx-ui-ease-standard);
|
|
204
|
+
}
|
|
205
|
+
:where([data-sidenav-sub-trigger][data-open])::after {
|
|
206
|
+
transform: rotate(180deg);
|
|
207
|
+
}
|
|
208
|
+
/* Hide the chevron on the compact rail (the flyout replaces it). */
|
|
209
|
+
:where([data-sidenav][data-state='compact']:not([data-mobile]) [data-sidenav-sub-trigger])::after {
|
|
210
|
+
display: none;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
/* Inline nested list (expanded / mobile). Collapsed via max-height so every child
|
|
214
|
+
hides (a grid-rows 0fr trick only collapses a single grid child — the rest fall
|
|
215
|
+
into implicit auto rows and stay visible). The cap is generous; nav lists are short. */
|
|
216
|
+
:where([data-sidenav-sub-content]:not([data-flyout])) {
|
|
217
|
+
margin: 0;
|
|
218
|
+
padding: 0 0 0 var(--flx-ui-space-5);
|
|
219
|
+
list-style: none;
|
|
220
|
+
max-height: 0;
|
|
221
|
+
overflow: hidden;
|
|
222
|
+
opacity: 0;
|
|
223
|
+
transition:
|
|
224
|
+
max-height var(--flx-ui-duration-normal) var(--flx-ui-ease-standard),
|
|
225
|
+
opacity var(--flx-ui-duration-fast) var(--flx-ui-ease-standard);
|
|
226
|
+
}
|
|
227
|
+
:where([data-sidenav-sub-content]:not([data-flyout])[data-open]) {
|
|
228
|
+
max-height: 40rem;
|
|
229
|
+
opacity: 1;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
/* Flyout panel (compact rail): a floating anchored menu of the nested links. */
|
|
233
|
+
:where([data-sidenav-sub-content][data-flyout]) {
|
|
234
|
+
position: absolute;
|
|
235
|
+
z-index: var(--flx-ui-z-popover, 40);
|
|
236
|
+
min-width: 12rem;
|
|
237
|
+
margin: 0;
|
|
238
|
+
padding: var(--flx-ui-space-1);
|
|
239
|
+
list-style: none;
|
|
240
|
+
display: flex;
|
|
241
|
+
flex-direction: column;
|
|
242
|
+
gap: var(--flx-ui-space-1);
|
|
243
|
+
background: var(--flx-ui-color-bg);
|
|
244
|
+
border: var(--flx-ui-border-width-thin) solid var(--flx-ui-color-border);
|
|
245
|
+
border-radius: var(--flx-ui-radius-lg);
|
|
246
|
+
box-shadow: var(--flx-ui-shadow-lg);
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
/* ── Mobile overlay drawer ────────────────────────────────────────────────── */
|
|
250
|
+
:where([data-sidenav-overlay]) {
|
|
251
|
+
position: fixed;
|
|
252
|
+
inset: 0;
|
|
253
|
+
z-index: var(--flx-ui-z-modal, 50);
|
|
254
|
+
}
|
|
255
|
+
:where([data-sidenav-overlay][data-state='closed']) {
|
|
256
|
+
pointer-events: none;
|
|
257
|
+
}
|
|
258
|
+
:where([data-sidenav-backdrop]) {
|
|
259
|
+
position: fixed;
|
|
260
|
+
inset: 0;
|
|
261
|
+
background: var(--flx-ui-color-overlay);
|
|
262
|
+
opacity: 0;
|
|
263
|
+
transition: opacity var(--flx-ui-duration-normal) var(--flx-ui-ease-standard);
|
|
264
|
+
}
|
|
265
|
+
:where([data-sidenav-backdrop][data-state='open']) {
|
|
266
|
+
opacity: 1;
|
|
267
|
+
}
|
|
268
|
+
/* The overlay rail is full-height, positioned against its side, always expanded. */
|
|
269
|
+
:where([data-sidenav][data-mobile]) {
|
|
270
|
+
position: fixed;
|
|
271
|
+
top: 0;
|
|
272
|
+
bottom: 0;
|
|
273
|
+
--flx-ui-sidenav-width: 16rem;
|
|
274
|
+
max-width: 85vw;
|
|
275
|
+
box-shadow: var(--flx-ui-shadow-xl);
|
|
276
|
+
animation: flx-sidenav-in var(--flx-ui-duration-normal) var(--flx-ui-ease-standard);
|
|
277
|
+
}
|
|
278
|
+
:where([data-sidenav][data-mobile][data-side='left']) {
|
|
279
|
+
left: 0;
|
|
280
|
+
}
|
|
281
|
+
:where([data-sidenav][data-mobile][data-side='right']) {
|
|
282
|
+
right: 0;
|
|
283
|
+
}
|
|
284
|
+
@keyframes flx-sidenav-in {
|
|
285
|
+
from {
|
|
286
|
+
transform: translateX(var(--flx-ui-sidenav-enter-x, -100%));
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
:where([data-sidenav][data-mobile][data-side='right']) {
|
|
290
|
+
--flx-ui-sidenav-enter-x: 100%;
|
|
291
|
+
}
|
|
292
|
+
@media (prefers-reduced-motion: reduce) {
|
|
293
|
+
:where([data-sidenav][data-mobile]) {
|
|
294
|
+
animation: none;
|
|
295
|
+
}
|
|
296
|
+
}
|
|
127
297
|
}
|
package/dist/css/slider.css
CHANGED
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
left: 0;
|
|
43
43
|
width: 100%;
|
|
44
44
|
}
|
|
45
|
-
:where([role='slider']) {
|
|
45
|
+
:where([data-slider] [role='slider']) {
|
|
46
46
|
position: absolute;
|
|
47
47
|
width: 16px;
|
|
48
48
|
height: 16px;
|
|
@@ -52,15 +52,15 @@
|
|
|
52
52
|
box-shadow: var(--flx-ui-shadow-sm);
|
|
53
53
|
cursor: grab;
|
|
54
54
|
}
|
|
55
|
-
:where([role='slider'][data-orientation='horizontal']) {
|
|
55
|
+
:where([data-slider] [role='slider'][data-orientation='horizontal']) {
|
|
56
56
|
top: 50%;
|
|
57
57
|
transform: translate(-50%, -50%);
|
|
58
58
|
}
|
|
59
|
-
:where([role='slider'][data-orientation='vertical']) {
|
|
59
|
+
:where([data-slider] [role='slider'][data-orientation='vertical']) {
|
|
60
60
|
left: 50%;
|
|
61
61
|
transform: translate(-50%, 50%);
|
|
62
62
|
}
|
|
63
|
-
:where([role='slider']:focus-visible) {
|
|
63
|
+
:where([data-slider] [role='slider']:focus-visible) {
|
|
64
64
|
outline: none;
|
|
65
65
|
box-shadow: var(--flx-ui-ctl-ring);
|
|
66
66
|
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
@layer flx.components {
|
|
2
|
+
/* ----------------------------------------------------------------------------
|
|
3
|
+
* Speed dial — a FAB trigger with actions that fan out in a direction.
|
|
4
|
+
* ------------------------------------------------------------------------- */
|
|
5
|
+
:where([data-speed-dial]) {
|
|
6
|
+
position: relative;
|
|
7
|
+
display: inline-flex;
|
|
8
|
+
width: max-content;
|
|
9
|
+
}
|
|
10
|
+
:where([data-speed-dial-actions]) {
|
|
11
|
+
position: absolute;
|
|
12
|
+
display: flex;
|
|
13
|
+
gap: var(--flx-ui-space-3);
|
|
14
|
+
align-items: center;
|
|
15
|
+
opacity: 1;
|
|
16
|
+
transition: opacity var(--flx-ui-duration-fast) var(--flx-ui-ease-standard);
|
|
17
|
+
}
|
|
18
|
+
/* Off by default — the actions float bare. `filled` opts into a surface. */
|
|
19
|
+
:where([data-speed-dial-actions][data-filled]) {
|
|
20
|
+
gap: var(--flx-ui-space-2);
|
|
21
|
+
padding: var(--flx-ui-space-2);
|
|
22
|
+
background: var(--flx-ui-color-bg);
|
|
23
|
+
border: var(--flx-ui-border-width-thin) solid var(--flx-ui-color-border);
|
|
24
|
+
border-radius: var(--flx-ui-radius-lg);
|
|
25
|
+
box-shadow: var(--flx-ui-shadow-lg);
|
|
26
|
+
}
|
|
27
|
+
/* Hidden (and unfocusable) until the dial opens. */
|
|
28
|
+
:where([data-speed-dial][data-state='closed']) [data-speed-dial-actions] {
|
|
29
|
+
visibility: hidden;
|
|
30
|
+
opacity: 0;
|
|
31
|
+
pointer-events: none;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/* Fan-out direction, anchored to the trigger. */
|
|
35
|
+
:where([data-speed-dial][data-direction='up']) [data-speed-dial-actions] {
|
|
36
|
+
flex-direction: column-reverse;
|
|
37
|
+
bottom: 100%;
|
|
38
|
+
left: 50%;
|
|
39
|
+
transform: translateX(-50%);
|
|
40
|
+
margin-bottom: var(--flx-ui-space-3);
|
|
41
|
+
}
|
|
42
|
+
:where([data-speed-dial][data-direction='down']) [data-speed-dial-actions] {
|
|
43
|
+
flex-direction: column;
|
|
44
|
+
top: 100%;
|
|
45
|
+
left: 50%;
|
|
46
|
+
transform: translateX(-50%);
|
|
47
|
+
margin-top: var(--flx-ui-space-3);
|
|
48
|
+
}
|
|
49
|
+
:where([data-speed-dial][data-direction='left']) [data-speed-dial-actions] {
|
|
50
|
+
flex-direction: row-reverse;
|
|
51
|
+
right: 100%;
|
|
52
|
+
top: 50%;
|
|
53
|
+
transform: translateY(-50%);
|
|
54
|
+
margin-right: var(--flx-ui-space-3);
|
|
55
|
+
}
|
|
56
|
+
:where([data-speed-dial][data-direction='right']) [data-speed-dial-actions] {
|
|
57
|
+
flex-direction: row;
|
|
58
|
+
left: 100%;
|
|
59
|
+
top: 50%;
|
|
60
|
+
transform: translateY(-50%);
|
|
61
|
+
margin-left: var(--flx-ui-space-3);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/* An action + its optional label. */
|
|
65
|
+
:where([data-speed-dial-action-wrap]) {
|
|
66
|
+
display: inline-flex;
|
|
67
|
+
align-items: center;
|
|
68
|
+
gap: var(--flx-ui-space-2);
|
|
69
|
+
}
|
|
70
|
+
/* For vertical directions the label reads to the left of the button. */
|
|
71
|
+
:where([data-speed-dial][data-direction='down']) [data-speed-dial-action-wrap],
|
|
72
|
+
:where([data-speed-dial][data-direction='up']) [data-speed-dial-action-wrap] {
|
|
73
|
+
flex-direction: row-reverse;
|
|
74
|
+
}
|
|
75
|
+
:where([data-speed-dial-action-label]) {
|
|
76
|
+
padding: 2px var(--flx-ui-space-2);
|
|
77
|
+
border-radius: var(--flx-ui-radius-sm);
|
|
78
|
+
background: var(--flx-ui-color-fg);
|
|
79
|
+
color: var(--flx-ui-color-bg);
|
|
80
|
+
font-size: var(--flx-ui-font-size-xs);
|
|
81
|
+
font-weight: var(--flx-ui-font-weight-medium);
|
|
82
|
+
white-space: nowrap;
|
|
83
|
+
box-shadow: var(--flx-ui-shadow-sm);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
@layer flx.components {
|
|
2
|
+
:where([data-splitter]) {
|
|
3
|
+
--flx-ui-splitter-thickness: 1px;
|
|
4
|
+
--flx-ui-splitter-hit-area: var(--flx-ui-space-2);
|
|
5
|
+
|
|
6
|
+
display: flex;
|
|
7
|
+
min-width: 0;
|
|
8
|
+
min-height: 0;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
:where([data-splitter][data-orientation='horizontal']) { flex-direction: row; }
|
|
12
|
+
:where([data-splitter][data-orientation='vertical']) { flex-direction: column; }
|
|
13
|
+
|
|
14
|
+
/* `min-*: 0` lets a panel shrink below its content instead of forcing the
|
|
15
|
+
splitter wider than its container — the same rule the page body needs. */
|
|
16
|
+
:where([data-splitter-panel]) {
|
|
17
|
+
min-width: 0;
|
|
18
|
+
min-height: 0;
|
|
19
|
+
overflow: auto;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/*
|
|
23
|
+
* The divider is a hairline, but the grab area is wider — a 1px target is
|
|
24
|
+
* unusable with a mouse and impossible with a finger. The line is drawn by a
|
|
25
|
+
* pseudo-element so the hit area can be generous without looking heavy.
|
|
26
|
+
*/
|
|
27
|
+
:where([data-splitter-handle]) {
|
|
28
|
+
position: relative;
|
|
29
|
+
flex: none;
|
|
30
|
+
display: flex;
|
|
31
|
+
align-items: center;
|
|
32
|
+
justify-content: center;
|
|
33
|
+
background: transparent;
|
|
34
|
+
border: 0;
|
|
35
|
+
padding: 0;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
:where([data-splitter-handle])::before {
|
|
39
|
+
content: '';
|
|
40
|
+
position: absolute;
|
|
41
|
+
background: var(--flx-ui-color-border);
|
|
42
|
+
transition: background var(--flx-ui-duration-fast) var(--flx-ui-ease-standard);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
:where([data-splitter-handle][data-orientation='horizontal']) {
|
|
46
|
+
width: var(--flx-ui-splitter-hit-area);
|
|
47
|
+
cursor: col-resize;
|
|
48
|
+
}
|
|
49
|
+
:where([data-splitter-handle][data-orientation='horizontal'])::before {
|
|
50
|
+
inset-block: 0;
|
|
51
|
+
width: var(--flx-ui-splitter-thickness);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
:where([data-splitter-handle][data-orientation='vertical']) {
|
|
55
|
+
height: var(--flx-ui-splitter-hit-area);
|
|
56
|
+
cursor: row-resize;
|
|
57
|
+
}
|
|
58
|
+
:where([data-splitter-handle][data-orientation='vertical'])::before {
|
|
59
|
+
inset-inline: 0;
|
|
60
|
+
height: var(--flx-ui-splitter-thickness);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
:where([data-splitter-handle]:hover)::before,
|
|
64
|
+
:where([data-splitter-handle][data-dragging])::before {
|
|
65
|
+
background: var(--flx-ui-color-primary);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
:where([data-splitter-handle]:focus-visible) {
|
|
69
|
+
outline: var(--flx-ui-border-width-thick) solid var(--flx-ui-color-focus-ring);
|
|
70
|
+
outline-offset: -2px;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/* While dragging, the pointer owns the whole splitter: no text selection, and
|
|
74
|
+
no panel swallowing the pointer as the cursor crosses it. */
|
|
75
|
+
:where([data-splitter][data-dragging]) {
|
|
76
|
+
user-select: none;
|
|
77
|
+
}
|
|
78
|
+
:where([data-splitter][data-dragging]) :where([data-splitter-panel]) {
|
|
79
|
+
pointer-events: none;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
@layer flx.components {
|
|
2
|
+
/* Statistic (from @fluixi-ui/statistic). A KPI: caption, big value, and an
|
|
3
|
+
optional delta line coloured by the container's data-trend. */
|
|
4
|
+
:where([data-statistic]) {
|
|
5
|
+
display: flex;
|
|
6
|
+
flex-direction: column;
|
|
7
|
+
gap: var(--flx-ui-space-1);
|
|
8
|
+
min-width: 0;
|
|
9
|
+
}
|
|
10
|
+
:where([data-statistic-label]) {
|
|
11
|
+
font-size: var(--flx-ui-font-size-xs);
|
|
12
|
+
font-weight: var(--flx-ui-font-weight-medium);
|
|
13
|
+
color: var(--flx-ui-color-fg-subtle);
|
|
14
|
+
letter-spacing: var(--flx-ui-letter-spacing-wide);
|
|
15
|
+
text-transform: uppercase;
|
|
16
|
+
}
|
|
17
|
+
:where([data-statistic-value]) {
|
|
18
|
+
font-size: var(--flx-ui-font-size-2xl);
|
|
19
|
+
font-weight: var(--flx-ui-font-weight-bold);
|
|
20
|
+
color: var(--flx-ui-color-fg);
|
|
21
|
+
line-height: 1.1;
|
|
22
|
+
font-variant-numeric: tabular-nums;
|
|
23
|
+
}
|
|
24
|
+
:where([data-statistic-delta]) {
|
|
25
|
+
display: inline-flex;
|
|
26
|
+
align-items: center;
|
|
27
|
+
gap: var(--flx-ui-space-1);
|
|
28
|
+
font-size: var(--flx-ui-font-size-xs);
|
|
29
|
+
font-weight: var(--flx-ui-font-weight-semibold);
|
|
30
|
+
color: var(--flx-ui-color-fg-subtle);
|
|
31
|
+
}
|
|
32
|
+
:where([data-statistic][data-trend='up'] [data-statistic-delta]) { color: var(--flx-ui-color-success); }
|
|
33
|
+
:where([data-statistic][data-trend='down'] [data-statistic-delta]) { color: var(--flx-ui-color-danger); }
|
|
34
|
+
}
|
package/dist/css/stepper.css
CHANGED
|
@@ -66,9 +66,9 @@
|
|
|
66
66
|
font-size: var(--flx-ui-font-size-sm);
|
|
67
67
|
font-weight: var(--flx-ui-font-weight-medium);
|
|
68
68
|
line-height: 1;
|
|
69
|
-
transition: background var(--flx-ui-duration-fast) var(--flx-ui-
|
|
70
|
-
border-color var(--flx-ui-duration-fast) var(--flx-ui-
|
|
71
|
-
color var(--flx-ui-duration-fast) var(--flx-ui-
|
|
69
|
+
transition: background var(--flx-ui-duration-fast) var(--flx-ui-ease-standard),
|
|
70
|
+
border-color var(--flx-ui-duration-fast) var(--flx-ui-ease-standard),
|
|
71
|
+
color var(--flx-ui-duration-fast) var(--flx-ui-ease-standard);
|
|
72
72
|
}
|
|
73
73
|
:where([data-stepper-indicator][data-state='active']) {
|
|
74
74
|
border-color: var(--flx-ui-color-primary);
|