@axiapps/axi-design 1.33.0 → 1.35.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 +155 -26
- package/docs/RULES.md +31 -0
- package/package.json +1 -1
- package/src/data.css +16 -5
- package/src/forms.css +3 -1
- package/src/primitives.css +40 -11
- package/src/prose.css +5 -2
- package/src/shells.css +71 -6
- package/src/tokens.css +20 -1
package/dist/axi.css
CHANGED
|
@@ -84,7 +84,26 @@
|
|
|
84
84
|
against a fill lighter than itself. Every outline in this language is
|
|
85
85
|
near-black on the assumption of a ground the lines can be darker than; a
|
|
86
86
|
well IS at ground level, so an ink edge round one is a black line on a
|
|
87
|
-
black field. Raised takes ink, sunk takes the rule.
|
|
87
|
+
black field. Raised takes ink, sunk takes the rule.
|
|
88
|
+
|
|
89
|
+
And what the fill names is not the .axi-well class - it is the level. A
|
|
90
|
+
button at rest, a field, a select, a checkbox, an avatar, a rank, a code
|
|
91
|
+
span, a hovered row in a popover: not one of them is raised off what holds
|
|
92
|
+
it, and every one of them was spelled --axi-ground, because on a theme
|
|
93
|
+
whose surfaces are opaque "flat on its container" and "the page colour"
|
|
94
|
+
are the same colour. They stop being the same colour the instant a theme
|
|
95
|
+
makes the container translucent, which is how the whole set went black at
|
|
96
|
+
once and why this is written here rather than fourteen times downstream.
|
|
97
|
+
Above this level is --axi-surface (.axi-kbd is the one control in the
|
|
98
|
+
language that is genuinely raised, and says so). Below it is --axi-ground
|
|
99
|
+
proper, which now means the page and only the page: body, the sheet, the
|
|
100
|
+
window, the masthead - the things content scrolls under, which need real
|
|
101
|
+
opacity and not a subtraction. Everything between the two is this token.
|
|
102
|
+
|
|
103
|
+
The LINE does not come along. --axi-well-line is for a well cut into the
|
|
104
|
+
page, where there is nothing left for ink to be darker than; a control is
|
|
105
|
+
cut into a SURFACE and its ink edge still has a fill above it to read
|
|
106
|
+
against. Every component below keeps --axi-ink-line. */
|
|
88
107
|
--axi-well-fill: var(--axi-ground);
|
|
89
108
|
--axi-well-line: var(--axi-rule);
|
|
90
109
|
--axi-text: #f4f6f9;
|
|
@@ -371,13 +390,29 @@ button.axi-panel--tile:hover,
|
|
|
371
390
|
padding: var(--axi-well-pad, 10px);
|
|
372
391
|
}
|
|
373
392
|
|
|
393
|
+
/* The reading-scale well, which the comment above describes and this language
|
|
394
|
+
then made every consumer spell out by hand. Saying `--axi-radius-sm` inline
|
|
395
|
+
is fine for the handful of instances that comment imagined; the first real
|
|
396
|
+
consumer to be counted had fifty, and fifty inline style attributes is the
|
|
397
|
+
thing a class exists to prevent. The same argument produced .axi-btn--sm.
|
|
398
|
+
|
|
399
|
+
Only the radius, because that is the only thing that changes: a recess the
|
|
400
|
+
size of a single reading still holds objects that carry their own padding, so
|
|
401
|
+
the pad knob is still the right way to say anything else. */
|
|
402
|
+
.axi-well--sm { --axi-well-radius: var(--axi-radius-sm); }
|
|
403
|
+
|
|
374
404
|
/* ---------- button ---------- */
|
|
375
405
|
.axi-btn {
|
|
376
406
|
display: inline-flex; align-items: center; gap: 8px;
|
|
377
407
|
padding: var(--axi-btn-pad, 12px 20px);
|
|
378
408
|
border: var(--axi-border-control) solid var(--axi-ink-line);
|
|
379
409
|
border-radius: var(--axi-radius-sm);
|
|
380
|
-
|
|
410
|
+
/* Flat on its container, which is --axi-well-fill and not the page colour -
|
|
411
|
+
the argument is in src/tokens.css at that token. A button at rest carries
|
|
412
|
+
no block: it is level with the panel holding it and lifts on hover, so the
|
|
413
|
+
resting fill is the level's, and --axi-btn--primary below is the one that
|
|
414
|
+
rests raised and fills with the accent instead. */
|
|
415
|
+
background: var(--axi-well-fill);
|
|
381
416
|
color: var(--axi-text-dim);
|
|
382
417
|
font: var(--axi-t-label);
|
|
383
418
|
letter-spacing: var(--axi-ls-label);
|
|
@@ -460,7 +495,8 @@ button.axi-panel--tile:hover,
|
|
|
460
495
|
padding: var(--axi-pill-pad, 12px 20px);
|
|
461
496
|
border: var(--axi-border-control) solid var(--axi-ink-line);
|
|
462
497
|
border-radius: var(--axi-radius-sm);
|
|
463
|
-
|
|
498
|
+
/* The button's fill for the button's reason - see .axi-btn above. */
|
|
499
|
+
background: var(--axi-well-fill);
|
|
464
500
|
color: var(--axi-text-dim);
|
|
465
501
|
font: var(--axi-t-label);
|
|
466
502
|
letter-spacing: var(--axi-ls-label);
|
|
@@ -654,7 +690,10 @@ button.axi-panel--tile:hover,
|
|
|
654
690
|
.axi-input {
|
|
655
691
|
width: 100%;
|
|
656
692
|
padding: var(--axi-input-pad, 11px 12px);
|
|
657
|
-
|
|
693
|
+
/* A field is the recessed thing in any bar it sits in - .axi-kbd's comment
|
|
694
|
+
below leans on exactly that - so it takes the level's fill. See
|
|
695
|
+
--axi-well-fill in src/tokens.css. */
|
|
696
|
+
background: var(--axi-well-fill);
|
|
658
697
|
border: var(--axi-border-control) solid var(--axi-ink-line);
|
|
659
698
|
border-radius: var(--axi-radius-sm);
|
|
660
699
|
color: var(--axi-text);
|
|
@@ -689,14 +728,15 @@ button.axi-panel--tile:hover,
|
|
|
689
728
|
`em`, not `px`: this lands in body copy and in 10px captions alike, and a
|
|
690
729
|
literal that does not track the text around it reads as a different voice.
|
|
691
730
|
|
|
692
|
-
It sits on --axi-
|
|
731
|
+
It sits on --axi-well-fill where .axi-kbd sits on --axi-surface, and the
|
|
693
732
|
reason is already written down one rule below: a key is raised off what it
|
|
694
|
-
is printed on, and a quoted literal is sunk into it.
|
|
733
|
+
is printed on, and a quoted literal is sunk into it. It said --axi-ground
|
|
734
|
+
for as long as sunk and the page were the same colour; see that token. */
|
|
695
735
|
.axi-code,
|
|
696
736
|
.axi-prose code {
|
|
697
737
|
font-family: var(--axi-mono);
|
|
698
738
|
font-size: .88em;
|
|
699
|
-
background: var(--axi-
|
|
739
|
+
background: var(--axi-well-fill);
|
|
700
740
|
color: var(--axi-text);
|
|
701
741
|
border: var(--axi-border-hairline) solid var(--axi-ink-line);
|
|
702
742
|
border-radius: var(--axi-radius-sm);
|
|
@@ -736,7 +776,10 @@ button.axi-panel--tile:hover,
|
|
|
736
776
|
padding: 10px 30px 10px 9px;
|
|
737
777
|
border: var(--axi-border-control) solid var(--axi-ink-line);
|
|
738
778
|
border-radius: var(--axi-radius-sm);
|
|
739
|
-
|
|
779
|
+
/* The field's fill, because a closed select is a field - see .axi-input. The
|
|
780
|
+
longhand stays: a caret rides in background-image and the shorthand would
|
|
781
|
+
reset it. */
|
|
782
|
+
background-color: var(--axi-well-fill);
|
|
740
783
|
color: var(--axi-text-dim);
|
|
741
784
|
font: var(--axi-t-label);
|
|
742
785
|
font-size: 12.5px;
|
|
@@ -795,8 +838,12 @@ button.axi-panel--tile:hover,
|
|
|
795
838
|
letter-spacing: var(--axi-ls-label);
|
|
796
839
|
text-transform: uppercase;
|
|
797
840
|
}
|
|
841
|
+
/* A row under the cursor sinks rather than lighting up, so the hover is the
|
|
842
|
+
level's fill - and this popover is filled with --axi-surface-raised, which
|
|
843
|
+
a theme may take translucent, so an opaque row here is the black patch
|
|
844
|
+
--axi-well-fill exists to prevent. Same for the picker's rows below. */
|
|
798
845
|
.axi-select option:hover, .axi-select option:focus {
|
|
799
|
-
background: var(--axi-
|
|
846
|
+
background: var(--axi-well-fill); color: var(--axi-text);
|
|
800
847
|
}
|
|
801
848
|
/* The page-wide focus ring sits 2px outside its element; inside a picker
|
|
802
849
|
that is 2px into the neighbouring row, so pull it back in. */
|
|
@@ -895,7 +942,7 @@ button.axi-panel--tile:hover,
|
|
|
895
942
|
font-weight: 900;
|
|
896
943
|
}
|
|
897
944
|
.axi-picker__opt:hover, .axi-picker__opt:focus {
|
|
898
|
-
background: var(--axi-
|
|
945
|
+
background: var(--axi-well-fill); color: var(--axi-text);
|
|
899
946
|
}
|
|
900
947
|
/* The page-wide focus ring sits 2px outside its element; inside a popover
|
|
901
948
|
this tight that is 2px into the neighbouring row, so pull it back in. */
|
|
@@ -910,7 +957,8 @@ button.axi-panel--tile:hover,
|
|
|
910
957
|
who wants round avatars sets --axi-radius-sm and gets rounded controls
|
|
911
958
|
everywhere - which is the honest version of the request.
|
|
912
959
|
Flat: outlined, no block. An avatar is content inside a panel, the same as
|
|
913
|
-
.axi-stat and .axi-table__rank, not a thing raised off it
|
|
960
|
+
.axi-stat and .axi-table__rank, not a thing raised off it - which is what
|
|
961
|
+
--axi-well-fill below is saying, and all three now say it the same way. */
|
|
914
962
|
.axi-avatar {
|
|
915
963
|
width: var(--axi-avatar-size, 40px);
|
|
916
964
|
height: var(--axi-avatar-size, 40px);
|
|
@@ -918,7 +966,7 @@ button.axi-panel--tile:hover,
|
|
|
918
966
|
display: grid;
|
|
919
967
|
place-items: center;
|
|
920
968
|
overflow: hidden;
|
|
921
|
-
background: var(--axi-
|
|
969
|
+
background: var(--axi-well-fill);
|
|
922
970
|
color: var(--axi-text-dim);
|
|
923
971
|
border: var(--axi-border-control) solid var(--axi-ink-line);
|
|
924
972
|
border-radius: var(--axi-radius-sm);
|
|
@@ -983,7 +1031,9 @@ button.axi-panel--tile:hover,
|
|
|
983
1031
|
height: var(--axi-check-size, 22px);
|
|
984
1032
|
display: inline-grid;
|
|
985
1033
|
place-items: center;
|
|
986
|
-
|
|
1034
|
+
/* An empty box is a hole you put a mark in, so the level's fill - see
|
|
1035
|
+
--axi-well-fill in src/tokens.css. :checked below replaces it outright. */
|
|
1036
|
+
background: var(--axi-well-fill);
|
|
987
1037
|
border: var(--axi-border-control) solid var(--axi-ink-line);
|
|
988
1038
|
/* The text-sized step, not the control-sized one - see --axi-radius-xs in
|
|
989
1039
|
src/tokens.css for why a 22px box cannot take a corner scaled for a 36px
|
|
@@ -1105,9 +1155,18 @@ textarea.axi-input {
|
|
|
1105
1155
|
}
|
|
1106
1156
|
|
|
1107
1157
|
/* ---------- masthead ---------- */
|
|
1158
|
+
/* Opaque, because content scrolls under it. Which is also why it paints the
|
|
1159
|
+
page's light as well as the page's colour: an opaque strip across the top of
|
|
1160
|
+
a lit page is a dark band over that light, and the band is there on every
|
|
1161
|
+
page of a site the whole time it is open. Attachment fixed, the same as
|
|
1162
|
+
`body`, so the strip's share of the light is the share the page would have
|
|
1163
|
+
shown there - a wash positioned to this element's own box instead would
|
|
1164
|
+
line up with nothing. */
|
|
1108
1165
|
.axi-mast {
|
|
1109
1166
|
position: sticky; top: 0; z-index: 40;
|
|
1110
|
-
background: var(--axi-ground);
|
|
1167
|
+
background-color: var(--axi-ground);
|
|
1168
|
+
background-image: var(--axi-ground-image);
|
|
1169
|
+
background-attachment: fixed;
|
|
1111
1170
|
border-bottom: var(--axi-border-panel) solid var(--axi-ink-line);
|
|
1112
1171
|
}
|
|
1113
1172
|
.axi-mast__in {
|
|
@@ -1318,6 +1377,41 @@ textarea.axi-input {
|
|
|
1318
1377
|
the faint tone, and inside a filled item it follows the item's ink. */
|
|
1319
1378
|
.axi-rail__item .axi-icon { color: var(--axi-text-faint); }
|
|
1320
1379
|
.axi-rail__item[aria-current] .axi-icon { color: var(--axi-accent-ink); }
|
|
1380
|
+
/* A rail nested inside a panel whose content already spends the accent: a
|
|
1381
|
+
metric picker beside the table it drives, a filter list beside its results.
|
|
1382
|
+
The language already refuses two fills at two levels inside one rail - that
|
|
1383
|
+
is why .axi-rail__subitem has no fill - and a rail that is itself the inner
|
|
1384
|
+
level is the same refusal one container further out. Two filled rails on
|
|
1385
|
+
one screen name two places, and only one of them is where you are.
|
|
1386
|
+
|
|
1387
|
+
What it cannot do is borrow the subitem's answer. A subitem is one of a
|
|
1388
|
+
handful of leaves under an open category; a picker like this is twenty rows
|
|
1389
|
+
and the primary control of its own panel, so brightened text alone loses
|
|
1390
|
+
the selection in the list. This is the third weight between the two: the
|
|
1391
|
+
row rises off the rail as any hovered row does, and the accent arrives on
|
|
1392
|
+
its leading edge. The accent still says which row without the row claiming
|
|
1393
|
+
to be the place.
|
|
1394
|
+
|
|
1395
|
+
The edge is the item's own border, which .axi-rail__item already reserves
|
|
1396
|
+
at the control weight and draws transparent - so the bar costs no shadow,
|
|
1397
|
+
no extra box and no reflow when it lights up. Logical, not left: this is
|
|
1398
|
+
the leading edge, the same correction .axi-rail--flush took.
|
|
1399
|
+
|
|
1400
|
+
The modifier goes on the list, not on .axi-rail, because a nested picker
|
|
1401
|
+
usually has no rail box around it - it sits directly in the panel or well
|
|
1402
|
+
that holds it, and inheriting a 208px width and a panel shadow is the
|
|
1403
|
+
opposite of what it wants. */
|
|
1404
|
+
.axi-rail__nav--quiet .axi-rail__item[aria-current],
|
|
1405
|
+
.axi-rail__nav--quiet .axi-rail__item[aria-current]:hover {
|
|
1406
|
+
background: var(--axi-surface-raised);
|
|
1407
|
+
color: var(--axi-text);
|
|
1408
|
+
border-color: transparent;
|
|
1409
|
+
border-inline-start-color: var(--axi-accent);
|
|
1410
|
+
}
|
|
1411
|
+
/* No accent fill here, so the icon has no accent ink to follow - it follows
|
|
1412
|
+
the row's own text, the way it does in an unselected item. */
|
|
1413
|
+
.axi-rail__nav--quiet .axi-rail__item[aria-current] .axi-icon { color: var(--axi-text); }
|
|
1414
|
+
|
|
1321
1415
|
/* The second level, indented under the item it belongs to. */
|
|
1322
1416
|
.axi-rail__sub { display: flex; flex-direction: column; margin: 3px 0 5px 10px; }
|
|
1323
1417
|
.axi-rail__subitem {
|
|
@@ -1483,7 +1577,8 @@ textarea.axi-input {
|
|
|
1483
1577
|
padding: 7px 8px; border-radius: var(--axi-radius-sm);
|
|
1484
1578
|
font-size: 13px; font-weight: 600; color: var(--axi-text-dim); cursor: pointer;
|
|
1485
1579
|
}
|
|
1486
|
-
|
|
1580
|
+
/* A hovered row sinks - the same fill the select's and the picker's rows use. */
|
|
1581
|
+
.axi-menu__pop label:hover { background: var(--axi-well-fill); color: var(--axi-text); }
|
|
1487
1582
|
.axi-menu__pop input { margin: 3px 0 0; }
|
|
1488
1583
|
|
|
1489
1584
|
/* ---------- command palette ---------- */
|
|
@@ -1597,7 +1692,7 @@ textarea.axi-input {
|
|
|
1597
1692
|
.axi-palette__trigger {
|
|
1598
1693
|
display: flex; align-items: center; width: 100%; overflow: hidden;
|
|
1599
1694
|
padding: 0 10px 0 0;
|
|
1600
|
-
background: var(--axi-
|
|
1695
|
+
background: var(--axi-well-fill);
|
|
1601
1696
|
border: var(--axi-border-control) solid var(--axi-ink-line);
|
|
1602
1697
|
border-radius: var(--axi-radius-sm);
|
|
1603
1698
|
color: var(--axi-text-dim);
|
|
@@ -1781,7 +1876,8 @@ textarea.axi-input {
|
|
|
1781
1876
|
width: 32px; height: 32px;
|
|
1782
1877
|
display: grid; place-items: center;
|
|
1783
1878
|
border-radius: var(--axi-radius-sm);
|
|
1784
|
-
|
|
1879
|
+
/* A control flat on the drawer's head - see --axi-well-fill in tokens. */
|
|
1880
|
+
background: var(--axi-well-fill);
|
|
1785
1881
|
border: var(--axi-border-control) solid var(--axi-ink-line);
|
|
1786
1882
|
color: var(--axi-text-dim);
|
|
1787
1883
|
font-size: 15px; font-weight: 900; cursor: pointer;
|
|
@@ -1847,6 +1943,13 @@ textarea.axi-input {
|
|
|
1847
1943
|
overflow-y: auto;
|
|
1848
1944
|
background-color: var(--axi-ground);
|
|
1849
1945
|
background-image: var(--axi-ground-image);
|
|
1946
|
+
/* Fixed for both of the reasons `body` is: the light stays put while the
|
|
1947
|
+
sheet's own content scrolls, and it is positioned to the viewport rather
|
|
1948
|
+
than to this box - which matters here because --axi-sheet-top pushes that
|
|
1949
|
+
box down under an app's titlebar, and a wash measured from its top edge
|
|
1950
|
+
would sit lower than the one on the page it covers. Opening a sheet would
|
|
1951
|
+
nudge the light sideways. */
|
|
1952
|
+
background-attachment: fixed;
|
|
1850
1953
|
padding: var(--axi-sheet-pad, 12px 16px);
|
|
1851
1954
|
}
|
|
1852
1955
|
/* The heading the sheet opened with, divided from the body by a rule. Rule 8:
|
|
@@ -1869,7 +1972,8 @@ textarea.axi-input {
|
|
|
1869
1972
|
margin: 0;
|
|
1870
1973
|
padding: 11px 13px;
|
|
1871
1974
|
border-left: var(--axi-border-panel) solid var(--axi-accent);
|
|
1872
|
-
|
|
1975
|
+
/* Sunk into the prose around it, so the well's fill - see .axi-stat. */
|
|
1976
|
+
background: var(--axi-well-fill);
|
|
1873
1977
|
border-radius: 0 var(--axi-radius-sm) var(--axi-radius-sm) 0;
|
|
1874
1978
|
}
|
|
1875
1979
|
.axi-quote :where(p) { margin: 0; font-size: 13px; font-style: italic; color: var(--axi-text-dim); line-height: 1.5; }
|
|
@@ -1886,13 +1990,24 @@ textarea.axi-input {
|
|
|
1886
1990
|
takes the panel outline. It carries no block, because a block is an
|
|
1887
1991
|
element's shadow on the surface behind it and there is nothing behind a
|
|
1888
1992
|
window that this language is entitled to draw on.
|
|
1993
|
+
|
|
1994
|
+
It is the page. Not a page inside one - the only one, for as long as the app
|
|
1995
|
+
is running, which is why it paints the ground's IMAGE as well as the
|
|
1996
|
+
ground's colour. `body` is behind it and lights nothing, because a window
|
|
1997
|
+
covers the viewport and is opaque by the same requirement that makes it
|
|
1998
|
+
opaque over its own content. A window that skipped the image would render a
|
|
1999
|
+
theme whose character is the light - glass - as flat near-black: every panel
|
|
2000
|
+
inside it correctly translucent, over nothing. Longhands for the reason
|
|
2001
|
+
.axi-sheet gives at length below; no attachment, because this element's box
|
|
2002
|
+
IS the viewport and never scrolls, so fixed and scroll paint the same pixels.
|
|
1889
2003
|
The titlebar is filled with the ink line rather than a surface: it is the
|
|
1890
2004
|
outline widened into a strip, which is why the app's content reads as
|
|
1891
2005
|
sitting inside the outline instead of under a second toolbar. */
|
|
1892
2006
|
.axi-window {
|
|
1893
2007
|
height: 100vh;
|
|
1894
2008
|
display: flex; flex-direction: column; overflow: hidden;
|
|
1895
|
-
background: var(--axi-ground);
|
|
2009
|
+
background-color: var(--axi-ground);
|
|
2010
|
+
background-image: var(--axi-ground-image);
|
|
1896
2011
|
border: var(--axi-border-panel) solid var(--axi-ink-line);
|
|
1897
2012
|
border-radius: var(--axi-radius);
|
|
1898
2013
|
}
|
|
@@ -2159,10 +2274,18 @@ textarea.axi-input {
|
|
|
2159
2274
|
an outline and no block - it is content, not something raised off the
|
|
2160
2275
|
surface it sits on. The number stays in --axi-text unless it has a real
|
|
2161
2276
|
state: rule 5 applies to a figure exactly as it applies to a chip, and a
|
|
2162
|
-
tile coloured for emphasis is decoration impersonating status.
|
|
2277
|
+
tile coloured for emphasis is decoration impersonating status.
|
|
2278
|
+
|
|
2279
|
+
Flat on the ground is the WELL's fill and not the page's. A tile is a recess
|
|
2280
|
+
cut into the panel holding it, which is the same shape .axi-well names, and
|
|
2281
|
+
spelled --axi-ground it stops being a recess the moment a theme makes that
|
|
2282
|
+
panel translucent: an opaque page colour inside a pane of glass is a black
|
|
2283
|
+
patch. The outline stays the ink line rather than following the well's,
|
|
2284
|
+
because a tile is cut into a SURFACE and an ink edge still has something to
|
|
2285
|
+
be darker than there. Same split in .axi-meter and .axi-plot below. */
|
|
2163
2286
|
.axi-stat {
|
|
2164
2287
|
padding: 12px 14px;
|
|
2165
|
-
background: var(--axi-
|
|
2288
|
+
background: var(--axi-well-fill);
|
|
2166
2289
|
border: var(--axi-border-control) solid var(--axi-ink-line);
|
|
2167
2290
|
border-radius: var(--axi-radius-sm);
|
|
2168
2291
|
}
|
|
@@ -2249,7 +2372,8 @@ textarea.axi-input {
|
|
|
2249
2372
|
display: grid; place-items: center;
|
|
2250
2373
|
border: var(--axi-border-control) solid var(--axi-ink-line);
|
|
2251
2374
|
border-radius: var(--axi-radius-sm);
|
|
2252
|
-
|
|
2375
|
+
/* Flat in the row, like the tile above and the avatar it stands beside. */
|
|
2376
|
+
background: var(--axi-well-fill);
|
|
2253
2377
|
font: var(--axi-t-micro);
|
|
2254
2378
|
color: var(--axi-text-faint);
|
|
2255
2379
|
}
|
|
@@ -2353,7 +2477,8 @@ textarea.axi-input {
|
|
|
2353
2477
|
.axi-meter {
|
|
2354
2478
|
display: flex;
|
|
2355
2479
|
height: var(--axi-meter-h, 12px);
|
|
2356
|
-
|
|
2480
|
+
/* The trough is a recess, so it takes the well's fill - see .axi-stat. */
|
|
2481
|
+
background: var(--axi-well-fill);
|
|
2357
2482
|
border: var(--axi-border-control) solid var(--axi-ink-line);
|
|
2358
2483
|
border-radius: var(--axi-radius-sm);
|
|
2359
2484
|
overflow: hidden;
|
|
@@ -2469,7 +2594,8 @@ textarea.axi-input {
|
|
|
2469
2594
|
.axi-plot {
|
|
2470
2595
|
position: relative;
|
|
2471
2596
|
height: var(--axi-plot-h, 180px);
|
|
2472
|
-
|
|
2597
|
+
/* A frame cut into the panel, not laid on the page - see .axi-stat. */
|
|
2598
|
+
background-color: var(--axi-well-fill);
|
|
2473
2599
|
background-image: repeating-linear-gradient(
|
|
2474
2600
|
to top,
|
|
2475
2601
|
var(--axi-rule) 0 var(--axi-border-hairline),
|
|
@@ -2639,9 +2765,12 @@ textarea.axi-input {
|
|
|
2639
2765
|
|
|
2640
2766
|
/* .axi-prose code is declared beside .axi-code in primitives.css: one rule,
|
|
2641
2767
|
both selectors, because they are one object. */
|
|
2768
|
+
/* A code block and a quote are both fields sunk into the prose around them,
|
|
2769
|
+
so both take --axi-well-fill rather than the page colour - the reason is
|
|
2770
|
+
written out at .axi-stat in src/data.css. */
|
|
2642
2771
|
.axi-prose pre {
|
|
2643
2772
|
margin: 0 0 18px; padding: 14px 16px; overflow-x: auto;
|
|
2644
|
-
background: var(--axi-
|
|
2773
|
+
background: var(--axi-well-fill);
|
|
2645
2774
|
border: var(--axi-border-control) solid var(--axi-ink-line);
|
|
2646
2775
|
border-radius: var(--axi-radius-sm);
|
|
2647
2776
|
box-shadow: var(--axi-shadow-control);
|
|
@@ -2652,7 +2781,7 @@ textarea.axi-input {
|
|
|
2652
2781
|
margin: 0 0 18px;
|
|
2653
2782
|
padding: 11px 13px;
|
|
2654
2783
|
border-left: var(--axi-border-panel) solid var(--axi-accent);
|
|
2655
|
-
background: var(--axi-
|
|
2784
|
+
background: var(--axi-well-fill);
|
|
2656
2785
|
border-radius: 0 var(--axi-radius-sm) var(--axi-radius-sm) 0;
|
|
2657
2786
|
}
|
|
2658
2787
|
.axi-prose blockquote p { margin: 0; font-style: italic; }
|
package/docs/RULES.md
CHANGED
|
@@ -702,3 +702,34 @@ whole section exists to prevent.
|
|
|
702
702
|
|
|
703
703
|
The test to write is not "does `.axi-code` exist". It is "are both spellings in
|
|
704
704
|
the same rule", because only the second one fails when someone splits them.
|
|
705
|
+
|
|
706
|
+
### A refusal holds at every level, not just the one it was written for
|
|
707
|
+
|
|
708
|
+
The rail refuses two accent fills inside itself. That is why
|
|
709
|
+
`.axi-rail__subitem` is brightened text and not a second filled row: with two
|
|
710
|
+
fills the reader has to decide which of them answers "where am I", and the
|
|
711
|
+
answer to one question cannot be two things.
|
|
712
|
+
|
|
713
|
+
Written that way, the refusal sounds like it is about indentation. It is not.
|
|
714
|
+
It is about how many times one screen may claim to be a place, and nesting a
|
|
715
|
+
whole rail inside a panel is the same arithmetic as nesting a row inside a
|
|
716
|
+
rail. A stats page with a category rail down the side and a twenty-row metric
|
|
717
|
+
picker inside each section has two rails, both correct on their own, and both
|
|
718
|
+
filled — so the screen makes the claim twice and neither wins. The app that
|
|
719
|
+
hit this had already reasoned its way to the same conclusion and written the
|
|
720
|
+
quiet treatment by hand, in its own stylesheet, with a comment giving exactly
|
|
721
|
+
this reason. Two parties deriving the same rule independently is the signal
|
|
722
|
+
that the rule belongs in the language, not in either party's override file.
|
|
723
|
+
|
|
724
|
+
So when adding a component, take every refusal the neighbouring components
|
|
725
|
+
state and ask what it is really counting. If the answer is "per screen" rather
|
|
726
|
+
than "per box", the component needs a way to stand down — and the modifier is
|
|
727
|
+
cheaper than the override every consumer writes instead. `.axi-rail__nav--quiet`
|
|
728
|
+
is that: the fill goes, the accent stays as the leading edge, and nothing else
|
|
729
|
+
moves.
|
|
730
|
+
|
|
731
|
+
What the modifier must not do is reach for the weaker treatment that already
|
|
732
|
+
exists. A subitem drops the fill *and* the weight, which is right for a few
|
|
733
|
+
leaves under an open category and wrong for a picker that is the primary
|
|
734
|
+
control of its own panel — there, brightened text loses the selection in the
|
|
735
|
+
list. Standing down is one step, not two.
|
package/package.json
CHANGED
package/src/data.css
CHANGED
|
@@ -15,10 +15,18 @@
|
|
|
15
15
|
an outline and no block - it is content, not something raised off the
|
|
16
16
|
surface it sits on. The number stays in --axi-text unless it has a real
|
|
17
17
|
state: rule 5 applies to a figure exactly as it applies to a chip, and a
|
|
18
|
-
tile coloured for emphasis is decoration impersonating status.
|
|
18
|
+
tile coloured for emphasis is decoration impersonating status.
|
|
19
|
+
|
|
20
|
+
Flat on the ground is the WELL's fill and not the page's. A tile is a recess
|
|
21
|
+
cut into the panel holding it, which is the same shape .axi-well names, and
|
|
22
|
+
spelled --axi-ground it stops being a recess the moment a theme makes that
|
|
23
|
+
panel translucent: an opaque page colour inside a pane of glass is a black
|
|
24
|
+
patch. The outline stays the ink line rather than following the well's,
|
|
25
|
+
because a tile is cut into a SURFACE and an ink edge still has something to
|
|
26
|
+
be darker than there. Same split in .axi-meter and .axi-plot below. */
|
|
19
27
|
.axi-stat {
|
|
20
28
|
padding: 12px 14px;
|
|
21
|
-
background: var(--axi-
|
|
29
|
+
background: var(--axi-well-fill);
|
|
22
30
|
border: var(--axi-border-control) solid var(--axi-ink-line);
|
|
23
31
|
border-radius: var(--axi-radius-sm);
|
|
24
32
|
}
|
|
@@ -105,7 +113,8 @@
|
|
|
105
113
|
display: grid; place-items: center;
|
|
106
114
|
border: var(--axi-border-control) solid var(--axi-ink-line);
|
|
107
115
|
border-radius: var(--axi-radius-sm);
|
|
108
|
-
|
|
116
|
+
/* Flat in the row, like the tile above and the avatar it stands beside. */
|
|
117
|
+
background: var(--axi-well-fill);
|
|
109
118
|
font: var(--axi-t-micro);
|
|
110
119
|
color: var(--axi-text-faint);
|
|
111
120
|
}
|
|
@@ -209,7 +218,8 @@
|
|
|
209
218
|
.axi-meter {
|
|
210
219
|
display: flex;
|
|
211
220
|
height: var(--axi-meter-h, 12px);
|
|
212
|
-
|
|
221
|
+
/* The trough is a recess, so it takes the well's fill - see .axi-stat. */
|
|
222
|
+
background: var(--axi-well-fill);
|
|
213
223
|
border: var(--axi-border-control) solid var(--axi-ink-line);
|
|
214
224
|
border-radius: var(--axi-radius-sm);
|
|
215
225
|
overflow: hidden;
|
|
@@ -325,7 +335,8 @@
|
|
|
325
335
|
.axi-plot {
|
|
326
336
|
position: relative;
|
|
327
337
|
height: var(--axi-plot-h, 180px);
|
|
328
|
-
|
|
338
|
+
/* A frame cut into the panel, not laid on the page - see .axi-stat. */
|
|
339
|
+
background-color: var(--axi-well-fill);
|
|
329
340
|
background-image: repeating-linear-gradient(
|
|
330
341
|
to top,
|
|
331
342
|
var(--axi-rule) 0 var(--axi-border-hairline),
|
package/src/forms.css
CHANGED
|
@@ -34,7 +34,9 @@
|
|
|
34
34
|
height: var(--axi-check-size, 22px);
|
|
35
35
|
display: inline-grid;
|
|
36
36
|
place-items: center;
|
|
37
|
-
|
|
37
|
+
/* An empty box is a hole you put a mark in, so the level's fill - see
|
|
38
|
+
--axi-well-fill in src/tokens.css. :checked below replaces it outright. */
|
|
39
|
+
background: var(--axi-well-fill);
|
|
38
40
|
border: var(--axi-border-control) solid var(--axi-ink-line);
|
|
39
41
|
/* The text-sized step, not the control-sized one - see --axi-radius-xs in
|
|
40
42
|
src/tokens.css for why a 22px box cannot take a corner scaled for a 36px
|
package/src/primitives.css
CHANGED
|
@@ -97,13 +97,29 @@ button.axi-panel--tile:hover,
|
|
|
97
97
|
padding: var(--axi-well-pad, 10px);
|
|
98
98
|
}
|
|
99
99
|
|
|
100
|
+
/* The reading-scale well, which the comment above describes and this language
|
|
101
|
+
then made every consumer spell out by hand. Saying `--axi-radius-sm` inline
|
|
102
|
+
is fine for the handful of instances that comment imagined; the first real
|
|
103
|
+
consumer to be counted had fifty, and fifty inline style attributes is the
|
|
104
|
+
thing a class exists to prevent. The same argument produced .axi-btn--sm.
|
|
105
|
+
|
|
106
|
+
Only the radius, because that is the only thing that changes: a recess the
|
|
107
|
+
size of a single reading still holds objects that carry their own padding, so
|
|
108
|
+
the pad knob is still the right way to say anything else. */
|
|
109
|
+
.axi-well--sm { --axi-well-radius: var(--axi-radius-sm); }
|
|
110
|
+
|
|
100
111
|
/* ---------- button ---------- */
|
|
101
112
|
.axi-btn {
|
|
102
113
|
display: inline-flex; align-items: center; gap: 8px;
|
|
103
114
|
padding: var(--axi-btn-pad, 12px 20px);
|
|
104
115
|
border: var(--axi-border-control) solid var(--axi-ink-line);
|
|
105
116
|
border-radius: var(--axi-radius-sm);
|
|
106
|
-
|
|
117
|
+
/* Flat on its container, which is --axi-well-fill and not the page colour -
|
|
118
|
+
the argument is in src/tokens.css at that token. A button at rest carries
|
|
119
|
+
no block: it is level with the panel holding it and lifts on hover, so the
|
|
120
|
+
resting fill is the level's, and --axi-btn--primary below is the one that
|
|
121
|
+
rests raised and fills with the accent instead. */
|
|
122
|
+
background: var(--axi-well-fill);
|
|
107
123
|
color: var(--axi-text-dim);
|
|
108
124
|
font: var(--axi-t-label);
|
|
109
125
|
letter-spacing: var(--axi-ls-label);
|
|
@@ -186,7 +202,8 @@ button.axi-panel--tile:hover,
|
|
|
186
202
|
padding: var(--axi-pill-pad, 12px 20px);
|
|
187
203
|
border: var(--axi-border-control) solid var(--axi-ink-line);
|
|
188
204
|
border-radius: var(--axi-radius-sm);
|
|
189
|
-
|
|
205
|
+
/* The button's fill for the button's reason - see .axi-btn above. */
|
|
206
|
+
background: var(--axi-well-fill);
|
|
190
207
|
color: var(--axi-text-dim);
|
|
191
208
|
font: var(--axi-t-label);
|
|
192
209
|
letter-spacing: var(--axi-ls-label);
|
|
@@ -380,7 +397,10 @@ button.axi-panel--tile:hover,
|
|
|
380
397
|
.axi-input {
|
|
381
398
|
width: 100%;
|
|
382
399
|
padding: var(--axi-input-pad, 11px 12px);
|
|
383
|
-
|
|
400
|
+
/* A field is the recessed thing in any bar it sits in - .axi-kbd's comment
|
|
401
|
+
below leans on exactly that - so it takes the level's fill. See
|
|
402
|
+
--axi-well-fill in src/tokens.css. */
|
|
403
|
+
background: var(--axi-well-fill);
|
|
384
404
|
border: var(--axi-border-control) solid var(--axi-ink-line);
|
|
385
405
|
border-radius: var(--axi-radius-sm);
|
|
386
406
|
color: var(--axi-text);
|
|
@@ -415,14 +435,15 @@ button.axi-panel--tile:hover,
|
|
|
415
435
|
`em`, not `px`: this lands in body copy and in 10px captions alike, and a
|
|
416
436
|
literal that does not track the text around it reads as a different voice.
|
|
417
437
|
|
|
418
|
-
It sits on --axi-
|
|
438
|
+
It sits on --axi-well-fill where .axi-kbd sits on --axi-surface, and the
|
|
419
439
|
reason is already written down one rule below: a key is raised off what it
|
|
420
|
-
is printed on, and a quoted literal is sunk into it.
|
|
440
|
+
is printed on, and a quoted literal is sunk into it. It said --axi-ground
|
|
441
|
+
for as long as sunk and the page were the same colour; see that token. */
|
|
421
442
|
.axi-code,
|
|
422
443
|
.axi-prose code {
|
|
423
444
|
font-family: var(--axi-mono);
|
|
424
445
|
font-size: .88em;
|
|
425
|
-
background: var(--axi-
|
|
446
|
+
background: var(--axi-well-fill);
|
|
426
447
|
color: var(--axi-text);
|
|
427
448
|
border: var(--axi-border-hairline) solid var(--axi-ink-line);
|
|
428
449
|
border-radius: var(--axi-radius-sm);
|
|
@@ -462,7 +483,10 @@ button.axi-panel--tile:hover,
|
|
|
462
483
|
padding: 10px 30px 10px 9px;
|
|
463
484
|
border: var(--axi-border-control) solid var(--axi-ink-line);
|
|
464
485
|
border-radius: var(--axi-radius-sm);
|
|
465
|
-
|
|
486
|
+
/* The field's fill, because a closed select is a field - see .axi-input. The
|
|
487
|
+
longhand stays: a caret rides in background-image and the shorthand would
|
|
488
|
+
reset it. */
|
|
489
|
+
background-color: var(--axi-well-fill);
|
|
466
490
|
color: var(--axi-text-dim);
|
|
467
491
|
font: var(--axi-t-label);
|
|
468
492
|
font-size: 12.5px;
|
|
@@ -521,8 +545,12 @@ button.axi-panel--tile:hover,
|
|
|
521
545
|
letter-spacing: var(--axi-ls-label);
|
|
522
546
|
text-transform: uppercase;
|
|
523
547
|
}
|
|
548
|
+
/* A row under the cursor sinks rather than lighting up, so the hover is the
|
|
549
|
+
level's fill - and this popover is filled with --axi-surface-raised, which
|
|
550
|
+
a theme may take translucent, so an opaque row here is the black patch
|
|
551
|
+
--axi-well-fill exists to prevent. Same for the picker's rows below. */
|
|
524
552
|
.axi-select option:hover, .axi-select option:focus {
|
|
525
|
-
background: var(--axi-
|
|
553
|
+
background: var(--axi-well-fill); color: var(--axi-text);
|
|
526
554
|
}
|
|
527
555
|
/* The page-wide focus ring sits 2px outside its element; inside a picker
|
|
528
556
|
that is 2px into the neighbouring row, so pull it back in. */
|
|
@@ -621,7 +649,7 @@ button.axi-panel--tile:hover,
|
|
|
621
649
|
font-weight: 900;
|
|
622
650
|
}
|
|
623
651
|
.axi-picker__opt:hover, .axi-picker__opt:focus {
|
|
624
|
-
background: var(--axi-
|
|
652
|
+
background: var(--axi-well-fill); color: var(--axi-text);
|
|
625
653
|
}
|
|
626
654
|
/* The page-wide focus ring sits 2px outside its element; inside a popover
|
|
627
655
|
this tight that is 2px into the neighbouring row, so pull it back in. */
|
|
@@ -636,7 +664,8 @@ button.axi-panel--tile:hover,
|
|
|
636
664
|
who wants round avatars sets --axi-radius-sm and gets rounded controls
|
|
637
665
|
everywhere - which is the honest version of the request.
|
|
638
666
|
Flat: outlined, no block. An avatar is content inside a panel, the same as
|
|
639
|
-
.axi-stat and .axi-table__rank, not a thing raised off it
|
|
667
|
+
.axi-stat and .axi-table__rank, not a thing raised off it - which is what
|
|
668
|
+
--axi-well-fill below is saying, and all three now say it the same way. */
|
|
640
669
|
.axi-avatar {
|
|
641
670
|
width: var(--axi-avatar-size, 40px);
|
|
642
671
|
height: var(--axi-avatar-size, 40px);
|
|
@@ -644,7 +673,7 @@ button.axi-panel--tile:hover,
|
|
|
644
673
|
display: grid;
|
|
645
674
|
place-items: center;
|
|
646
675
|
overflow: hidden;
|
|
647
|
-
background: var(--axi-
|
|
676
|
+
background: var(--axi-well-fill);
|
|
648
677
|
color: var(--axi-text-dim);
|
|
649
678
|
border: var(--axi-border-control) solid var(--axi-ink-line);
|
|
650
679
|
border-radius: var(--axi-radius-sm);
|
package/src/prose.css
CHANGED
|
@@ -48,9 +48,12 @@
|
|
|
48
48
|
|
|
49
49
|
/* .axi-prose code is declared beside .axi-code in primitives.css: one rule,
|
|
50
50
|
both selectors, because they are one object. */
|
|
51
|
+
/* A code block and a quote are both fields sunk into the prose around them,
|
|
52
|
+
so both take --axi-well-fill rather than the page colour - the reason is
|
|
53
|
+
written out at .axi-stat in src/data.css. */
|
|
51
54
|
.axi-prose pre {
|
|
52
55
|
margin: 0 0 18px; padding: 14px 16px; overflow-x: auto;
|
|
53
|
-
background: var(--axi-
|
|
56
|
+
background: var(--axi-well-fill);
|
|
54
57
|
border: var(--axi-border-control) solid var(--axi-ink-line);
|
|
55
58
|
border-radius: var(--axi-radius-sm);
|
|
56
59
|
box-shadow: var(--axi-shadow-control);
|
|
@@ -61,7 +64,7 @@
|
|
|
61
64
|
margin: 0 0 18px;
|
|
62
65
|
padding: 11px 13px;
|
|
63
66
|
border-left: var(--axi-border-panel) solid var(--axi-accent);
|
|
64
|
-
background: var(--axi-
|
|
67
|
+
background: var(--axi-well-fill);
|
|
65
68
|
border-radius: 0 var(--axi-radius-sm) var(--axi-radius-sm) 0;
|
|
66
69
|
}
|
|
67
70
|
.axi-prose blockquote p { margin: 0; font-style: italic; }
|
package/src/shells.css
CHANGED
|
@@ -13,9 +13,18 @@
|
|
|
13
13
|
}
|
|
14
14
|
|
|
15
15
|
/* ---------- masthead ---------- */
|
|
16
|
+
/* Opaque, because content scrolls under it. Which is also why it paints the
|
|
17
|
+
page's light as well as the page's colour: an opaque strip across the top of
|
|
18
|
+
a lit page is a dark band over that light, and the band is there on every
|
|
19
|
+
page of a site the whole time it is open. Attachment fixed, the same as
|
|
20
|
+
`body`, so the strip's share of the light is the share the page would have
|
|
21
|
+
shown there - a wash positioned to this element's own box instead would
|
|
22
|
+
line up with nothing. */
|
|
16
23
|
.axi-mast {
|
|
17
24
|
position: sticky; top: 0; z-index: 40;
|
|
18
|
-
background: var(--axi-ground);
|
|
25
|
+
background-color: var(--axi-ground);
|
|
26
|
+
background-image: var(--axi-ground-image);
|
|
27
|
+
background-attachment: fixed;
|
|
19
28
|
border-bottom: var(--axi-border-panel) solid var(--axi-ink-line);
|
|
20
29
|
}
|
|
21
30
|
.axi-mast__in {
|
|
@@ -226,6 +235,41 @@
|
|
|
226
235
|
the faint tone, and inside a filled item it follows the item's ink. */
|
|
227
236
|
.axi-rail__item .axi-icon { color: var(--axi-text-faint); }
|
|
228
237
|
.axi-rail__item[aria-current] .axi-icon { color: var(--axi-accent-ink); }
|
|
238
|
+
/* A rail nested inside a panel whose content already spends the accent: a
|
|
239
|
+
metric picker beside the table it drives, a filter list beside its results.
|
|
240
|
+
The language already refuses two fills at two levels inside one rail - that
|
|
241
|
+
is why .axi-rail__subitem has no fill - and a rail that is itself the inner
|
|
242
|
+
level is the same refusal one container further out. Two filled rails on
|
|
243
|
+
one screen name two places, and only one of them is where you are.
|
|
244
|
+
|
|
245
|
+
What it cannot do is borrow the subitem's answer. A subitem is one of a
|
|
246
|
+
handful of leaves under an open category; a picker like this is twenty rows
|
|
247
|
+
and the primary control of its own panel, so brightened text alone loses
|
|
248
|
+
the selection in the list. This is the third weight between the two: the
|
|
249
|
+
row rises off the rail as any hovered row does, and the accent arrives on
|
|
250
|
+
its leading edge. The accent still says which row without the row claiming
|
|
251
|
+
to be the place.
|
|
252
|
+
|
|
253
|
+
The edge is the item's own border, which .axi-rail__item already reserves
|
|
254
|
+
at the control weight and draws transparent - so the bar costs no shadow,
|
|
255
|
+
no extra box and no reflow when it lights up. Logical, not left: this is
|
|
256
|
+
the leading edge, the same correction .axi-rail--flush took.
|
|
257
|
+
|
|
258
|
+
The modifier goes on the list, not on .axi-rail, because a nested picker
|
|
259
|
+
usually has no rail box around it - it sits directly in the panel or well
|
|
260
|
+
that holds it, and inheriting a 208px width and a panel shadow is the
|
|
261
|
+
opposite of what it wants. */
|
|
262
|
+
.axi-rail__nav--quiet .axi-rail__item[aria-current],
|
|
263
|
+
.axi-rail__nav--quiet .axi-rail__item[aria-current]:hover {
|
|
264
|
+
background: var(--axi-surface-raised);
|
|
265
|
+
color: var(--axi-text);
|
|
266
|
+
border-color: transparent;
|
|
267
|
+
border-inline-start-color: var(--axi-accent);
|
|
268
|
+
}
|
|
269
|
+
/* No accent fill here, so the icon has no accent ink to follow - it follows
|
|
270
|
+
the row's own text, the way it does in an unselected item. */
|
|
271
|
+
.axi-rail__nav--quiet .axi-rail__item[aria-current] .axi-icon { color: var(--axi-text); }
|
|
272
|
+
|
|
229
273
|
/* The second level, indented under the item it belongs to. */
|
|
230
274
|
.axi-rail__sub { display: flex; flex-direction: column; margin: 3px 0 5px 10px; }
|
|
231
275
|
.axi-rail__subitem {
|
|
@@ -391,7 +435,8 @@
|
|
|
391
435
|
padding: 7px 8px; border-radius: var(--axi-radius-sm);
|
|
392
436
|
font-size: 13px; font-weight: 600; color: var(--axi-text-dim); cursor: pointer;
|
|
393
437
|
}
|
|
394
|
-
|
|
438
|
+
/* A hovered row sinks - the same fill the select's and the picker's rows use. */
|
|
439
|
+
.axi-menu__pop label:hover { background: var(--axi-well-fill); color: var(--axi-text); }
|
|
395
440
|
.axi-menu__pop input { margin: 3px 0 0; }
|
|
396
441
|
|
|
397
442
|
/* ---------- command palette ---------- */
|
|
@@ -505,7 +550,7 @@
|
|
|
505
550
|
.axi-palette__trigger {
|
|
506
551
|
display: flex; align-items: center; width: 100%; overflow: hidden;
|
|
507
552
|
padding: 0 10px 0 0;
|
|
508
|
-
background: var(--axi-
|
|
553
|
+
background: var(--axi-well-fill);
|
|
509
554
|
border: var(--axi-border-control) solid var(--axi-ink-line);
|
|
510
555
|
border-radius: var(--axi-radius-sm);
|
|
511
556
|
color: var(--axi-text-dim);
|
|
@@ -689,7 +734,8 @@
|
|
|
689
734
|
width: 32px; height: 32px;
|
|
690
735
|
display: grid; place-items: center;
|
|
691
736
|
border-radius: var(--axi-radius-sm);
|
|
692
|
-
|
|
737
|
+
/* A control flat on the drawer's head - see --axi-well-fill in tokens. */
|
|
738
|
+
background: var(--axi-well-fill);
|
|
693
739
|
border: var(--axi-border-control) solid var(--axi-ink-line);
|
|
694
740
|
color: var(--axi-text-dim);
|
|
695
741
|
font-size: 15px; font-weight: 900; cursor: pointer;
|
|
@@ -755,6 +801,13 @@
|
|
|
755
801
|
overflow-y: auto;
|
|
756
802
|
background-color: var(--axi-ground);
|
|
757
803
|
background-image: var(--axi-ground-image);
|
|
804
|
+
/* Fixed for both of the reasons `body` is: the light stays put while the
|
|
805
|
+
sheet's own content scrolls, and it is positioned to the viewport rather
|
|
806
|
+
than to this box - which matters here because --axi-sheet-top pushes that
|
|
807
|
+
box down under an app's titlebar, and a wash measured from its top edge
|
|
808
|
+
would sit lower than the one on the page it covers. Opening a sheet would
|
|
809
|
+
nudge the light sideways. */
|
|
810
|
+
background-attachment: fixed;
|
|
758
811
|
padding: var(--axi-sheet-pad, 12px 16px);
|
|
759
812
|
}
|
|
760
813
|
/* The heading the sheet opened with, divided from the body by a rule. Rule 8:
|
|
@@ -777,7 +830,8 @@
|
|
|
777
830
|
margin: 0;
|
|
778
831
|
padding: 11px 13px;
|
|
779
832
|
border-left: var(--axi-border-panel) solid var(--axi-accent);
|
|
780
|
-
|
|
833
|
+
/* Sunk into the prose around it, so the well's fill - see .axi-stat. */
|
|
834
|
+
background: var(--axi-well-fill);
|
|
781
835
|
border-radius: 0 var(--axi-radius-sm) var(--axi-radius-sm) 0;
|
|
782
836
|
}
|
|
783
837
|
.axi-quote :where(p) { margin: 0; font-size: 13px; font-style: italic; color: var(--axi-text-dim); line-height: 1.5; }
|
|
@@ -794,13 +848,24 @@
|
|
|
794
848
|
takes the panel outline. It carries no block, because a block is an
|
|
795
849
|
element's shadow on the surface behind it and there is nothing behind a
|
|
796
850
|
window that this language is entitled to draw on.
|
|
851
|
+
|
|
852
|
+
It is the page. Not a page inside one - the only one, for as long as the app
|
|
853
|
+
is running, which is why it paints the ground's IMAGE as well as the
|
|
854
|
+
ground's colour. `body` is behind it and lights nothing, because a window
|
|
855
|
+
covers the viewport and is opaque by the same requirement that makes it
|
|
856
|
+
opaque over its own content. A window that skipped the image would render a
|
|
857
|
+
theme whose character is the light - glass - as flat near-black: every panel
|
|
858
|
+
inside it correctly translucent, over nothing. Longhands for the reason
|
|
859
|
+
.axi-sheet gives at length below; no attachment, because this element's box
|
|
860
|
+
IS the viewport and never scrolls, so fixed and scroll paint the same pixels.
|
|
797
861
|
The titlebar is filled with the ink line rather than a surface: it is the
|
|
798
862
|
outline widened into a strip, which is why the app's content reads as
|
|
799
863
|
sitting inside the outline instead of under a second toolbar. */
|
|
800
864
|
.axi-window {
|
|
801
865
|
height: 100vh;
|
|
802
866
|
display: flex; flex-direction: column; overflow: hidden;
|
|
803
|
-
background: var(--axi-ground);
|
|
867
|
+
background-color: var(--axi-ground);
|
|
868
|
+
background-image: var(--axi-ground-image);
|
|
804
869
|
border: var(--axi-border-panel) solid var(--axi-ink-line);
|
|
805
870
|
border-radius: var(--axi-radius);
|
|
806
871
|
}
|
package/src/tokens.css
CHANGED
|
@@ -80,7 +80,26 @@
|
|
|
80
80
|
against a fill lighter than itself. Every outline in this language is
|
|
81
81
|
near-black on the assumption of a ground the lines can be darker than; a
|
|
82
82
|
well IS at ground level, so an ink edge round one is a black line on a
|
|
83
|
-
black field. Raised takes ink, sunk takes the rule.
|
|
83
|
+
black field. Raised takes ink, sunk takes the rule.
|
|
84
|
+
|
|
85
|
+
And what the fill names is not the .axi-well class - it is the level. A
|
|
86
|
+
button at rest, a field, a select, a checkbox, an avatar, a rank, a code
|
|
87
|
+
span, a hovered row in a popover: not one of them is raised off what holds
|
|
88
|
+
it, and every one of them was spelled --axi-ground, because on a theme
|
|
89
|
+
whose surfaces are opaque "flat on its container" and "the page colour"
|
|
90
|
+
are the same colour. They stop being the same colour the instant a theme
|
|
91
|
+
makes the container translucent, which is how the whole set went black at
|
|
92
|
+
once and why this is written here rather than fourteen times downstream.
|
|
93
|
+
Above this level is --axi-surface (.axi-kbd is the one control in the
|
|
94
|
+
language that is genuinely raised, and says so). Below it is --axi-ground
|
|
95
|
+
proper, which now means the page and only the page: body, the sheet, the
|
|
96
|
+
window, the masthead - the things content scrolls under, which need real
|
|
97
|
+
opacity and not a subtraction. Everything between the two is this token.
|
|
98
|
+
|
|
99
|
+
The LINE does not come along. --axi-well-line is for a well cut into the
|
|
100
|
+
page, where there is nothing left for ink to be darker than; a control is
|
|
101
|
+
cut into a SURFACE and its ink edge still has a fill above it to read
|
|
102
|
+
against. Every component below keeps --axi-ink-line. */
|
|
84
103
|
--axi-well-fill: var(--axi-ground);
|
|
85
104
|
--axi-well-line: var(--axi-rule);
|
|
86
105
|
--axi-text: #f4f6f9;
|