@axiapps/axi-design 1.42.0 → 1.43.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/accents.json +2 -1
- package/dist/accents.css +1 -0
- package/dist/axi.css +37 -0
- package/docs/RULES.md +63 -1
- package/package.json +1 -1
- package/src/shells.css +37 -0
package/accents.json
CHANGED
|
@@ -9,5 +9,6 @@
|
|
|
9
9
|
{ "id": "crimson-red", "label": "Crimson Red", "hex": "#ef4444" },
|
|
10
10
|
{ "id": "slate-silver", "label": "Slate Silver", "hex": "#94a3b8" },
|
|
11
11
|
{ "id": "teal-ocean", "label": "Teal Ocean", "hex": "#14b8a6" },
|
|
12
|
-
{ "id": "gold-bronze", "label": "Gold Bronze", "hex": "#d4a017" }
|
|
12
|
+
{ "id": "gold-bronze", "label": "Gold Bronze", "hex": "#d4a017" },
|
|
13
|
+
{ "id": "electric-cyan", "label": "Electric Cyan", "hex": "#22d3ee" }
|
|
13
14
|
]
|
package/dist/accents.css
CHANGED
package/dist/axi.css
CHANGED
|
@@ -2016,7 +2016,44 @@ textarea.axi-input {
|
|
|
2016
2016
|
.axi-card:hover .axi-card__go { color: var(--axi-text); }
|
|
2017
2017
|
|
|
2018
2018
|
/* ---------- drawer ---------- */
|
|
2019
|
+
/* A scrim's layer is not a property of the scrim. It is "directly below the
|
|
2020
|
+
thing I dismiss", and this language has two things that get dismissed at two
|
|
2021
|
+
different rungs, so the scrim has two.
|
|
2022
|
+
|
|
2023
|
+
The default is the drawer-and-modal rung at 50, which is where
|
|
2024
|
+
--axi-scrim's own value was tuned (its token comment reads "behind a
|
|
2025
|
+
drawer"). `.axi-scrim--sheet` is the same scrim one rung below the sheet at
|
|
2026
|
+
45.
|
|
2027
|
+
|
|
2028
|
+
Without that modifier a sheet cannot be scrimmed at all, and the failure is
|
|
2029
|
+
not cosmetic - it is a dead interface. Both elements are `position: fixed` in
|
|
2030
|
+
the same stacking context with no isolation between them, so at 50 over 45
|
|
2031
|
+
the scrim covers the sheet completely: measured with
|
|
2032
|
+
`document.elementFromPoint` at the centre of an open sheet, the element
|
|
2033
|
+
returned is the scrim. Every click lands on the dismiss handler instead of on
|
|
2034
|
+
the content, so the sheet opens and then does nothing.
|
|
2035
|
+
|
|
2036
|
+
The sheet still wants a scrim even though it is opaque and covers the view,
|
|
2037
|
+
for two reasons the sheet's own note explains. --axi-sheet-top pushes it down
|
|
2038
|
+
under an app's titlebar, so a strip of live page stays visible above it and
|
|
2039
|
+
wants darkening; and the scrim is the click-to-dismiss target for that strip,
|
|
2040
|
+
which is a function rather than an appearance.
|
|
2041
|
+
|
|
2042
|
+
A sheet that opens a modal or a drawer is unaffected: those land at 50 and
|
|
2043
|
+
51, above both the sheet and its scrim, which is the ordering the sheet's own
|
|
2044
|
+
comment argues for. That is why this is a second rung and not a change to the
|
|
2045
|
+
first - moving the scrim below 45 outright would put it under the drawer it
|
|
2046
|
+
was measured for.
|
|
2047
|
+
|
|
2048
|
+
No motion here, deliberately. This language has no transition vocabulary -
|
|
2049
|
+
no duration or easing tokens - and rule 11 is a restriction on work
|
|
2050
|
+
indicators rather than a system for animating chrome. A consumer that fades
|
|
2051
|
+
a scrim in owns that animation, and owns keeping its keyframes off the fill:
|
|
2052
|
+
an enter/exit class that also sets a background is a colour literal standing
|
|
2053
|
+
on top of --axi-scrim, which is how the one consumer here had quietly
|
|
2054
|
+
replaced the token with rgba(10, 14, 18, .85). */
|
|
2019
2055
|
.axi-scrim { position: fixed; inset: 0; z-index: 50; background: var(--axi-scrim); backdrop-filter: var(--axi-surface-filter); border: 0; }
|
|
2056
|
+
.axi-scrim--sheet { z-index: 44; }
|
|
2020
2057
|
.axi-drawer {
|
|
2021
2058
|
position: fixed; top: 0; right: 0; bottom: 0; z-index: 51;
|
|
2022
2059
|
width: min(var(--axi-drawer-width, 560px), 100vw);
|
package/docs/RULES.md
CHANGED
|
@@ -548,6 +548,7 @@ instead of joining it.
|
|
|
548
548
|
| Table corner | 3 | where the two cross |
|
|
549
549
|
| Sticky chrome | 40 | `.axi-mast` |
|
|
550
550
|
| Popovers | 41 | `.axi-menu__pop`, `.axi-picker__pop` |
|
|
551
|
+
| Sheet scrim | 44 | `.axi-scrim--sheet` |
|
|
551
552
|
| Sheet | 45 | `.axi-sheet` |
|
|
552
553
|
| Scrim | 50 | `.axi-scrim` |
|
|
553
554
|
| Drawer | 51 | `.axi-drawer` |
|
|
@@ -572,6 +573,15 @@ A negative `z-index` inside a component's own `isolation` context — the sigil'
|
|
|
572
573
|
backing shape — is not a layer and is not listed. It is invisible outside the
|
|
573
574
|
component that owns it.
|
|
574
575
|
|
|
576
|
+
The scrim appears twice, and that is the table saying something rather than
|
|
577
|
+
repeating itself. A scrim's rung is not a property of the scrim; it is "directly
|
|
578
|
+
below the thing I dismiss", so a language with two dismissible surfaces at two
|
|
579
|
+
rungs has two scrims. Reading the single 50 as the scrim's own number is what
|
|
580
|
+
makes a sheet impossible to scrim: at 50 over the sheet's 45 the scrim covers
|
|
581
|
+
the sheet completely, every click lands on the dismiss handler, and the surface
|
|
582
|
+
opens dead. So when you add a dismissible surface, check whether it needs a
|
|
583
|
+
scrim rung directly beneath it, and add both rows together.
|
|
584
|
+
|
|
575
585
|
## Light mode
|
|
576
586
|
|
|
577
587
|
Not shipped. The system is *structured* for it: no component contains a colour
|
|
@@ -684,6 +694,44 @@ The line to hold is the one-for-one rule above, not a list of layers. A theme
|
|
|
684
694
|
that restates the block still paints every component; a theme that invents one
|
|
685
695
|
does not.
|
|
686
696
|
|
|
697
|
+
### A change to the language is not finished until every theme wears it
|
|
698
|
+
|
|
699
|
+
The one-for-one rule above is written as an obligation on a *theme* — here is
|
|
700
|
+
what a new theme owes the language. Read only that way it has a hole in it, and
|
|
701
|
+
the hole is every change that goes the other direction. A token added to
|
|
702
|
+
`tokens.css`, a component added to `src/`, a look retuned: each of those is a
|
|
703
|
+
change to the thing the themes are mirroring, and none of them is finished when
|
|
704
|
+
the main theme looks right. There are three themes — the language itself in
|
|
705
|
+
`src/tokens.css`, `flat`, and `glass` — and a change lands in all three or it
|
|
706
|
+
has not landed.
|
|
707
|
+
|
|
708
|
+
That is the symmetric half of the toll already stated above. **A new theme
|
|
709
|
+
capability costs a main-theme token first; a change to the main theme costs
|
|
710
|
+
every theme a look.** Neither direction is optional, and the second is the one
|
|
711
|
+
easy to skip, because the default theme is the one on screen while you work.
|
|
712
|
+
|
|
713
|
+
What "answered in every theme" means depends on the shape of the change:
|
|
714
|
+
|
|
715
|
+
- **A new token.** Every theme either restates it or can point at why it does
|
|
716
|
+
not need to. Two reasons count. The default is inert — `--axi-surface-filter`
|
|
717
|
+
and `--axi-ground-image` are `none`, so a theme that wants neither is already
|
|
718
|
+
correct. Or the token aliases one the theme did restate —
|
|
719
|
+
`--axi-surface-float: var(--axi-surface)`, so `flat` restating the surface
|
|
720
|
+
restates the float with it. A token holding a literal of its own is answered
|
|
721
|
+
by neither of those, and every theme has to say it. This is checked; see
|
|
722
|
+
below.
|
|
723
|
+
- **A new component.** It renders under all three, and you look at it under all
|
|
724
|
+
three. The gallery's theme switcher is there for exactly the reason the accent
|
|
725
|
+
switcher is: a component that hard-coded something looks fine until you
|
|
726
|
+
change the thing it hard-coded. A panel that reads as a panel on opaque slate
|
|
727
|
+
can vanish on a translucent one.
|
|
728
|
+
- **A retuned look.** The `-paint` companions are the case that made this a
|
|
729
|
+
section. Lifting them meant every surface a theme grades needs a flat
|
|
730
|
+
companion beside it, and both themes had to be edited in the same commit as
|
|
731
|
+
the tokens — edit one and the other hands a gradient straight to
|
|
732
|
+
`background-color`, which is not a subtle failure but it is an invisible one
|
|
733
|
+
from the theme you happened to be looking at.
|
|
734
|
+
|
|
687
735
|
**What is mechanically enforced.** `tests/themes.test.mjs` reads every
|
|
688
736
|
`dist/themes/*.css` and checks the mirror rather than trusting it: the file
|
|
689
737
|
contains exactly one rule, its selector is `[data-axi-theme="<id>"]` for the
|
|
@@ -693,6 +741,16 @@ non-empty value, and every property it declares is already declared in
|
|
|
693
741
|
takes a second selector. An invented token fails the last. The suite passes
|
|
694
742
|
vacuously while no theme exists, and binds the moment the first file lands.
|
|
695
743
|
|
|
744
|
+
The section above is checked from the other side by the same file: a token that
|
|
745
|
+
*any* theme restates must be restated by *every* theme, unless that theme
|
|
746
|
+
inherits an answer already — the main-theme default is inert, or the token
|
|
747
|
+
aliases another the theme did restate, and the check follows the alias chain
|
|
748
|
+
rather than taking the two reasons on trust. So a token one theme has an opinion
|
|
749
|
+
about cannot be a token another theme forgot. What no test can check is the
|
|
750
|
+
third bullet, the look you did not look at: a component can paint under all
|
|
751
|
+
three themes and still be wrong under two of them, and the only instrument for
|
|
752
|
+
that is the theme switcher in the gallery.
|
|
753
|
+
|
|
696
754
|
## Adding a component
|
|
697
755
|
|
|
698
756
|
1. Which rule justifies it? If none, write the rule first or stop.
|
|
@@ -702,7 +760,11 @@ vacuously while no theme exists, and binds the moment the first file lands.
|
|
|
702
760
|
[Themes](#themes).
|
|
703
761
|
4. Add it to the gallery, and check it with the accent switcher — if it does
|
|
704
762
|
not follow the accent, it hard-coded something.
|
|
705
|
-
5.
|
|
763
|
+
5. Then check it with the theme switcher, under all three — the language,
|
|
764
|
+
`flat` and `glass`. Translucent surfaces and a 16px corner break different
|
|
765
|
+
things than opaque ones do, and a component is not done until it reads right
|
|
766
|
+
under each. See [Themes](#themes).
|
|
767
|
+
6. `npm run build` and commit `dist/axi.css` with your source change.
|
|
706
768
|
|
|
707
769
|
### A style only reachable through a layer will be re-invented
|
|
708
770
|
|
package/package.json
CHANGED
package/src/shells.css
CHANGED
|
@@ -708,7 +708,44 @@
|
|
|
708
708
|
.axi-card:hover .axi-card__go { color: var(--axi-text); }
|
|
709
709
|
|
|
710
710
|
/* ---------- drawer ---------- */
|
|
711
|
+
/* A scrim's layer is not a property of the scrim. It is "directly below the
|
|
712
|
+
thing I dismiss", and this language has two things that get dismissed at two
|
|
713
|
+
different rungs, so the scrim has two.
|
|
714
|
+
|
|
715
|
+
The default is the drawer-and-modal rung at 50, which is where
|
|
716
|
+
--axi-scrim's own value was tuned (its token comment reads "behind a
|
|
717
|
+
drawer"). `.axi-scrim--sheet` is the same scrim one rung below the sheet at
|
|
718
|
+
45.
|
|
719
|
+
|
|
720
|
+
Without that modifier a sheet cannot be scrimmed at all, and the failure is
|
|
721
|
+
not cosmetic - it is a dead interface. Both elements are `position: fixed` in
|
|
722
|
+
the same stacking context with no isolation between them, so at 50 over 45
|
|
723
|
+
the scrim covers the sheet completely: measured with
|
|
724
|
+
`document.elementFromPoint` at the centre of an open sheet, the element
|
|
725
|
+
returned is the scrim. Every click lands on the dismiss handler instead of on
|
|
726
|
+
the content, so the sheet opens and then does nothing.
|
|
727
|
+
|
|
728
|
+
The sheet still wants a scrim even though it is opaque and covers the view,
|
|
729
|
+
for two reasons the sheet's own note explains. --axi-sheet-top pushes it down
|
|
730
|
+
under an app's titlebar, so a strip of live page stays visible above it and
|
|
731
|
+
wants darkening; and the scrim is the click-to-dismiss target for that strip,
|
|
732
|
+
which is a function rather than an appearance.
|
|
733
|
+
|
|
734
|
+
A sheet that opens a modal or a drawer is unaffected: those land at 50 and
|
|
735
|
+
51, above both the sheet and its scrim, which is the ordering the sheet's own
|
|
736
|
+
comment argues for. That is why this is a second rung and not a change to the
|
|
737
|
+
first - moving the scrim below 45 outright would put it under the drawer it
|
|
738
|
+
was measured for.
|
|
739
|
+
|
|
740
|
+
No motion here, deliberately. This language has no transition vocabulary -
|
|
741
|
+
no duration or easing tokens - and rule 11 is a restriction on work
|
|
742
|
+
indicators rather than a system for animating chrome. A consumer that fades
|
|
743
|
+
a scrim in owns that animation, and owns keeping its keyframes off the fill:
|
|
744
|
+
an enter/exit class that also sets a background is a colour literal standing
|
|
745
|
+
on top of --axi-scrim, which is how the one consumer here had quietly
|
|
746
|
+
replaced the token with rgba(10, 14, 18, .85). */
|
|
711
747
|
.axi-scrim { position: fixed; inset: 0; z-index: 50; background: var(--axi-scrim); backdrop-filter: var(--axi-surface-filter); border: 0; }
|
|
748
|
+
.axi-scrim--sheet { z-index: 44; }
|
|
712
749
|
.axi-drawer {
|
|
713
750
|
position: fixed; top: 0; right: 0; bottom: 0; z-index: 51;
|
|
714
751
|
width: min(var(--axi-drawer-width, 560px), 100vw);
|