@kwtv/components 0.3.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 +35 -0
- package/package.json +2 -2
- package/src/astro/Accordion.astro +10 -6
- package/src/astro/AccordionItem.astro +47 -43
- package/src/astro/ActiveFilterTags.astro +29 -25
- 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 +33 -29
- package/src/astro/Button.astro +132 -128
- package/src/astro/Card.astro +64 -60
- package/src/astro/CartLine.astro +59 -55
- package/src/astro/Checkbox.astro +36 -32
- package/src/astro/Chip.astro +68 -64
- package/src/astro/DotGrid.astro +50 -46
- package/src/astro/EmptyState.astro +26 -22
- package/src/astro/FilterGroup.astro +29 -25
- package/src/astro/Filters.astro +50 -46
- package/src/astro/Footer.astro +179 -175
- package/src/astro/FooterColumn.astro +39 -35
- package/src/astro/Header.astro +67 -63
- package/src/astro/Icon.astro +1 -1
- package/src/astro/IconButton.astro +64 -60
- package/src/astro/Marquee.astro +33 -29
- package/src/astro/NavDropdown.astro +120 -116
- package/src/astro/NavLink.astro +59 -55
- package/src/astro/Newsletter.astro +58 -54
- package/src/astro/Pager.astro +43 -39
- package/src/astro/PickCard.astro +72 -68
- package/src/astro/ProductCard.astro +120 -116
- package/src/astro/Radio.astro +36 -32
- package/src/astro/Skeleton.astro +43 -39
- package/src/astro/Social.astro +26 -22
- package/src/astro/StepIndicator.astro +55 -51
- package/src/astro/Sticker.astro +50 -46
- package/src/astro/Swatch.astro +44 -40
- package/src/astro/Table.astro +58 -54
- package/src/astro/TableCard.astro +39 -35
- package/src/astro/TextField.astro +92 -88
- package/src/astro/Totals.astro +39 -35
- package/src/react/Drawer.css +60 -56
- package/src/react/Modal.css +97 -93
- package/src/react/NewsCarousel.css +108 -104
- package/src/react/QuantityStepper.css +84 -80
- package/src/react/Select.css +159 -155
- package/src/react/Toast.css +128 -124
- package/src/styles/base.css +30 -26
- package/src/styles/controls.css +183 -179
- package/src/styles/motion.css +203 -199
package/README.md
CHANGED
|
@@ -71,6 +71,41 @@ import "@kwtv/components/styles/base.css";
|
|
|
71
71
|
import "@kwtv/components/styles/controls.css";
|
|
72
72
|
```
|
|
73
73
|
|
|
74
|
+
## Cascade layers
|
|
75
|
+
|
|
76
|
+
Every stylesheet in this package and in `@kwtv/tokens` sits in a cascade
|
|
77
|
+
layer, in one fixed order:
|
|
78
|
+
|
|
79
|
+
```css
|
|
80
|
+
@layer reset, tokens, base, components, motion, utilities;
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
| Layer | Holds |
|
|
84
|
+
| ------------ | --------------------------------------------------------------- |
|
|
85
|
+
| `reset` | Empty in the packages. The app's element defaults go here. |
|
|
86
|
+
| `tokens` | The token custom properties, in `palette`, `theme` and `scale`. |
|
|
87
|
+
| `base` | `base.css`: focus ring, touch targets, screen-reader helper. |
|
|
88
|
+
| `components` | Astro component styles, React island CSS and `controls.css`. |
|
|
89
|
+
| `motion` | `motion.css`. Above components, because it adjusts their parts. |
|
|
90
|
+
| `utilities` | `@kwtv/tokens/utilities.css`. |
|
|
91
|
+
|
|
92
|
+
Every package stylesheet opens with that order statement. The first one to
|
|
93
|
+
load fixes the order, so it holds whatever order the bundler emits files in.
|
|
94
|
+
|
|
95
|
+
In the app:
|
|
96
|
+
|
|
97
|
+
- Put element defaults (`*`, `html`, `body`, `a`, `button`) in
|
|
98
|
+
`@layer reset { }`. Left unlayered, a bare `a { color }` beats the footer
|
|
99
|
+
and button link colours.
|
|
100
|
+
- Leave everything else unlayered. Unlayered CSS beats every layer, so a
|
|
101
|
+
single class overrides any component rule. Do not raise specificity with
|
|
102
|
+
ids or repeated classes.
|
|
103
|
+
- `!important` flips inside layers: an important declaration in a lower layer
|
|
104
|
+
wins. The package uses it only to stop animation under reduced motion.
|
|
105
|
+
|
|
106
|
+
`npm run layers:check` fails when a package stylesheet is missing the order
|
|
107
|
+
statement or has a rule outside its layer.
|
|
108
|
+
|
|
74
109
|
## Conventions
|
|
75
110
|
|
|
76
111
|
- Use the `.astro`, `.tsx` and `.css` extensions shown in these examples.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kwtv/components",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"license": "UNLICENSED",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "KWTV UI components for Astro, with React islands. Built on the KWTV design tokens.",
|
|
@@ -34,6 +34,6 @@
|
|
|
34
34
|
}
|
|
35
35
|
},
|
|
36
36
|
"dependencies": {
|
|
37
|
-
"@kwtv/tokens": "^0.
|
|
37
|
+
"@kwtv/tokens": "^0.4.0"
|
|
38
38
|
}
|
|
39
39
|
}
|
|
@@ -15,11 +15,15 @@ const { class: className, ...rest } = Astro.props;
|
|
|
15
15
|
</div>
|
|
16
16
|
|
|
17
17
|
<style>
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
18
|
+
@layer reset, tokens, base, components, motion, utilities;
|
|
19
|
+
|
|
20
|
+
@layer components {
|
|
21
|
+
.ui-accordion {
|
|
22
|
+
display: flex;
|
|
23
|
+
flex-direction: column;
|
|
24
|
+
border: 1px solid var(--border);
|
|
25
|
+
border-radius: var(--radius-lg);
|
|
26
|
+
overflow: hidden;
|
|
27
|
+
}
|
|
24
28
|
}
|
|
25
29
|
</style>
|
|
@@ -31,53 +31,57 @@ const { summary, open = false, class: className, ...rest } = Astro.props;
|
|
|
31
31
|
</details>
|
|
32
32
|
|
|
33
33
|
<style>
|
|
34
|
-
|
|
35
|
-
border-top: 1px solid var(--border);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
.ui-accordion__sum {
|
|
39
|
-
display: flex;
|
|
40
|
-
align-items: center;
|
|
41
|
-
justify-content: space-between;
|
|
42
|
-
gap: var(--space-3);
|
|
43
|
-
min-height: 44px;
|
|
44
|
-
padding: var(--space-2) var(--space-4);
|
|
45
|
-
font-size: var(--text-sm);
|
|
46
|
-
font-weight: var(--weight-medium);
|
|
47
|
-
color: var(--text);
|
|
48
|
-
cursor: pointer;
|
|
49
|
-
list-style: none;
|
|
50
|
-
}
|
|
51
|
-
.ui-accordion__sum::-webkit-details-marker {
|
|
52
|
-
display: none;
|
|
53
|
-
}
|
|
54
|
-
.ui-accordion__sum:hover {
|
|
55
|
-
background: var(--surface-hover);
|
|
56
|
-
}
|
|
57
|
-
.ui-accordion__sum:focus-visible {
|
|
58
|
-
outline: 2px solid var(--focus);
|
|
59
|
-
outline-offset: -2px;
|
|
60
|
-
}
|
|
34
|
+
@layer reset, tokens, base, components, motion, utilities;
|
|
61
35
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
}
|
|
67
|
-
.ui-accordion__item[open] .ui-accordion__chev {
|
|
68
|
-
transform: rotate(180deg);
|
|
69
|
-
}
|
|
36
|
+
@layer components {
|
|
37
|
+
.ui-accordion__item + .ui-accordion__item {
|
|
38
|
+
border-top: 1px solid var(--border);
|
|
39
|
+
}
|
|
70
40
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
41
|
+
.ui-accordion__sum {
|
|
42
|
+
display: flex;
|
|
43
|
+
align-items: center;
|
|
44
|
+
justify-content: space-between;
|
|
45
|
+
gap: var(--space-3);
|
|
46
|
+
min-height: 44px;
|
|
47
|
+
padding: var(--space-2) var(--space-4);
|
|
48
|
+
font-size: var(--text-sm);
|
|
49
|
+
font-weight: var(--weight-medium);
|
|
50
|
+
color: var(--text);
|
|
51
|
+
cursor: pointer;
|
|
52
|
+
list-style: none;
|
|
53
|
+
}
|
|
54
|
+
.ui-accordion__sum::-webkit-details-marker {
|
|
55
|
+
display: none;
|
|
56
|
+
}
|
|
57
|
+
.ui-accordion__sum:hover {
|
|
58
|
+
background: var(--surface-hover);
|
|
59
|
+
}
|
|
60
|
+
.ui-accordion__sum:focus-visible {
|
|
61
|
+
outline: 2px solid var(--focus);
|
|
62
|
+
outline-offset: -2px;
|
|
63
|
+
}
|
|
77
64
|
|
|
78
|
-
@media (prefers-reduced-motion: reduce) {
|
|
79
65
|
.ui-accordion__chev {
|
|
80
|
-
|
|
66
|
+
display: inline-flex;
|
|
67
|
+
color: var(--text-muted);
|
|
68
|
+
transition: transform var(--duration-fast) var(--ease-standard);
|
|
69
|
+
}
|
|
70
|
+
.ui-accordion__item[open] .ui-accordion__chev {
|
|
71
|
+
transform: rotate(180deg);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
.ui-accordion__body {
|
|
75
|
+
padding: 0 var(--space-4) var(--space-4);
|
|
76
|
+
font-size: var(--text-sm);
|
|
77
|
+
line-height: var(--leading-sm);
|
|
78
|
+
color: var(--text-muted);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
@media (prefers-reduced-motion: reduce) {
|
|
82
|
+
.ui-accordion__chev {
|
|
83
|
+
transition: none;
|
|
84
|
+
}
|
|
81
85
|
}
|
|
82
86
|
}
|
|
83
87
|
</style>
|
|
@@ -44,31 +44,35 @@ const classes = ["ui-filtertags", className].filter(Boolean).join(" ");
|
|
|
44
44
|
</div>
|
|
45
45
|
|
|
46
46
|
<style>
|
|
47
|
-
|
|
48
|
-
display: flex;
|
|
49
|
-
flex-wrap: wrap;
|
|
50
|
-
align-items: center;
|
|
51
|
-
gap: var(--space-2);
|
|
52
|
-
}
|
|
47
|
+
@layer reset, tokens, base, components, motion, utilities;
|
|
53
48
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
49
|
+
@layer components {
|
|
50
|
+
.ui-filtertags {
|
|
51
|
+
display: flex;
|
|
52
|
+
flex-wrap: wrap;
|
|
53
|
+
align-items: center;
|
|
54
|
+
gap: var(--space-2);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
.ui-filtertags__clear {
|
|
58
|
+
padding: var(--space-1-5) var(--space-2);
|
|
59
|
+
background: transparent;
|
|
60
|
+
border: 0;
|
|
61
|
+
border-radius: var(--radius-sm);
|
|
62
|
+
font-family: var(--font-sans);
|
|
63
|
+
font-size: var(--text-xs);
|
|
64
|
+
font-weight: var(--weight-semibold);
|
|
65
|
+
color: var(--link);
|
|
66
|
+
cursor: pointer;
|
|
67
|
+
}
|
|
68
|
+
.ui-filtertags__clear:hover {
|
|
69
|
+
background: var(--surface-hover);
|
|
70
|
+
color: var(--link-hover);
|
|
71
|
+
}
|
|
72
|
+
.ui-filtertags__clear:focus-visible {
|
|
73
|
+
outline: 2px solid var(--focus);
|
|
74
|
+
outline-offset: 2px;
|
|
75
|
+
box-shadow: 0 0 0 4px var(--focus-outer);
|
|
76
|
+
}
|
|
73
77
|
}
|
|
74
78
|
</style>
|
package/src/astro/Alert.astro
CHANGED
|
@@ -41,53 +41,57 @@ const classes = ["ui-alert", `ui-alert--${tone}`, className]
|
|
|
41
41
|
</div>
|
|
42
42
|
|
|
43
43
|
<style>
|
|
44
|
-
|
|
45
|
-
display: flex;
|
|
46
|
-
align-items: flex-start;
|
|
47
|
-
gap: var(--space-2-5, 0.625rem);
|
|
48
|
-
padding: var(--space-3) var(--space-4);
|
|
49
|
-
border-left: 3px solid currentColor;
|
|
50
|
-
border-radius: var(--radius-md);
|
|
51
|
-
font-family: var(--font-sans);
|
|
52
|
-
font-size: var(--text-sm);
|
|
53
|
-
line-height: var(--leading-sm);
|
|
54
|
-
}
|
|
44
|
+
@layer reset, tokens, base, components, motion, utilities;
|
|
55
45
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
46
|
+
@layer components {
|
|
47
|
+
.ui-alert {
|
|
48
|
+
display: flex;
|
|
49
|
+
align-items: flex-start;
|
|
50
|
+
gap: var(--space-2-5, 0.625rem);
|
|
51
|
+
padding: var(--space-3) var(--space-4);
|
|
52
|
+
border-left: 3px solid currentColor;
|
|
53
|
+
border-radius: var(--radius-md);
|
|
54
|
+
font-family: var(--font-sans);
|
|
55
|
+
font-size: var(--text-sm);
|
|
56
|
+
line-height: var(--leading-sm);
|
|
57
|
+
}
|
|
61
58
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
gap: var(--space-1);
|
|
68
|
-
}
|
|
59
|
+
.ui-alert__icon {
|
|
60
|
+
display: inline-flex;
|
|
61
|
+
flex-shrink: 0;
|
|
62
|
+
margin-top: 1px;
|
|
63
|
+
}
|
|
69
64
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
65
|
+
/* Body keeps full strength; the left rule carries the tone. */
|
|
66
|
+
.ui-alert__body {
|
|
67
|
+
color: var(--text);
|
|
68
|
+
display: flex;
|
|
69
|
+
flex-direction: column;
|
|
70
|
+
gap: var(--space-1);
|
|
71
|
+
}
|
|
73
72
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
}
|
|
73
|
+
.ui-alert__title {
|
|
74
|
+
font-weight: var(--weight-semibold);
|
|
75
|
+
}
|
|
78
76
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
77
|
+
.ui-alert--info {
|
|
78
|
+
background: var(--surface-accent);
|
|
79
|
+
color: var(--surface-accent-fg, var(--primary));
|
|
80
|
+
}
|
|
83
81
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
82
|
+
.ui-alert--success {
|
|
83
|
+
background: var(--success-bg);
|
|
84
|
+
color: var(--success);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
.ui-alert--warning {
|
|
88
|
+
background: var(--warning-bg);
|
|
89
|
+
color: var(--warning);
|
|
90
|
+
}
|
|
88
91
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
+
.ui-alert--danger {
|
|
93
|
+
background: var(--danger-bg);
|
|
94
|
+
color: var(--danger);
|
|
95
|
+
}
|
|
92
96
|
}
|
|
93
97
|
</style>
|
package/src/astro/Badge.astro
CHANGED
|
@@ -58,81 +58,85 @@ const classes = [
|
|
|
58
58
|
</span>
|
|
59
59
|
|
|
60
60
|
<style>
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
61
|
+
@layer reset, tokens, base, components, motion, utilities;
|
|
62
|
+
|
|
63
|
+
@layer components {
|
|
64
|
+
.ui-badge {
|
|
65
|
+
display: inline-flex;
|
|
66
|
+
align-items: center;
|
|
67
|
+
gap: var(--space-1-5);
|
|
68
|
+
min-height: 24px;
|
|
69
|
+
padding: 0 var(--space-2);
|
|
70
|
+
border: 1px solid transparent;
|
|
71
|
+
border-radius: var(--radius-full);
|
|
72
|
+
font-family: var(--font-sans);
|
|
73
|
+
font-size: var(--text-xs);
|
|
74
|
+
font-weight: var(--weight-medium);
|
|
75
|
+
line-height: 1;
|
|
76
|
+
white-space: nowrap;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
.ui-badge__icon {
|
|
80
|
+
display: inline-flex;
|
|
81
|
+
flex-shrink: 0;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.ui-badge--neutral {
|
|
85
|
+
background: var(--surface-accent);
|
|
86
|
+
color: var(--surface-accent-fg, var(--text));
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
.ui-badge--success {
|
|
90
|
+
background: var(--success-bg);
|
|
91
|
+
color: var(--success);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
.ui-badge--warning {
|
|
95
|
+
background: var(--warning-bg);
|
|
96
|
+
color: var(--warning);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
.ui-badge--danger {
|
|
100
|
+
background: var(--danger-bg);
|
|
101
|
+
color: var(--danger);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/* Outline keeps the strong border and full-strength text, so it reads */
|
|
105
|
+
/* without relying on a fill. */
|
|
106
|
+
.ui-badge--outline {
|
|
107
|
+
background: transparent;
|
|
108
|
+
border: 1px solid var(--border-strong);
|
|
109
|
+
color: var(--text);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
.ui-badge--removable {
|
|
113
|
+
padding-right: var(--space-1);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/* Small × target grows with padding plus an equal negative margin, so the */
|
|
117
|
+
/* hit area grows without moving the layout. */
|
|
118
|
+
.ui-badge__x {
|
|
119
|
+
display: inline-flex;
|
|
120
|
+
align-items: center;
|
|
121
|
+
justify-content: center;
|
|
122
|
+
padding: var(--space-2);
|
|
123
|
+
margin: calc(-1 * var(--space-2));
|
|
124
|
+
margin-left: 0;
|
|
125
|
+
background: transparent;
|
|
126
|
+
border: 0;
|
|
127
|
+
border-radius: var(--radius-sm);
|
|
128
|
+
color: inherit;
|
|
129
|
+
cursor: pointer;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.ui-badge__x:hover {
|
|
133
|
+
color: var(--danger);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
.ui-badge__x:focus-visible {
|
|
137
|
+
outline: 2px solid var(--focus);
|
|
138
|
+
outline-offset: 2px;
|
|
139
|
+
box-shadow: 0 0 0 4px var(--focus-outer);
|
|
140
|
+
}
|
|
137
141
|
}
|
|
138
142
|
</style>
|