@axiapps/axi-design 1.12.0 → 1.13.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/README.md +10 -7
- package/dist/axi.css +21 -1
- package/dist/themes/glass.css +19 -6
- package/docs/RULES.md +59 -18
- package/package.json +1 -1
- package/src/base.css +7 -1
- package/src/tokens.css +14 -0
package/README.md
CHANGED
|
@@ -67,13 +67,16 @@ import '@axiapps/axi-design/themes/glass.css'
|
|
|
67
67
|
<html data-axi-theme="glass">
|
|
68
68
|
```
|
|
69
69
|
|
|
70
|
-
`glass`
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
70
|
+
`glass` repaints the material: translucent panels lit from the top-left over a
|
|
71
|
+
near-black page with three wide colour washes on it, hairline edges, rounded
|
|
72
|
+
corners and a soft drop instead of the main theme's hard offset block, with
|
|
73
|
+
popovers, drawers and modals blurring what sits behind them. The five saturated
|
|
74
|
+
inks, the measure and the type are untouched — they are the language, not the
|
|
75
|
+
paint. Remove the attribute and you are back on the main theme with no other
|
|
76
|
+
change: a theme restates tokens and never adds a component, so nothing in your
|
|
77
|
+
markup knows which one is on. That is the point — the look is maintained here
|
|
78
|
+
rather than copied into your app as a custom theme that then has to be kept in
|
|
79
|
+
step.
|
|
77
80
|
|
|
78
81
|
The main theme is the language and a theme is a repaint of it — [the
|
|
79
82
|
rules](docs/RULES.md#themes) say what a theme may and may not do.
|
package/dist/axi.css
CHANGED
|
@@ -16,6 +16,20 @@
|
|
|
16
16
|
:root {
|
|
17
17
|
/* --- surface & text --- */
|
|
18
18
|
--axi-ground: #15181d; /* the page itself */
|
|
19
|
+
/* An image layer painted over the ground colour, on the page and nowhere
|
|
20
|
+
else. The second toll the Themes section describes, and it exists for the
|
|
21
|
+
same reason --axi-surface-filter does: a glass theme wants the page lit
|
|
22
|
+
from a few directions, and it does not get to introduce a gradient any
|
|
23
|
+
more than it got to introduce a blur. Declared here inert (`none`), read
|
|
24
|
+
unconditionally by body, and restated by the theme.
|
|
25
|
+
|
|
26
|
+
Why a second token rather than letting a theme put the gradient in
|
|
27
|
+
--axi-ground itself: --axi-ground is read as `background-color` by the
|
|
28
|
+
plot and the select, where an image value is invalid and drops out, and
|
|
29
|
+
as the flat fill of the masthead, the tooltip row and a dozen inset
|
|
30
|
+
shapes, where a page-positioned radial would render as an arbitrary
|
|
31
|
+
wedge of colour. The ground stays a colour. This is the page's light. */
|
|
32
|
+
--axi-ground-image: none;
|
|
19
33
|
--axi-surface: #222731; /* a panel raised off the page */
|
|
20
34
|
--axi-surface-raised: #2b313d; /* a chip or popover raised off a panel */
|
|
21
35
|
--axi-ink-line: #0c0e12; /* the outline every raised element is drawn with */
|
|
@@ -143,7 +157,13 @@ html { color-scheme: dark; }
|
|
|
143
157
|
|
|
144
158
|
body {
|
|
145
159
|
margin: 0;
|
|
146
|
-
|
|
160
|
+
/* Longhands rather than the shorthand: the ground is a colour and the light
|
|
161
|
+
over it is an image, and `background:` would make setting either one
|
|
162
|
+
reset the other. Fixed so a theme's light stays put as the page scrolls
|
|
163
|
+
instead of stretching to the document's height. */
|
|
164
|
+
background-color: var(--axi-ground);
|
|
165
|
+
background-image: var(--axi-ground-image);
|
|
166
|
+
background-attachment: fixed;
|
|
147
167
|
color: var(--axi-text);
|
|
148
168
|
font: var(--axi-t-body);
|
|
149
169
|
-webkit-font-smoothing: antialiased;
|
package/dist/themes/glass.css
CHANGED
|
@@ -3,13 +3,26 @@
|
|
|
3
3
|
|
|
4
4
|
[data-axi-theme="glass"] {
|
|
5
5
|
--axi-ground: #0a0c10;
|
|
6
|
-
--axi-
|
|
7
|
-
--axi-surface
|
|
8
|
-
--axi-
|
|
6
|
+
--axi-ground-image: radial-gradient(900px 500px at 15% 0%, rgba(120, 90, 255, .30), transparent 60%), radial-gradient(700px 500px at 95% 30%, rgba(0, 190, 255, .22), transparent 62%), radial-gradient(600px 600px at 60% 100%, rgba(255, 90, 170, .20), transparent 60%);
|
|
7
|
+
--axi-surface: linear-gradient(145deg, rgba(58, 68, 92, .55), rgba(28, 33, 46, .42));
|
|
8
|
+
--axi-surface-raised: linear-gradient(145deg, rgba(86, 99, 130, .5), rgba(44, 52, 71, .38));
|
|
9
|
+
--axi-surface-filter: blur(18px) saturate(140%);
|
|
10
|
+
--axi-ink-line: rgba(180, 200, 255, .16);
|
|
11
|
+
--axi-rule: rgba(180, 200, 255, .14);
|
|
9
12
|
--axi-ground-deep: #0c0e12;
|
|
10
13
|
--axi-accent-ink: #0c0e12;
|
|
11
14
|
--axi-ink-on-fill: #0c0e12;
|
|
12
|
-
--axi-
|
|
13
|
-
--axi-
|
|
14
|
-
--axi-
|
|
15
|
+
--axi-text: #f2f5fb;
|
|
16
|
+
--axi-text-dim: #b3bdd0;
|
|
17
|
+
--axi-text-faint: #7f8aa0;
|
|
18
|
+
--axi-scrim: rgba(4, 6, 12, .66);
|
|
19
|
+
--axi-shadow-panel: 0 18px 44px rgba(0, 0, 0, .55), inset 0 1px 0 rgba(255, 255, 255, .14);
|
|
20
|
+
--axi-shadow-control: 0 6px 16px rgba(0, 0, 0, .45), inset 0 1px 0 rgba(255, 255, 255, .12);
|
|
21
|
+
--axi-shadow-panel-hover: 0 26px 60px rgba(0, 0, 0, .6), inset 0 1px 0 rgba(255, 255, 255, .2);
|
|
22
|
+
--axi-shadow-control-hover: 0 10px 24px rgba(0, 0, 0, .5), inset 0 1px 0 rgba(255, 255, 255, .18);
|
|
23
|
+
--axi-border-panel: 1px;
|
|
24
|
+
--axi-border-control: 1px;
|
|
25
|
+
--axi-border-hairline: 1px;
|
|
26
|
+
--axi-radius: 16px;
|
|
27
|
+
--axi-radius-sm: 10px;
|
|
15
28
|
}
|
package/docs/RULES.md
CHANGED
|
@@ -16,10 +16,11 @@ gridlines (a `repeating-linear-gradient` of hard stops, which is how N evenly
|
|
|
16
16
|
spaced rules get drawn without asking every consumer to emit N empty divs).
|
|
17
17
|
A gradient across a surface is still forbidden in every component file, and
|
|
18
18
|
always will be. The single relief is a *theme* restating the surface tokens
|
|
19
|
-
themselves —
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
themselves — and `--axi-ground-image`, the page's own light, which is declared
|
|
20
|
+
inert in `tokens.css` and read only by `body`; see [Themes](#themes). That is
|
|
21
|
+
what lets a glass theme exist without one component ever learning the word
|
|
22
|
+
"glass". A component cannot reach for that exception, because it cannot see it:
|
|
23
|
+
what it reads is the same surface token it was already reading.
|
|
23
24
|
|
|
24
25
|
## 2. No colour at partial opacity over the ground
|
|
25
26
|
|
|
@@ -28,13 +29,19 @@ just brown, and five muted inks over near-black are five browns. When something
|
|
|
28
29
|
should be quieter, reach for a neutral from the ramp — that is what the ramp is
|
|
29
30
|
for.
|
|
30
31
|
|
|
31
|
-
A theme gets the same carve-out as rule 1
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
32
|
+
A theme gets the same carve-out as rule 1: it may hold the *surface layer* at
|
|
33
|
+
partial opacity, because a translucent surface is that surface's own definition
|
|
34
|
+
rather than a colour laid over the ground. That layer is the two surfaces and
|
|
35
|
+
the lines that bound and divide them — `--axi-ink-line` and `--axi-rule` — for
|
|
36
|
+
the same reason: the edge of a translucent panel is as much the panel as its
|
|
37
|
+
face, and an opaque hairline around a pane of glass is a picture frame.
|
|
38
|
+
|
|
39
|
+
The five saturated inks are untouched. A muted `--axi-warn`, a faded accent, a
|
|
40
|
+
status ink at 60% — still forbidden, in a theme exactly as in a component,
|
|
41
|
+
because the paragraph above is about what happens to meaning when five inks
|
|
42
|
+
become five browns, and changing which stylesheet does the muting does not
|
|
43
|
+
change that. The neutral text ramp is likewise a theme's to restate but not to
|
|
44
|
+
fade: a theme picks where `--axi-text-dim` sits, it does not write text at 60%.
|
|
38
45
|
|
|
39
46
|
## 3. Every raised element is outlined and blocked
|
|
40
47
|
|
|
@@ -474,13 +481,47 @@ main-theme token first.** A glass theme wants a `backdrop-filter`; it does not
|
|
|
474
481
|
get to introduce one. `--axi-surface-filter` is declared in `tokens.css` with an
|
|
475
482
|
inert default (`none`), the surfaces read it unconditionally, and the theme
|
|
476
483
|
restates it. The main theme is unchanged in appearance and the hook is part of
|
|
477
|
-
the language rather than part of the theme.
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
+
the language rather than part of the theme. `--axi-ground-image` is the second
|
|
485
|
+
of these, on the same terms: the page's light, inert at `none`, read by `body`
|
|
486
|
+
and nowhere else. Every theme pays this toll, and it is what keeps the mirror
|
|
487
|
+
true: a token the theme could set that the main theme had never heard of is the
|
|
488
|
+
first step back toward theme-only components.
|
|
489
|
+
|
|
490
|
+
### What a theme may restate
|
|
491
|
+
|
|
492
|
+
Rules 1 and 2 name the relief a theme gets in the surface layer: a theme may
|
|
493
|
+
put a gradient on a surface and may hold a surface token at partial opacity. It
|
|
494
|
+
may not mute an ink. Read those two rules for why.
|
|
495
|
+
|
|
496
|
+
The relief is not confined to that layer, though, and the first draft of this
|
|
497
|
+
section said it was. **A theme may also restate the block and the corner** —
|
|
498
|
+
`--axi-shadow-*`, `--axi-border-*`, `--axi-radius` and `--axi-radius-sm`. Rule 3
|
|
499
|
+
requires that a raised element read as raised and an outlined one as outlined.
|
|
500
|
+
A hard offset block in the line ink is how the main theme answers that; a soft
|
|
501
|
+
drop with an inset top highlight is a different answer to the same question,
|
|
502
|
+
and a translucent panel wearing an opaque theme's block does not look like
|
|
503
|
+
glass, it looks like a bug. The block and the corner are how a theme says what
|
|
504
|
+
its material is.
|
|
505
|
+
|
|
506
|
+
What is **not** a theme's to restate, and each for its own reason:
|
|
507
|
+
|
|
508
|
+
- **The five saturated fills.** `--axi-accent`, `--axi-meta`, `--axi-ok`,
|
|
509
|
+
`--axi-warn`, `--axi-danger` carry meaning (rules 5, 6, 9, 10). Their `-ink`
|
|
510
|
+
companions are not on this list: `--axi-accent-ink` and `--axi-ink-on-fill`
|
|
511
|
+
are the colour a word is written in when it sits on a fill, and a theme that
|
|
512
|
+
lightens the outline has to be able to hold them dark.
|
|
513
|
+
- **The offset scale.** `--axi-offset-*` is what the main theme's block is
|
|
514
|
+
composed *from*. A theme restates the composed `--axi-shadow-*` wholesale or
|
|
515
|
+
leaves it; retuning the offsets underneath would leave the two spellings of
|
|
516
|
+
"the block" disagreeing.
|
|
517
|
+
- **The measure.** `--axi-page`, `--axi-gutter`. Where the text wraps is not a
|
|
518
|
+
look, and moving it would reflow every page rather than repaint it.
|
|
519
|
+
- **The type.** `--axi-sans`, `--axi-mono`, `--axi-t-*`, `--axi-ls-*`. The same
|
|
520
|
+
call, harder: the type scale is the voice.
|
|
521
|
+
|
|
522
|
+
The line to hold is the one-for-one rule above, not a list of layers. A theme
|
|
523
|
+
that restates the block still paints every component; a theme that invents one
|
|
524
|
+
does not.
|
|
484
525
|
|
|
485
526
|
**What is mechanically enforced.** `tests/themes.test.mjs` reads every
|
|
486
527
|
`dist/themes/*.css` and checks the mirror rather than trusting it: the file
|
package/package.json
CHANGED
package/src/base.css
CHANGED
|
@@ -11,7 +11,13 @@ html { color-scheme: dark; }
|
|
|
11
11
|
|
|
12
12
|
body {
|
|
13
13
|
margin: 0;
|
|
14
|
-
|
|
14
|
+
/* Longhands rather than the shorthand: the ground is a colour and the light
|
|
15
|
+
over it is an image, and `background:` would make setting either one
|
|
16
|
+
reset the other. Fixed so a theme's light stays put as the page scrolls
|
|
17
|
+
instead of stretching to the document's height. */
|
|
18
|
+
background-color: var(--axi-ground);
|
|
19
|
+
background-image: var(--axi-ground-image);
|
|
20
|
+
background-attachment: fixed;
|
|
15
21
|
color: var(--axi-text);
|
|
16
22
|
font: var(--axi-t-body);
|
|
17
23
|
-webkit-font-smoothing: antialiased;
|
package/src/tokens.css
CHANGED
|
@@ -12,6 +12,20 @@
|
|
|
12
12
|
:root {
|
|
13
13
|
/* --- surface & text --- */
|
|
14
14
|
--axi-ground: #15181d; /* the page itself */
|
|
15
|
+
/* An image layer painted over the ground colour, on the page and nowhere
|
|
16
|
+
else. The second toll the Themes section describes, and it exists for the
|
|
17
|
+
same reason --axi-surface-filter does: a glass theme wants the page lit
|
|
18
|
+
from a few directions, and it does not get to introduce a gradient any
|
|
19
|
+
more than it got to introduce a blur. Declared here inert (`none`), read
|
|
20
|
+
unconditionally by body, and restated by the theme.
|
|
21
|
+
|
|
22
|
+
Why a second token rather than letting a theme put the gradient in
|
|
23
|
+
--axi-ground itself: --axi-ground is read as `background-color` by the
|
|
24
|
+
plot and the select, where an image value is invalid and drops out, and
|
|
25
|
+
as the flat fill of the masthead, the tooltip row and a dozen inset
|
|
26
|
+
shapes, where a page-positioned radial would render as an arbitrary
|
|
27
|
+
wedge of colour. The ground stays a colour. This is the page's light. */
|
|
28
|
+
--axi-ground-image: none;
|
|
15
29
|
--axi-surface: #222731; /* a panel raised off the page */
|
|
16
30
|
--axi-surface-raised: #2b313d; /* a chip or popover raised off a panel */
|
|
17
31
|
--axi-ink-line: #0c0e12; /* the outline every raised element is drawn with */
|