@kwtv/components 0.2.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +52 -9
- package/package.json +2 -2
- package/src/astro/Accordion.astro +10 -6
- package/src/astro/AccordionItem.astro +55 -45
- package/src/astro/ActiveFilterTags.astro +41 -28
- package/src/astro/Alert.astro +45 -41
- package/src/astro/Badge.astro +80 -76
- package/src/astro/Band.astro +104 -58
- package/src/astro/Breadcrumb.astro +38 -30
- package/src/astro/Button.astro +135 -129
- package/src/astro/Card.astro +72 -62
- package/src/astro/CartLine.astro +72 -58
- package/src/astro/Checkbox.astro +36 -32
- package/src/astro/Chip.astro +68 -64
- package/src/astro/ChipRail.astro +6 -1
- package/src/astro/DotGrid.astro +55 -42
- package/src/astro/EmptyState.astro +29 -23
- package/src/astro/FilterGroup.astro +29 -26
- package/src/astro/Filters.astro +57 -47
- package/src/astro/Footer.astro +195 -178
- package/src/astro/FooterColumn.astro +39 -35
- package/src/astro/Header.astro +80 -67
- package/src/astro/Icon.astro +4 -2
- package/src/astro/IconButton.astro +67 -61
- package/src/astro/Marquee.astro +43 -41
- package/src/astro/NavDropdown.astro +169 -149
- package/src/astro/NavLink.astro +59 -56
- package/src/astro/Newsletter.astro +64 -56
- package/src/astro/Pager.astro +71 -46
- package/src/astro/PickCard.astro +72 -68
- package/src/astro/ProductCard.astro +134 -119
- package/src/astro/Radio.astro +36 -32
- package/src/astro/Skeleton.astro +60 -42
- package/src/astro/Social.astro +26 -21
- package/src/astro/StepIndicator.astro +70 -54
- package/src/astro/Sticker.astro +74 -49
- package/src/astro/Swatch.astro +44 -40
- package/src/astro/SwipeCarousel.astro +5 -1
- package/src/astro/Table.astro +66 -56
- package/src/astro/TableCard.astro +45 -37
- package/src/astro/TextField.astro +104 -91
- package/src/astro/Totals.astro +39 -35
- package/src/react/Drawer.css +60 -56
- package/src/react/Drawer.tsx +1 -5
- package/src/react/Modal.css +97 -93
- package/src/react/Modal.tsx +4 -6
- package/src/react/NewsCarousel.css +108 -104
- package/src/react/NewsCarousel.tsx +7 -1
- package/src/react/QuantityStepper.css +84 -80
- package/src/react/Select.css +159 -155
- package/src/react/Select.tsx +8 -2
- package/src/react/Toast.css +128 -124
- package/src/react/Toast.tsx +38 -4
- package/src/styles/base.css +30 -26
- package/src/styles/controls.css +183 -179
- package/src/styles/motion.css +203 -199
package/src/react/Toast.css
CHANGED
|
@@ -1,140 +1,144 @@
|
|
|
1
1
|
/* Toast. All values from the design-system tokens. */
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
position: fixed;
|
|
5
|
-
z-index: var(--z-toast);
|
|
6
|
-
display: flex;
|
|
7
|
-
flex-direction: column;
|
|
8
|
-
gap: var(--space-2);
|
|
9
|
-
padding: var(--space-4);
|
|
10
|
-
/* Shrink-wrap to the toasts instead of covering a whole corner, so the empty
|
|
11
|
-
area never overlays or blocks clicks on the page behind it. */
|
|
12
|
-
width: max-content;
|
|
13
|
-
max-width: 100vw;
|
|
14
|
-
}
|
|
3
|
+
@layer reset, tokens, base, components, motion, utilities;
|
|
15
4
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
5
|
+
@layer components {
|
|
6
|
+
.ui-toast-region {
|
|
7
|
+
position: fixed;
|
|
8
|
+
z-index: var(--z-toast);
|
|
9
|
+
display: flex;
|
|
10
|
+
flex-direction: column;
|
|
11
|
+
gap: var(--space-2);
|
|
12
|
+
padding: var(--space-4);
|
|
13
|
+
/* Shrink-wrap to the toasts instead of covering a whole corner, so the empty
|
|
14
|
+
area never overlays or blocks clicks on the page behind it. */
|
|
15
|
+
width: max-content;
|
|
16
|
+
max-width: 100vw;
|
|
17
|
+
}
|
|
21
18
|
|
|
22
|
-
.ui-toast-region--bottom-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
}
|
|
19
|
+
.ui-toast-region--bottom-right {
|
|
20
|
+
right: 0;
|
|
21
|
+
bottom: 0;
|
|
22
|
+
align-items: flex-end;
|
|
23
|
+
}
|
|
28
24
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
width: 100%;
|
|
36
|
-
max-width: 380px;
|
|
37
|
-
padding: var(--space-4);
|
|
38
|
-
/* ivory-light, not ivory-base: ivory-base (#C9C2B1) is dark enough that the
|
|
39
|
-
undo link drops to 3.79 on it, the very contrast problem this redesign
|
|
40
|
-
fixes. ivory-light keeps a warm card distinct from the page and clears AA
|
|
41
|
-
for the link (5.65) and everything on it. */
|
|
42
|
-
background: var(--surface-hover);
|
|
43
|
-
border: 1px solid var(--border);
|
|
44
|
-
border-radius: var(--radius-lg);
|
|
45
|
-
box-shadow: var(--shadow-xl);
|
|
46
|
-
font-size: var(--text-sm);
|
|
47
|
-
line-height: var(--leading-sm);
|
|
48
|
-
color: var(--text);
|
|
49
|
-
pointer-events: auto;
|
|
50
|
-
animation: ui-toast-in var(--duration-base) var(--ease-enter);
|
|
51
|
-
}
|
|
25
|
+
.ui-toast-region--bottom-center {
|
|
26
|
+
left: 50%;
|
|
27
|
+
bottom: 0;
|
|
28
|
+
transform: translateX(-50%);
|
|
29
|
+
align-items: center;
|
|
30
|
+
}
|
|
52
31
|
|
|
53
|
-
.
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
32
|
+
/* A light card lifted off the page by its shadow. Dark text keeps every word
|
|
33
|
+
at full contrast; the tone shows in a coloured icon, not the surface. */
|
|
34
|
+
.ui-toast {
|
|
35
|
+
display: flex;
|
|
36
|
+
align-items: flex-start;
|
|
37
|
+
gap: var(--space-3);
|
|
38
|
+
width: 100%;
|
|
39
|
+
max-width: 380px;
|
|
40
|
+
padding: var(--space-4);
|
|
41
|
+
/* ivory-light, not ivory-base: ivory-base (#C9C2B1) is dark enough that the
|
|
42
|
+
undo link drops to 3.79 on it, the very contrast problem this redesign
|
|
43
|
+
fixes. ivory-light keeps a warm card distinct from the page and clears AA
|
|
44
|
+
for the link (5.65) and everything on it. */
|
|
45
|
+
background: var(--surface-hover);
|
|
46
|
+
border: 1px solid var(--border);
|
|
47
|
+
border-radius: var(--radius-lg);
|
|
48
|
+
box-shadow: var(--shadow-xl);
|
|
49
|
+
font-size: var(--text-sm);
|
|
50
|
+
line-height: var(--leading-sm);
|
|
51
|
+
color: var(--text);
|
|
52
|
+
pointer-events: auto;
|
|
53
|
+
animation: ui-toast-in var(--duration-base) var(--ease-enter);
|
|
54
|
+
}
|
|
58
55
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
}
|
|
64
|
-
.ui-toast--danger .ui-toast__icon {
|
|
65
|
-
color: var(--danger);
|
|
66
|
-
}
|
|
67
|
-
.ui-toast--warning .ui-toast__icon {
|
|
68
|
-
color: var(--warning);
|
|
69
|
-
}
|
|
70
|
-
.ui-toast--info .ui-toast__icon {
|
|
71
|
-
color: var(--primary);
|
|
72
|
-
}
|
|
56
|
+
.ui-toast__icon {
|
|
57
|
+
display: inline-flex;
|
|
58
|
+
flex: none;
|
|
59
|
+
margin-top: 1px;
|
|
60
|
+
}
|
|
73
61
|
|
|
74
|
-
.
|
|
75
|
-
|
|
76
|
-
|
|
62
|
+
/* One coloured icon per tone. The status roles already clear 4.5:1 on the
|
|
63
|
+
light surface, so the glyph carries the meaning without tinting the card. */
|
|
64
|
+
.ui-toast--success .ui-toast__icon {
|
|
65
|
+
color: var(--success);
|
|
66
|
+
}
|
|
67
|
+
.ui-toast--danger .ui-toast__icon {
|
|
68
|
+
color: var(--danger);
|
|
69
|
+
}
|
|
70
|
+
.ui-toast--warning .ui-toast__icon {
|
|
71
|
+
color: var(--warning);
|
|
72
|
+
}
|
|
73
|
+
.ui-toast--info .ui-toast__icon {
|
|
74
|
+
color: var(--primary);
|
|
75
|
+
}
|
|
77
76
|
|
|
78
|
-
.ui-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
background: none;
|
|
82
|
-
border: 0;
|
|
83
|
-
padding: 0;
|
|
84
|
-
font: inherit;
|
|
85
|
-
font-weight: var(--weight-semibold);
|
|
86
|
-
color: var(--link);
|
|
87
|
-
text-decoration: underline;
|
|
88
|
-
cursor: pointer;
|
|
89
|
-
}
|
|
90
|
-
.ui-toast__action:hover {
|
|
91
|
-
color: var(--link-hover);
|
|
92
|
-
}
|
|
93
|
-
.ui-toast__action:focus-visible {
|
|
94
|
-
outline: 2px solid var(--focus);
|
|
95
|
-
outline-offset: 2px;
|
|
96
|
-
border-radius: var(--radius-sm);
|
|
97
|
-
}
|
|
77
|
+
.ui-toast__msg {
|
|
78
|
+
flex: 1;
|
|
79
|
+
}
|
|
98
80
|
|
|
99
|
-
.ui-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
outline-offset: 2px;
|
|
120
|
-
}
|
|
81
|
+
.ui-toast__action {
|
|
82
|
+
display: inline-block;
|
|
83
|
+
margin-top: var(--space-1);
|
|
84
|
+
background: none;
|
|
85
|
+
border: 0;
|
|
86
|
+
padding: 0;
|
|
87
|
+
font: inherit;
|
|
88
|
+
font-weight: var(--weight-semibold);
|
|
89
|
+
color: var(--link);
|
|
90
|
+
text-decoration: underline;
|
|
91
|
+
cursor: pointer;
|
|
92
|
+
}
|
|
93
|
+
.ui-toast__action:hover {
|
|
94
|
+
color: var(--link-hover);
|
|
95
|
+
}
|
|
96
|
+
.ui-toast__action:focus-visible {
|
|
97
|
+
outline: 2px solid var(--focus);
|
|
98
|
+
outline-offset: 2px;
|
|
99
|
+
border-radius: var(--radius-sm);
|
|
100
|
+
}
|
|
121
101
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
102
|
+
.ui-toast__x {
|
|
103
|
+
display: inline-flex;
|
|
104
|
+
flex: none;
|
|
105
|
+
align-items: center;
|
|
106
|
+
justify-content: center;
|
|
107
|
+
width: 24px;
|
|
108
|
+
height: 24px;
|
|
109
|
+
margin: -2px -2px 0 0;
|
|
110
|
+
background: none;
|
|
111
|
+
border: 0;
|
|
112
|
+
border-radius: var(--radius-sm);
|
|
113
|
+
color: var(--text-muted);
|
|
114
|
+
cursor: pointer;
|
|
115
|
+
}
|
|
116
|
+
.ui-toast__x:hover {
|
|
117
|
+
color: var(--text);
|
|
118
|
+
background: var(--surface-hover);
|
|
119
|
+
}
|
|
120
|
+
.ui-toast__x:focus-visible {
|
|
121
|
+
outline: 2px solid var(--focus);
|
|
122
|
+
outline-offset: 2px;
|
|
123
|
+
}
|
|
128
124
|
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
125
|
+
/* The SVG in the close button is decorative. Let clicks and the cursor fall
|
|
126
|
+
through to the button, so its pointer cursor always shows. */
|
|
127
|
+
.ui-toast__x svg,
|
|
128
|
+
.ui-toast__action svg {
|
|
129
|
+
pointer-events: none;
|
|
133
130
|
}
|
|
134
|
-
}
|
|
135
131
|
|
|
136
|
-
@
|
|
137
|
-
|
|
138
|
-
|
|
132
|
+
@keyframes ui-toast-in {
|
|
133
|
+
from {
|
|
134
|
+
opacity: 0;
|
|
135
|
+
transform: translateY(8px);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
@media (prefers-reduced-motion: reduce) {
|
|
140
|
+
.ui-toast {
|
|
141
|
+
animation: none;
|
|
142
|
+
}
|
|
139
143
|
}
|
|
140
144
|
}
|
package/src/react/Toast.tsx
CHANGED
|
@@ -71,20 +71,54 @@ export function Toast({
|
|
|
71
71
|
>
|
|
72
72
|
<span className="ui-toast__icon" aria-hidden="true">
|
|
73
73
|
{tone === "success" ? (
|
|
74
|
-
<svg
|
|
74
|
+
<svg
|
|
75
|
+
width="18"
|
|
76
|
+
height="18"
|
|
77
|
+
viewBox="0 0 24 24"
|
|
78
|
+
fill="none"
|
|
79
|
+
stroke="currentColor"
|
|
80
|
+
strokeWidth="2.4"
|
|
81
|
+
strokeLinecap="round"
|
|
82
|
+
strokeLinejoin="round"
|
|
83
|
+
>
|
|
75
84
|
<path d="M5 13l4 4L19 7" />
|
|
76
85
|
</svg>
|
|
77
86
|
) : tone === "warning" ? (
|
|
78
|
-
<svg
|
|
87
|
+
<svg
|
|
88
|
+
width="18"
|
|
89
|
+
height="18"
|
|
90
|
+
viewBox="0 0 24 24"
|
|
91
|
+
fill="none"
|
|
92
|
+
stroke="currentColor"
|
|
93
|
+
strokeWidth="2"
|
|
94
|
+
strokeLinecap="round"
|
|
95
|
+
strokeLinejoin="round"
|
|
96
|
+
>
|
|
79
97
|
<path d="M12 4l8.5 15h-17L12 4zM12 10v4M12 16.5v.5" />
|
|
80
98
|
</svg>
|
|
81
99
|
) : tone === "info" ? (
|
|
82
|
-
<svg
|
|
100
|
+
<svg
|
|
101
|
+
width="18"
|
|
102
|
+
height="18"
|
|
103
|
+
viewBox="0 0 24 24"
|
|
104
|
+
fill="none"
|
|
105
|
+
stroke="currentColor"
|
|
106
|
+
strokeWidth="2"
|
|
107
|
+
strokeLinecap="round"
|
|
108
|
+
>
|
|
83
109
|
<circle cx="12" cy="12" r="9" />
|
|
84
110
|
<path d="M12 11v5M12 8v.5" />
|
|
85
111
|
</svg>
|
|
86
112
|
) : (
|
|
87
|
-
<svg
|
|
113
|
+
<svg
|
|
114
|
+
width="18"
|
|
115
|
+
height="18"
|
|
116
|
+
viewBox="0 0 24 24"
|
|
117
|
+
fill="none"
|
|
118
|
+
stroke="currentColor"
|
|
119
|
+
strokeWidth="2"
|
|
120
|
+
strokeLinecap="round"
|
|
121
|
+
>
|
|
88
122
|
<circle cx="12" cy="12" r="9" />
|
|
89
123
|
<path d="M12 8v4.5M12 16v.5" />
|
|
90
124
|
</svg>
|
package/src/styles/base.css
CHANGED
|
@@ -7,33 +7,37 @@
|
|
|
7
7
|
* `@kwtv/tokens/tokens.css` before this file.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
.ui-sr-only {
|
|
12
|
-
position: absolute;
|
|
13
|
-
width: 1px;
|
|
14
|
-
height: 1px;
|
|
15
|
-
padding: 0;
|
|
16
|
-
margin: -1px;
|
|
17
|
-
overflow: hidden;
|
|
18
|
-
clip-path: inset(50%);
|
|
19
|
-
white-space: nowrap;
|
|
20
|
-
border: 0;
|
|
21
|
-
}
|
|
10
|
+
@layer reset, tokens, base, components, motion, utilities;
|
|
22
11
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
.ui-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
12
|
+
@layer base {
|
|
13
|
+
/* Screen-reader-only, still announced. */
|
|
14
|
+
.ui-sr-only {
|
|
15
|
+
position: absolute;
|
|
16
|
+
width: 1px;
|
|
17
|
+
height: 1px;
|
|
18
|
+
padding: 0;
|
|
19
|
+
margin: -1px;
|
|
20
|
+
overflow: hidden;
|
|
21
|
+
clip-path: inset(50%);
|
|
22
|
+
white-space: nowrap;
|
|
23
|
+
border: 0;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/* The two-tone focus ring. An outer halo keeps the ring visible on mid-tone
|
|
27
|
+
fills where a single colour would disappear. SC 2.4.7 and 2.4.11. */
|
|
28
|
+
.ui-focus-ring:focus-visible,
|
|
29
|
+
.ui-focus-ring.ui-focus-ring--pinned {
|
|
30
|
+
outline: 2px solid var(--focus);
|
|
31
|
+
outline-offset: 2px;
|
|
32
|
+
box-shadow: 0 0 0 4px var(--focus-outer);
|
|
33
|
+
}
|
|
31
34
|
|
|
32
|
-
/* Touch-target floor. Labelled rows and small controls hold 32 px, icon-only
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
@media (max-width: 700px), (pointer: coarse) {
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
/* Touch-target floor. Labelled rows and small controls hold 32 px, icon-only
|
|
36
|
+
controls hold 44 px, the mobile primary action holds 48 px. The lever is the
|
|
37
|
+
label or the row, not the native control inside it. */
|
|
38
|
+
@media (max-width: 700px), (pointer: coarse) {
|
|
39
|
+
.ui-touch :where(button, a, label, [role="button"]):not(.ui-touch--exempt) {
|
|
40
|
+
min-height: 32px;
|
|
41
|
+
}
|
|
38
42
|
}
|
|
39
43
|
}
|