@redseed/redseed-ui-tailwindcss 7.55.0 → 7.56.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/colors.css +14 -1
- package/components/badge.css +20 -3
- package/components/button_card.css +4 -1
- package/components/button_slot.css +6 -1
- package/components/button_tertiary.css +9 -2
- package/components/card.css +23 -2
- package/components/card_header.css +11 -0
- package/components/checkbox_card.css +4 -1
- package/components/comment.css +3 -1
- package/components/form_field_checkbox.css +28 -2
- package/components/form_fields_login.css +12 -1
- package/components/form_fields_register.css +12 -1
- package/components/list_item.css +64 -1
- package/components/message_box.css +14 -0
- package/components/meta_info.css +11 -3
- package/components/metric_card.css +70 -1
- package/components/page_header.css +76 -0
- package/components/radio_card.css +32 -7
- package/components/section_header.css +16 -2
- package/components/stage_dial.css +22 -0
- package/components/switcher.css +46 -0
- package/components/switcher_item.css +21 -2
- package/components/tab_slider_item.css +22 -1
- package/components.css +0 -1
- package/package.json +1 -1
- package/tokens.css +5 -1
- package/components/hero_section.css +0 -32
package/colors.css
CHANGED
|
@@ -565,7 +565,20 @@
|
|
|
565
565
|
--Colors-Warm-Mauve-800: #855878;
|
|
566
566
|
--Colors-Warm-Mauve-900: #6a4660;
|
|
567
567
|
--Colors-Warm-Mauve-950: #4c3145;
|
|
568
|
-
/* Secondary brand accents (single tokens, Figma Brand palette · Secondary)
|
|
568
|
+
/* Secondary brand accents (single tokens, Figma Brand palette · Secondary)
|
|
569
|
+
|
|
570
|
+
DO NOT USE these in product surfaces. Components and pages draw only on
|
|
571
|
+
the six primary identity ramps above — Journey Green, Deep Teal, Modern
|
|
572
|
+
Bone, Warm Yellow, Soft Lilac, Warm Mauve — plus the Grey ramp and the
|
|
573
|
+
semantic tokens (success / warning / error / info).
|
|
574
|
+
|
|
575
|
+
They are defined here for completeness against the Figma palette, which
|
|
576
|
+
is why they have no ramp: single values only, so they cannot carry text
|
|
577
|
+
either. Cornflower measures 3.2:1 on white and Apricot Lift 2.25:1, both
|
|
578
|
+
short of the 4.5:1 that WCAG 1.4.3 asks of body text.
|
|
579
|
+
|
|
580
|
+
One accepted exception: --color-button-primary-hover consumes Plum Ink
|
|
581
|
+
(see tokens.css). That is deliberate and predates this note. */
|
|
569
582
|
--Colors-Apricot-Lift: #e89b6c;
|
|
570
583
|
--Colors-Cornflower: #6e8fd6;
|
|
571
584
|
--Colors-Marigold: #f2b33c;
|
package/components/badge.css
CHANGED
|
@@ -1,19 +1,30 @@
|
|
|
1
1
|
.rsui-badge {
|
|
2
|
-
|
|
2
|
+
/* whitespace-nowrap: a badge is a pill, so its label must stay on one line. Without it
|
|
3
|
+
a badge in a narrow column wrapped to two lines and grew to 42px tall — seen in
|
|
4
|
+
production on the Twinsies home page, where "1 answer to redo" and "2 answers to redo"
|
|
5
|
+
both broke across two lines inside a rounded-full chip. Every other chip-shaped
|
|
6
|
+
control in the system already declares this: Pill, ButtonSlot, TabSliderItem and
|
|
7
|
+
SwitcherItem. Badge was the only one that did not. */
|
|
8
|
+
@apply inline-flex items-center justify-center gap-x-1 whitespace-nowrap;
|
|
3
9
|
@apply w-fit h-fit rounded-full;
|
|
4
10
|
@apply text-sm font-medium leading-4;
|
|
5
11
|
}
|
|
6
12
|
|
|
13
|
+
/* Horizontal padding grows with the size: it used to sit at px-2 for xs, sm and md alike,
|
|
14
|
+
so a md badge was exactly as wide as an xs one and its 8/8 padding collapsed to square —
|
|
15
|
+
on a rounded-full shape that puts the label closer to the curved ends than to the flat
|
|
16
|
+
top and bottom. The 8 / 10 / 12 progression matches Pill, the other chip in the system.
|
|
17
|
+
Vertical padding is untouched, so no badge changes height. */
|
|
7
18
|
.rsui-badge--xs {
|
|
8
19
|
@apply text-xs leading-3 px-2 py-0.5;
|
|
9
20
|
}
|
|
10
21
|
|
|
11
22
|
.rsui-badge--sm {
|
|
12
|
-
@apply px-2 py-1;
|
|
23
|
+
@apply px-2.5 py-1;
|
|
13
24
|
}
|
|
14
25
|
|
|
15
26
|
.rsui-badge--md {
|
|
16
|
-
@apply px-
|
|
27
|
+
@apply px-3 py-2;
|
|
17
28
|
}
|
|
18
29
|
|
|
19
30
|
.rsui-badge--secondary {
|
|
@@ -40,6 +51,12 @@
|
|
|
40
51
|
@apply text-brand-500 bg-brand-50 border border-brand-200;
|
|
41
52
|
}
|
|
42
53
|
|
|
54
|
+
/* Classic and Coach still ride the pre-rebrand pink and redseed-blue ramps rather than the
|
|
55
|
+
current brand ones (Skillscheck above already moved to Journey Green). Left as-is on
|
|
56
|
+
purpose: both categories are due to be phased out, so re-homing them onto brand colours
|
|
57
|
+
would be churn. There is also only one unclaimed brand ramp (Deep Teal) against two
|
|
58
|
+
categories — Journey Green, Warm Mauve and Modern Bone are taken by brand, AI and page
|
|
59
|
+
grounds. Revisit only if the phase-out stalls. */
|
|
43
60
|
.rsui-badge--classic {
|
|
44
61
|
@apply text-pink-500 bg-pink-50 border border-pink-200;
|
|
45
62
|
}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
/* ButtonCard now takes the family's tonal hover from .rsui-card--hoverable, which it opts
|
|
2
|
+
into via :hoverable="!disabled". It previously cancelled the card shadow and darkened the
|
|
3
|
+
border instead — the only bespoke hover treatment in the family, and the reason hovering
|
|
4
|
+
a ButtonCard looked nothing like hovering a Card. */
|
|
1
5
|
.rsui-button-card {
|
|
2
|
-
@apply hover:shadow-none hover:border-text-primary;
|
|
3
6
|
}
|
|
4
7
|
|
|
5
8
|
.rsui-button-card--disabled {
|
|
@@ -53,8 +53,13 @@
|
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
/* modifier xs size */
|
|
56
|
+
/* px-2.5, not px-1.5: horizontal padding steps 10/12/14/16/18/20 across xs..2xl, and
|
|
57
|
+
xs was the only size where px equalled py — every other size runs 1.4-1.6x wider than
|
|
58
|
+
tall, so an xs label sat 6px from the border and read visibly cramped. Height is
|
|
59
|
+
unchanged (py untouched); only the button's width grows. --xs-icon keeps its own p-1.5
|
|
60
|
+
because a square icon button is correct at that size. */
|
|
56
61
|
.rsui-button-slot--xs {
|
|
57
|
-
@apply text-sm px-
|
|
62
|
+
@apply text-sm px-2.5 py-1.5 gap-1;
|
|
58
63
|
}
|
|
59
64
|
|
|
60
65
|
/* modifier xs size with icon */
|
|
@@ -3,13 +3,20 @@
|
|
|
3
3
|
@apply text-button-tertiary bg-transparent border-transparent;
|
|
4
4
|
|
|
5
5
|
/* default hover state */
|
|
6
|
-
|
|
6
|
+
/* A ghost button fills faintly on hover; it must not sprout an outline. This used to
|
|
7
|
+
set border-button-tertiary-hover, taking the border from transparent to solid
|
|
8
|
+
#124943 — so hovering a borderless button made a hard dark rule appear, while the
|
|
9
|
+
fill stayed transparent. That is the inverse of the intended ghost behaviour, and
|
|
10
|
+
the opposite of primary (fill darkens) and secondary (outline darkens). */
|
|
11
|
+
@apply hover:text-button-tertiary-hover hover:bg-background-secondary hover:border-transparent;
|
|
7
12
|
|
|
8
13
|
/* default focus state */
|
|
9
14
|
@apply focus-visible:ring-button-tertiary focus-visible:border-transparent;
|
|
10
15
|
|
|
11
16
|
/* default active state */
|
|
12
|
-
|
|
17
|
+
/* Pressed goes one step darker than hover (transparent -> Grey-50 -> Grey-100) so the
|
|
18
|
+
press reads as deeper rather than clearing the hover fill back to nothing. */
|
|
19
|
+
@apply active:text-button-tertiary-active active:bg-background-tertiary-invert active:border-transparent;
|
|
13
20
|
|
|
14
21
|
/* default disabled state */
|
|
15
22
|
@apply disabled:bg-transparent disabled:border-transparent disabled:text-text-disabled;
|
package/components/card.css
CHANGED
|
@@ -68,6 +68,9 @@
|
|
|
68
68
|
@apply relative border-0;
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
+
/* Positioning only. The dashed outline itself is drawn by the <rect> inside this element —
|
|
72
|
+
it is an <svg>, and the rect strokes 1px with stroke-dasharray 8 16. Do not add CSS border
|
|
73
|
+
utilities here: they paint a second dashed edge on top of the SVG stroke. */
|
|
71
74
|
.rsui-card__draft-border {
|
|
72
75
|
@apply absolute inset-0 size-full pointer-events-none rounded-xl border-border-secondary;
|
|
73
76
|
}
|
|
@@ -79,8 +82,20 @@
|
|
|
79
82
|
@apply overflow-x-hidden;
|
|
80
83
|
}
|
|
81
84
|
|
|
82
|
-
.
|
|
83
|
-
|
|
85
|
+
/* Hover state layer. The card family is an Outlined system — flat, 1px border, no resting
|
|
86
|
+
elevation — so hover tints the surface rather than lifting it. Two reasons this is a
|
|
87
|
+
::before scrim and not a background-color swap: every colour variant (secondary, brand,
|
|
88
|
+
success, info, warning, error, draft, ai) has to survive underneath it, and a scrim
|
|
89
|
+
composites over the ai variant's gradient where a flat colour could not. ::before rather
|
|
90
|
+
than ::after so it paints beneath the card's content in DOM order. */
|
|
91
|
+
.rsui-card--hoverable::before {
|
|
92
|
+
content: '';
|
|
93
|
+
@apply absolute inset-0 rounded-xl pointer-events-none;
|
|
94
|
+
@apply bg-background-primary-contrast opacity-0 transition-opacity duration-200;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.rsui-card--hoverable:hover::before {
|
|
98
|
+
@apply opacity-5;
|
|
84
99
|
}
|
|
85
100
|
|
|
86
101
|
.rsui-card--clickable {
|
|
@@ -105,6 +120,12 @@
|
|
|
105
120
|
colour alone (WCAG 1.4.1). */
|
|
106
121
|
.rsui-card__action-layer--active {
|
|
107
122
|
@apply ring-2 ring-offset-2 ring-brand-500;
|
|
123
|
+
|
|
124
|
+
/* Hold the brand ring through focus. Without this the focus-visible rule above repaints
|
|
125
|
+
the ring border-primary grey, so focusing a selected card silently dropped its
|
|
126
|
+
selection cue — the ring is the same geometry for both states, so only colour carries
|
|
127
|
+
the difference. */
|
|
128
|
+
@apply focus-visible:ring-brand-500;
|
|
108
129
|
}
|
|
109
130
|
|
|
110
131
|
.rsui-card__action-layer-label {
|
|
@@ -28,6 +28,17 @@
|
|
|
28
28
|
@apply @md/card-header:items-center;
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
/* Centring only holds while the text block is a lone title. `--single-line` means the *title*
|
|
32
|
+
is clamped to one line, not that the header is one row — add a subtitle and a badge and the
|
|
33
|
+
block is 78px tall, where centring a 48px avatar left it sitting 15px low against the text
|
|
34
|
+
it belongs to. Seen in production on the Twinsies meeting cards. Top-align as soon as the
|
|
35
|
+
block carries more than the title; a lone title is shorter than the avatar, so centring
|
|
36
|
+
stays correct there. */
|
|
37
|
+
.rsui-card-header__header--single-line:has(.rsui-card-header__subtitle),
|
|
38
|
+
.rsui-card-header__header--single-line:has(.rsui-card-header__badge) {
|
|
39
|
+
@apply @md/card-header:items-start;
|
|
40
|
+
}
|
|
41
|
+
|
|
31
42
|
.rsui-card-header__avatar {
|
|
32
43
|
@apply w-12 overflow-hidden flex items-center justify-center;
|
|
33
44
|
}
|
|
@@ -83,7 +83,10 @@
|
|
|
83
83
|
/* Success state styling */
|
|
84
84
|
/* Increase specificity so it overrides base .rsui-card styles */
|
|
85
85
|
.rsui-card.rsui-checkbox-card--success {
|
|
86
|
-
|
|
86
|
+
/* bg-background-success, not the raw bg-success-100 palette step: this was the only
|
|
87
|
+
success surface in the library painting #DCFAE6 while Card, Badge, MessageBox and
|
|
88
|
+
Section all use the #ECFDF3 token — two different success greens, same border. */
|
|
89
|
+
@apply bg-background-success border-border-success;
|
|
87
90
|
}
|
|
88
91
|
|
|
89
92
|
.rsui-checkbox-card--success .rsui-checkbox-card__title-text {
|
package/components/comment.css
CHANGED
|
@@ -78,7 +78,9 @@
|
|
|
78
78
|
}
|
|
79
79
|
|
|
80
80
|
.rsui-comment__body {
|
|
81
|
-
|
|
81
|
+
/* 14px vertical, matching the row rhythm ListItem uses — a comment is a row of prose
|
|
82
|
+
and read tight against its neighbour at 12px. */
|
|
83
|
+
@apply py-3.5 px-4 rounded-xl border;
|
|
82
84
|
@apply rounded-tl-none ml-8;
|
|
83
85
|
@apply text-text-primary bg-background-primary;
|
|
84
86
|
@apply border-border-primary;
|
|
@@ -7,7 +7,9 @@
|
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
.rsui-form-field-checkbox__check {
|
|
10
|
-
|
|
10
|
+
/* Centres the tick. The input is absolutely positioned so it stays out of flow and keeps
|
|
11
|
+
filling the box; only the SVG is laid out here. */
|
|
12
|
+
@apply size-6 shrink-0 relative flex items-center justify-center bg-background-primary rounded-lg cursor-pointer;
|
|
11
13
|
@apply has-[:disabled]:text-text-disabled has-[:disabled]:cursor-default;
|
|
12
14
|
}
|
|
13
15
|
|
|
@@ -16,11 +18,21 @@
|
|
|
16
18
|
@apply w-full h-full text-text-primary border border-border-primary text-transparent bg-none;
|
|
17
19
|
@apply focus-visible:ring-3 focus-visible:ring-border-primary focus-visible:border-border-primary;
|
|
18
20
|
@apply invalid:border-border-error invalid:ring-0;
|
|
21
|
+
|
|
22
|
+
/* Checked fills the box and the tick inverts, which is how every mainstream checkbox
|
|
23
|
+
reads. It used to stay transparent, so a checked box was a white square with a dark
|
|
24
|
+
tick — and the success variant already filled, so the default was the odd one out. */
|
|
25
|
+
@apply checked:bg-text-primary checked:border-text-primary;
|
|
26
|
+
|
|
19
27
|
@apply disabled:text-text-disabled disabled:bg-background-disabled disabled:cursor-default;
|
|
28
|
+
@apply disabled:checked:bg-background-disabled disabled:checked:border-border-disabled;
|
|
20
29
|
}
|
|
21
30
|
|
|
31
|
+
/* The tick is inset rather than size-full. At size-full a 24px glyph sat in a 24px box with
|
|
32
|
+
no breathing room, so its strokes ran into the border and the control read cramped. Each
|
|
33
|
+
size keeps roughly a 4px optical inset — see the sm/xs overrides further down. */
|
|
22
34
|
.rsui-form-field-checkbox__check svg {
|
|
23
|
-
@apply size-
|
|
35
|
+
@apply size-4 relative z-1 pointer-events-none stroke-[2.5] origin-center;
|
|
24
36
|
/* Short, cute draw-on: the tick strokes itself in with a tiny pop.
|
|
25
37
|
dasharray is set a touch above the check path length so the resting
|
|
26
38
|
state has no gap. Disabled under reduced-motion below. */
|
|
@@ -28,6 +40,12 @@
|
|
|
28
40
|
animation: rsui-checkbox-tick 200ms ease-out;
|
|
29
41
|
}
|
|
30
42
|
|
|
43
|
+
/* Invert the tick against the filled box. Scoped to :not(:disabled) because a disabled
|
|
44
|
+
checked box keeps the pale disabled fill, where an inverted tick would disappear. */
|
|
45
|
+
.rsui-form-field-checkbox__check:has(input:checked:not(:disabled)) svg {
|
|
46
|
+
@apply text-text-on-color;
|
|
47
|
+
}
|
|
48
|
+
|
|
31
49
|
@keyframes rsui-checkbox-tick {
|
|
32
50
|
0% { stroke-dashoffset: 30; transform: scale(0.8); }
|
|
33
51
|
60% { transform: scale(1.06); }
|
|
@@ -53,6 +71,10 @@
|
|
|
53
71
|
@apply rounded-md;
|
|
54
72
|
}
|
|
55
73
|
|
|
74
|
+
.rsui-form-field-checkbox__check--sm svg {
|
|
75
|
+
@apply size-3;
|
|
76
|
+
}
|
|
77
|
+
|
|
56
78
|
.rsui-form-field-checkbox__label--sm {
|
|
57
79
|
@apply leading-5 text-sm;
|
|
58
80
|
}
|
|
@@ -65,6 +87,10 @@
|
|
|
65
87
|
@apply rounded;
|
|
66
88
|
}
|
|
67
89
|
|
|
90
|
+
.rsui-form-field-checkbox__check--xs svg {
|
|
91
|
+
@apply size-2;
|
|
92
|
+
}
|
|
93
|
+
|
|
68
94
|
.rsui-form-field-checkbox__label--xs {
|
|
69
95
|
@apply leading-4 text-xs;
|
|
70
96
|
}
|
|
@@ -1,4 +1,15 @@
|
|
|
1
|
+
/* The field group owns its own spacing. It used to render a bare list of siblings and
|
|
2
|
+
inherit spacing from `.rsui-form-slot__content > *`, so anywhere that ancestor was absent —
|
|
3
|
+
including every one of its own stories — the fields and the submit button collapsed flush
|
|
4
|
+
against each other with a 0px gap. gap-space-md (16px) matches the mt-4 that rule applied,
|
|
5
|
+
so the group is unchanged inside FormSlot and correct everywhere else. */
|
|
6
|
+
.rsui-form-fields-login {
|
|
7
|
+
@apply flex flex-col gap-space-md;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/* pt-4 dropped: the group's gap-space-md now supplies the 16px above this link, and
|
|
11
|
+
keeping both stacked them into 32px. */
|
|
1
12
|
.rsui-form-login__signup {
|
|
2
|
-
@apply text-sm
|
|
13
|
+
@apply text-sm;
|
|
3
14
|
}
|
|
4
15
|
|
|
@@ -1,4 +1,15 @@
|
|
|
1
|
+
/* The field group owns its own spacing. It used to render a bare list of siblings and
|
|
2
|
+
inherit spacing from `.rsui-form-slot__content > *`, so anywhere that ancestor was absent —
|
|
3
|
+
including every one of its own stories — the fields and the submit button collapsed flush
|
|
4
|
+
against each other with a 0px gap. gap-space-md (16px) matches the mt-4 that rule applied,
|
|
5
|
+
so the group is unchanged inside FormSlot and correct everywhere else. */
|
|
6
|
+
.rsui-form-fields-register {
|
|
7
|
+
@apply flex flex-col gap-space-md;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
/* pt-4 dropped: the group's gap-space-md now supplies the 16px above this link, and
|
|
11
|
+
keeping both stacked them into 32px. */
|
|
1
12
|
.rsui-form-register__signin {
|
|
2
|
-
@apply text-sm
|
|
13
|
+
@apply text-sm;
|
|
3
14
|
}
|
|
4
15
|
|
package/components/list_item.css
CHANGED
|
@@ -1,5 +1,9 @@
|
|
|
1
1
|
.rsui-list-item {
|
|
2
|
-
|
|
2
|
+
/* 14px vertical rather than the 12px of a flat p-3: at 12px a two-line row reads as
|
|
3
|
+
cramped against its neighbours, which is the note that came back from laying these
|
|
4
|
+
out on a real page. Horizontal padding is unchanged. Half-steps are already used
|
|
5
|
+
across the button sizes, so 3.5 is in keeping. */
|
|
6
|
+
@apply relative flex flex-col rounded-xl px-3 py-3.5 overflow-hidden;
|
|
3
7
|
}
|
|
4
8
|
|
|
5
9
|
.rsui-list-item--clickable {
|
|
@@ -69,6 +73,65 @@
|
|
|
69
73
|
@apply mt-2 flex flex-wrap gap-x-4 gap-y-2;
|
|
70
74
|
}
|
|
71
75
|
|
|
76
|
+
/* Leading icon. Inline, unlike .rsui-list-item__avatar above, which hangs outside the row
|
|
77
|
+
box on a negative offset — an avatar identifies a person, an icon classifies the row, so
|
|
78
|
+
they sit differently and can be used together. */
|
|
79
|
+
.rsui-list-item__icon {
|
|
80
|
+
@apply shrink-0 size-8 rounded-lg overflow-hidden;
|
|
81
|
+
@apply flex items-center justify-center;
|
|
82
|
+
@apply bg-background-secondary;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.rsui-list-item__icon svg {
|
|
86
|
+
@apply size-4;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/* Accent rail — a pseudo-element, so an accented row has the same DOM as a plain one.
|
|
90
|
+
Needs z-1 to sit above .rsui-list-item__bg, which is absolute and would otherwise paint
|
|
91
|
+
over it; the root's rounded-xl clips the rail into the corner. */
|
|
92
|
+
.rsui-list-item--accented::before {
|
|
93
|
+
content: '';
|
|
94
|
+
@apply absolute left-0 top-0 bottom-0 w-1 z-1 pointer-events-none;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
.rsui-list-item--accent-warning::before {
|
|
98
|
+
@apply bg-background-warning-contrast;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
.rsui-list-item--accent-info::before {
|
|
102
|
+
@apply bg-background-info-contrast;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.rsui-list-item--accent-success::before {
|
|
106
|
+
@apply bg-background-success-contrast;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.rsui-list-item--accent-error::before {
|
|
110
|
+
@apply bg-background-error-contrast;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
.rsui-list-item--accent-neutral::before {
|
|
114
|
+
@apply bg-background-primary-contrast;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/* The icon tile takes the accent's own tint when both are used, so the rail and the tile
|
|
118
|
+
read as one mark rather than two. */
|
|
119
|
+
.rsui-list-item--accent-warning .rsui-list-item__icon {
|
|
120
|
+
@apply bg-background-warning;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
.rsui-list-item--accent-info .rsui-list-item__icon {
|
|
124
|
+
@apply bg-background-info;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
.rsui-list-item--accent-success .rsui-list-item__icon {
|
|
128
|
+
@apply bg-background-success;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.rsui-list-item--accent-error .rsui-list-item__icon {
|
|
132
|
+
@apply bg-background-error;
|
|
133
|
+
}
|
|
134
|
+
|
|
72
135
|
.rsui-list-item__description {
|
|
73
136
|
@apply line-clamp-2 mt-2 text-base;
|
|
74
137
|
}
|
|
@@ -22,6 +22,20 @@
|
|
|
22
22
|
@apply bg-background-error border-border-error text-text-primary;
|
|
23
23
|
}
|
|
24
24
|
|
|
25
|
+
/* AI. Same surface language ButtonAI and .rsui-card--ai already use — the warm
|
|
26
|
+
gradient with the Warm Mauve border — so an AI message reads as the same
|
|
27
|
+
family as an AI action. The title carries text-ai for identity; the body stays
|
|
28
|
+
text-primary, because a whole paragraph in Warm Mauve is harder to read and
|
|
29
|
+
the border plus gradient already say "AI". */
|
|
30
|
+
.rsui-message-box--ai {
|
|
31
|
+
@apply bg-linear-to-tr from-background-ai-from to-background-ai-to;
|
|
32
|
+
@apply border-border-ai text-text-primary;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.rsui-message-box--ai .rsui-message-box__title {
|
|
36
|
+
@apply text-text-ai;
|
|
37
|
+
}
|
|
38
|
+
|
|
25
39
|
.rsui-message-box__head {
|
|
26
40
|
@apply flex justify-between items-center gap-x-2;
|
|
27
41
|
}
|
package/components/meta_info.css
CHANGED
|
@@ -2,16 +2,23 @@
|
|
|
2
2
|
@apply flex flex-col gap-y-1;
|
|
3
3
|
}
|
|
4
4
|
|
|
5
|
+
/* gap-x rather than space-x: space-* works by adding margins to children, which is the
|
|
6
|
+
legacy pattern, double-counts against any gap and breaks once the row wraps. Every other
|
|
7
|
+
component in the library spaces with gap. */
|
|
5
8
|
.rsui-meta-info__top {
|
|
6
|
-
@apply flex
|
|
9
|
+
@apply flex gap-x-1 items-center;
|
|
7
10
|
}
|
|
8
11
|
|
|
9
12
|
.rsui-meta-info__label-icon {
|
|
10
13
|
@apply flex items-center justify-center;
|
|
11
14
|
}
|
|
12
15
|
|
|
16
|
+
/* The label is the descriptor, so it recedes: medium weight in the tertiary tone. It used to
|
|
17
|
+
be semibold near-black while the value was regular grey, which inverted the hierarchy — the
|
|
18
|
+
eye landed on "Age" instead of on the number. Grey-600 on white measures 7.26:1, so it stays
|
|
19
|
+
comfortably readable at 12px. */
|
|
13
20
|
.rsui-meta-info__label {
|
|
14
|
-
@apply font-
|
|
21
|
+
@apply font-medium text-xs text-text-tertiary;
|
|
15
22
|
}
|
|
16
23
|
|
|
17
24
|
.rsui-meta-info__help {
|
|
@@ -22,9 +29,10 @@
|
|
|
22
29
|
@apply focus-visible:ring-offset-2 focus-visible:ring-2 focus-visible:ring-border-primary;
|
|
23
30
|
}
|
|
24
31
|
|
|
32
|
+
/* The value carries the information, so it takes the emphasis the label gave up. */
|
|
25
33
|
.rsui-meta-info__value {
|
|
26
34
|
@apply flex items-center gap-x-space-xs;
|
|
27
|
-
@apply text-xs text-text-
|
|
35
|
+
@apply text-xs font-semibold text-text-primary;
|
|
28
36
|
}
|
|
29
37
|
|
|
30
38
|
.rsui-meta-info--md .rsui-meta-info__label {
|
|
@@ -37,4 +37,73 @@
|
|
|
37
37
|
selection ring (WCAG 1.4.1); the brand number is colour reinforcement only. */
|
|
38
38
|
.rsui-metric-card--active .rsui-metric-card__number {
|
|
39
39
|
@apply text-text-brand;
|
|
40
|
-
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/* ---------------------------------------------------------------------------
|
|
43
|
+
Tonal variants
|
|
44
|
+
|
|
45
|
+
Same vocabulary and same mechanism as .rsui-page-header — green / teal /
|
|
46
|
+
light, with surface, ink, muted ink and rule moving together as a named set,
|
|
47
|
+
carried on --rsui-metric-card-* custom properties. Plain properties rather
|
|
48
|
+
than new @theme keys, for the reasons in #285.
|
|
49
|
+
|
|
50
|
+
The tile is a step LIGHTER than the band it sits on (Journey Green 700 on an
|
|
51
|
+
800 band), so it reads as a raised panel. Each tone names an explicit surface
|
|
52
|
+
rather than a translucent white, so a toned tile still works standing alone
|
|
53
|
+
where there is no band beneath it to show through.
|
|
54
|
+
|
|
55
|
+
metric_card.css imports after card.css, so these single-class rules out-rank
|
|
56
|
+
.rsui-card's own surface at equal specificity. Combining a tone with one of
|
|
57
|
+
Card's semantic variants (brand, success, …) is not supported — pick one.
|
|
58
|
+
--------------------------------------------------------------------------- */
|
|
59
|
+
.rsui-metric-card--toned {
|
|
60
|
+
background: var(--rsui-metric-card-surface, var(--color-background-secondary));
|
|
61
|
+
border-color: var(--rsui-metric-card-rule, var(--color-border-primary));
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
.rsui-metric-card--tone-green {
|
|
65
|
+
--rsui-metric-card-surface: var(--Colors-Journey-Green-700);
|
|
66
|
+
--rsui-metric-card-ink: var(--Colors-Base-white);
|
|
67
|
+
/* 200, not the 300 PageHeader uses. The tile surface is a step lighter than the
|
|
68
|
+
header band it sits on, and 300 on 700 measures 4.46:1 — a hair under AA. */
|
|
69
|
+
--rsui-metric-card-ink-muted: var(--Colors-Journey-Green-200);
|
|
70
|
+
--rsui-metric-card-rule: rgba(255, 255, 255, 0.18);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
.rsui-metric-card--tone-teal {
|
|
74
|
+
--rsui-metric-card-surface: var(--Colors-Deep-Teal-600);
|
|
75
|
+
--rsui-metric-card-ink: var(--Colors-Base-white);
|
|
76
|
+
--rsui-metric-card-ink-muted: var(--Colors-Deep-Teal-300);
|
|
77
|
+
--rsui-metric-card-rule: rgba(255, 255, 255, 0.18);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/* The white-label case: same layout, inverted ink. */
|
|
81
|
+
.rsui-metric-card--tone-light {
|
|
82
|
+
--rsui-metric-card-surface: var(--Colors-Modern-Bone-200);
|
|
83
|
+
--rsui-metric-card-ink: var(--Colors-Grey-900);
|
|
84
|
+
--rsui-metric-card-ink-muted: var(--Colors-Grey-600);
|
|
85
|
+
--rsui-metric-card-rule: var(--Colors-Grey-300);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/* Tone-agnostic: only the variable values differ, so the light tone resolves
|
|
89
|
+
these same selectors to dark ink. */
|
|
90
|
+
.rsui-metric-card--toned .rsui-metric-card__number {
|
|
91
|
+
color: var(--rsui-metric-card-ink);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
.rsui-metric-card--toned .rsui-metric-card__label {
|
|
95
|
+
color: var(--rsui-metric-card-ink-muted);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.rsui-metric-card--toned .rsui-metric-card__icon {
|
|
99
|
+
color: var(--rsui-metric-card-ink-muted);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/* The active state's brand-coloured number is colour reinforcement only — the
|
|
103
|
+
Card action layer carries the actual selection ring (WCAG 1.4.1). On a tonal
|
|
104
|
+
surface that reinforcement has to go: text-brand is Brand-500 (#136c52),
|
|
105
|
+
which against the green tile's #0e5942 is about 1.3:1 and simply invisible.
|
|
106
|
+
The ring still does the work. */
|
|
107
|
+
.rsui-metric-card--toned.rsui-metric-card--active .rsui-metric-card__number {
|
|
108
|
+
color: var(--rsui-metric-card-ink);
|
|
109
|
+
}
|
|
@@ -77,3 +77,79 @@
|
|
|
77
77
|
@apply flex flex-col gap-1 lg:flex-row lg:items-center lg:gap-4;
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
+
|
|
81
|
+
/* ---------------------------------------------------------------------------
|
|
82
|
+
Tonal variants
|
|
83
|
+
|
|
84
|
+
White-labelling is why these are named sets rather than a background prop.
|
|
85
|
+
Pass a colour alone and a client who picks a light one gets white text on
|
|
86
|
+
white; background, ink, muted ink and rule have to move together, the way
|
|
87
|
+
Card handles its variants.
|
|
88
|
+
|
|
89
|
+
Plain custom properties rather than new @theme keys, for two reasons: the
|
|
90
|
+
four values must travel as a set, and a new theme key does not reliably
|
|
91
|
+
generate a utility — the trap in #285 that made every focus ring invisible.
|
|
92
|
+
Same pattern .rsui-stage-dial already uses for its accent.
|
|
93
|
+
|
|
94
|
+
A toned header carries its own padding, because the band has to read as a
|
|
95
|
+
band. Place it outside the page's content gutter so it bleeds to the edges;
|
|
96
|
+
an untoned header is unchanged and still inherits the layout's padding.
|
|
97
|
+
--------------------------------------------------------------------------- */
|
|
98
|
+
.rsui-page-header--toned {
|
|
99
|
+
/* Fallbacks keep an unrecognised tone legible rather than transparent. */
|
|
100
|
+
background: var(--rsui-page-header-bg, var(--color-background-secondary));
|
|
101
|
+
|
|
102
|
+
@apply py-space-lg px-space-xl;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
.rsui-page-header--tone-green {
|
|
106
|
+
--rsui-page-header-bg: var(--Colors-Journey-Green-800);
|
|
107
|
+
--rsui-page-header-ink: var(--Colors-Base-white);
|
|
108
|
+
--rsui-page-header-ink-muted: var(--Colors-Journey-Green-300);
|
|
109
|
+
--rsui-page-header-rule: rgba(255, 255, 255, 0.18);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
.rsui-page-header--tone-teal {
|
|
113
|
+
--rsui-page-header-bg: var(--Colors-Deep-Teal-700);
|
|
114
|
+
--rsui-page-header-ink: var(--Colors-Base-white);
|
|
115
|
+
--rsui-page-header-ink-muted: var(--Colors-Deep-Teal-300);
|
|
116
|
+
--rsui-page-header-rule: rgba(255, 255, 255, 0.18);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/* The white-label case. Same layout, inverted ink — a client's own background
|
|
120
|
+
may be light, so the component cannot assume light-on-dark. */
|
|
121
|
+
.rsui-page-header--tone-light {
|
|
122
|
+
--rsui-page-header-bg: var(--Colors-Base-white);
|
|
123
|
+
--rsui-page-header-ink: var(--Colors-Grey-900);
|
|
124
|
+
--rsui-page-header-ink-muted: var(--Colors-Grey-600);
|
|
125
|
+
--rsui-page-header-rule: var(--Colors-Grey-300);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/* Ink application is tone-agnostic: only the variable values differ, so the
|
|
129
|
+
light tone resolves these to dark ink through the same rules. */
|
|
130
|
+
.rsui-page-header--toned .rsui-page-header__title h1 {
|
|
131
|
+
color: var(--rsui-page-header-ink);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
.rsui-page-header--toned .rsui-page-header__subtitle {
|
|
135
|
+
color: var(--rsui-page-header-ink-muted);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
.rsui-page-header--toned .rsui-page-header__meta {
|
|
139
|
+
border-top: 1px solid var(--rsui-page-header-rule);
|
|
140
|
+
|
|
141
|
+
@apply mt-space-md pt-space-md;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
/* MetaInfo sets its own dark label and value tokens, which disappear on a dark
|
|
145
|
+
band. Reaching into another component's classes is not ideal, but an
|
|
146
|
+
invisible meta row is worse, and what a slot looks like on this component's
|
|
147
|
+
own tonal surface is this stylesheet's business. */
|
|
148
|
+
.rsui-page-header--toned .rsui-meta-info__label {
|
|
149
|
+
color: var(--rsui-page-header-ink);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
.rsui-page-header--toned .rsui-meta-info__value,
|
|
153
|
+
.rsui-page-header--toned .rsui-meta-info__help {
|
|
154
|
+
color: var(--rsui-page-header-ink-muted);
|
|
155
|
+
}
|
|
@@ -1,25 +1,50 @@
|
|
|
1
1
|
.rsui-radio-card {
|
|
2
2
|
@apply relative cursor-pointer transition-all;
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
/* No resting shadow: this was the only card in the family that sat lifted while the
|
|
4
|
+
other seven are flat. Padding matches the family's 24/32 rhythm rather than the 12/12
|
|
5
|
+
it used to carry alone. ring-offset-2 matches the focus geometry every other card
|
|
6
|
+
uses — this ring previously hugged the border with no offset. */
|
|
7
|
+
@apply rounded-xl outline-hidden select-none;
|
|
8
|
+
@apply flex flex-col gap-3 py-space-lg px-space-xl max-w-80 w-80;
|
|
5
9
|
@apply bg-background-primary border border-border-primary;
|
|
6
|
-
@apply focus-visible:ring-2 focus-visible:ring-border-primary;
|
|
10
|
+
@apply focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-border-primary;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
/* Hover state layer, matching .rsui-card--hoverable. ::before because ::after already
|
|
14
|
+
carries the disabled scrim below. */
|
|
15
|
+
.rsui-radio-card::before {
|
|
16
|
+
content: '';
|
|
17
|
+
@apply absolute inset-0 rounded-xl pointer-events-none;
|
|
18
|
+
@apply bg-background-primary-contrast opacity-0 transition-opacity duration-200;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.rsui-radio-card:hover::before {
|
|
22
|
+
@apply opacity-5;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.rsui-radio-card--disabled:hover::before {
|
|
26
|
+
@apply opacity-0;
|
|
7
27
|
}
|
|
8
28
|
|
|
9
29
|
.rsui-radio-card--flexible {
|
|
10
30
|
@apply max-w-full w-full;
|
|
11
31
|
}
|
|
12
32
|
|
|
33
|
+
/* Selection is the family's brand ring — the same ring-2 / ring-offset-2 / brand-500 that
|
|
34
|
+
Card's action layer and CardGroup use. This used to be a 10% translucent scrim, a third
|
|
35
|
+
distinct idiom for "selected" in one component family. The ring is a shape boundary
|
|
36
|
+
(present vs absent) rather than colour alone, which is the WCAG 1.4.1 property Card's own
|
|
37
|
+
comment calls out, and it holds its brand colour through focus. */
|
|
13
38
|
.rsui-radio-card--selected {
|
|
14
|
-
@apply
|
|
15
|
-
|
|
16
|
-
@apply after:content-[''] after:absolute after:inset-0 after:rounded-md after:opacity-10 after:bg-background-primary-contrast;
|
|
39
|
+
@apply ring-2 ring-offset-2 ring-brand-500 border-border-primary;
|
|
40
|
+
@apply focus-visible:ring-brand-500;
|
|
17
41
|
}
|
|
18
42
|
|
|
19
43
|
.rsui-radio-card--disabled {
|
|
20
44
|
@apply focus-visible:ring-0 border-border-disabled cursor-default;
|
|
21
45
|
|
|
22
|
-
|
|
46
|
+
/* Same corner correction as --selected above, and more visible here at 60% opacity. */
|
|
47
|
+
@apply after:content-[''] after:absolute after:inset-0 after:rounded-xl after:opacity-60 after:bg-background-disabled;
|
|
23
48
|
}
|
|
24
49
|
|
|
25
50
|
.rsui-radio-card__title-row {
|
|
@@ -44,12 +44,24 @@
|
|
|
44
44
|
@apply basis-full;
|
|
45
45
|
}
|
|
46
46
|
|
|
47
|
+
/* Redundant now that the base badge carries no margin — kept as a guard so re-adding one
|
|
48
|
+
cannot break the stacked layout, where the badge starts a new line and must sit flush. */
|
|
47
49
|
.rsui-section-header__title--stacked .rsui-section-header__badge {
|
|
48
50
|
@apply ml-0;
|
|
49
51
|
}
|
|
50
52
|
|
|
53
|
+
/* ACTION SIZE: section-header actions belong at `sm`, not the button default of `md`. A md
|
|
54
|
+
button is 42px against a 32px title box, so a cluster of them outweighs the heading they
|
|
55
|
+
belong to. This is guidance rather than something enforced here: constraining button height
|
|
56
|
+
from inside the header would silently override a size prop the consumer passed. The stories
|
|
57
|
+
demonstrate the `sm` pairing.
|
|
58
|
+
|
|
59
|
+
TITLE SIZE: text-3xl from lg up. At a flat text-2xl the title box was 32px while even an sm
|
|
60
|
+
button is 38px, so the heading never led its own actions. Responsive rather than flat, and
|
|
61
|
+
matching how PageHeader scales, because mobile stacks the actions anyway (see
|
|
62
|
+
__actions-mobile) and the imbalance only really shows on wide screens. */
|
|
51
63
|
.rsui-section-header__title-text {
|
|
52
|
-
@apply text-2xl font-bold line-clamp-2 md:line-clamp-1 text-text-primary;
|
|
64
|
+
@apply text-2xl lg:text-3xl font-bold line-clamp-2 md:line-clamp-1 text-text-primary;
|
|
53
65
|
/* Reset heading UA margins so an <h1>-<h6> title matches the previous <div> */
|
|
54
66
|
/* min-w-0 lets the title shrink and truncate first; the badge is shrink-0 so */
|
|
55
67
|
/* it keeps its size. No flex-1 — a growing title pushes the See-all badge up */
|
|
@@ -62,8 +74,10 @@
|
|
|
62
74
|
@apply line-clamp-none md:line-clamp-none;
|
|
63
75
|
}
|
|
64
76
|
|
|
77
|
+
/* No ml-space-xs here: the parent is a flex row that already supplies gap-space-xs, so the
|
|
78
|
+
margin stacked on top of it and the badge sat 16px from its label instead of 8px. */
|
|
65
79
|
.rsui-section-header__badge {
|
|
66
|
-
@apply
|
|
80
|
+
@apply flex items-center shrink-0;
|
|
67
81
|
}
|
|
68
82
|
|
|
69
83
|
.rsui-section-header__subtitle {
|
|
@@ -53,6 +53,28 @@
|
|
|
53
53
|
@apply absolute inset-[15%] flex items-center justify-center text-center;
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
+
/* On a coloured or dark surface. The centre content has no colour of its own and
|
|
57
|
+
inherits the page ink, which on a dark band is near-invisible — this is the
|
|
58
|
+
only thing the variant needs to change. Same mechanism as
|
|
59
|
+
.rsui-body-text--on-color, including the child selector, since the slot
|
|
60
|
+
usually holds its own elements.
|
|
61
|
+
|
|
62
|
+
The track is deliberately NOT changed, because measuring said it did not need
|
|
63
|
+
to be. Grey-400 against the two tonal bands:
|
|
64
|
+
|
|
65
|
+
on Journey Green 800 (#0a4c38) 4.13:1
|
|
66
|
+
on Deep Teal 700 (#0c3035) 5.84:1
|
|
67
|
+
|
|
68
|
+
both clear of the 3:1 WCAG 1.4.11 asks of a non-text graphic. The obvious
|
|
69
|
+
"improvement" would have made it worse: a translucent white track, which is
|
|
70
|
+
what this looked like in the mock, measures 1.64:1 at 18% and 2.61:1 at 35%
|
|
71
|
+
— both failures. If a consumer wants the track tinted to their band, that is
|
|
72
|
+
a --rsui-stage-dial-* style override, not a default. */
|
|
73
|
+
.rsui-stage-dial--on-color .rsui-stage-dial__content {
|
|
74
|
+
@apply text-text-on-color;
|
|
75
|
+
@apply *:text-text-on-color;
|
|
76
|
+
}
|
|
77
|
+
|
|
56
78
|
@media (prefers-reduced-motion: reduce) {
|
|
57
79
|
.rsui-stage-dial--animate .rsui-stage-dial__fill {
|
|
58
80
|
transition: none;
|
package/components/switcher.css
CHANGED
|
@@ -14,3 +14,49 @@
|
|
|
14
14
|
.rsui-switcher .rsui-switcher-item {
|
|
15
15
|
@apply w-full sm:w-fit;
|
|
16
16
|
}
|
|
17
|
+
|
|
18
|
+
/* Chips variant — a filter chip set rather than a segmented control. Opt in with
|
|
19
|
+
the `chips` prop; the default is untouched.
|
|
20
|
+
|
|
21
|
+
Two differences, and both are the reason it exists:
|
|
22
|
+
1. No tonal container, so the chips sit directly on the page rather than in
|
|
23
|
+
a grey well.
|
|
24
|
+
2. One row that scrolls sideways when it runs out of width, instead of
|
|
25
|
+
stacking. The default stacks below `sm` — documented and deliberate for a
|
|
26
|
+
segmented control — but a stacking chip set makes its container grow by an
|
|
27
|
+
unpredictable number of lines, which is what this avoids.
|
|
28
|
+
|
|
29
|
+
Every rule below has to out-specify a same-specificity rule above it, so this
|
|
30
|
+
block must stay last in the file. */
|
|
31
|
+
.rsui-switcher--chips {
|
|
32
|
+
@apply w-full flex-row items-center flex-nowrap gap-2;
|
|
33
|
+
@apply bg-transparent p-0 rounded-none;
|
|
34
|
+
|
|
35
|
+
/* The default is overflow-hidden; this row is meant to scroll. Scrollbar
|
|
36
|
+
hidden to match .rsui-tab-slider, which already does exactly this. */
|
|
37
|
+
@apply overflow-x-auto;
|
|
38
|
+
scrollbar-width: none;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.rsui-switcher--chips::-webkit-scrollbar {
|
|
42
|
+
display: none;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/* Overrides `w-full sm:w-fit` above: a chip is sized by its own label at every
|
|
46
|
+
width, never stretched to fill the row. */
|
|
47
|
+
.rsui-switcher--chips .rsui-switcher-item {
|
|
48
|
+
@apply w-fit rounded-full;
|
|
49
|
+
@apply bg-background-primary text-text-secondary border-border-primary;
|
|
50
|
+
|
|
51
|
+
/* 44px, so a chip clears the Apple HIG touch target on a phone. The default
|
|
52
|
+
item computes to 42px and is deliberately left alone. */
|
|
53
|
+
@apply min-h-11;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
.rsui-switcher--chips .rsui-switcher-item--active {
|
|
57
|
+
@apply bg-background-primary-contrast text-text-on-color border-transparent;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
.rsui-switcher--chips .rsui-switcher-item--disabled {
|
|
61
|
+
@apply bg-background-disabled text-text-disabled border-transparent;
|
|
62
|
+
}
|
|
@@ -1,7 +1,24 @@
|
|
|
1
|
+
/* The item is a native <button role="tab"> so it is keyboard operable and announces as a
|
|
2
|
+
tab (it used to be a click-handled <div>, which no keyboard could reach). These plain
|
|
3
|
+
declarations strip the UA button chrome so the visual design is unchanged — written out
|
|
4
|
+
rather than assumed from Tailwind preflight, because RSUI's index.css does not import
|
|
5
|
+
Tailwind itself and the consuming app may not ship preflight. */
|
|
1
6
|
.rsui-switcher-item {
|
|
7
|
+
appearance: none;
|
|
8
|
+
background: none;
|
|
9
|
+
margin: 0;
|
|
10
|
+
border: 0 solid transparent;
|
|
11
|
+
font: inherit;
|
|
12
|
+
color: inherit;
|
|
13
|
+
|
|
2
14
|
@apply h-fit inline-flex shrink-0 items-center justify-center select-none outline-hidden whitespace-nowrap will-change-transform cursor-pointer;
|
|
3
15
|
@apply font-semibold gap-2 rounded-lg border border-transparent transition;
|
|
4
16
|
@apply text-base px-3 py-2;
|
|
17
|
+
|
|
18
|
+
/* The class list above sets outline-hidden, which previously left the item with no focus
|
|
19
|
+
indicator at all once it became focusable. Drawn inset because .rsui-switcher is
|
|
20
|
+
overflow-hidden and would clip an offset ring. */
|
|
21
|
+
@apply focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-border-primary;
|
|
5
22
|
}
|
|
6
23
|
|
|
7
24
|
.rsui-switcher-item--active {
|
|
@@ -16,6 +33,8 @@
|
|
|
16
33
|
@apply size-6;
|
|
17
34
|
}
|
|
18
35
|
|
|
36
|
+
/* No ml-space-xs here: the parent is a flex row that already supplies gap-space-xs, so the
|
|
37
|
+
margin stacked on top of it and the badge sat 16px from its label instead of 8px. */
|
|
19
38
|
.rsui-switcher-item__badge {
|
|
20
|
-
@apply
|
|
21
|
-
}
|
|
39
|
+
@apply flex items-center;
|
|
40
|
+
}
|
|
@@ -1,7 +1,26 @@
|
|
|
1
|
+
/* The item is a native <button role="tab"> so it is keyboard operable and announces as a
|
|
2
|
+
tab (it used to be a click-handled <div>, which no keyboard could reach). These plain
|
|
3
|
+
declarations strip the UA button chrome so the visual design is byte-for-byte unchanged.
|
|
4
|
+
They are written out rather than assumed from Tailwind preflight because RSUI's index.css
|
|
5
|
+
does not import Tailwind itself — the consuming app does, and may not ship preflight.
|
|
6
|
+
The border reset matters most: the @apply below sets only `border-b-2`, so without an
|
|
7
|
+
all-sides width of 0 the UA's default `medium outset` border would remain on the other
|
|
8
|
+
three sides and widen every tab. */
|
|
1
9
|
.rsui-tab-slider-item {
|
|
10
|
+
appearance: none;
|
|
11
|
+
background: none;
|
|
12
|
+
margin: 0;
|
|
13
|
+
border: 0 solid transparent;
|
|
14
|
+
font: inherit;
|
|
15
|
+
color: inherit;
|
|
16
|
+
|
|
2
17
|
@apply inline-flex shrink-0 items-center justify-center select-none cursor-pointer whitespace-nowrap;
|
|
3
18
|
@apply text-base px-4 py-3 gap-2 border-b-2 border-transparent -mb-px;
|
|
4
19
|
@apply text-text-secondary;
|
|
20
|
+
|
|
21
|
+
/* Focus is drawn inside the box: .rsui-tab-slider is an overflow-x-auto scroller, so an
|
|
22
|
+
offset ring on the first or last tab would be clipped by it. */
|
|
23
|
+
@apply outline-hidden focus-visible:ring-2 focus-visible:ring-inset focus-visible:ring-border-primary;
|
|
5
24
|
}
|
|
6
25
|
|
|
7
26
|
.rsui-tab-slider-item--active {
|
|
@@ -16,6 +35,8 @@
|
|
|
16
35
|
@apply size-5;
|
|
17
36
|
}
|
|
18
37
|
|
|
38
|
+
/* No ml-space-xs here: the parent is a flex row that already supplies gap-space-xs, so the
|
|
39
|
+
margin stacked on top of it and the badge sat 16px from its label instead of 8px. */
|
|
19
40
|
.rsui-tab-slider-item__badge {
|
|
20
|
-
@apply
|
|
41
|
+
@apply flex items-center;
|
|
21
42
|
}
|
package/components.css
CHANGED
|
@@ -54,7 +54,6 @@ Please be careful when adding new components and updating the order.
|
|
|
54
54
|
@import './components/form_wrapper_build.css';
|
|
55
55
|
@import './components/form_wrapper_lms.css';
|
|
56
56
|
@import './components/grid_container.css';
|
|
57
|
-
@import './components/hero_section.css';
|
|
58
57
|
@import './components/icon.css';
|
|
59
58
|
@import './components/image.css';
|
|
60
59
|
@import './components/image_16by9.css';
|
package/package.json
CHANGED
package/tokens.css
CHANGED
|
@@ -12,7 +12,11 @@
|
|
|
12
12
|
--color-text-warning: #b54708;
|
|
13
13
|
--color-text-error: #b42318;
|
|
14
14
|
--color-text-info: #0077cc;
|
|
15
|
-
|
|
15
|
+
/* Warm-Mauve-800, not -600: the AI treatments set this over the pale AI gradient
|
|
16
|
+
(#ebe0fa -> #fff6eb), where -600 measured 2.93:1 and failed WCAG AA for 14px text.
|
|
17
|
+
-800 clears it at 4.52:1 at the gradient's worst point. Consumed by Badge AI,
|
|
18
|
+
Button AI, the AI body-text modifier and the AI icon treatments. */
|
|
19
|
+
--color-text-ai: var(--Colors-Warm-Mauve-800);
|
|
16
20
|
--color-text-on-color: var(--Colors-Base-white);
|
|
17
21
|
|
|
18
22
|
--color-background-primary: var(--Colors-Base-white);
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
.rsui-hero-section {
|
|
2
|
-
@apply rounded-xl px-5 py-6 flex flex-col gap-4 md:gap-6 relative overflow-hidden bg-text-primary text-text-on-color;
|
|
3
|
-
}
|
|
4
|
-
|
|
5
|
-
.rsui-hero-section::before {
|
|
6
|
-
content: '';
|
|
7
|
-
position: absolute;
|
|
8
|
-
inset: 0;
|
|
9
|
-
background-size: auto;
|
|
10
|
-
background-position: right center;
|
|
11
|
-
background-repeat: no-repeat;
|
|
12
|
-
opacity: 1;
|
|
13
|
-
z-index: 0;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
.rsui-hero-section > * {
|
|
17
|
-
position: relative;
|
|
18
|
-
z-index: 1;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
.rsui-hero-section__cards {
|
|
22
|
-
@apply grid grid-cols-1 md:grid-cols-3 gap-4 md:gap-6;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
.rsui-hero-section__cards--hidden {
|
|
26
|
-
@apply hidden;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
.rsui-hero-section__content--hidden {
|
|
30
|
-
@apply hidden;
|
|
31
|
-
}
|
|
32
|
-
|