@apliteni/apliteni-ui 0.126.0 → 0.128.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/guidelines/spacing.md +51 -0
- package/package.json +1 -1
- package/react/dist/index.css +9 -0
- package/react/dist/index.js +4 -0
- package/src/styles/input.css +64 -9
- package/src/styles/table.css +3 -0
- package/src/styles/tap-zone.css +7 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Spacing
|
|
2
|
+
|
|
3
|
+
## Use two gaps
|
|
4
|
+
|
|
5
|
+
<!-- rule: two-gaps -->
|
|
6
|
+
|
|
7
|
+
**Rule:** Use the inner gap between parts of one group and the group gap between groups.
|
|
8
|
+
|
|
9
|
+
**Why:** Two distances show what belongs together, and a reader never has to compare a third.
|
|
10
|
+
|
|
11
|
+
**Do:** Treat a control row and the table it filters as one group.
|
|
12
|
+
|
|
13
|
+
**Don't:** Add a third distance between sections.
|
|
14
|
+
|
|
15
|
+
## Widen inner gaps on a touch phone
|
|
16
|
+
|
|
17
|
+
<!-- rule: two-gaps-phone -->
|
|
18
|
+
|
|
19
|
+
**Rule:** On a touch phone, match inner gaps to the chip rows' gap.
|
|
20
|
+
|
|
21
|
+
**Why:** Chip rows open for a finger, so a smaller gap joins the table to the last row.
|
|
22
|
+
|
|
23
|
+
**Do:** Move the table down with the chips.
|
|
24
|
+
|
|
25
|
+
**Don't:** Keep the table's desktop gap.
|
|
26
|
+
|
|
27
|
+
**Except:** The view strip stays tight, because its tabs meet the floor.
|
|
28
|
+
|
|
29
|
+
## Keep a title on its block
|
|
30
|
+
|
|
31
|
+
<!-- rule: title -->
|
|
32
|
+
|
|
33
|
+
**Rule:** Keep a page or card title one inner gap above what it names, at every width.
|
|
34
|
+
|
|
35
|
+
**Why:** With space on both sides, a title can belong to either block.
|
|
36
|
+
|
|
37
|
+
**Do:** Hold a card's title to its first line.
|
|
38
|
+
|
|
39
|
+
**Don't:** Float a title halfway between two groups.
|
|
40
|
+
|
|
41
|
+
## Put text on the column edge
|
|
42
|
+
|
|
43
|
+
<!-- rule: text-edge -->
|
|
44
|
+
|
|
45
|
+
**Rule:** A control that draws no box starts its first label on the page title's edge.
|
|
46
|
+
|
|
47
|
+
**Why:** With nothing drawn around it, an indented label reads as a misaligned line.
|
|
48
|
+
|
|
49
|
+
**Do:** Let the view strip's highlight and ring hang into the margin.
|
|
50
|
+
|
|
51
|
+
**Don't:** Move a filter chip or a table off the column edge.
|
package/package.json
CHANGED
package/react/dist/index.css
CHANGED
|
@@ -49,6 +49,7 @@
|
|
|
49
49
|
height: min(max(100%, var(--tap-min)), calc(100% + var(--tap-clear-y)));
|
|
50
50
|
}
|
|
51
51
|
.ui-check input::before,
|
|
52
|
+
.ui-table__selection input[type=checkbox]::before,
|
|
52
53
|
.ui-toast__close::before {
|
|
53
54
|
width: max(var(--tap-aa), min(max(100%, var(--tap-min)), calc(100% + var(--tap-clear-x))));
|
|
54
55
|
height: max(var(--tap-aa), min(max(100%, var(--tap-min)), calc(100% + var(--tap-clear-y))));
|
|
@@ -102,6 +103,14 @@
|
|
|
102
103
|
--tap-clear-x: var(--tap-gap);
|
|
103
104
|
--tap-clear-y: 0px;
|
|
104
105
|
}
|
|
106
|
+
.ui-table__selection {
|
|
107
|
+
--tap-clear-x: var(--tap-min);
|
|
108
|
+
--tap-clear-y: var(--tap-min);
|
|
109
|
+
}
|
|
110
|
+
.ui-table--dense .ui-table__selection,
|
|
111
|
+
.ui-table--compact .ui-table__selection {
|
|
112
|
+
--tap-clear-y: 0px;
|
|
113
|
+
}
|
|
105
114
|
.ui-toast {
|
|
106
115
|
row-gap: var(--tap-gap) !important;
|
|
107
116
|
--tap-clear-y: var(--tap-gap);
|
package/react/dist/index.js
CHANGED
|
@@ -1420,6 +1420,7 @@ function DataTable({
|
|
|
1420
1420
|
}
|
|
1421
1421
|
);
|
|
1422
1422
|
const pageAllOn = selectable && slice.length > 0 && slice.every((r) => selected.has(r.name));
|
|
1423
|
+
const pageSomeOn = selectable && !pageAllOn && slice.some((r) => selected.has(r.name));
|
|
1423
1424
|
return /* @__PURE__ */ jsxs13(Fragment4, { children: [
|
|
1424
1425
|
/* @__PURE__ */ jsx17(
|
|
1425
1426
|
"div",
|
|
@@ -1442,6 +1443,9 @@ function DataTable({
|
|
|
1442
1443
|
type: "checkbox",
|
|
1443
1444
|
checked: pageAllOn,
|
|
1444
1445
|
"aria-label": "Select all rows on this page",
|
|
1446
|
+
ref: (input) => {
|
|
1447
|
+
if (input) input.indeterminate = pageSomeOn;
|
|
1448
|
+
},
|
|
1445
1449
|
onChange: () => onTogglePage(slice.map((r) => r.name))
|
|
1446
1450
|
}
|
|
1447
1451
|
) }) : null,
|
package/src/styles/input.css
CHANGED
|
@@ -123,7 +123,9 @@
|
|
|
123
123
|
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%235c6270' stroke-width='2.4' stroke-linecap='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E");
|
|
124
124
|
}
|
|
125
125
|
|
|
126
|
-
/* Checkbox / radio — custom, token-driven
|
|
126
|
+
/* Checkbox / radio — custom, token-driven. DataTable's selection boxes are bare
|
|
127
|
+
inputs in a cell with no label, and take the same box so a partial page reads in
|
|
128
|
+
the kit's paint rather than the browser's. #619 */
|
|
127
129
|
.ui-check {
|
|
128
130
|
display: inline-flex;
|
|
129
131
|
align-items: flex-start;
|
|
@@ -133,7 +135,8 @@
|
|
|
133
135
|
color: var(--text);
|
|
134
136
|
line-height: 1.5;
|
|
135
137
|
}
|
|
136
|
-
.ui-check input
|
|
138
|
+
.ui-check input,
|
|
139
|
+
.ui-table__selection input[type="checkbox"] {
|
|
137
140
|
appearance: none;
|
|
138
141
|
width: 19px;
|
|
139
142
|
height: 19px;
|
|
@@ -146,6 +149,9 @@
|
|
|
146
149
|
transition: border-color var(--dur-fast) var(--ease), background var(--dur-fast) var(--ease);
|
|
147
150
|
position: relative;
|
|
148
151
|
}
|
|
152
|
+
/* In a cell there is no label line to sit beside, so the box centres on the row's
|
|
153
|
+
text instead of dropping 1px to meet a label's first line. */
|
|
154
|
+
.ui-table__selection input[type="checkbox"] { margin-top: 0; vertical-align: middle; }
|
|
149
155
|
/* The target, not the ink. The box above is drawn at 19x19 because that is what
|
|
150
156
|
sits beside a 15px label without shouting; WCAG 2.5.8 wants 24 CSS px of
|
|
151
157
|
pointer target, which is a different question. This overlay answers it and
|
|
@@ -155,7 +161,8 @@
|
|
|
155
161
|
inside the same <label> (which toggles the same input, so an overlap there
|
|
156
162
|
would cost nothing) and 14px between stacked rows in the specimen. Measured
|
|
157
163
|
in stories/guidelines/accessibility-floor.test.js. #219 */
|
|
158
|
-
.ui-check input::before
|
|
164
|
+
.ui-check input::before,
|
|
165
|
+
.ui-table__selection input[type="checkbox"]::before {
|
|
159
166
|
content: '';
|
|
160
167
|
position: absolute;
|
|
161
168
|
left: 50%;
|
|
@@ -171,9 +178,12 @@
|
|
|
171
178
|
accent band is the second band #578 round r34 took off the focus rules, and a
|
|
172
179
|
pointer resting on a focused control would put it back. One indicator, which is
|
|
173
180
|
what the kit's rows already chose. why: docs/foundations.md#the-focus-ring */
|
|
174
|
-
.ui-check input:enabled:hover:not(:focus-visible)
|
|
175
|
-
.ui-
|
|
176
|
-
.ui-check input
|
|
181
|
+
.ui-check input:enabled:hover:not(:focus-visible),
|
|
182
|
+
.ui-table__selection input[type="checkbox"]:enabled:hover:not(:focus-visible) { border-color: var(--accent); }
|
|
183
|
+
.ui-check input:checked,
|
|
184
|
+
.ui-table__selection input[type="checkbox"]:checked { background: var(--accent); border-color: var(--accent); }
|
|
185
|
+
.ui-check input[type="checkbox"]:checked::after,
|
|
186
|
+
.ui-table__selection input[type="checkbox"]:checked::after {
|
|
177
187
|
content: "";
|
|
178
188
|
position: absolute;
|
|
179
189
|
left: 5px; top: 1.5px;
|
|
@@ -199,14 +209,59 @@
|
|
|
199
209
|
ground together. A checked box drops the accent for the reason a disabled primary
|
|
200
210
|
button does: the accent IS the "press me". Its mark inverts to --disabled-surface,
|
|
201
211
|
so the tick and the dot keep the measured --disabled-ink pair in both themes. */
|
|
202
|
-
.ui-check input:disabled
|
|
212
|
+
.ui-check input:disabled,
|
|
213
|
+
.ui-table__selection input[type="checkbox"]:disabled {
|
|
203
214
|
background: var(--disabled-surface); /* code-bg: inherit — control paint; the containing surface is the ground, for a chip and for a band alike. */
|
|
204
215
|
border-color: var(--disabled-border);
|
|
205
216
|
cursor: not-allowed;
|
|
206
217
|
}
|
|
207
|
-
.ui-check input:disabled:checked
|
|
208
|
-
.ui-
|
|
218
|
+
.ui-check input:disabled:checked,
|
|
219
|
+
.ui-table__selection input[type="checkbox"]:disabled:checked { background: var(--disabled-ink); border-color: var(--disabled-ink); }
|
|
220
|
+
.ui-check input[type="checkbox"]:disabled:checked::after,
|
|
221
|
+
.ui-table__selection input[type="checkbox"]:disabled:checked::after { border-color: var(--disabled-surface); }
|
|
209
222
|
.ui-check input[type="radio"]:disabled:checked::after { background: var(--disabled-surface); /* code-bg: inherit — the mark inside the box; the box carries the focus indicator. */ }
|
|
223
|
+
/* Partial: some of a group is on, not all. The checked box's fill with a level
|
|
224
|
+
dash where the tick would be, so the box still reads as "on" from across a table
|
|
225
|
+
and the dash alone says "not all". It wins over a tick when both are set, as the
|
|
226
|
+
browser's own box does. Drawn with a border, not a background, so forced colours
|
|
227
|
+
keeps the dash. #619 */
|
|
228
|
+
.ui-check input[type="checkbox"]:indeterminate,
|
|
229
|
+
.ui-table__selection input[type="checkbox"]:indeterminate { background: var(--accent); border-color: var(--accent); }
|
|
230
|
+
.ui-check input[type="checkbox"]:indeterminate::after,
|
|
231
|
+
.ui-table__selection input[type="checkbox"]:indeterminate::after {
|
|
232
|
+
content: "";
|
|
233
|
+
position: absolute;
|
|
234
|
+
inset: 0;
|
|
235
|
+
margin: auto;
|
|
236
|
+
width: 11px; height: 0; /* odd, so the 17px padding box splits into equal gaps */
|
|
237
|
+
border: solid var(--accent-contrast);
|
|
238
|
+
border-width: 2px 0 0;
|
|
239
|
+
transform: none;
|
|
240
|
+
}
|
|
241
|
+
/* White ink falls below 3:1 on the lighter dark-theme accents, so the tick, the dash and
|
|
242
|
+
the radio's dot take the ink a selected Segmented pill takes there. */
|
|
243
|
+
:where(:root[data-theme="dark"]) .ui-check input[type="checkbox"]:enabled:is(:checked, :indeterminate)::after,
|
|
244
|
+
:where(:root[data-theme="dark"]) .ui-table__selection input[type="checkbox"]:enabled:is(:checked, :indeterminate)::after { border-color: var(--signal-contrast); }
|
|
245
|
+
:where(:root[data-theme="dark"]) .ui-check input[type="radio"]:enabled:checked::after { background: var(--signal-contrast); }
|
|
246
|
+
.ui-check input[type="checkbox"]:disabled:indeterminate,
|
|
247
|
+
.ui-table__selection input[type="checkbox"]:disabled:indeterminate { background: var(--disabled-ink); border-color: var(--disabled-ink); }
|
|
248
|
+
.ui-check input[type="checkbox"]:disabled:indeterminate::after,
|
|
249
|
+
.ui-table__selection input[type="checkbox"]:disabled:indeterminate::after { border-color: var(--disabled-surface); }
|
|
250
|
+
/* Forced colours replace every fill, so a disabled box that painted only a fill and
|
|
251
|
+
a --disabled-* edge drew the same edge and mark as an enabled one, and a radio's dot
|
|
252
|
+
vanished. GrayText is the system colour for an unavailable control. The tick and the
|
|
253
|
+
dash are borders, so they keep it; the dot is a fill, so it names a system colour. */
|
|
254
|
+
@media (forced-colors: active) {
|
|
255
|
+
.ui-check input:disabled,
|
|
256
|
+
.ui-check input:disabled:is(:checked, :indeterminate),
|
|
257
|
+
.ui-check input[type="checkbox"]:disabled:is(:checked, :indeterminate),
|
|
258
|
+
.ui-table__selection input[type="checkbox"]:disabled,
|
|
259
|
+
.ui-table__selection input[type="checkbox"]:disabled:is(:checked, :indeterminate) { border-color: GrayText; }
|
|
260
|
+
.ui-check input[type="checkbox"]:disabled:is(:checked, :indeterminate)::after,
|
|
261
|
+
.ui-table__selection input[type="checkbox"]:disabled:is(:checked, :indeterminate)::after { border-color: GrayText; }
|
|
262
|
+
.ui-check input[type="radio"]:enabled:checked::after { background: CanvasText; }
|
|
263
|
+
.ui-check input[type="radio"]:disabled:checked::after { background: GrayText; }
|
|
264
|
+
}
|
|
210
265
|
/* The label is the click target, so the cursor belongs on it, and the words it
|
|
211
266
|
holds go quiet with the box beside them. */
|
|
212
267
|
.ui-check:has(input:disabled) { /* muted-ink: state — unavailable control */ color: var(--disabled-ink); cursor: not-allowed; }
|
package/src/styles/table.css
CHANGED
|
@@ -467,6 +467,9 @@ a.ui-identity:hover { text-decoration: underline; }
|
|
|
467
467
|
.ui-table--pinned .ui-identity__name { min-width: 0; max-width: 100%; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
468
468
|
}
|
|
469
469
|
|
|
470
|
+
/* Automatic layout hands every column a share of the free width, and a box is not worth one: the selection column takes the width of its box and the gap after it. The pinned table below fixes it instead. */
|
|
471
|
+
.ui-table .ui-table__selection { width: 1%; }
|
|
472
|
+
|
|
470
473
|
/* One width reserves the selection track and offsets the adjacent identity. */
|
|
471
474
|
.ui-table--pinned { --ui-table-selection-width: var(--space-12); --ui-table-identity-max: min(var(--panel-sm), 50vw); }
|
|
472
475
|
.ui-table--pinned .ui-table__selection { box-sizing: border-box; width: var(--ui-table-selection-width); min-width: var(--ui-table-selection-width); max-width: var(--ui-table-selection-width); padding-inline: 0; text-align: center; }
|
package/src/styles/tap-zone.css
CHANGED
|
@@ -96,6 +96,7 @@
|
|
|
96
96
|
with a 1.5px border, so without it the clamp takes this layer DOWN to 22
|
|
97
97
|
and under the kit's own minimum. */
|
|
98
98
|
.ui-check input::before,
|
|
99
|
+
.ui-table__selection input[type="checkbox"]::before,
|
|
99
100
|
.ui-toast__close::before {
|
|
100
101
|
width: max(var(--tap-aa), min(max(100%, var(--tap-min)), calc(100% + var(--tap-clear-x))));
|
|
101
102
|
height: max(var(--tap-aa), min(max(100%, var(--tap-min)), calc(100% + var(--tap-clear-y))));
|
|
@@ -168,6 +169,12 @@
|
|
|
168
169
|
}
|
|
169
170
|
.ui-table__act { --tap-clear-x: var(--tap-gap); --tap-clear-y: 0px; }
|
|
170
171
|
|
|
172
|
+
/* The selection box is 19px in a 58px row and a 34px header: the layer has room to reach the floor both ways. */
|
|
173
|
+
.ui-table__selection { --tap-clear-x: var(--tap-min); --tap-clear-y: var(--tap-min); }
|
|
174
|
+
/* A dense or compact table's rows are 33px to 40px apart and share an edge, so a layer that grows down takes the pixels nearest the next row's box. Those rows keep the 24px floor. */
|
|
175
|
+
.ui-table--dense .ui-table__selection,
|
|
176
|
+
.ui-table--compact .ui-table__selection { --tap-clear-y: 0px; }
|
|
177
|
+
|
|
171
178
|
/* Down only, like the nine rows below: a toast is a full row at this width,
|
|
172
179
|
and opening it across took 24px out of the message for no reach at all —
|
|
173
180
|
its action already clears the floor on the vertical half. The box does not
|