@axiapps/axi-design 1.34.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 +144 -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 +29 -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;
|
|
@@ -388,7 +407,12 @@ button.axi-panel--tile:hover,
|
|
|
388
407
|
padding: var(--axi-btn-pad, 12px 20px);
|
|
389
408
|
border: var(--axi-border-control) solid var(--axi-ink-line);
|
|
390
409
|
border-radius: var(--axi-radius-sm);
|
|
391
|
-
|
|
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);
|
|
392
416
|
color: var(--axi-text-dim);
|
|
393
417
|
font: var(--axi-t-label);
|
|
394
418
|
letter-spacing: var(--axi-ls-label);
|
|
@@ -471,7 +495,8 @@ button.axi-panel--tile:hover,
|
|
|
471
495
|
padding: var(--axi-pill-pad, 12px 20px);
|
|
472
496
|
border: var(--axi-border-control) solid var(--axi-ink-line);
|
|
473
497
|
border-radius: var(--axi-radius-sm);
|
|
474
|
-
|
|
498
|
+
/* The button's fill for the button's reason - see .axi-btn above. */
|
|
499
|
+
background: var(--axi-well-fill);
|
|
475
500
|
color: var(--axi-text-dim);
|
|
476
501
|
font: var(--axi-t-label);
|
|
477
502
|
letter-spacing: var(--axi-ls-label);
|
|
@@ -665,7 +690,10 @@ button.axi-panel--tile:hover,
|
|
|
665
690
|
.axi-input {
|
|
666
691
|
width: 100%;
|
|
667
692
|
padding: var(--axi-input-pad, 11px 12px);
|
|
668
|
-
|
|
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);
|
|
669
697
|
border: var(--axi-border-control) solid var(--axi-ink-line);
|
|
670
698
|
border-radius: var(--axi-radius-sm);
|
|
671
699
|
color: var(--axi-text);
|
|
@@ -700,14 +728,15 @@ button.axi-panel--tile:hover,
|
|
|
700
728
|
`em`, not `px`: this lands in body copy and in 10px captions alike, and a
|
|
701
729
|
literal that does not track the text around it reads as a different voice.
|
|
702
730
|
|
|
703
|
-
It sits on --axi-
|
|
731
|
+
It sits on --axi-well-fill where .axi-kbd sits on --axi-surface, and the
|
|
704
732
|
reason is already written down one rule below: a key is raised off what it
|
|
705
|
-
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. */
|
|
706
735
|
.axi-code,
|
|
707
736
|
.axi-prose code {
|
|
708
737
|
font-family: var(--axi-mono);
|
|
709
738
|
font-size: .88em;
|
|
710
|
-
background: var(--axi-
|
|
739
|
+
background: var(--axi-well-fill);
|
|
711
740
|
color: var(--axi-text);
|
|
712
741
|
border: var(--axi-border-hairline) solid var(--axi-ink-line);
|
|
713
742
|
border-radius: var(--axi-radius-sm);
|
|
@@ -747,7 +776,10 @@ button.axi-panel--tile:hover,
|
|
|
747
776
|
padding: 10px 30px 10px 9px;
|
|
748
777
|
border: var(--axi-border-control) solid var(--axi-ink-line);
|
|
749
778
|
border-radius: var(--axi-radius-sm);
|
|
750
|
-
|
|
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);
|
|
751
783
|
color: var(--axi-text-dim);
|
|
752
784
|
font: var(--axi-t-label);
|
|
753
785
|
font-size: 12.5px;
|
|
@@ -806,8 +838,12 @@ button.axi-panel--tile:hover,
|
|
|
806
838
|
letter-spacing: var(--axi-ls-label);
|
|
807
839
|
text-transform: uppercase;
|
|
808
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. */
|
|
809
845
|
.axi-select option:hover, .axi-select option:focus {
|
|
810
|
-
background: var(--axi-
|
|
846
|
+
background: var(--axi-well-fill); color: var(--axi-text);
|
|
811
847
|
}
|
|
812
848
|
/* The page-wide focus ring sits 2px outside its element; inside a picker
|
|
813
849
|
that is 2px into the neighbouring row, so pull it back in. */
|
|
@@ -906,7 +942,7 @@ button.axi-panel--tile:hover,
|
|
|
906
942
|
font-weight: 900;
|
|
907
943
|
}
|
|
908
944
|
.axi-picker__opt:hover, .axi-picker__opt:focus {
|
|
909
|
-
background: var(--axi-
|
|
945
|
+
background: var(--axi-well-fill); color: var(--axi-text);
|
|
910
946
|
}
|
|
911
947
|
/* The page-wide focus ring sits 2px outside its element; inside a popover
|
|
912
948
|
this tight that is 2px into the neighbouring row, so pull it back in. */
|
|
@@ -921,7 +957,8 @@ button.axi-panel--tile:hover,
|
|
|
921
957
|
who wants round avatars sets --axi-radius-sm and gets rounded controls
|
|
922
958
|
everywhere - which is the honest version of the request.
|
|
923
959
|
Flat: outlined, no block. An avatar is content inside a panel, the same as
|
|
924
|
-
.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. */
|
|
925
962
|
.axi-avatar {
|
|
926
963
|
width: var(--axi-avatar-size, 40px);
|
|
927
964
|
height: var(--axi-avatar-size, 40px);
|
|
@@ -929,7 +966,7 @@ button.axi-panel--tile:hover,
|
|
|
929
966
|
display: grid;
|
|
930
967
|
place-items: center;
|
|
931
968
|
overflow: hidden;
|
|
932
|
-
background: var(--axi-
|
|
969
|
+
background: var(--axi-well-fill);
|
|
933
970
|
color: var(--axi-text-dim);
|
|
934
971
|
border: var(--axi-border-control) solid var(--axi-ink-line);
|
|
935
972
|
border-radius: var(--axi-radius-sm);
|
|
@@ -994,7 +1031,9 @@ button.axi-panel--tile:hover,
|
|
|
994
1031
|
height: var(--axi-check-size, 22px);
|
|
995
1032
|
display: inline-grid;
|
|
996
1033
|
place-items: center;
|
|
997
|
-
|
|
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);
|
|
998
1037
|
border: var(--axi-border-control) solid var(--axi-ink-line);
|
|
999
1038
|
/* The text-sized step, not the control-sized one - see --axi-radius-xs in
|
|
1000
1039
|
src/tokens.css for why a 22px box cannot take a corner scaled for a 36px
|
|
@@ -1116,9 +1155,18 @@ textarea.axi-input {
|
|
|
1116
1155
|
}
|
|
1117
1156
|
|
|
1118
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. */
|
|
1119
1165
|
.axi-mast {
|
|
1120
1166
|
position: sticky; top: 0; z-index: 40;
|
|
1121
|
-
background: var(--axi-ground);
|
|
1167
|
+
background-color: var(--axi-ground);
|
|
1168
|
+
background-image: var(--axi-ground-image);
|
|
1169
|
+
background-attachment: fixed;
|
|
1122
1170
|
border-bottom: var(--axi-border-panel) solid var(--axi-ink-line);
|
|
1123
1171
|
}
|
|
1124
1172
|
.axi-mast__in {
|
|
@@ -1329,6 +1377,41 @@ textarea.axi-input {
|
|
|
1329
1377
|
the faint tone, and inside a filled item it follows the item's ink. */
|
|
1330
1378
|
.axi-rail__item .axi-icon { color: var(--axi-text-faint); }
|
|
1331
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
|
+
|
|
1332
1415
|
/* The second level, indented under the item it belongs to. */
|
|
1333
1416
|
.axi-rail__sub { display: flex; flex-direction: column; margin: 3px 0 5px 10px; }
|
|
1334
1417
|
.axi-rail__subitem {
|
|
@@ -1494,7 +1577,8 @@ textarea.axi-input {
|
|
|
1494
1577
|
padding: 7px 8px; border-radius: var(--axi-radius-sm);
|
|
1495
1578
|
font-size: 13px; font-weight: 600; color: var(--axi-text-dim); cursor: pointer;
|
|
1496
1579
|
}
|
|
1497
|
-
|
|
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); }
|
|
1498
1582
|
.axi-menu__pop input { margin: 3px 0 0; }
|
|
1499
1583
|
|
|
1500
1584
|
/* ---------- command palette ---------- */
|
|
@@ -1608,7 +1692,7 @@ textarea.axi-input {
|
|
|
1608
1692
|
.axi-palette__trigger {
|
|
1609
1693
|
display: flex; align-items: center; width: 100%; overflow: hidden;
|
|
1610
1694
|
padding: 0 10px 0 0;
|
|
1611
|
-
background: var(--axi-
|
|
1695
|
+
background: var(--axi-well-fill);
|
|
1612
1696
|
border: var(--axi-border-control) solid var(--axi-ink-line);
|
|
1613
1697
|
border-radius: var(--axi-radius-sm);
|
|
1614
1698
|
color: var(--axi-text-dim);
|
|
@@ -1792,7 +1876,8 @@ textarea.axi-input {
|
|
|
1792
1876
|
width: 32px; height: 32px;
|
|
1793
1877
|
display: grid; place-items: center;
|
|
1794
1878
|
border-radius: var(--axi-radius-sm);
|
|
1795
|
-
|
|
1879
|
+
/* A control flat on the drawer's head - see --axi-well-fill in tokens. */
|
|
1880
|
+
background: var(--axi-well-fill);
|
|
1796
1881
|
border: var(--axi-border-control) solid var(--axi-ink-line);
|
|
1797
1882
|
color: var(--axi-text-dim);
|
|
1798
1883
|
font-size: 15px; font-weight: 900; cursor: pointer;
|
|
@@ -1858,6 +1943,13 @@ textarea.axi-input {
|
|
|
1858
1943
|
overflow-y: auto;
|
|
1859
1944
|
background-color: var(--axi-ground);
|
|
1860
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;
|
|
1861
1953
|
padding: var(--axi-sheet-pad, 12px 16px);
|
|
1862
1954
|
}
|
|
1863
1955
|
/* The heading the sheet opened with, divided from the body by a rule. Rule 8:
|
|
@@ -1880,7 +1972,8 @@ textarea.axi-input {
|
|
|
1880
1972
|
margin: 0;
|
|
1881
1973
|
padding: 11px 13px;
|
|
1882
1974
|
border-left: var(--axi-border-panel) solid var(--axi-accent);
|
|
1883
|
-
|
|
1975
|
+
/* Sunk into the prose around it, so the well's fill - see .axi-stat. */
|
|
1976
|
+
background: var(--axi-well-fill);
|
|
1884
1977
|
border-radius: 0 var(--axi-radius-sm) var(--axi-radius-sm) 0;
|
|
1885
1978
|
}
|
|
1886
1979
|
.axi-quote :where(p) { margin: 0; font-size: 13px; font-style: italic; color: var(--axi-text-dim); line-height: 1.5; }
|
|
@@ -1897,13 +1990,24 @@ textarea.axi-input {
|
|
|
1897
1990
|
takes the panel outline. It carries no block, because a block is an
|
|
1898
1991
|
element's shadow on the surface behind it and there is nothing behind a
|
|
1899
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.
|
|
1900
2003
|
The titlebar is filled with the ink line rather than a surface: it is the
|
|
1901
2004
|
outline widened into a strip, which is why the app's content reads as
|
|
1902
2005
|
sitting inside the outline instead of under a second toolbar. */
|
|
1903
2006
|
.axi-window {
|
|
1904
2007
|
height: 100vh;
|
|
1905
2008
|
display: flex; flex-direction: column; overflow: hidden;
|
|
1906
|
-
background: var(--axi-ground);
|
|
2009
|
+
background-color: var(--axi-ground);
|
|
2010
|
+
background-image: var(--axi-ground-image);
|
|
1907
2011
|
border: var(--axi-border-panel) solid var(--axi-ink-line);
|
|
1908
2012
|
border-radius: var(--axi-radius);
|
|
1909
2013
|
}
|
|
@@ -2170,10 +2274,18 @@ textarea.axi-input {
|
|
|
2170
2274
|
an outline and no block - it is content, not something raised off the
|
|
2171
2275
|
surface it sits on. The number stays in --axi-text unless it has a real
|
|
2172
2276
|
state: rule 5 applies to a figure exactly as it applies to a chip, and a
|
|
2173
|
-
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. */
|
|
2174
2286
|
.axi-stat {
|
|
2175
2287
|
padding: 12px 14px;
|
|
2176
|
-
background: var(--axi-
|
|
2288
|
+
background: var(--axi-well-fill);
|
|
2177
2289
|
border: var(--axi-border-control) solid var(--axi-ink-line);
|
|
2178
2290
|
border-radius: var(--axi-radius-sm);
|
|
2179
2291
|
}
|
|
@@ -2260,7 +2372,8 @@ textarea.axi-input {
|
|
|
2260
2372
|
display: grid; place-items: center;
|
|
2261
2373
|
border: var(--axi-border-control) solid var(--axi-ink-line);
|
|
2262
2374
|
border-radius: var(--axi-radius-sm);
|
|
2263
|
-
|
|
2375
|
+
/* Flat in the row, like the tile above and the avatar it stands beside. */
|
|
2376
|
+
background: var(--axi-well-fill);
|
|
2264
2377
|
font: var(--axi-t-micro);
|
|
2265
2378
|
color: var(--axi-text-faint);
|
|
2266
2379
|
}
|
|
@@ -2364,7 +2477,8 @@ textarea.axi-input {
|
|
|
2364
2477
|
.axi-meter {
|
|
2365
2478
|
display: flex;
|
|
2366
2479
|
height: var(--axi-meter-h, 12px);
|
|
2367
|
-
|
|
2480
|
+
/* The trough is a recess, so it takes the well's fill - see .axi-stat. */
|
|
2481
|
+
background: var(--axi-well-fill);
|
|
2368
2482
|
border: var(--axi-border-control) solid var(--axi-ink-line);
|
|
2369
2483
|
border-radius: var(--axi-radius-sm);
|
|
2370
2484
|
overflow: hidden;
|
|
@@ -2480,7 +2594,8 @@ textarea.axi-input {
|
|
|
2480
2594
|
.axi-plot {
|
|
2481
2595
|
position: relative;
|
|
2482
2596
|
height: var(--axi-plot-h, 180px);
|
|
2483
|
-
|
|
2597
|
+
/* A frame cut into the panel, not laid on the page - see .axi-stat. */
|
|
2598
|
+
background-color: var(--axi-well-fill);
|
|
2484
2599
|
background-image: repeating-linear-gradient(
|
|
2485
2600
|
to top,
|
|
2486
2601
|
var(--axi-rule) 0 var(--axi-border-hairline),
|
|
@@ -2650,9 +2765,12 @@ textarea.axi-input {
|
|
|
2650
2765
|
|
|
2651
2766
|
/* .axi-prose code is declared beside .axi-code in primitives.css: one rule,
|
|
2652
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. */
|
|
2653
2771
|
.axi-prose pre {
|
|
2654
2772
|
margin: 0 0 18px; padding: 14px 16px; overflow-x: auto;
|
|
2655
|
-
background: var(--axi-
|
|
2773
|
+
background: var(--axi-well-fill);
|
|
2656
2774
|
border: var(--axi-border-control) solid var(--axi-ink-line);
|
|
2657
2775
|
border-radius: var(--axi-radius-sm);
|
|
2658
2776
|
box-shadow: var(--axi-shadow-control);
|
|
@@ -2663,7 +2781,7 @@ textarea.axi-input {
|
|
|
2663
2781
|
margin: 0 0 18px;
|
|
2664
2782
|
padding: 11px 13px;
|
|
2665
2783
|
border-left: var(--axi-border-panel) solid var(--axi-accent);
|
|
2666
|
-
background: var(--axi-
|
|
2784
|
+
background: var(--axi-well-fill);
|
|
2667
2785
|
border-radius: 0 var(--axi-radius-sm) var(--axi-radius-sm) 0;
|
|
2668
2786
|
}
|
|
2669
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
|
@@ -114,7 +114,12 @@ button.axi-panel--tile:hover,
|
|
|
114
114
|
padding: var(--axi-btn-pad, 12px 20px);
|
|
115
115
|
border: var(--axi-border-control) solid var(--axi-ink-line);
|
|
116
116
|
border-radius: var(--axi-radius-sm);
|
|
117
|
-
|
|
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);
|
|
118
123
|
color: var(--axi-text-dim);
|
|
119
124
|
font: var(--axi-t-label);
|
|
120
125
|
letter-spacing: var(--axi-ls-label);
|
|
@@ -197,7 +202,8 @@ button.axi-panel--tile:hover,
|
|
|
197
202
|
padding: var(--axi-pill-pad, 12px 20px);
|
|
198
203
|
border: var(--axi-border-control) solid var(--axi-ink-line);
|
|
199
204
|
border-radius: var(--axi-radius-sm);
|
|
200
|
-
|
|
205
|
+
/* The button's fill for the button's reason - see .axi-btn above. */
|
|
206
|
+
background: var(--axi-well-fill);
|
|
201
207
|
color: var(--axi-text-dim);
|
|
202
208
|
font: var(--axi-t-label);
|
|
203
209
|
letter-spacing: var(--axi-ls-label);
|
|
@@ -391,7 +397,10 @@ button.axi-panel--tile:hover,
|
|
|
391
397
|
.axi-input {
|
|
392
398
|
width: 100%;
|
|
393
399
|
padding: var(--axi-input-pad, 11px 12px);
|
|
394
|
-
|
|
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);
|
|
395
404
|
border: var(--axi-border-control) solid var(--axi-ink-line);
|
|
396
405
|
border-radius: var(--axi-radius-sm);
|
|
397
406
|
color: var(--axi-text);
|
|
@@ -426,14 +435,15 @@ button.axi-panel--tile:hover,
|
|
|
426
435
|
`em`, not `px`: this lands in body copy and in 10px captions alike, and a
|
|
427
436
|
literal that does not track the text around it reads as a different voice.
|
|
428
437
|
|
|
429
|
-
It sits on --axi-
|
|
438
|
+
It sits on --axi-well-fill where .axi-kbd sits on --axi-surface, and the
|
|
430
439
|
reason is already written down one rule below: a key is raised off what it
|
|
431
|
-
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. */
|
|
432
442
|
.axi-code,
|
|
433
443
|
.axi-prose code {
|
|
434
444
|
font-family: var(--axi-mono);
|
|
435
445
|
font-size: .88em;
|
|
436
|
-
background: var(--axi-
|
|
446
|
+
background: var(--axi-well-fill);
|
|
437
447
|
color: var(--axi-text);
|
|
438
448
|
border: var(--axi-border-hairline) solid var(--axi-ink-line);
|
|
439
449
|
border-radius: var(--axi-radius-sm);
|
|
@@ -473,7 +483,10 @@ button.axi-panel--tile:hover,
|
|
|
473
483
|
padding: 10px 30px 10px 9px;
|
|
474
484
|
border: var(--axi-border-control) solid var(--axi-ink-line);
|
|
475
485
|
border-radius: var(--axi-radius-sm);
|
|
476
|
-
|
|
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);
|
|
477
490
|
color: var(--axi-text-dim);
|
|
478
491
|
font: var(--axi-t-label);
|
|
479
492
|
font-size: 12.5px;
|
|
@@ -532,8 +545,12 @@ button.axi-panel--tile:hover,
|
|
|
532
545
|
letter-spacing: var(--axi-ls-label);
|
|
533
546
|
text-transform: uppercase;
|
|
534
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. */
|
|
535
552
|
.axi-select option:hover, .axi-select option:focus {
|
|
536
|
-
background: var(--axi-
|
|
553
|
+
background: var(--axi-well-fill); color: var(--axi-text);
|
|
537
554
|
}
|
|
538
555
|
/* The page-wide focus ring sits 2px outside its element; inside a picker
|
|
539
556
|
that is 2px into the neighbouring row, so pull it back in. */
|
|
@@ -632,7 +649,7 @@ button.axi-panel--tile:hover,
|
|
|
632
649
|
font-weight: 900;
|
|
633
650
|
}
|
|
634
651
|
.axi-picker__opt:hover, .axi-picker__opt:focus {
|
|
635
|
-
background: var(--axi-
|
|
652
|
+
background: var(--axi-well-fill); color: var(--axi-text);
|
|
636
653
|
}
|
|
637
654
|
/* The page-wide focus ring sits 2px outside its element; inside a popover
|
|
638
655
|
this tight that is 2px into the neighbouring row, so pull it back in. */
|
|
@@ -647,7 +664,8 @@ button.axi-panel--tile:hover,
|
|
|
647
664
|
who wants round avatars sets --axi-radius-sm and gets rounded controls
|
|
648
665
|
everywhere - which is the honest version of the request.
|
|
649
666
|
Flat: outlined, no block. An avatar is content inside a panel, the same as
|
|
650
|
-
.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. */
|
|
651
669
|
.axi-avatar {
|
|
652
670
|
width: var(--axi-avatar-size, 40px);
|
|
653
671
|
height: var(--axi-avatar-size, 40px);
|
|
@@ -655,7 +673,7 @@ button.axi-panel--tile:hover,
|
|
|
655
673
|
display: grid;
|
|
656
674
|
place-items: center;
|
|
657
675
|
overflow: hidden;
|
|
658
|
-
background: var(--axi-
|
|
676
|
+
background: var(--axi-well-fill);
|
|
659
677
|
color: var(--axi-text-dim);
|
|
660
678
|
border: var(--axi-border-control) solid var(--axi-ink-line);
|
|
661
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;
|