@apliteni/apliteni-ui 0.12.0 → 0.23.2
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/react/dist/index.css +19 -0
- package/react/dist/index.d.ts +43 -2
- package/react/dist/index.js +98 -6
- package/src/assets/icons.js +5 -26
- package/src/components/account-nav.js +1 -1
- package/src/components/confirm.js +27 -28
- package/src/components/drawer.js +27 -28
- package/src/components/dropdown.js +26 -23
- package/src/components/index.js +9 -13
- package/src/components/loading.js +126 -0
- package/src/components/nav.js +7 -20
- package/src/components/overlay.js +7 -16
- package/src/components/shell.js +10 -9
- package/src/components/success.js +8 -17
- package/src/components/topbar.js +8 -12
- package/src/index.css +6 -1
- package/src/index.js +1 -0
- package/src/inline.js +4 -0
- package/src/styles/badge.css +1 -1
- package/src/styles/base.css +5 -18
- package/src/styles/button.css +18 -5
- package/src/styles/callout.css +37 -26
- package/src/styles/card.css +1 -1
- package/src/styles/code.css +7 -1
- package/src/styles/confirm.css +10 -13
- package/src/styles/drawer.css +9 -6
- package/src/styles/dropdown.css +14 -7
- package/src/styles/empty.css +1 -1
- package/src/styles/feedback.css +25 -16
- package/src/styles/footer.css +15 -6
- package/src/styles/input.css +28 -2
- package/src/styles/layout.css +14 -10
- package/src/styles/loading.css +129 -0
- package/src/styles/motion.css +21 -39
- package/src/styles/nav.css +14 -12
- package/src/styles/reduced-motion.css +21 -0
- package/src/styles/success.css +8 -8
- package/src/styles/table.css +20 -17
- package/src/styles/topbar.css +27 -12
- package/src/tokens/accents.css +10 -14
- package/src/tokens/tokens.css +95 -22
package/src/styles/confirm.css
CHANGED
|
@@ -1,25 +1,22 @@
|
|
|
1
|
-
/*
|
|
2
|
-
*
|
|
3
|
-
*
|
|
4
|
-
* re-themes across accents + light/dark. Shares its scrim + focus-trap
|
|
5
|
-
* behaviour with the drawer (see overlay.js).
|
|
1
|
+
/* Confirm — the kit's confirmation dialog: a centred panel over a scrim, for the
|
|
2
|
+
* question a destructive action has to ask. Fully token-driven, and it shares
|
|
3
|
+
* its scrim and focus-trap behaviour with the drawer (see overlay.js).
|
|
6
4
|
*
|
|
7
|
-
*
|
|
8
|
-
* switched rather than transitioned. A transitioned visibility is still
|
|
5
|
+
* `visibility` is SWITCHED rather than transitioned: transitioned, it is still
|
|
9
6
|
* `hidden` in the frame the class lands, so openConfirm()'s focus() would have
|
|
10
|
-
* nothing to focus
|
|
11
|
-
* switch; the panel and scrim inherit it.
|
|
7
|
+
* nothing to focus. The root owns the switch; panel and scrim inherit it.
|
|
12
8
|
*
|
|
13
|
-
* Local tokens
|
|
9
|
+
* Local tokens so the panel and scrim re-theme cleanly:
|
|
14
10
|
* --confirm-surface panel background --confirm-shadow panel elevation
|
|
15
|
-
* --confirm-scrim backdrop colour
|
|
16
|
-
*
|
|
11
|
+
* --confirm-scrim backdrop colour
|
|
12
|
+
*
|
|
13
|
+
* why: docs/specification.md#motion */
|
|
17
14
|
|
|
18
15
|
.ui-confirm {
|
|
19
16
|
--confirm-surface: var(--surface-2);
|
|
20
17
|
--confirm-shadow: var(--shadow-lg);
|
|
21
18
|
--confirm-scrim: var(--scrim);
|
|
22
|
-
--confirm-w:
|
|
19
|
+
--confirm-w: var(--panel-md);
|
|
23
20
|
|
|
24
21
|
position: fixed;
|
|
25
22
|
inset: 0;
|
package/src/styles/drawer.css
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
--drawer-surface: var(--surface-2);
|
|
15
15
|
--drawer-shadow: var(--shadow-lg);
|
|
16
16
|
--drawer-scrim: var(--scrim);
|
|
17
|
-
--drawer-w:
|
|
17
|
+
--drawer-w: var(--panel-md); /* left|right panels: width */
|
|
18
18
|
--drawer-h: 45vh; /* top|bottom panels: height */
|
|
19
19
|
|
|
20
20
|
position: fixed;
|
|
@@ -102,9 +102,9 @@
|
|
|
102
102
|
|
|
103
103
|
/* -- Sizes ----------------------------------------------------------------- */
|
|
104
104
|
/* left|right → width; top|bottom → height. Same names, axis chosen by side. */
|
|
105
|
-
.ui-drawer--right.ui-drawer--sm, .ui-drawer--left.ui-drawer--sm { --drawer-w:
|
|
106
|
-
.ui-drawer--right.ui-drawer--md, .ui-drawer--left.ui-drawer--md { --drawer-w:
|
|
107
|
-
.ui-drawer--right.ui-drawer--lg, .ui-drawer--left.ui-drawer--lg { --drawer-w:
|
|
105
|
+
.ui-drawer--right.ui-drawer--sm, .ui-drawer--left.ui-drawer--sm { --drawer-w: var(--panel-sm); }
|
|
106
|
+
.ui-drawer--right.ui-drawer--md, .ui-drawer--left.ui-drawer--md { --drawer-w: var(--panel-md); }
|
|
107
|
+
.ui-drawer--right.ui-drawer--lg, .ui-drawer--left.ui-drawer--lg { --drawer-w: var(--panel-lg); }
|
|
108
108
|
.ui-drawer--top.ui-drawer--sm, .ui-drawer--bottom.ui-drawer--sm { --drawer-h: 30vh; }
|
|
109
109
|
.ui-drawer--top.ui-drawer--md, .ui-drawer--bottom.ui-drawer--md { --drawer-h: 45vh; }
|
|
110
110
|
.ui-drawer--top.ui-drawer--lg, .ui-drawer--bottom.ui-drawer--lg { --drawer-h: 72vh; }
|
|
@@ -138,11 +138,14 @@
|
|
|
138
138
|
background: transparent;
|
|
139
139
|
border: 1px solid transparent;
|
|
140
140
|
border-radius: var(--radius-sm);
|
|
141
|
-
transition:
|
|
141
|
+
transition:
|
|
142
|
+
color var(--dur-fast) var(--ease),
|
|
143
|
+
background var(--dur-fast) var(--ease),
|
|
144
|
+
border-color var(--dur-fast) var(--ease);
|
|
142
145
|
}
|
|
143
146
|
.ui-drawer__close:hover { color: var(--strong); background: var(--surface); }
|
|
144
147
|
.ui-drawer__close:focus-visible { outline: none; box-shadow: var(--ring); border-color: var(--accent); }
|
|
145
|
-
.ui-drawer__close svg { width: 18px; height: 18px; stroke: currentColor; fill: none; stroke-width: 1
|
|
148
|
+
.ui-drawer__close svg { width: 18px; height: 18px; stroke: currentColor; fill: none; stroke-width: 2.1; }
|
|
146
149
|
|
|
147
150
|
.ui-drawer__body {
|
|
148
151
|
flex: 1 1 auto;
|
package/src/styles/dropdown.css
CHANGED
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
border: 1px solid var(--border);
|
|
22
22
|
border-radius: var(--radius-pill);
|
|
23
23
|
padding: 7px 11px 7px 13px;
|
|
24
|
-
transition: border-color
|
|
24
|
+
transition: border-color var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease);
|
|
25
25
|
}
|
|
26
26
|
.ui-dropdown__trigger:hover { border-color: var(--accent); }
|
|
27
27
|
.ui-dropdown__trigger:focus-visible { outline: none; box-shadow: var(--ring); border-color: var(--accent); }
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
border-right: 1.6px solid var(--muted);
|
|
35
35
|
border-bottom: 1.6px solid var(--muted);
|
|
36
36
|
transform: rotate(45deg) translateY(-1px);
|
|
37
|
-
transition: transform
|
|
37
|
+
transition: transform var(--dur-fast) var(--ease);
|
|
38
38
|
flex: none;
|
|
39
39
|
}
|
|
40
40
|
.ui-dropdown.open .ui-dropdown__chevron { transform: rotate(-135deg) translateY(2px); }
|
|
@@ -53,7 +53,12 @@
|
|
|
53
53
|
opacity: 0;
|
|
54
54
|
visibility: hidden;
|
|
55
55
|
transform: translateY(-6px);
|
|
56
|
-
transition:
|
|
56
|
+
transition:
|
|
57
|
+
opacity var(--dur-med) var(--ease),
|
|
58
|
+
transform var(--dur-med) var(--ease),
|
|
59
|
+
/* `linear`, not var(--ease): visibility is discrete, so easing it buys nothing and a
|
|
60
|
+
curve leaving [0, 1] flips it mid-fade. Same rule the drawer states at length. */
|
|
61
|
+
visibility var(--dur-med) linear;
|
|
57
62
|
z-index: var(--z-dropdown);
|
|
58
63
|
}
|
|
59
64
|
.ui-dropdown__panel.is-end { left: auto; right: 0; }
|
|
@@ -70,7 +75,7 @@
|
|
|
70
75
|
cursor: pointer;
|
|
71
76
|
text-decoration: none;
|
|
72
77
|
color: var(--text);
|
|
73
|
-
transition: background
|
|
78
|
+
transition: background var(--dur-fast) var(--ease);
|
|
74
79
|
}
|
|
75
80
|
.ui-dropdown__item:hover { background: var(--surface); }
|
|
76
81
|
.ui-dropdown__item:focus-visible { outline: none; background: var(--surface); box-shadow: var(--ring); }
|
|
@@ -78,11 +83,11 @@
|
|
|
78
83
|
.ui-dropdown__label { font-family: var(--font-sans); font-size: 12.5px; color: var(--strong); font-weight: 600; letter-spacing: 0.01em; }
|
|
79
84
|
.ui-dropdown__desc { font-size: 11px; color: var(--muted); line-height: 1.35; }
|
|
80
85
|
.ui-dropdown__ic { display: inline-flex; flex: none; color: var(--muted); }
|
|
81
|
-
.ui-dropdown__ic svg { width: 18px; height: 18px; stroke: currentColor; fill: none; stroke-width: 1
|
|
86
|
+
.ui-dropdown__ic svg { width: 18px; height: 18px; stroke: currentColor; fill: none; stroke-width: 2.1; }
|
|
82
87
|
|
|
83
88
|
/* Trailing selected tick (listbox variant) */
|
|
84
89
|
.ui-dropdown__tick { margin-left: auto; flex: none; display: none; color: var(--accent); }
|
|
85
|
-
.ui-dropdown__tick svg { width: 16px; height: 16px; stroke: currentColor; fill: none; stroke-width: 2.
|
|
90
|
+
.ui-dropdown__tick svg { width: 16px; height: 16px; stroke: currentColor; fill: none; stroke-width: 2.4; }
|
|
86
91
|
.ui-dropdown__item.is-selected .ui-dropdown__tick { display: inline-flex; }
|
|
87
92
|
.ui-dropdown__item.is-selected .ui-dropdown__label { color: var(--accent); }
|
|
88
93
|
|
|
@@ -106,7 +111,9 @@
|
|
|
106
111
|
.ui-dropdown__badge.is-accent { color: var(--accent); background: color-mix(in srgb, var(--accent) 14%, transparent); }
|
|
107
112
|
|
|
108
113
|
/* Disabled + danger rows */
|
|
109
|
-
.ui-dropdown__item.is-disabled {
|
|
114
|
+
.ui-dropdown__item.is-disabled { color: var(--disabled-ink); cursor: not-allowed; pointer-events: none; }
|
|
115
|
+
.ui-dropdown__item.is-disabled .ui-dropdown__label,
|
|
116
|
+
.ui-dropdown__item.is-disabled .ui-dropdown__desc { color: inherit; }
|
|
110
117
|
.ui-dropdown__item.is-danger .ui-dropdown__label { color: var(--muted); }
|
|
111
118
|
.ui-dropdown__item.is-danger:hover .ui-dropdown__label { color: var(--pink); }
|
|
112
119
|
|
package/src/styles/empty.css
CHANGED
package/src/styles/feedback.css
CHANGED
|
@@ -27,7 +27,10 @@
|
|
|
27
27
|
box-shadow: 0 10px 26px var(--ui-fb-pill-glow),
|
|
28
28
|
0 2px 6px color-mix(in srgb, var(--shadow-ink) 28%, transparent),
|
|
29
29
|
inset 0 1px 0 color-mix(in srgb, var(--sheen) 28%, transparent);
|
|
30
|
-
transition:
|
|
30
|
+
transition:
|
|
31
|
+
transform var(--dur-fast) var(--ease-spring),
|
|
32
|
+
opacity var(--dur-fast) var(--ease),
|
|
33
|
+
box-shadow var(--dur-fast) var(--ease);
|
|
31
34
|
}
|
|
32
35
|
.ui-fbpill.show { opacity: 1; pointer-events: auto; transform: translate(-50%, -100%) translateY(-9px) scale(1); }
|
|
33
36
|
.ui-fbpill:hover {
|
|
@@ -37,19 +40,19 @@
|
|
|
37
40
|
}
|
|
38
41
|
.ui-fbpill.show:hover { transform: translate(-50%, -100%) translateY(-12px) scale(1.04); }
|
|
39
42
|
.ui-fbpill:active { transform: translate(-50%, -100%) translateY(-8px) scale(.98); }
|
|
40
|
-
.ui-fbpill svg { width: 16px; height: 16px; color: currentColor; filter: drop-shadow(0 1px 1px color-mix(in srgb, var(--shadow-ink) 25%, transparent)); }
|
|
43
|
+
.ui-fbpill svg { width: 16px; height: 16px; stroke-width: 2.4; color: currentColor; filter: drop-shadow(0 1px 1px color-mix(in srgb, var(--shadow-ink) 25%, transparent)); }
|
|
41
44
|
.ui-fbpill::before {
|
|
42
45
|
content: ""; position: absolute; top: 0; bottom: 0; left: -60%; width: 45%;
|
|
43
46
|
background: linear-gradient(100deg, transparent, color-mix(in srgb, var(--sheen) 55%, transparent), transparent); transform: skewX(-18deg);
|
|
44
47
|
}
|
|
45
|
-
.ui-fbpill.show::before { animation: uiFbSheen 1.15s ease .12s 1; }
|
|
46
|
-
.ui-fbpill:hover::before { animation: uiFbSheen .7s ease 1; }
|
|
48
|
+
.ui-fbpill.show::before { animation: uiFbSheen 1.15s ease .12s 1; } /* motion: ambient — a decorative sheen crossing the pill; its length is the width it travels, not a response */
|
|
49
|
+
.ui-fbpill:hover::before { animation: uiFbSheen .7s ease 1; } /* motion: ambient — the same sweep, quicker on hover so it finishes inside the gesture */
|
|
47
50
|
@keyframes uiFbSheen { 0% { left: -60%; } 100% { left: 130%; } }
|
|
48
51
|
|
|
49
52
|
/* Scrim behind the open composer */
|
|
50
53
|
.ui-fbscrim {
|
|
51
54
|
position: fixed; inset: 0; z-index: 70; background: var(--scrim);
|
|
52
|
-
opacity: 0; pointer-events: none; transition: opacity
|
|
55
|
+
opacity: 0; pointer-events: none; transition: opacity var(--dur-med) var(--ease);
|
|
53
56
|
}
|
|
54
57
|
.ui-fbscrim.show { opacity: 1; pointer-events: auto; }
|
|
55
58
|
|
|
@@ -58,47 +61,53 @@
|
|
|
58
61
|
position: fixed; z-index: 71; left: 50%; bottom: 26px; transform: translateX(-50%) translateY(14px);
|
|
59
62
|
width: min(520px, calc(100vw - 32px)); background: var(--bg-elevated); border-radius: 18px;
|
|
60
63
|
box-shadow: var(--shadow-lg); opacity: 0; pointer-events: none;
|
|
61
|
-
transition: opacity
|
|
64
|
+
transition: opacity var(--dur-med) var(--ease), transform var(--dur-med) var(--ease); overflow: hidden;
|
|
62
65
|
}
|
|
63
66
|
.ui-fbcomposer.show { opacity: 1; pointer-events: auto; transform: translateX(-50%) translateY(0); }
|
|
64
67
|
|
|
65
68
|
.ui-fbc__head { display: flex; align-items: center; gap: 12px; padding: 17px 20px 0; }
|
|
66
69
|
.ui-fbc__chip { display: inline-flex; align-items: center; gap: 8px; color: var(--accent); font-size: 13px; font-weight: var(--weight-semibold); letter-spacing: .01em; white-space: nowrap; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
|
|
67
|
-
.ui-fbc__chip svg { width: 14px; height: 14px; flex: none; opacity: .85; }
|
|
70
|
+
.ui-fbc__chip svg { width: 14px; height: 14px; flex: none; opacity: .85; stroke-width: 2.7; }
|
|
68
71
|
.ui-fbc__x { margin-left: auto; background: var(--surface-2); color: var(--dim); border: 0; width: 28px; height: 28px; border-radius: 8px; cursor: pointer; display: grid; place-items: center; flex: none; }
|
|
69
72
|
.ui-fbc__x:hover { color: var(--strong); }
|
|
70
|
-
.ui-fbc__x svg { width: 14px; height: 14px; }
|
|
73
|
+
.ui-fbc__x svg { width: 14px; height: 14px; stroke-width: 2.7; }
|
|
71
74
|
.ui-fbc__quote { margin: 14px 20px 0; background: var(--surface-2); border-radius: 12px; padding: 12px 15px; display: flex; gap: 11px; }
|
|
72
75
|
.ui-fbc__qm { color: var(--accent); font-size: 22px; font-weight: var(--weight-bold); line-height: .9; flex: none; opacity: .55; }
|
|
73
76
|
.ui-fbc__quote q { quotes: none; color: var(--dim); font-style: italic; font-size: 13.5px; line-height: 1.55; }
|
|
74
77
|
.ui-fbc__body { padding: 14px 20px 0; }
|
|
75
78
|
.ui-fbcomposer textarea {
|
|
76
79
|
width: 100%; min-height: 96px; resize: vertical; font-family: var(--font-sans); font-size: 14.5px; line-height: 1.55;
|
|
77
|
-
color: var(--strong); background: var(--surface-2); border: 0; border-radius: 12px; padding: 13px 15px; transition: box-shadow
|
|
80
|
+
color: var(--strong); background: var(--surface-2); border: 0; border-radius: 12px; padding: 13px 15px; transition: box-shadow var(--dur-fast) var(--ease);
|
|
78
81
|
}
|
|
79
82
|
.ui-fbcomposer textarea::placeholder { color: var(--muted); }
|
|
80
83
|
.ui-fbcomposer textarea:focus { outline: none; box-shadow: 0 0 0 2px var(--accent); }
|
|
81
84
|
.ui-fbc__foot { display: flex; align-items: center; justify-content: flex-end; gap: 12px; padding: 16px 20px 18px; }
|
|
82
85
|
|
|
83
|
-
.ui-fbbtn { font-family: var(--font-sans); font-size: 13.5px; font-weight: var(--weight-semibold); border-radius: 10px; padding: 9px 17px; cursor: pointer; border: 0; transition: filter
|
|
86
|
+
.ui-fbbtn { font-family: var(--font-sans); font-size: 13.5px; font-weight: var(--weight-semibold); border-radius: 10px; padding: 9px 17px; cursor: pointer; border: 0; transition: filter var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease); }
|
|
84
87
|
.ui-fbbtn.ghost { background: transparent; color: var(--dim); }
|
|
85
88
|
.ui-fbbtn.ghost:hover { color: var(--strong); background: var(--surface-2); }
|
|
86
89
|
.ui-fbbtn.primary { background: var(--accent-strong); color: var(--accent-contrast); display: inline-flex; align-items: center; gap: 9px; }
|
|
87
90
|
.ui-fbbtn.primary:hover { filter: brightness(1.08); }
|
|
88
|
-
.ui-
|
|
91
|
+
/* Same flat pair as .ui-btn:disabled, for the same reason (#220). */
|
|
92
|
+
.ui-fbbtn.primary:disabled {
|
|
93
|
+
background: var(--disabled-surface);
|
|
94
|
+
color: var(--disabled-ink);
|
|
95
|
+
cursor: default;
|
|
96
|
+
filter: none;
|
|
97
|
+
}
|
|
89
98
|
.ui-fbc__send { display: inline-flex; align-items: center; justify-content: center; gap: 8px; }
|
|
90
|
-
.ui-fbspin { flex: none; width: 14px; height: 14px; box-sizing: border-box; border-radius: 50%; border: 2px solid color-mix(in srgb, currentColor 40%, transparent); border-top-color: currentColor; animation: uiFbSpin .7s linear infinite; }
|
|
99
|
+
.ui-fbspin { flex: none; width: 14px; height: 14px; box-sizing: border-box; border-radius: 50%; border: 2px solid color-mix(in srgb, currentColor 40%, transparent); border-top-color: currentColor; animation: uiFbSpin .7s linear infinite; } /* motion: ambient — a spinner turns until the request answers */
|
|
91
100
|
@keyframes uiFbSpin { to { transform: rotate(360deg); } }
|
|
92
101
|
|
|
93
102
|
/* Success state */
|
|
94
103
|
.ui-fbc__done { padding: 30px 26px 24px; text-align: center; background: radial-gradient(112% 60% at 50% 0%, var(--glow-green), transparent 62%); }
|
|
95
104
|
.ui-fbc__ck { width: 88px; height: 88px; margin: 0 auto 13px; display: grid; place-items: center; }
|
|
96
|
-
.ui-fbck { width: 88px; height: 88px; overflow: visible; display: block; transform-origin: center; animation: uiFbCkSpring 1s cubic-bezier(.22,1,.3,1) both; }
|
|
105
|
+
.ui-fbck { width: 88px; height: 88px; overflow: visible; display: block; transform-origin: center; animation: uiFbCkSpring 1s cubic-bezier(.22,1,.3,1) both; } /* motion: choreographed — the frame the mark and the comet are timed against */
|
|
97
106
|
.ui-fbck-t { fill: none; stroke: var(--surface-2); stroke-width: 9; stroke-linecap: round; stroke-linejoin: round; }
|
|
98
|
-
.ui-fbck-m { fill: none; stroke: var(--green); stroke-width: 9; stroke-linecap: round; stroke-linejoin: round; stroke-dasharray: 118; stroke-dashoffset: 118; animation: uiFbCkDraw .6s cubic-bezier(.5,0,.3,1) .1s forwards; }
|
|
99
|
-
.ui-fbck-s { fill: none; stroke: var(--sheen); stroke-width: 9; stroke-linecap: round; stroke-linejoin: round; stroke-dasharray: 15 400; stroke-dashoffset: 133; filter: drop-shadow(0 0 8px var(--green)) drop-shadow(0 0 15px var(--green)); opacity: 0; animation: uiFbCkComet .6s cubic-bezier(.5,0,.3,1) .1s forwards; }
|
|
107
|
+
.ui-fbck-m { fill: none; stroke: var(--green); stroke-width: 9; stroke-linecap: round; stroke-linejoin: round; stroke-dasharray: 118; stroke-dashoffset: 118; animation: uiFbCkDraw .6s cubic-bezier(.5,0,.3,1) .1s forwards; /* motion: choreographed — the mark draws while the spring is still settling */ }
|
|
108
|
+
.ui-fbck-s { fill: none; stroke: var(--sheen); stroke-width: 9; stroke-linecap: round; stroke-linejoin: round; stroke-dasharray: 15 400; stroke-dashoffset: 133; filter: drop-shadow(0 0 8px var(--green)) drop-shadow(0 0 15px var(--green)); opacity: 0; animation: uiFbCkComet .6s cubic-bezier(.5,0,.3,1) .1s forwards; /* motion: choreographed — the comet rides the mark, so it shares its duration and delay exactly */ }
|
|
100
109
|
.ui-fbc__done h4 { color: var(--strong); font-size: 19px; font-weight: var(--weight-semibold); letter-spacing: -.01em; margin-bottom: 7px; }
|
|
101
|
-
.ui-fbc__done p { color: var(--dim); font-size: 13.5px; line-height: 1.55; max-width:
|
|
110
|
+
.ui-fbc__done p { color: var(--dim); font-size: 13.5px; line-height: 1.55; max-width: var(--prose-caption); margin: 0 auto; }
|
|
102
111
|
.ui-fbc__done p b { color: var(--text); font-weight: var(--weight-semibold); }
|
|
103
112
|
.ui-fbc__done .row { margin-top: 18px; display: flex; gap: 10px; justify-content: center; }
|
|
104
113
|
@keyframes uiFbCkDraw { to { stroke-dashoffset: 0; } }
|
package/src/styles/footer.css
CHANGED
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
}
|
|
22
22
|
.ui-footer__in {
|
|
23
23
|
width: 100%;
|
|
24
|
-
max-width:
|
|
24
|
+
max-width: var(--container);
|
|
25
25
|
margin: 0 auto;
|
|
26
26
|
padding: 40px clamp(14px, 2.4vw, 26px) 30px;
|
|
27
27
|
}
|
|
@@ -34,6 +34,10 @@
|
|
|
34
34
|
flex-wrap: wrap;
|
|
35
35
|
padding-bottom: 30px;
|
|
36
36
|
}
|
|
37
|
+
/* Under --panel-sm, and deliberately: this is a flex TRACK in a wrapping
|
|
38
|
+
row, not a panel and not a paragraph — its width is what decides when the
|
|
39
|
+
footer breaks into columns, so it answers to the row rather than to a
|
|
40
|
+
scale. The one width below the floor the measure gate draws. See #208. */
|
|
37
41
|
.ui-footer__brand { max-width: 300px; }
|
|
38
42
|
.ui-footer .ui-footer__brand .brand { font-size: 15px; }
|
|
39
43
|
.ui-footer__tagline {
|
|
@@ -52,7 +56,10 @@
|
|
|
52
56
|
border: 1px solid var(--footer-border);
|
|
53
57
|
color: var(--footer-link);
|
|
54
58
|
background: var(--surface);
|
|
55
|
-
transition:
|
|
59
|
+
transition:
|
|
60
|
+
color var(--dur-fast) var(--ease),
|
|
61
|
+
border-color var(--dur-fast) var(--ease),
|
|
62
|
+
transform var(--dur-fast) var(--ease);
|
|
56
63
|
}
|
|
57
64
|
.ui-footer__social:hover { color: var(--accent); border-color: var(--accent); transform: translateY(-1px); }
|
|
58
65
|
.ui-footer__social svg { width: 17px; height: 17px; display: block; }
|
|
@@ -76,7 +83,7 @@
|
|
|
76
83
|
font-size: 13.5px;
|
|
77
84
|
color: var(--footer-link);
|
|
78
85
|
text-decoration: none;
|
|
79
|
-
transition: color
|
|
86
|
+
transition: color var(--dur-fast) var(--ease);
|
|
80
87
|
}
|
|
81
88
|
.ui-footer__links a:hover { color: var(--footer-link-hover); }
|
|
82
89
|
|
|
@@ -94,7 +101,7 @@
|
|
|
94
101
|
}
|
|
95
102
|
.ui-footer__legal { color: var(--footer-link); }
|
|
96
103
|
.ui-footer__legal-links { display: flex; gap: 22px; flex-wrap: wrap; }
|
|
97
|
-
.ui-footer__legal-links a { color: var(--footer-link); text-decoration: none; transition: color
|
|
104
|
+
.ui-footer__legal-links a { color: var(--footer-link); text-decoration: none; transition: color var(--dur-fast) var(--ease); }
|
|
98
105
|
.ui-footer__legal-links a:hover { color: var(--footer-link-hover); }
|
|
99
106
|
.ui-footer__switcher { display: inline-flex; align-items: center; gap: 12px; margin-left: auto; }
|
|
100
107
|
|
|
@@ -110,13 +117,15 @@
|
|
|
110
117
|
.ui-footer--app .ui-footer__in { max-width: none; padding: 12px clamp(14px, 2.4vw, 22px); }
|
|
111
118
|
.ui-footer--app .ui-footer__bar { padding-top: 0; border-top: 0; font-size: 12.5px; }
|
|
112
119
|
|
|
113
|
-
/* Responsive — columns collapse to a stacked layout on narrow screens.
|
|
120
|
+
/* Responsive — columns collapse to a stacked layout on narrow screens. Two of
|
|
121
|
+
the kit's three steps, and the second one is the phone step rather than a
|
|
122
|
+
fourth value of the footer's own: docs/specification.md#breakpoints. */
|
|
114
123
|
@media (max-width: 720px) {
|
|
115
124
|
.ui-footer__top { flex-direction: column; gap: 30px; }
|
|
116
125
|
.ui-footer__nav { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 26px 30px; }
|
|
117
126
|
.ui-footer__brand { max-width: none; }
|
|
118
127
|
}
|
|
119
|
-
@media (max-width:
|
|
128
|
+
@media (max-width: 560px) {
|
|
120
129
|
.ui-footer__nav { grid-template-columns: 1fr; }
|
|
121
130
|
.ui-footer__bar { flex-direction: column; align-items: flex-start; }
|
|
122
131
|
.ui-footer__switcher { margin-left: 0; }
|
package/src/styles/input.css
CHANGED
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
.ui-field__req { color: var(--pink); margin-left: 4px; }
|
|
16
16
|
.ui-field__hint { color: var(--muted); font-size: var(--text-sm); margin-top: 7px; line-height: 1.5; }
|
|
17
17
|
.ui-field__error { color: var(--pink); font-size: var(--text-sm); margin-top: 7px; display: flex; align-items: center; gap: 6px; }
|
|
18
|
+
.ui-field__error svg { width: 16px; height: 16px; flex: none; stroke-width: 2.4; }
|
|
18
19
|
|
|
19
20
|
.ui-input,
|
|
20
21
|
.ui-textarea,
|
|
@@ -46,8 +47,15 @@
|
|
|
46
47
|
.ui-input::placeholder,
|
|
47
48
|
.ui-textarea::placeholder { color: var(--muted); opacity: 0.9; }
|
|
48
49
|
|
|
50
|
+
/* The value a reader typed is still the value; it goes quiet, it does not fade
|
|
51
|
+
into the field under it the way an opacity would take both down together. #220 */
|
|
49
52
|
.ui-input:disabled,
|
|
50
|
-
.ui-textarea:disabled {
|
|
53
|
+
.ui-textarea:disabled {
|
|
54
|
+
background: var(--disabled-surface);
|
|
55
|
+
border-color: var(--disabled-border);
|
|
56
|
+
color: var(--disabled-ink);
|
|
57
|
+
cursor: not-allowed;
|
|
58
|
+
}
|
|
51
59
|
|
|
52
60
|
.ui-input.is-invalid,
|
|
53
61
|
.ui-textarea.is-invalid { border-color: var(--pink); }
|
|
@@ -64,7 +72,7 @@
|
|
|
64
72
|
color: var(--muted);
|
|
65
73
|
pointer-events: none;
|
|
66
74
|
}
|
|
67
|
-
.ui-input-group__icon svg { width: 100%; height: 100%; stroke: currentColor; fill: none; stroke-width:
|
|
75
|
+
.ui-input-group__icon svg { width: 100%; height: 100%; stroke: currentColor; fill: none; stroke-width: 2.2; }
|
|
68
76
|
|
|
69
77
|
.ui-select {
|
|
70
78
|
appearance: none;
|
|
@@ -98,6 +106,24 @@
|
|
|
98
106
|
transition: border-color var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease);
|
|
99
107
|
position: relative;
|
|
100
108
|
}
|
|
109
|
+
/* The target, not the ink. The box above is drawn at 19x19 because that is what
|
|
110
|
+
sits beside a 15px label without shouting; WCAG 2.5.8 wants 24 CSS px of
|
|
111
|
+
pointer target, which is a different question. This overlay answers it and
|
|
112
|
+
the checkbox keeps its size. ::after is the tick and the dot, so the target
|
|
113
|
+
is ::before — it paints first, under both, and is transparent anyway.
|
|
114
|
+
Centred, so the overhang is 2.5px on every side: 11px of gap to the label
|
|
115
|
+
inside the same <label> (which toggles the same input, so an overlap there
|
|
116
|
+
would cost nothing) and 14px between stacked rows in the specimen. Measured
|
|
117
|
+
in stories/guidelines/accessibility-floor.test.js. #219 */
|
|
118
|
+
.ui-check input::before {
|
|
119
|
+
content: '';
|
|
120
|
+
position: absolute;
|
|
121
|
+
left: 50%;
|
|
122
|
+
top: 50%;
|
|
123
|
+
width: 24px;
|
|
124
|
+
height: 24px;
|
|
125
|
+
transform: translate(-50%, -50%);
|
|
126
|
+
}
|
|
101
127
|
.ui-check input[type="radio"] { border-radius: 50%; }
|
|
102
128
|
.ui-check input:hover { border-color: var(--accent); }
|
|
103
129
|
.ui-check input:checked { background: var(--accent); border-color: var(--accent); }
|
package/src/styles/layout.css
CHANGED
|
@@ -114,12 +114,14 @@
|
|
|
114
114
|
The width is what keeps the auto margins honest: an auto inline margin takes
|
|
115
115
|
a grid item out of stretch, and Chrome then lays it out at its max-content
|
|
116
116
|
width, which is how the payout ledger pushed the page 529px sideways at 375.
|
|
117
|
-
|
|
118
|
-
|
|
117
|
+
--measure is the ONE source for this width now. shell.js used to carry its
|
|
118
|
+
own copy of the number and a test held the two in step; it now omits the
|
|
119
|
+
property rather than writing a default, so an absent or unparseable maxWidth
|
|
120
|
+
lands here, on the token, instead of on a second literal. See issue #198. */
|
|
119
121
|
.ui-app__main {
|
|
120
122
|
min-width: 0;
|
|
121
123
|
width: 100%;
|
|
122
|
-
max-width: var(--ui-app-main,
|
|
124
|
+
max-width: var(--ui-app-main, var(--measure));
|
|
123
125
|
margin-inline: auto;
|
|
124
126
|
padding: 40px clamp(24px, 4vw, 56px) 72px;
|
|
125
127
|
}
|
|
@@ -134,7 +136,7 @@
|
|
|
134
136
|
letter-spacing: var(--tracking-tight);
|
|
135
137
|
margin-bottom: 8px;
|
|
136
138
|
}
|
|
137
|
-
.ui-app__sub { color: var(--dim); font-size: 15px; line-height: 1.6; max-width:
|
|
139
|
+
.ui-app__sub { color: var(--dim); font-size: 15px; line-height: 1.6; max-width: var(--prose-body); margin-bottom: 32px; }
|
|
138
140
|
.ui-app__body { display: flex; flex-direction: column; gap: var(--space-5); }
|
|
139
141
|
/* A flex child's min-width is its content by default, so one wide block — a
|
|
140
142
|
ledger, a code sample — pushes the whole page sideways instead of scrolling
|
|
@@ -219,7 +221,7 @@
|
|
|
219
221
|
position: relative;
|
|
220
222
|
z-index: 1;
|
|
221
223
|
width: 100%;
|
|
222
|
-
max-width:
|
|
224
|
+
max-width: var(--panel-md);
|
|
223
225
|
background: var(--surface);
|
|
224
226
|
border-radius: 22px;
|
|
225
227
|
padding: 38px 36px 32px;
|
|
@@ -245,7 +247,7 @@
|
|
|
245
247
|
background: var(--glow-purple);
|
|
246
248
|
color: var(--accent);
|
|
247
249
|
}
|
|
248
|
-
.ui-scope__icon svg { width: 21px; height: 21px; stroke: currentColor; fill: none; stroke-width: 1.
|
|
250
|
+
.ui-scope__icon svg { width: 21px; height: 21px; stroke: currentColor; fill: none; stroke-width: 1.8; }
|
|
249
251
|
.ui-scope__t { color: var(--strong); font-size: 14px; font-weight: 500; }
|
|
250
252
|
.ui-scope__d { color: var(--dim); font-size: 13px; margin-top: 2px; line-height: 1.5; }
|
|
251
253
|
|
|
@@ -275,7 +277,7 @@
|
|
|
275
277
|
letter-spacing: -0.025em;
|
|
276
278
|
font-weight: 700;
|
|
277
279
|
color: var(--strong);
|
|
278
|
-
max-width:
|
|
280
|
+
max-width: var(--prose-display);
|
|
279
281
|
margin: 0 auto 22px;
|
|
280
282
|
}
|
|
281
283
|
.ui-hero__title .grad {
|
|
@@ -287,7 +289,7 @@
|
|
|
287
289
|
.ui-hero__sub {
|
|
288
290
|
font-size: clamp(16px, 2.1vw, 20px);
|
|
289
291
|
color: var(--dim);
|
|
290
|
-
max-width:
|
|
292
|
+
max-width: var(--prose-lede);
|
|
291
293
|
margin: 0 auto 34px;
|
|
292
294
|
line-height: 1.6;
|
|
293
295
|
}
|
|
@@ -298,7 +300,9 @@
|
|
|
298
300
|
display: grid;
|
|
299
301
|
grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
|
|
300
302
|
gap: 20px;
|
|
301
|
-
|
|
303
|
+
/* Was 1080px — a third page-scale number with nothing arguing for it. The
|
|
304
|
+
feature row is a top-level band and lines up with the page it sits on. */
|
|
305
|
+
max-width: var(--container);
|
|
302
306
|
margin: 0 auto;
|
|
303
307
|
padding: 0 26px;
|
|
304
308
|
}
|
|
@@ -314,6 +318,6 @@
|
|
|
314
318
|
.ui-feature h3 { color: var(--strong); font-size: 17px; font-weight: 600; margin-bottom: 7px; }
|
|
315
319
|
.ui-feature p { color: var(--dim); font-size: 14.5px; line-height: 1.6; }
|
|
316
320
|
|
|
317
|
-
.ui-section-head { text-align: center; max-width:
|
|
321
|
+
.ui-section-head { text-align: center; max-width: var(--panel-lg); margin: 0 auto clamp(40px, 6vh, 64px); }
|
|
318
322
|
.ui-section-head h2 { color: var(--strong); font-size: clamp(28px, 4vw, 40px); font-weight: 700; letter-spacing: -0.02em; margin-bottom: 14px; }
|
|
319
323
|
.ui-section-head p { color: var(--dim); font-size: 17px; line-height: 1.6; }
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/* Loading and permission-denied — the screen-scale states. Markup comes from
|
|
2
|
+
* components/loading.js; this file owns layout and nothing else.
|
|
3
|
+
*
|
|
4
|
+
* The shimmer is .m-skeleton from styles/motion.css, so reduced motion is
|
|
5
|
+
* already handled by the global net and there is one shimmer in the kit.
|
|
6
|
+
*
|
|
7
|
+
* .ui-denied deliberately borrows every colour .ui-empty uses: to a reader the
|
|
8
|
+
* two are the same event — what you came for is not here — and giving denial its
|
|
9
|
+
* own red made it read as a fault the reader had committed. The lock says which
|
|
10
|
+
* of the two it is.
|
|
11
|
+
*
|
|
12
|
+
* why: docs/specification.md#pending-and-denied-states */
|
|
13
|
+
|
|
14
|
+
/* Visually hidden, still read aloud. The kit had no such utility, and the live
|
|
15
|
+
region needs one: its message is for assistive tech only — the sighted
|
|
16
|
+
reader is already looking at the skeleton. */
|
|
17
|
+
.ui-sr {
|
|
18
|
+
position: absolute;
|
|
19
|
+
width: 1px;
|
|
20
|
+
height: 1px;
|
|
21
|
+
margin: -1px;
|
|
22
|
+
padding: 0;
|
|
23
|
+
overflow: hidden;
|
|
24
|
+
clip: rect(0 0 0 0);
|
|
25
|
+
clip-path: inset(50%);
|
|
26
|
+
white-space: nowrap;
|
|
27
|
+
border: 0;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/* -- The live region ------------------------------------------------------- */
|
|
31
|
+
.ui-busy {
|
|
32
|
+
display: block;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/* -- Skeleton -------------------------------------------------------------- */
|
|
36
|
+
.ui-skel {
|
|
37
|
+
display: flex;
|
|
38
|
+
flex-direction: column;
|
|
39
|
+
gap: 12px;
|
|
40
|
+
}
|
|
41
|
+
.ui-skel__bar {
|
|
42
|
+
display: block;
|
|
43
|
+
height: 13px;
|
|
44
|
+
width: 100%;
|
|
45
|
+
border-radius: var(--radius-xs);
|
|
46
|
+
}
|
|
47
|
+
/* Last line of a paragraph run stops short, the way real prose does — a block
|
|
48
|
+
of four identical full-width bars reads as a table, not as text. Any explicit
|
|
49
|
+
width from skeleton({ lines: [...] }) is inline and still wins. */
|
|
50
|
+
.ui-skel > .ui-skel__bar:last-child:not(:only-child) {
|
|
51
|
+
width: 62%;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/* Table shape: the column rhythm the real table will have, so the placeholder
|
|
55
|
+
does not resize the page out from under the reader when the rows land. */
|
|
56
|
+
.ui-skel--table {
|
|
57
|
+
gap: 0;
|
|
58
|
+
}
|
|
59
|
+
.ui-skel--table .ui-skel__row {
|
|
60
|
+
display: grid;
|
|
61
|
+
grid-template-columns: 1.6fr repeat(calc(var(--skel-cols) - 1), 1fr);
|
|
62
|
+
gap: 18px;
|
|
63
|
+
align-items: center;
|
|
64
|
+
padding: 14px 0;
|
|
65
|
+
border-bottom: 1px solid var(--border);
|
|
66
|
+
}
|
|
67
|
+
.ui-skel--table .ui-skel__row:last-child {
|
|
68
|
+
border-bottom: 0;
|
|
69
|
+
}
|
|
70
|
+
.ui-skel--table .ui-skel__bar {
|
|
71
|
+
height: 11px;
|
|
72
|
+
}
|
|
73
|
+
.ui-skel--table .ui-skel__row--head .ui-skel__bar {
|
|
74
|
+
height: 9px;
|
|
75
|
+
width: 58%;
|
|
76
|
+
opacity: 0.7;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/* -- Permission denied ----------------------------------------------------- */
|
|
80
|
+
.ui-denied {
|
|
81
|
+
display: flex;
|
|
82
|
+
flex-direction: column;
|
|
83
|
+
align-items: center;
|
|
84
|
+
text-align: center;
|
|
85
|
+
gap: 8px;
|
|
86
|
+
padding: 48px 24px;
|
|
87
|
+
color: var(--muted);
|
|
88
|
+
}
|
|
89
|
+
.ui-denied__seal {
|
|
90
|
+
width: 44px;
|
|
91
|
+
height: 44px;
|
|
92
|
+
margin-bottom: 6px;
|
|
93
|
+
border-radius: 50%;
|
|
94
|
+
display: grid;
|
|
95
|
+
place-items: center;
|
|
96
|
+
color: var(--dim);
|
|
97
|
+
background: color-mix(in srgb, var(--text) 7%, transparent);
|
|
98
|
+
}
|
|
99
|
+
.ui-denied__seal svg {
|
|
100
|
+
width: 20px;
|
|
101
|
+
height: 20px;
|
|
102
|
+
stroke: currentColor;
|
|
103
|
+
fill: none;
|
|
104
|
+
stroke-width: 1.9;
|
|
105
|
+
}
|
|
106
|
+
.ui-denied__title {
|
|
107
|
+
color: var(--text);
|
|
108
|
+
font-size: var(--text-md);
|
|
109
|
+
font-weight: var(--weight-medium);
|
|
110
|
+
margin: 2px 0 0;
|
|
111
|
+
}
|
|
112
|
+
.ui-denied__sub {
|
|
113
|
+
font-size: var(--text-sm);
|
|
114
|
+
max-width: var(--prose-caption);
|
|
115
|
+
margin: 0;
|
|
116
|
+
line-height: 1.55;
|
|
117
|
+
}
|
|
118
|
+
/* The missing scope, verbatim. A reader who can name what they lack can ask
|
|
119
|
+
for it; "insufficient permissions" sends them to a ticket to find out. */
|
|
120
|
+
.ui-denied__need {
|
|
121
|
+
font-size: var(--text-sm);
|
|
122
|
+
margin-top: 4px;
|
|
123
|
+
}
|
|
124
|
+
.ui-denied__actions {
|
|
125
|
+
display: flex;
|
|
126
|
+
gap: 10px;
|
|
127
|
+
justify-content: center;
|
|
128
|
+
margin-top: 12px;
|
|
129
|
+
}
|