@gtivr4/a1-design-system-react 0.3.1 → 0.4.1
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/package.json +1 -1
- package/src/components/calendar/Calendar.jsx +76 -13
- package/src/components/calendar/calendar.css +71 -0
- package/src/components/choice-group/ChoiceGroup.jsx +2 -0
- package/src/components/choice-group/choice-group.css +11 -0
- package/src/components/data-table/DataTable.jsx +5 -5
- package/src/components/field/SelectField.jsx +1 -1
- package/src/components/field/TextField.jsx +1 -1
- package/src/components/field/TextareaField.jsx +1 -1
- package/src/components/field/field.css +8 -8
- package/src/components/field-row/FieldRow.jsx +2 -2
- package/src/components/fieldset/Fieldset.jsx +1 -1
- package/src/components/grid/Grid.jsx +1 -0
- package/src/components/heading/Heading.jsx +1 -1
- package/src/components/heading/heading.css +2 -0
- package/src/components/notification/Notification.jsx +4 -4
- package/src/components/notification/notification.css +1 -1
- package/src/components/paragraph/Paragraph.jsx +1 -1
- package/src/components/paragraph/paragraph.css +2 -0
- package/src/components/section/Section.jsx +8 -8
- package/src/components/section/section.css +3 -2
- package/src/components/segmented-control/segmented.css +0 -1
- package/src/components/status-bar/StatusBar.jsx +92 -0
- package/src/components/status-bar/status-bar.css +146 -0
- package/src/index.js +1 -0
- package/src/themes.css +1 -0
- package/src/tokens.css +10 -0
package/package.json
CHANGED
|
@@ -42,6 +42,12 @@ export function Calendar({
|
|
|
42
42
|
dimPast = true,
|
|
43
43
|
variant = "scroll",
|
|
44
44
|
todayButton = false,
|
|
45
|
+
selectable = false,
|
|
46
|
+
selectedDate,
|
|
47
|
+
defaultSelectedDate,
|
|
48
|
+
onChange,
|
|
49
|
+
minDate,
|
|
50
|
+
maxDate,
|
|
45
51
|
className = "",
|
|
46
52
|
...props
|
|
47
53
|
}) {
|
|
@@ -63,6 +69,35 @@ export function Calendar({
|
|
|
63
69
|
const [viewMonth, setViewMonth] = useState(centerMonth);
|
|
64
70
|
const currentMonthRef = useRef(null);
|
|
65
71
|
|
|
72
|
+
// Selection — controlled when selectedDate is provided, otherwise internal state
|
|
73
|
+
const isControlled = selectedDate !== undefined;
|
|
74
|
+
const [internalSelected, setInternalSelected] = useState(defaultSelectedDate ?? null);
|
|
75
|
+
const selected = isControlled ? selectedDate : internalSelected;
|
|
76
|
+
|
|
77
|
+
function isSameDay(d, y, m, day) {
|
|
78
|
+
return d instanceof Date && d.getFullYear() === y && d.getMonth() === m && d.getDate() === day;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function isDayDisabled(y, m, day) {
|
|
82
|
+
const date = new Date(y, m, day);
|
|
83
|
+
if (minDate) {
|
|
84
|
+
const min = new Date(minDate.getFullYear(), minDate.getMonth(), minDate.getDate());
|
|
85
|
+
if (date < min) return true;
|
|
86
|
+
}
|
|
87
|
+
if (maxDate) {
|
|
88
|
+
const max = new Date(maxDate.getFullYear(), maxDate.getMonth(), maxDate.getDate());
|
|
89
|
+
if (date > max) return true;
|
|
90
|
+
}
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function handleDayClick(y, m, day) {
|
|
95
|
+
if (isDayDisabled(y, m, day)) return;
|
|
96
|
+
const date = new Date(y, m, day);
|
|
97
|
+
if (!isControlled) setInternalSelected(date);
|
|
98
|
+
onChange?.(date);
|
|
99
|
+
}
|
|
100
|
+
|
|
66
101
|
// ── Localised strings ─────────────────────────────────────────
|
|
67
102
|
|
|
68
103
|
// Month names
|
|
@@ -210,15 +245,30 @@ export function Calendar({
|
|
|
210
245
|
dimPast &&
|
|
211
246
|
new Date(year, month, day) < new Date(todayYear, todayMonth, todayDay);
|
|
212
247
|
|
|
248
|
+
const isSelected = isSameDay(selected, year, month, day);
|
|
249
|
+
const isDisabled = isDayDisabled(year, month, day);
|
|
250
|
+
|
|
213
251
|
return (
|
|
214
252
|
<td
|
|
215
253
|
key={di}
|
|
216
254
|
className={[
|
|
217
255
|
"a1-calendar__day",
|
|
218
|
-
isToday
|
|
219
|
-
isPast
|
|
256
|
+
isToday && "a1-calendar__day--today",
|
|
257
|
+
isPast && "a1-calendar__day--past",
|
|
258
|
+
isSelected && "a1-calendar__day--selected",
|
|
259
|
+
isDisabled && "a1-calendar__day--disabled",
|
|
220
260
|
].filter(Boolean).join(" ")}
|
|
221
261
|
aria-current={isToday ? "date" : undefined}
|
|
262
|
+
aria-selected={isSelected ? true : undefined}
|
|
263
|
+
aria-disabled={isDisabled ? true : undefined}
|
|
264
|
+
tabIndex={selectable && !isDisabled ? 0 : undefined}
|
|
265
|
+
onClick={selectable && !isDisabled ? () => handleDayClick(year, month, day) : undefined}
|
|
266
|
+
onKeyDown={selectable && !isDisabled ? (e) => {
|
|
267
|
+
if (e.key === "Enter" || e.key === " ") {
|
|
268
|
+
e.preventDefault();
|
|
269
|
+
handleDayClick(year, month, day);
|
|
270
|
+
}
|
|
271
|
+
} : undefined}
|
|
222
272
|
>
|
|
223
273
|
<span className="a1-calendar__day-number" aria-hidden="true">
|
|
224
274
|
{day}
|
|
@@ -235,17 +285,27 @@ export function Calendar({
|
|
|
235
285
|
|
|
236
286
|
// ── Paginated variant ─────────────────────────────────────────
|
|
237
287
|
if (variant === "paginated") {
|
|
238
|
-
const
|
|
239
|
-
const
|
|
288
|
+
const minYear = minDate ? minDate.getFullYear() : todayYear - 10;
|
|
289
|
+
const minMon = minDate ? minDate.getMonth() : 0;
|
|
290
|
+
const maxYear = maxDate ? maxDate.getFullYear() : todayYear + 15;
|
|
291
|
+
const maxMon = maxDate ? maxDate.getMonth() : 11;
|
|
292
|
+
|
|
293
|
+
const yearStart = minDate ? minDate.getFullYear() : todayYear - 10;
|
|
294
|
+
const yearEnd = maxDate ? maxDate.getFullYear() : todayYear + 15;
|
|
240
295
|
const years = Array.from({ length: yearEnd - yearStart + 1 }, (_, i) => yearStart + i);
|
|
241
296
|
|
|
297
|
+
const prevAtMin = viewYear === minYear && viewMonth === minMon;
|
|
298
|
+
const nextAtMax = viewYear === maxYear && viewMonth === maxMon;
|
|
299
|
+
|
|
242
300
|
const goPrev = () => {
|
|
301
|
+
if (prevAtMin) return;
|
|
243
302
|
const p = addMonths(viewYear, viewMonth, -1);
|
|
244
303
|
setViewYear(p.year);
|
|
245
304
|
setViewMonth(p.month);
|
|
246
305
|
};
|
|
247
306
|
|
|
248
307
|
const goNext = () => {
|
|
308
|
+
if (nextAtMax) return;
|
|
249
309
|
const n = addMonths(viewYear, viewMonth, 1);
|
|
250
310
|
setViewYear(n.year);
|
|
251
311
|
setViewMonth(n.month);
|
|
@@ -263,19 +323,19 @@ export function Calendar({
|
|
|
263
323
|
|
|
264
324
|
return (
|
|
265
325
|
<div
|
|
266
|
-
className={["a1-calendar", "a1-calendar--paginated", className].filter(Boolean).join(" ")}
|
|
326
|
+
className={["a1-calendar", "a1-calendar--paginated", selectable && "a1-calendar--selectable", className].filter(Boolean).join(" ")}
|
|
267
327
|
{...props}
|
|
268
328
|
>
|
|
269
329
|
<div className="a1-calendar__inner">
|
|
270
330
|
<div className="a1-calendar__nav">
|
|
271
331
|
|
|
272
332
|
<span className="a1-calendar__nav-wide">
|
|
273
|
-
<Button variant="tertiary" size="sm" icon={isRtl ? "chevron_right" : "chevron_left"} iconPosition="start" onClick={goPrev}>
|
|
333
|
+
<Button variant="tertiary" size="sm" icon={isRtl ? "chevron_right" : "chevron_left"} iconPosition="start" onClick={goPrev} disabled={prevAtMin}>
|
|
274
334
|
{prevMonthLabel}
|
|
275
335
|
</Button>
|
|
276
336
|
</span>
|
|
277
337
|
<span className="a1-calendar__nav-narrow">
|
|
278
|
-
<IconButton icon={isRtl ? "chevron_right" : "chevron_left"} label={prevMonthLabel} variant="tertiary" onClick={goPrev} />
|
|
338
|
+
<IconButton icon={isRtl ? "chevron_right" : "chevron_left"} label={prevMonthLabel} variant="tertiary" onClick={goPrev} disabled={prevAtMin} />
|
|
279
339
|
</span>
|
|
280
340
|
|
|
281
341
|
<div className="a1-calendar__nav-label">
|
|
@@ -286,9 +346,12 @@ export function Calendar({
|
|
|
286
346
|
value={viewMonth}
|
|
287
347
|
onChange={e => setViewMonth(Number(e.target.value))}
|
|
288
348
|
>
|
|
289
|
-
{MONTHS.map((name, i) =>
|
|
290
|
-
|
|
291
|
-
|
|
349
|
+
{MONTHS.map((name, i) => {
|
|
350
|
+
const disabled =
|
|
351
|
+
(viewYear === minYear && i < minMon) ||
|
|
352
|
+
(viewYear === maxYear && i > maxMon);
|
|
353
|
+
return <option key={i} value={i} disabled={disabled}>{name}</option>;
|
|
354
|
+
})}
|
|
292
355
|
</SelectField>
|
|
293
356
|
<SelectField
|
|
294
357
|
className="a1-calendar__nav-field"
|
|
@@ -327,12 +390,12 @@ export function Calendar({
|
|
|
327
390
|
</div>
|
|
328
391
|
|
|
329
392
|
<span className="a1-calendar__nav-wide">
|
|
330
|
-
<Button variant="tertiary" size="sm" icon={isRtl ? "chevron_left" : "chevron_right"} iconPosition="end" onClick={goNext}>
|
|
393
|
+
<Button variant="tertiary" size="sm" icon={isRtl ? "chevron_left" : "chevron_right"} iconPosition="end" onClick={goNext} disabled={nextAtMax}>
|
|
331
394
|
{nextMonthLabel}
|
|
332
395
|
</Button>
|
|
333
396
|
</span>
|
|
334
397
|
<span className="a1-calendar__nav-narrow">
|
|
335
|
-
<IconButton icon={isRtl ? "chevron_left" : "chevron_right"} label={nextMonthLabel} variant="tertiary" onClick={goNext} />
|
|
398
|
+
<IconButton icon={isRtl ? "chevron_left" : "chevron_right"} label={nextMonthLabel} variant="tertiary" onClick={goNext} disabled={nextAtMax} />
|
|
336
399
|
</span>
|
|
337
400
|
|
|
338
401
|
</div>
|
|
@@ -351,7 +414,7 @@ export function Calendar({
|
|
|
351
414
|
|
|
352
415
|
return (
|
|
353
416
|
<div
|
|
354
|
-
className={["a1-calendar", className].filter(Boolean).join(" ")}
|
|
417
|
+
className={["a1-calendar", selectable && "a1-calendar--selectable", className].filter(Boolean).join(" ")}
|
|
355
418
|
{...props}
|
|
356
419
|
>
|
|
357
420
|
<div className="a1-calendar__inner">
|
|
@@ -110,6 +110,50 @@
|
|
|
110
110
|
background: var(--semantic-color-surface-raised);
|
|
111
111
|
}
|
|
112
112
|
|
|
113
|
+
/* ── Selected — full-cell fill (display and selectable modes) ─── */
|
|
114
|
+
|
|
115
|
+
.a1-calendar__day--selected {
|
|
116
|
+
background: var(--semantic-color-action-background);
|
|
117
|
+
color: var(--semantic-color-text-inverse);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/* ── Disabled (out of range) — same surface as past dates ──────── */
|
|
121
|
+
|
|
122
|
+
.a1-calendar__day--disabled {
|
|
123
|
+
background: var(--semantic-color-surface-raised);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/* ── Selectable mode (opt-in via selectable prop) ──────────────── */
|
|
127
|
+
|
|
128
|
+
.a1-calendar--selectable .a1-calendar__day:not(.a1-calendar__day--empty):not(.a1-calendar__day--disabled) {
|
|
129
|
+
cursor: pointer;
|
|
130
|
+
}
|
|
131
|
+
.a1-calendar--selectable .a1-calendar__day--disabled {
|
|
132
|
+
cursor: not-allowed;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/* Today — neutral ring instead of action fill (yields to selected) */
|
|
136
|
+
.a1-calendar--selectable .a1-calendar__day--today:not(.a1-calendar__day--selected) {
|
|
137
|
+
background: transparent;
|
|
138
|
+
color: var(--semantic-color-text-default);
|
|
139
|
+
}
|
|
140
|
+
.a1-calendar--selectable .a1-calendar__day--today:not(.a1-calendar__day--selected) .a1-calendar__day-number {
|
|
141
|
+
outline: 2px solid var(--semantic-color-text-default);
|
|
142
|
+
outline-offset: -1px;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/* Full-cell hover for non-selected, non-disabled days */
|
|
146
|
+
.a1-calendar--selectable .a1-calendar__day:not(.a1-calendar__day--empty):not(.a1-calendar__day--disabled):not(.a1-calendar__day--selected):hover {
|
|
147
|
+
background: var(--semantic-color-surface-panel);
|
|
148
|
+
color: var(--semantic-color-text-default);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/* Focus ring */
|
|
152
|
+
.a1-calendar--selectable .a1-calendar__day:focus-visible {
|
|
153
|
+
outline: var(--component-field-focus-ring-width) solid var(--component-field-focus-ring-color);
|
|
154
|
+
outline-offset: -2px;
|
|
155
|
+
}
|
|
156
|
+
|
|
113
157
|
/* ── Paginated variant — nav bar ─────────────────────────── */
|
|
114
158
|
|
|
115
159
|
.a1-calendar__nav {
|
|
@@ -178,6 +222,33 @@
|
|
|
178
222
|
color: var(--semantic-color-text-inverse);
|
|
179
223
|
}
|
|
180
224
|
|
|
225
|
+
/* Selected: revert to circle in narrow view */
|
|
226
|
+
.a1-calendar__day--selected {
|
|
227
|
+
background: transparent;
|
|
228
|
+
color: var(--semantic-color-text-default);
|
|
229
|
+
}
|
|
230
|
+
.a1-calendar__day--selected .a1-calendar__day-number {
|
|
231
|
+
background: var(--semantic-color-action-background);
|
|
232
|
+
color: var(--semantic-color-text-inverse);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
/* Selectable: today ring (suppress action-bg circle from non-selectable narrow rule) */
|
|
236
|
+
.a1-calendar--selectable .a1-calendar__day--today:not(.a1-calendar__day--selected) .a1-calendar__day-number {
|
|
237
|
+
background: transparent;
|
|
238
|
+
color: var(--semantic-color-text-default);
|
|
239
|
+
outline: 2px solid var(--semantic-color-text-default);
|
|
240
|
+
outline-offset: -1px;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/* Selectable: hover as circle in narrow */
|
|
244
|
+
.a1-calendar--selectable .a1-calendar__day:not(.a1-calendar__day--empty):not(.a1-calendar__day--disabled):not(.a1-calendar__day--selected):hover {
|
|
245
|
+
background: transparent;
|
|
246
|
+
color: var(--semantic-color-text-default);
|
|
247
|
+
}
|
|
248
|
+
.a1-calendar--selectable .a1-calendar__day:not(.a1-calendar__day--empty):not(.a1-calendar__day--disabled):not(.a1-calendar__day--selected):hover .a1-calendar__day-number {
|
|
249
|
+
background: var(--semantic-color-surface-panel);
|
|
250
|
+
}
|
|
251
|
+
|
|
181
252
|
.a1-calendar__nav {
|
|
182
253
|
padding-block: var(--component-calendar-heading-padding-block-compact);
|
|
183
254
|
}
|
|
@@ -16,6 +16,7 @@ export function ChoiceGroup({
|
|
|
16
16
|
size = "default",
|
|
17
17
|
columns,
|
|
18
18
|
multiple = false,
|
|
19
|
+
inlineIcon = false,
|
|
19
20
|
required = false,
|
|
20
21
|
name,
|
|
21
22
|
options = [],
|
|
@@ -76,6 +77,7 @@ export function ChoiceGroup({
|
|
|
76
77
|
"a1-choice-group",
|
|
77
78
|
resolvedSize !== "default" && `a1-choice-group--${resolvedSize}`,
|
|
78
79
|
multiple ? "a1-choice-group--multiple" : "a1-choice-group--single",
|
|
80
|
+
inlineIcon && "a1-choice-group--inline-icon",
|
|
79
81
|
isFixedColumns && "a1-choice-group--fixed-columns",
|
|
80
82
|
responsiveClass,
|
|
81
83
|
error && "a1-choice-group--error",
|
|
@@ -317,6 +317,17 @@
|
|
|
317
317
|
background-size: 80%;
|
|
318
318
|
}
|
|
319
319
|
|
|
320
|
+
/* ─── Inline icon layout ────────────────────────────────────────────────────── */
|
|
321
|
+
|
|
322
|
+
.a1-choice-group--inline-icon .a1-choice-item {
|
|
323
|
+
flex-direction: row;
|
|
324
|
+
align-items: center;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
.a1-choice-group--inline-icon .a1-choice-item__icon {
|
|
328
|
+
flex-shrink: 0;
|
|
329
|
+
}
|
|
330
|
+
|
|
320
331
|
/* ─── Error state ───────────────────────────────────────────────────────────── */
|
|
321
332
|
|
|
322
333
|
.a1-choice-group--error
|
|
@@ -22,8 +22,8 @@ import "./data-table.css";
|
|
|
22
22
|
* }>
|
|
23
23
|
* rows: Array<Record<string, any>>
|
|
24
24
|
* getRowId?: (row: Record<string, any>, index: number) => string | number
|
|
25
|
-
*
|
|
26
|
-
*
|
|
25
|
+
* size?: "comfortable" | "default" | "compact"
|
|
26
|
+
* omit (default) — switches between densities automatically based on available container width
|
|
27
27
|
*/
|
|
28
28
|
|
|
29
29
|
// Estimated minimum content width per column type at a "neutral" padding level
|
|
@@ -193,7 +193,7 @@ function SelectionCheckbox({ checked, indeterminate = false, label, onChange })
|
|
|
193
193
|
export function DataTable({
|
|
194
194
|
columns = [],
|
|
195
195
|
rows = [],
|
|
196
|
-
|
|
196
|
+
size,
|
|
197
197
|
zebra = false,
|
|
198
198
|
scrollable = false,
|
|
199
199
|
caption,
|
|
@@ -238,14 +238,14 @@ export function DataTable({
|
|
|
238
238
|
const [internalSearchColumn, setInternalSearchColumn] = useState(defaultSearchColumn);
|
|
239
239
|
const [internalSelectedRowIds, setInternalSelectedRowIds] = useState(() => normalizeRowIds(defaultSelectedRowIds));
|
|
240
240
|
|
|
241
|
-
const isAuto =
|
|
241
|
+
const isAuto = size === undefined;
|
|
242
242
|
const isSortControlled = sort !== undefined;
|
|
243
243
|
const isPageControlled = page !== undefined;
|
|
244
244
|
const isFilterControlled = filterValue !== undefined;
|
|
245
245
|
const isSearchControlled = searchValue !== undefined;
|
|
246
246
|
const isSearchColumnControlled = searchColumn !== undefined;
|
|
247
247
|
const isSelectionControlled = selectedRowIds !== undefined;
|
|
248
|
-
const activeDensity = isAuto ? autoDensity :
|
|
248
|
+
const activeDensity = isAuto ? autoDensity : size;
|
|
249
249
|
const activeSort = isSortControlled ? normalizeSort(sort) : internalSort;
|
|
250
250
|
const activePage = isPageControlled ? page : internalPage;
|
|
251
251
|
const activeFilterValue = isFilterControlled
|
|
@@ -6,7 +6,7 @@ import { FieldsetContext } from "../fieldset/FieldsetContext.js";
|
|
|
6
6
|
import "./field.css";
|
|
7
7
|
|
|
8
8
|
const SIZES = ["comfortable", "default", "compact"];
|
|
9
|
-
const LABEL_POSITIONS = ["above", "
|
|
9
|
+
const LABEL_POSITIONS = ["above", "before"];
|
|
10
10
|
|
|
11
11
|
export const SelectField = forwardRef(function SelectField({
|
|
12
12
|
label,
|
|
@@ -5,7 +5,7 @@ import { FieldsetContext } from "../fieldset/FieldsetContext.js";
|
|
|
5
5
|
import "./field.css";
|
|
6
6
|
|
|
7
7
|
const SIZES = ["comfortable", "default", "compact"];
|
|
8
|
-
const LABEL_POSITIONS = ["above", "
|
|
8
|
+
const LABEL_POSITIONS = ["above", "before"];
|
|
9
9
|
|
|
10
10
|
export const TextField = forwardRef(function TextField({
|
|
11
11
|
label,
|
|
@@ -6,7 +6,7 @@ import "./field.css";
|
|
|
6
6
|
import "./textarea-field.css";
|
|
7
7
|
|
|
8
8
|
const SIZES = ["comfortable", "default", "compact"];
|
|
9
|
-
const LABEL_POSITIONS = ["above", "
|
|
9
|
+
const LABEL_POSITIONS = ["above", "before"];
|
|
10
10
|
const ROW_SIZES = { sm: 2, md: 4, lg: 8, xl: 12 };
|
|
11
11
|
|
|
12
12
|
function resolveRows(rows) {
|
|
@@ -336,9 +336,9 @@
|
|
|
336
336
|
color: var(--semantic-color-status-error-background);
|
|
337
337
|
}
|
|
338
338
|
|
|
339
|
-
/* ───
|
|
339
|
+
/* ─── Before label layout ───────────────────────────────────────────────────── */
|
|
340
340
|
|
|
341
|
-
.a1-field--label-
|
|
341
|
+
.a1-field--label-before {
|
|
342
342
|
display: grid;
|
|
343
343
|
grid-template-columns: var(--a1-field-side-label-width) 1fr;
|
|
344
344
|
column-gap: var(--base-spacing-16);
|
|
@@ -346,12 +346,12 @@
|
|
|
346
346
|
align-items: start;
|
|
347
347
|
}
|
|
348
348
|
|
|
349
|
-
.a1-field--label-
|
|
349
|
+
.a1-field--label-before .a1-field__label {
|
|
350
350
|
padding-top: calc((var(--a1-field-height) - 1lh) / 2);
|
|
351
351
|
padding-bottom: 0;
|
|
352
352
|
}
|
|
353
353
|
|
|
354
|
-
.a1-field--label-
|
|
354
|
+
.a1-field--label-before .a1-field__message {
|
|
355
355
|
grid-column: 1;
|
|
356
356
|
grid-row: 2;
|
|
357
357
|
/* Fine-tuned margin: overrides the base margin-top added for the above-label
|
|
@@ -359,22 +359,22 @@
|
|
|
359
359
|
margin-top: calc((var(--a1-field-label-size) * 1.5 - var(--a1-field-height)) / 2 + var(--base-spacing-2));
|
|
360
360
|
}
|
|
361
361
|
|
|
362
|
-
/* ───
|
|
362
|
+
/* ─── Before label → stacked on xs/sm ─────────────────────────────────────── */
|
|
363
363
|
|
|
364
364
|
@media (--bp-sm-down) {
|
|
365
|
-
.a1-field--label-
|
|
365
|
+
.a1-field--label-before {
|
|
366
366
|
display: flex;
|
|
367
367
|
flex-direction: column;
|
|
368
368
|
gap: var(--a1-field-gap); /* restore: grid overrode row-gap to base-spacing-4 */
|
|
369
369
|
align-items: stretch; /* restore: grid set align-items: start */
|
|
370
370
|
}
|
|
371
371
|
|
|
372
|
-
.a1-field--label-
|
|
372
|
+
.a1-field--label-before .a1-field__label {
|
|
373
373
|
padding-top: 0;
|
|
374
374
|
padding-bottom: var(--a1-field-gap);
|
|
375
375
|
}
|
|
376
376
|
|
|
377
|
-
.a1-field--label-
|
|
377
|
+
.a1-field--label-before .a1-field__message {
|
|
378
378
|
margin-top: var(--a1-field-gap);
|
|
379
379
|
}
|
|
380
380
|
}
|
|
@@ -5,9 +5,9 @@ import "./field-row.css";
|
|
|
5
5
|
export function FieldRow({ children, className = "", ...props }) {
|
|
6
6
|
const ctx = useContext(FieldsetContext);
|
|
7
7
|
|
|
8
|
-
//
|
|
8
|
+
// Before-label fields already use an internal two-column grid;
|
|
9
9
|
// stacking the row prevents layout conflicts.
|
|
10
|
-
const stacked = ctx?.labelPosition === "
|
|
10
|
+
const stacked = ctx?.labelPosition === "before";
|
|
11
11
|
|
|
12
12
|
const classes = [
|
|
13
13
|
"a1-field-row",
|
|
@@ -2,7 +2,7 @@ import { FieldsetContext } from "./FieldsetContext.js";
|
|
|
2
2
|
import "./fieldset.css";
|
|
3
3
|
|
|
4
4
|
const SIZES = ["comfortable", "default", "compact"];
|
|
5
|
-
const LABEL_POSITIONS = ["above", "
|
|
5
|
+
const LABEL_POSITIONS = ["above", "before"];
|
|
6
6
|
|
|
7
7
|
export function Fieldset({
|
|
8
8
|
legend,
|
|
@@ -7,7 +7,7 @@ const margins = ["sm", "md", "lg"];
|
|
|
7
7
|
const levels = ["h1", "h2", "h3", "h4", "h5", "h6"];
|
|
8
8
|
const breakpoints = ["xs", "sm", "md", "lg", "xl"];
|
|
9
9
|
const textWraps = ["balance"];
|
|
10
|
-
const aligns = ["left", "center", "right"];
|
|
10
|
+
const aligns = ["left", "center", "right", "start", "end"];
|
|
11
11
|
|
|
12
12
|
const levelDefaults = { h1: "xl", h2: "lg", h3: "md", h4: "sm", h5: "xs", h6: "xs" };
|
|
13
13
|
|
|
@@ -88,6 +88,8 @@
|
|
|
88
88
|
.a1-heading--align-left { text-align: start; }
|
|
89
89
|
.a1-heading--align-center { text-align: center; }
|
|
90
90
|
.a1-heading--align-right { text-align: end; }
|
|
91
|
+
.a1-heading--align-start { text-align: start; }
|
|
92
|
+
.a1-heading--align-end { text-align: end; }
|
|
91
93
|
|
|
92
94
|
/* Expressive marks */
|
|
93
95
|
.a1-heading-mark {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import "./notification.css";
|
|
2
2
|
|
|
3
|
-
const
|
|
3
|
+
const statuses = ["neutral", "error", "success", "warn", "info"];
|
|
4
4
|
const positions = ["top-right", "top-left", "bottom-right", "bottom-left"];
|
|
5
5
|
|
|
6
6
|
function formatCount(n, max) {
|
|
@@ -15,11 +15,11 @@ export function Notification({
|
|
|
15
15
|
count,
|
|
16
16
|
label,
|
|
17
17
|
dot = false,
|
|
18
|
-
|
|
18
|
+
status = "neutral",
|
|
19
19
|
position = "top-right",
|
|
20
20
|
max = 99,
|
|
21
21
|
}) {
|
|
22
|
-
const
|
|
22
|
+
const resolvedStatus = statuses.includes(status) ? status : "neutral";
|
|
23
23
|
const resolvedPosition = positions.includes(position) ? position : "top-right";
|
|
24
24
|
|
|
25
25
|
const isDot = dot || (count === undefined && label === undefined);
|
|
@@ -35,7 +35,7 @@ export function Notification({
|
|
|
35
35
|
|
|
36
36
|
const classes = [
|
|
37
37
|
"a1-notification",
|
|
38
|
-
`a1-notification--${
|
|
38
|
+
`a1-notification--${resolvedStatus}`,
|
|
39
39
|
`a1-notification--${resolvedPosition}`,
|
|
40
40
|
isDot && "a1-notification--dot",
|
|
41
41
|
]
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
|
|
44
44
|
/* ── Variants ───────────────────────────────────────────────────────────── */
|
|
45
45
|
|
|
46
|
-
.a1-notification--
|
|
46
|
+
.a1-notification--neutral {
|
|
47
47
|
--a1-notification-background: var(--base-color-neutral-600);
|
|
48
48
|
--a1-notification-foreground: var(--base-color-neutral-0);
|
|
49
49
|
}
|
|
@@ -4,7 +4,7 @@ const sizes = ["xs", "sm", "md", "lg", "xl"];
|
|
|
4
4
|
const colors = ["default", "muted"];
|
|
5
5
|
const breakpoints = ["xs", "sm", "md", "lg", "xl"];
|
|
6
6
|
const textWraps = ["balance"];
|
|
7
|
-
const aligns = ["left", "center", "right"];
|
|
7
|
+
const aligns = ["left", "center", "right", "start", "end"];
|
|
8
8
|
|
|
9
9
|
function isResponsiveSize(size) {
|
|
10
10
|
return size && typeof size === "object" && !Array.isArray(size);
|
|
@@ -46,6 +46,8 @@
|
|
|
46
46
|
.a1-paragraph--align-left { text-align: start; }
|
|
47
47
|
.a1-paragraph--align-center { text-align: center; }
|
|
48
48
|
.a1-paragraph--align-right { text-align: end; }
|
|
49
|
+
.a1-paragraph--align-start { text-align: start; }
|
|
50
|
+
.a1-paragraph--align-end { text-align: end; }
|
|
49
51
|
|
|
50
52
|
.a1-paragraph + .a1-paragraph,
|
|
51
53
|
.a1-paragraph + .a1-heading {
|
|
@@ -31,7 +31,7 @@ export function Section({
|
|
|
31
31
|
inverse = false,
|
|
32
32
|
contentWidth,
|
|
33
33
|
height,
|
|
34
|
-
|
|
34
|
+
align,
|
|
35
35
|
className = "",
|
|
36
36
|
children,
|
|
37
37
|
...props
|
|
@@ -72,14 +72,14 @@ export function Section({
|
|
|
72
72
|
classes.push(`a1-section--height-${height}`);
|
|
73
73
|
}
|
|
74
74
|
|
|
75
|
-
if (typeof
|
|
76
|
-
if (VALID_ALIGNMENTS.includes(
|
|
77
|
-
classes.push(`a1-section--align-${
|
|
75
|
+
if (typeof align === "string") {
|
|
76
|
+
if (VALID_ALIGNMENTS.includes(align)) {
|
|
77
|
+
classes.push(`a1-section--align-${align}`);
|
|
78
78
|
}
|
|
79
|
-
} else if (
|
|
80
|
-
for (const [bp,
|
|
81
|
-
if (VALID_ALIGNMENTS.includes(
|
|
82
|
-
classes.push(`a1-section--${bp}-align-${
|
|
79
|
+
} else if (align && typeof align === "object") {
|
|
80
|
+
for (const [bp, alignVal] of Object.entries(align)) {
|
|
81
|
+
if (VALID_ALIGNMENTS.includes(alignVal)) {
|
|
82
|
+
classes.push(`a1-section--${bp}-align-${alignVal}`);
|
|
83
83
|
}
|
|
84
84
|
}
|
|
85
85
|
}
|
|
@@ -111,7 +111,7 @@
|
|
|
111
111
|
/* ── Alignment ─────────────────────────────────────────────────────────────── */
|
|
112
112
|
/*
|
|
113
113
|
* Aligns direct children as layout items.
|
|
114
|
-
* Use the object prop for responsive changes:
|
|
114
|
+
* Use the object prop for responsive changes: align={{ xs: "center", lg: "left" }}
|
|
115
115
|
*/
|
|
116
116
|
|
|
117
117
|
.a1-section[class*="-align-"] {
|
|
@@ -206,10 +206,11 @@
|
|
|
206
206
|
|
|
207
207
|
/* ── Padding — static (with built-in responsive scaling) ───────────────────── */
|
|
208
208
|
/*
|
|
209
|
-
*
|
|
209
|
+
* Four tiers scale across three breakpoints:
|
|
210
210
|
* lg 96/64 → 96/40 at ≤1024 → 64/24 at ≤640
|
|
211
211
|
* md 64/40 → 40/24 at ≤1024 → 32/16 at ≤640
|
|
212
212
|
* sm 32/24 → 24/16 at ≤1024 → 16/12 at ≤640
|
|
213
|
+
* xs 16/16 → 12/12 at ≤1024 → 8/8 at ≤640
|
|
213
214
|
* Block (top/bottom) / Inline (left/right)
|
|
214
215
|
*/
|
|
215
216
|
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { useId, useState, useEffect } from "react";
|
|
2
|
+
import { Button } from "../button/Button.jsx";
|
|
3
|
+
import { useLabel } from "../labels/Labels.jsx";
|
|
4
|
+
import "./status-bar.css";
|
|
5
|
+
|
|
6
|
+
const SIZES = ["sm", "md", "lg"];
|
|
7
|
+
const POSITIONS = ["above", "below", "before", "after"];
|
|
8
|
+
|
|
9
|
+
export function StatusBar({
|
|
10
|
+
value = 0,
|
|
11
|
+
max = 100,
|
|
12
|
+
label,
|
|
13
|
+
labelPosition = "above",
|
|
14
|
+
size = "md",
|
|
15
|
+
indeterminate = false,
|
|
16
|
+
className = "",
|
|
17
|
+
...props
|
|
18
|
+
}) {
|
|
19
|
+
const labelId = useId();
|
|
20
|
+
|
|
21
|
+
const pauseLabel = useLabel("statusBar.pause", "Pause");
|
|
22
|
+
const playLabel = useLabel("statusBar.play", "Play");
|
|
23
|
+
|
|
24
|
+
const [paused, setPaused] = useState(false);
|
|
25
|
+
const [showPause, setShowPause] = useState(false);
|
|
26
|
+
|
|
27
|
+
useEffect(() => {
|
|
28
|
+
if (!indeterminate) {
|
|
29
|
+
setShowPause(false);
|
|
30
|
+
setPaused(false);
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
const t = setTimeout(() => setShowPause(true), 3000);
|
|
34
|
+
return () => clearTimeout(t);
|
|
35
|
+
}, [indeterminate]);
|
|
36
|
+
|
|
37
|
+
const resolvedSize = SIZES.includes(size) ? size : "md";
|
|
38
|
+
const resolvedPosition = POSITIONS.includes(labelPosition) ? labelPosition : "above";
|
|
39
|
+
|
|
40
|
+
const pct = Math.min(100, Math.max(0, max > 0 ? (value / max) * 100 : 0));
|
|
41
|
+
const isLabelFirst = resolvedPosition === "above" || resolvedPosition === "before";
|
|
42
|
+
|
|
43
|
+
const classes = [
|
|
44
|
+
"a1-status-bar",
|
|
45
|
+
resolvedSize !== "md" && `a1-status-bar--${resolvedSize}`,
|
|
46
|
+
`a1-status-bar--${resolvedPosition}`,
|
|
47
|
+
indeterminate && "a1-status-bar--indeterminate",
|
|
48
|
+
indeterminate && paused && "a1-status-bar--paused",
|
|
49
|
+
className,
|
|
50
|
+
].filter(Boolean).join(" ");
|
|
51
|
+
|
|
52
|
+
const labelEl = label ? (
|
|
53
|
+
<span id={labelId} className="a1-status-bar__label">{label}</span>
|
|
54
|
+
) : null;
|
|
55
|
+
|
|
56
|
+
return (
|
|
57
|
+
<div className={classes}>
|
|
58
|
+
{isLabelFirst && labelEl}
|
|
59
|
+
<div className="a1-status-bar__bar-row">
|
|
60
|
+
<div
|
|
61
|
+
className="a1-status-bar__track"
|
|
62
|
+
role="progressbar"
|
|
63
|
+
aria-valuenow={indeterminate ? undefined : value}
|
|
64
|
+
aria-valuemin={0}
|
|
65
|
+
aria-valuemax={max}
|
|
66
|
+
aria-labelledby={label ? labelId : undefined}
|
|
67
|
+
{...props}
|
|
68
|
+
>
|
|
69
|
+
<div
|
|
70
|
+
className={[
|
|
71
|
+
"a1-status-bar__fill",
|
|
72
|
+
indeterminate && "a1-status-bar__fill--indeterminate",
|
|
73
|
+
].filter(Boolean).join(" ")}
|
|
74
|
+
style={indeterminate ? undefined : { inlineSize: `${pct}%` }}
|
|
75
|
+
/>
|
|
76
|
+
</div>
|
|
77
|
+
{showPause && (
|
|
78
|
+
<Button
|
|
79
|
+
size="sm"
|
|
80
|
+
variant="secondary"
|
|
81
|
+
icon={paused ? "play_arrow" : "pause"}
|
|
82
|
+
className="a1-status-bar__pause"
|
|
83
|
+
onClick={() => setPaused(p => !p)}
|
|
84
|
+
>
|
|
85
|
+
{paused ? playLabel : pauseLabel}
|
|
86
|
+
</Button>
|
|
87
|
+
)}
|
|
88
|
+
</div>
|
|
89
|
+
{!isLabelFirst && labelEl}
|
|
90
|
+
</div>
|
|
91
|
+
);
|
|
92
|
+
}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/* ─── StatusBar ─────────────────────────────────────────────────────────────── */
|
|
2
|
+
|
|
3
|
+
.a1-status-bar {
|
|
4
|
+
--a1-sb-height: var(--component-status-bar-md-height);
|
|
5
|
+
--a1-sb-track-bg: var(--component-status-bar-track-background);
|
|
6
|
+
--a1-sb-fill-bg: var(--component-status-bar-fill-background);
|
|
7
|
+
--a1-sb-radius: var(--component-status-bar-border-radius);
|
|
8
|
+
--a1-sb-border-width: var(--component-status-bar-border-width);
|
|
9
|
+
--a1-sb-border-color: var(--component-status-bar-border-color);
|
|
10
|
+
--a1-sb-label-gap: var(--component-status-bar-label-gap);
|
|
11
|
+
|
|
12
|
+
display: flex;
|
|
13
|
+
flex-direction: column;
|
|
14
|
+
gap: var(--a1-sb-label-gap);
|
|
15
|
+
inline-size: 100%;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/* ─── Sizes ─────────────────────────────────────────────────────────────────── */
|
|
19
|
+
|
|
20
|
+
.a1-status-bar--sm { --a1-sb-height: var(--component-status-bar-sm-height); }
|
|
21
|
+
.a1-status-bar--lg { --a1-sb-height: var(--component-status-bar-lg-height); }
|
|
22
|
+
|
|
23
|
+
/* ─── Label positions ───────────────────────────────────────────────────────── */
|
|
24
|
+
|
|
25
|
+
/* below: column layout, DOM order is [bar-row, label] so no CSS change needed */
|
|
26
|
+
|
|
27
|
+
.a1-status-bar--before,
|
|
28
|
+
.a1-status-bar--after {
|
|
29
|
+
flex-direction: row;
|
|
30
|
+
align-items: center;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
.a1-status-bar--before .a1-status-bar__bar-row,
|
|
34
|
+
.a1-status-bar--after .a1-status-bar__bar-row {
|
|
35
|
+
flex: 1;
|
|
36
|
+
min-inline-size: 0;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.a1-status-bar--before .a1-status-bar__label,
|
|
40
|
+
.a1-status-bar--after .a1-status-bar__label {
|
|
41
|
+
flex-shrink: 0;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/* ─── Bar row (track + optional pause button) ───────────────────────────────── */
|
|
45
|
+
|
|
46
|
+
.a1-status-bar__bar-row {
|
|
47
|
+
display: flex;
|
|
48
|
+
flex-direction: row;
|
|
49
|
+
align-items: center;
|
|
50
|
+
gap: var(--base-spacing-8);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
.a1-status-bar__bar-row .a1-status-bar__track {
|
|
54
|
+
flex: 1;
|
|
55
|
+
min-inline-size: 0;
|
|
56
|
+
inline-size: auto;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/* ─── Label ─────────────────────────────────────────────────────────────────── */
|
|
60
|
+
|
|
61
|
+
.a1-status-bar__label {
|
|
62
|
+
display: block;
|
|
63
|
+
font-family: var(--component-paragraph-font-family);
|
|
64
|
+
font-size: var(--semantic-font-size-body-sm);
|
|
65
|
+
font-weight: var(--base-font-weight-regular);
|
|
66
|
+
color: var(--semantic-color-text-default);
|
|
67
|
+
line-height: var(--semantic-font-line-height-body);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/* ─── Track ─────────────────────────────────────────────────────────────────── */
|
|
71
|
+
|
|
72
|
+
.a1-status-bar__track {
|
|
73
|
+
position: relative;
|
|
74
|
+
display: flex; /* flex direction inherits writing mode — fills from inline-start in RTL */
|
|
75
|
+
block-size: var(--a1-sb-height);
|
|
76
|
+
inline-size: 100%;
|
|
77
|
+
background-color: var(--a1-sb-track-bg);
|
|
78
|
+
border-radius: var(--a1-sb-radius);
|
|
79
|
+
border: var(--a1-sb-border-width) solid var(--a1-sb-border-color);
|
|
80
|
+
overflow: hidden;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/* ─── Fill ──────────────────────────────────────────────────────────────────── */
|
|
84
|
+
|
|
85
|
+
/* Flex child — grows from inline-start, which in RTL means it grows from the right */
|
|
86
|
+
.a1-status-bar__fill {
|
|
87
|
+
flex-shrink: 0;
|
|
88
|
+
block-size: 100%;
|
|
89
|
+
inline-size: 0;
|
|
90
|
+
background-color: var(--a1-sb-fill-bg);
|
|
91
|
+
border-radius: inherit;
|
|
92
|
+
transition: inline-size var(--semantic-motion-duration-normal) var(--semantic-motion-easing-standard);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/* ─── Indeterminate (loading) ───────────────────────────────────────────────── */
|
|
96
|
+
|
|
97
|
+
/* Absolute positioning takes the fill out of flex flow for the sweep animation */
|
|
98
|
+
.a1-status-bar__fill--indeterminate {
|
|
99
|
+
position: absolute;
|
|
100
|
+
inset-block: 0;
|
|
101
|
+
left: 0;
|
|
102
|
+
inline-size: 35%;
|
|
103
|
+
animation: a1-sb-indeterminate var(--component-status-bar-indeterminate-duration) ease-in-out infinite;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/* RTL: anchor to the physical right and reverse the sweep direction */
|
|
107
|
+
[dir="rtl"] .a1-status-bar__fill--indeterminate {
|
|
108
|
+
left: auto;
|
|
109
|
+
right: 0;
|
|
110
|
+
animation-direction: reverse;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
.a1-status-bar--paused .a1-status-bar__fill--indeterminate {
|
|
114
|
+
animation-play-state: paused;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
@keyframes a1-sb-indeterminate {
|
|
118
|
+
0% { transform: translateX(-115%); }
|
|
119
|
+
100% { transform: translateX(300%); }
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
@media (prefers-reduced-motion: reduce) {
|
|
123
|
+
.a1-status-bar__fill--indeterminate {
|
|
124
|
+
animation: none;
|
|
125
|
+
inline-size: 100%;
|
|
126
|
+
opacity: 0.4;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/* ─── Pause / play button ────────────────────────────────────────────────────── */
|
|
131
|
+
|
|
132
|
+
.a1-status-bar__pause {
|
|
133
|
+
flex-shrink: 0;
|
|
134
|
+
animation: a1-sb-pause-appear var(--semantic-motion-duration-normal) var(--semantic-motion-easing-enter);
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
@keyframes a1-sb-pause-appear {
|
|
138
|
+
from { opacity: 0; transform: scale(0.75); }
|
|
139
|
+
to { opacity: 1; transform: scale(1); }
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
@media (prefers-reduced-motion: reduce) {
|
|
143
|
+
.a1-status-bar__pause {
|
|
144
|
+
animation: none;
|
|
145
|
+
}
|
|
146
|
+
}
|
package/src/index.js
CHANGED
|
@@ -5,6 +5,7 @@ export { Blockquote } from "./components/blockquote/Blockquote.jsx";
|
|
|
5
5
|
export { Breadcrumb } from "./components/breadcrumb/Breadcrumb.jsx";
|
|
6
6
|
export { Notification } from "./components/notification/Notification.jsx";
|
|
7
7
|
export { Snackbar } from "./components/snackbar/Snackbar.jsx";
|
|
8
|
+
export { StatusBar } from "./components/status-bar/StatusBar.jsx";
|
|
8
9
|
export { Bleed } from "./components/bleed/Bleed.jsx";
|
|
9
10
|
export { IconButton } from "./components/icon-button/IconButton.jsx";
|
|
10
11
|
export { Button } from "./components/button/Button.jsx";export { ButtonContainer } from "./components/button-container/ButtonContainer.jsx";
|
package/src/themes.css
CHANGED
|
@@ -52,6 +52,7 @@ html.a1-theme-accessible {
|
|
|
52
52
|
--component-side-nav-border-width: 2px;
|
|
53
53
|
--component-tab-border-width: 2px;
|
|
54
54
|
--component-top-header-border-width: 2px;
|
|
55
|
+
--component-status-bar-border-width: 2px;
|
|
55
56
|
--component-button-font-family: var(--theme-a1-accessible-font-family-body);
|
|
56
57
|
--component-paragraph-font-family: var(--theme-a1-accessible-font-family-body);
|
|
57
58
|
--component-heading-font-family-heading: var(--theme-a1-accessible-font-family-heading);
|
package/src/tokens.css
CHANGED
|
@@ -646,6 +646,16 @@
|
|
|
646
646
|
--component-side-nav-item-font-line-height: 1.5;
|
|
647
647
|
--component-side-nav-item-active-font-weight: 500;
|
|
648
648
|
--component-side-nav-item-chevron-size: 1.125rem;
|
|
649
|
+
--component-status-bar-sm-height: 0.25rem;
|
|
650
|
+
--component-status-bar-md-height: 0.5rem;
|
|
651
|
+
--component-status-bar-lg-height: 0.75rem;
|
|
652
|
+
--component-status-bar-border-radius: 624.9375rem;
|
|
653
|
+
--component-status-bar-border-width: 0;
|
|
654
|
+
--component-status-bar-border-color: #a6b2c4;
|
|
655
|
+
--component-status-bar-track-background: #e1e8f3;
|
|
656
|
+
--component-status-bar-fill-background: #7c3aed;
|
|
657
|
+
--component-status-bar-label-gap: 0.5rem;
|
|
658
|
+
--component-status-bar-indeterminate-duration: 1400ms;
|
|
649
659
|
--component-switch-track-width: 2.5rem;
|
|
650
660
|
--component-switch-track-height: 1.375rem;
|
|
651
661
|
--component-switch-thumb-size: 1rem;
|