@axiapps/axi-design 1.20.0 → 1.21.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/dist/axi.css +95 -3
- package/docs/RULES.md +12 -0
- package/package.json +1 -1
- package/src/data.css +95 -3
package/dist/axi.css
CHANGED
|
@@ -1842,7 +1842,11 @@ textarea.axi-input {
|
|
|
1842
1842
|
.axi-table td { text-align: right; white-space: nowrap; }
|
|
1843
1843
|
.axi-table th:first-child,
|
|
1844
1844
|
.axi-table td:first-child { text-align: left; }
|
|
1845
|
-
|
|
1845
|
+
/* `thead th`, not `th`. A row's name is a `<th scope="row">` - that is what
|
|
1846
|
+
tells a screen reader which cell labels the row - and it is a name, not a
|
|
1847
|
+
column heading: uppercase micro type down the first column would shout every
|
|
1848
|
+
row's label at the reader. A row header takes the cell treatment below. */
|
|
1849
|
+
.axi-table thead th {
|
|
1846
1850
|
padding: 0 10px 10px;
|
|
1847
1851
|
font: var(--axi-t-micro);
|
|
1848
1852
|
letter-spacing: var(--axi-ls-micro);
|
|
@@ -1850,7 +1854,8 @@ textarea.axi-input {
|
|
|
1850
1854
|
color: var(--axi-text-faint);
|
|
1851
1855
|
border-bottom: var(--axi-border-control) solid var(--axi-rule);
|
|
1852
1856
|
}
|
|
1853
|
-
.axi-table td
|
|
1857
|
+
.axi-table td,
|
|
1858
|
+
.axi-table tbody th {
|
|
1854
1859
|
padding: 9px 10px;
|
|
1855
1860
|
font: var(--axi-t-small);
|
|
1856
1861
|
font-weight: 700;
|
|
@@ -1861,7 +1866,7 @@ textarea.axi-input {
|
|
|
1861
1866
|
hovering a row is not a status, and forty rows that each flash a colour on
|
|
1862
1867
|
the way past the one you want is the tinted-everything failure rule 2 is
|
|
1863
1868
|
about. */
|
|
1864
|
-
.axi-table tbody tr:hover td { background: var(--axi-surface-raised); color: var(--axi-text); }
|
|
1869
|
+
.axi-table tbody tr:hover :is(td, th) { background: var(--axi-surface-raised); color: var(--axi-text); }
|
|
1865
1870
|
/* The measured value in a row, as opposed to its supporting numbers. */
|
|
1866
1871
|
.axi-table__num { color: var(--axi-text); }
|
|
1867
1872
|
/* A name cell: an icon, a diamond or a rank beside the label. */
|
|
@@ -1879,6 +1884,93 @@ textarea.axi-input {
|
|
|
1879
1884
|
}
|
|
1880
1885
|
.axi-table__rank--top { background: var(--axi-accent); color: var(--axi-accent-ink); }
|
|
1881
1886
|
|
|
1887
|
+
/* A table too wide and too tall for the panel holding it: twenty numeric
|
|
1888
|
+
columns against forty players, scrolled in both directions. Rule 8 still
|
|
1889
|
+
decides what every line means - the head is a lid at the control step, the
|
|
1890
|
+
rows are hairlines - and the only new thing here is that the lid and the
|
|
1891
|
+
row's name have to stay put while the numbers move under them.
|
|
1892
|
+
|
|
1893
|
+
`border-collapse: separate` is load-bearing, not housekeeping. A collapsed
|
|
1894
|
+
table hoists its cell borders onto the table itself, and a border owned by
|
|
1895
|
+
the table scrolls away with it, so a sticky head drawn under `collapse`
|
|
1896
|
+
loses the very line that makes it a lid. Separate borders stay with the
|
|
1897
|
+
cell that declared them. Each modifier sets it, so either works alone.
|
|
1898
|
+
|
|
1899
|
+
Note what is NOT here. No block: an edge that has to hold under scrolling
|
|
1900
|
+
is a border, and a block in this language is an offset rectangle, which is
|
|
1901
|
+
not the shape of the top of a column. No scrolled-under state either - the
|
|
1902
|
+
head's edge is drawn whether anything has moved beneath it or not, so there
|
|
1903
|
+
is nothing for scrolling to reveal. */
|
|
1904
|
+
/* The isolation is the reason the three z-indexes below can be 1, 2 and 3:
|
|
1905
|
+
they are resolved in here and cannot compete with the page stack. See the
|
|
1906
|
+
layer table in docs/RULES.md. */
|
|
1907
|
+
.axi-table__scroll { overflow: auto; isolation: isolate; }
|
|
1908
|
+
/* The head stays. */
|
|
1909
|
+
.axi-table--sticky { border-collapse: separate; border-spacing: 0; }
|
|
1910
|
+
.axi-table--sticky thead th {
|
|
1911
|
+
position: sticky;
|
|
1912
|
+
top: 0;
|
|
1913
|
+
z-index: 2;
|
|
1914
|
+
/* The float surface, not the raised one, and this is the whole reason
|
|
1915
|
+
--axi-surface-float exists: rows travel behind both of these, and a glass
|
|
1916
|
+
theme's ordinary surfaces are alpha, so a head at --axi-surface-raised
|
|
1917
|
+
would have numbers sliding through it. Opaque is not a look here, it is
|
|
1918
|
+
the requirement. */
|
|
1919
|
+
background: var(--axi-surface-float);
|
|
1920
|
+
border-bottom: var(--axi-border-control) solid var(--axi-ink-line);
|
|
1921
|
+
}
|
|
1922
|
+
/* The first column stays. It holds the row's name, and a name scrolled out of
|
|
1923
|
+
sight makes every number left of it anonymous - which is the whole reason a
|
|
1924
|
+
wide table is readable at all. Its edge is the cut the head carries, turned
|
|
1925
|
+
ninety degrees. */
|
|
1926
|
+
.axi-table--pinned { border-collapse: separate; border-spacing: 0; }
|
|
1927
|
+
.axi-table--pinned :is(thead, tbody) :is(th, td):first-child {
|
|
1928
|
+
position: sticky;
|
|
1929
|
+
left: 0;
|
|
1930
|
+
z-index: 1;
|
|
1931
|
+
background: var(--axi-surface-float);
|
|
1932
|
+
border-right: var(--axi-border-control) solid var(--axi-ink-line);
|
|
1933
|
+
}
|
|
1934
|
+
/* The corner belongs to both and has to outrank both. */
|
|
1935
|
+
.axi-table--sticky.axi-table--pinned thead th:first-child { z-index: 3; }
|
|
1936
|
+
/* Twenty columns do not get a leaderboard's padding. The type steps down with
|
|
1937
|
+
them; everything else about the table is unchanged, which is the point of
|
|
1938
|
+
its being a modifier rather than a second table. */
|
|
1939
|
+
.axi-table--dense thead th { padding: 0 7px 6px; }
|
|
1940
|
+
.axi-table--dense :is(td, tbody th) { padding: 5px 7px; font: var(--axi-t-micro); }
|
|
1941
|
+
/* The sorted column, named with the attribute a screen reader already needs
|
|
1942
|
+
in order to announce it. A class beside `aria-sort` would be a second
|
|
1943
|
+
source of truth for one fact. The mark is ink on the head and its edge -
|
|
1944
|
+
not a fill down the column, which is rule 2's tinted-everything failure
|
|
1945
|
+
applied to the one column you are trying to read. */
|
|
1946
|
+
.axi-table th[aria-sort] {
|
|
1947
|
+
color: var(--axi-accent);
|
|
1948
|
+
border-bottom-color: var(--axi-accent);
|
|
1949
|
+
}
|
|
1950
|
+
/* CSS cannot reach "the cells under the sorted head", so the consumer marks
|
|
1951
|
+
them. Full-strength text against the column's dimmed neighbours. */
|
|
1952
|
+
.axi-table__cell--sorted { color: var(--axi-text); }
|
|
1953
|
+
/* A sortable heading is a button, because sorting is an action and a <th> you
|
|
1954
|
+
can click but not tab to is a column the keyboard cannot sort. It inherits
|
|
1955
|
+
everything and adds nothing, so a heading looks the same whether it sorts or
|
|
1956
|
+
not - the only thing that marks a sorted column is aria-sort above. */
|
|
1957
|
+
.axi-table__sort {
|
|
1958
|
+
display: flex;
|
|
1959
|
+
align-items: center;
|
|
1960
|
+
justify-content: flex-end;
|
|
1961
|
+
gap: 6px;
|
|
1962
|
+
width: 100%;
|
|
1963
|
+
padding: 0;
|
|
1964
|
+
background: none;
|
|
1965
|
+
border: 0;
|
|
1966
|
+
font: inherit;
|
|
1967
|
+
color: inherit;
|
|
1968
|
+
letter-spacing: inherit;
|
|
1969
|
+
text-transform: inherit;
|
|
1970
|
+
cursor: pointer;
|
|
1971
|
+
}
|
|
1972
|
+
.axi-table th:first-child .axi-table__sort { justify-content: flex-start; }
|
|
1973
|
+
|
|
1882
1974
|
/* ---------- meter ---------- */
|
|
1883
1975
|
/* Rule 9: a proportion is a length. The track is the ground, the fill is the
|
|
1884
1976
|
value, and the fill is one ink at full strength - a tinted or faded bar is
|
package/docs/RULES.md
CHANGED
|
@@ -461,6 +461,9 @@ instead of joining it.
|
|
|
461
461
|
|
|
462
462
|
| Layer | z-index | What sits here |
|
|
463
463
|
|---|---|---|
|
|
464
|
+
| Pinned column | 1 | `.axi-table--pinned`'s first column |
|
|
465
|
+
| Sticky head | 2 | `.axi-table--sticky`'s `thead th` |
|
|
466
|
+
| Table corner | 3 | where the two cross |
|
|
464
467
|
| Sticky chrome | 40 | `.axi-mast` |
|
|
465
468
|
| Popovers | 41 | `.axi-menu__pop`, `.axi-picker__pop` |
|
|
466
469
|
| Scrim | 50 | `.axi-scrim` |
|
|
@@ -473,6 +476,15 @@ The modal has no number on purpose. A `<dialog>` opened with `showModal()` is
|
|
|
473
476
|
promoted to the browser's top layer, which sits above every `z-index` there is;
|
|
474
477
|
writing a number in that row would describe a competition the modal is not in.
|
|
475
478
|
|
|
479
|
+
The first three are sealed rather than low. `.axi-table__scroll` sets
|
|
480
|
+
`isolation: isolate`, so those numbers are resolved inside the scroll container
|
|
481
|
+
and never compete with the page layers under them - a table's sticky head
|
|
482
|
+
cannot climb over a mast, and a table inside a drawer cannot reach out of it.
|
|
483
|
+
They are listed because a table needs three orderings among its own cells and a
|
|
484
|
+
number that is never written down is a number that drifts; the isolation is
|
|
485
|
+
what keeps 1, 2 and 3 from meaning anything outside the table that declares
|
|
486
|
+
them.
|
|
487
|
+
|
|
476
488
|
A negative `z-index` inside a component's own `isolation` context — the sigil's
|
|
477
489
|
backing shape — is not a layer and is not listed. It is invisible outside the
|
|
478
490
|
component that owns it.
|
package/package.json
CHANGED
package/src/data.css
CHANGED
|
@@ -64,7 +64,11 @@
|
|
|
64
64
|
.axi-table td { text-align: right; white-space: nowrap; }
|
|
65
65
|
.axi-table th:first-child,
|
|
66
66
|
.axi-table td:first-child { text-align: left; }
|
|
67
|
-
|
|
67
|
+
/* `thead th`, not `th`. A row's name is a `<th scope="row">` - that is what
|
|
68
|
+
tells a screen reader which cell labels the row - and it is a name, not a
|
|
69
|
+
column heading: uppercase micro type down the first column would shout every
|
|
70
|
+
row's label at the reader. A row header takes the cell treatment below. */
|
|
71
|
+
.axi-table thead th {
|
|
68
72
|
padding: 0 10px 10px;
|
|
69
73
|
font: var(--axi-t-micro);
|
|
70
74
|
letter-spacing: var(--axi-ls-micro);
|
|
@@ -72,7 +76,8 @@
|
|
|
72
76
|
color: var(--axi-text-faint);
|
|
73
77
|
border-bottom: var(--axi-border-control) solid var(--axi-rule);
|
|
74
78
|
}
|
|
75
|
-
.axi-table td
|
|
79
|
+
.axi-table td,
|
|
80
|
+
.axi-table tbody th {
|
|
76
81
|
padding: 9px 10px;
|
|
77
82
|
font: var(--axi-t-small);
|
|
78
83
|
font-weight: 700;
|
|
@@ -83,7 +88,7 @@
|
|
|
83
88
|
hovering a row is not a status, and forty rows that each flash a colour on
|
|
84
89
|
the way past the one you want is the tinted-everything failure rule 2 is
|
|
85
90
|
about. */
|
|
86
|
-
.axi-table tbody tr:hover td { background: var(--axi-surface-raised); color: var(--axi-text); }
|
|
91
|
+
.axi-table tbody tr:hover :is(td, th) { background: var(--axi-surface-raised); color: var(--axi-text); }
|
|
87
92
|
/* The measured value in a row, as opposed to its supporting numbers. */
|
|
88
93
|
.axi-table__num { color: var(--axi-text); }
|
|
89
94
|
/* A name cell: an icon, a diamond or a rank beside the label. */
|
|
@@ -101,6 +106,93 @@
|
|
|
101
106
|
}
|
|
102
107
|
.axi-table__rank--top { background: var(--axi-accent); color: var(--axi-accent-ink); }
|
|
103
108
|
|
|
109
|
+
/* A table too wide and too tall for the panel holding it: twenty numeric
|
|
110
|
+
columns against forty players, scrolled in both directions. Rule 8 still
|
|
111
|
+
decides what every line means - the head is a lid at the control step, the
|
|
112
|
+
rows are hairlines - and the only new thing here is that the lid and the
|
|
113
|
+
row's name have to stay put while the numbers move under them.
|
|
114
|
+
|
|
115
|
+
`border-collapse: separate` is load-bearing, not housekeeping. A collapsed
|
|
116
|
+
table hoists its cell borders onto the table itself, and a border owned by
|
|
117
|
+
the table scrolls away with it, so a sticky head drawn under `collapse`
|
|
118
|
+
loses the very line that makes it a lid. Separate borders stay with the
|
|
119
|
+
cell that declared them. Each modifier sets it, so either works alone.
|
|
120
|
+
|
|
121
|
+
Note what is NOT here. No block: an edge that has to hold under scrolling
|
|
122
|
+
is a border, and a block in this language is an offset rectangle, which is
|
|
123
|
+
not the shape of the top of a column. No scrolled-under state either - the
|
|
124
|
+
head's edge is drawn whether anything has moved beneath it or not, so there
|
|
125
|
+
is nothing for scrolling to reveal. */
|
|
126
|
+
/* The isolation is the reason the three z-indexes below can be 1, 2 and 3:
|
|
127
|
+
they are resolved in here and cannot compete with the page stack. See the
|
|
128
|
+
layer table in docs/RULES.md. */
|
|
129
|
+
.axi-table__scroll { overflow: auto; isolation: isolate; }
|
|
130
|
+
/* The head stays. */
|
|
131
|
+
.axi-table--sticky { border-collapse: separate; border-spacing: 0; }
|
|
132
|
+
.axi-table--sticky thead th {
|
|
133
|
+
position: sticky;
|
|
134
|
+
top: 0;
|
|
135
|
+
z-index: 2;
|
|
136
|
+
/* The float surface, not the raised one, and this is the whole reason
|
|
137
|
+
--axi-surface-float exists: rows travel behind both of these, and a glass
|
|
138
|
+
theme's ordinary surfaces are alpha, so a head at --axi-surface-raised
|
|
139
|
+
would have numbers sliding through it. Opaque is not a look here, it is
|
|
140
|
+
the requirement. */
|
|
141
|
+
background: var(--axi-surface-float);
|
|
142
|
+
border-bottom: var(--axi-border-control) solid var(--axi-ink-line);
|
|
143
|
+
}
|
|
144
|
+
/* The first column stays. It holds the row's name, and a name scrolled out of
|
|
145
|
+
sight makes every number left of it anonymous - which is the whole reason a
|
|
146
|
+
wide table is readable at all. Its edge is the cut the head carries, turned
|
|
147
|
+
ninety degrees. */
|
|
148
|
+
.axi-table--pinned { border-collapse: separate; border-spacing: 0; }
|
|
149
|
+
.axi-table--pinned :is(thead, tbody) :is(th, td):first-child {
|
|
150
|
+
position: sticky;
|
|
151
|
+
left: 0;
|
|
152
|
+
z-index: 1;
|
|
153
|
+
background: var(--axi-surface-float);
|
|
154
|
+
border-right: var(--axi-border-control) solid var(--axi-ink-line);
|
|
155
|
+
}
|
|
156
|
+
/* The corner belongs to both and has to outrank both. */
|
|
157
|
+
.axi-table--sticky.axi-table--pinned thead th:first-child { z-index: 3; }
|
|
158
|
+
/* Twenty columns do not get a leaderboard's padding. The type steps down with
|
|
159
|
+
them; everything else about the table is unchanged, which is the point of
|
|
160
|
+
its being a modifier rather than a second table. */
|
|
161
|
+
.axi-table--dense thead th { padding: 0 7px 6px; }
|
|
162
|
+
.axi-table--dense :is(td, tbody th) { padding: 5px 7px; font: var(--axi-t-micro); }
|
|
163
|
+
/* The sorted column, named with the attribute a screen reader already needs
|
|
164
|
+
in order to announce it. A class beside `aria-sort` would be a second
|
|
165
|
+
source of truth for one fact. The mark is ink on the head and its edge -
|
|
166
|
+
not a fill down the column, which is rule 2's tinted-everything failure
|
|
167
|
+
applied to the one column you are trying to read. */
|
|
168
|
+
.axi-table th[aria-sort] {
|
|
169
|
+
color: var(--axi-accent);
|
|
170
|
+
border-bottom-color: var(--axi-accent);
|
|
171
|
+
}
|
|
172
|
+
/* CSS cannot reach "the cells under the sorted head", so the consumer marks
|
|
173
|
+
them. Full-strength text against the column's dimmed neighbours. */
|
|
174
|
+
.axi-table__cell--sorted { color: var(--axi-text); }
|
|
175
|
+
/* A sortable heading is a button, because sorting is an action and a <th> you
|
|
176
|
+
can click but not tab to is a column the keyboard cannot sort. It inherits
|
|
177
|
+
everything and adds nothing, so a heading looks the same whether it sorts or
|
|
178
|
+
not - the only thing that marks a sorted column is aria-sort above. */
|
|
179
|
+
.axi-table__sort {
|
|
180
|
+
display: flex;
|
|
181
|
+
align-items: center;
|
|
182
|
+
justify-content: flex-end;
|
|
183
|
+
gap: 6px;
|
|
184
|
+
width: 100%;
|
|
185
|
+
padding: 0;
|
|
186
|
+
background: none;
|
|
187
|
+
border: 0;
|
|
188
|
+
font: inherit;
|
|
189
|
+
color: inherit;
|
|
190
|
+
letter-spacing: inherit;
|
|
191
|
+
text-transform: inherit;
|
|
192
|
+
cursor: pointer;
|
|
193
|
+
}
|
|
194
|
+
.axi-table th:first-child .axi-table__sort { justify-content: flex-start; }
|
|
195
|
+
|
|
104
196
|
/* ---------- meter ---------- */
|
|
105
197
|
/* Rule 9: a proportion is a length. The track is the ground, the fill is the
|
|
106
198
|
value, and the fill is one ink at full strength - a tinted or faded bar is
|