mote.css 0.2.1 → 0.3.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/CHANGELOG.md +30 -2
- package/README.md +4 -2
- package/mote.components.css +108 -6
- package/mote.css +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,32 @@ All notable changes to this project are documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [0.3.0] - 2026-10-19
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- Layout module in `mote.components.css`:
|
|
13
|
+
- `.mote-doc` document shell — opt in with one class on `<body>` and the
|
|
14
|
+
landmarks become the layout via `:has()`: sticky left rail for `nav`,
|
|
15
|
+
right rail for `aside`, `main` flexing between them, footer pinned to the
|
|
16
|
+
viewport bottom on short pages (body-scoped `min-height: 100svh`),
|
|
17
|
+
everything collapsing to a single column under 50rem. No classes on the
|
|
18
|
+
landmarks; `:where()` keeps every rule overridable.
|
|
19
|
+
- `.mote-grid` card grid — auto-fill columns computed from the container;
|
|
20
|
+
no breakpoints, no column utilities.
|
|
21
|
+
- Classless page shell: `body > header` and its nav are styled from landmarks
|
|
22
|
+
alone (sticky translucent bar + nav pills). `.mote-header` / `.mote-nav`
|
|
23
|
+
remain for the one case landmarks cannot express — shells wrapped in a
|
|
24
|
+
`<div>`.
|
|
25
|
+
|
|
26
|
+
### Changed
|
|
27
|
+
|
|
28
|
+
- Documentation restructured: every element documented exactly once, with all
|
|
29
|
+
its status variants in place; the Status classes section is now the token
|
|
30
|
+
contract plus a consumer map. Complete status coverage (including muted)
|
|
31
|
+
across notes, badges, toasts, blockquotes, progress, meters, spinners and
|
|
32
|
+
summary markers.
|
|
33
|
+
|
|
8
34
|
## [0.2.1] - 2026-10-16
|
|
9
35
|
|
|
10
36
|
### Fixed
|
|
@@ -17,8 +43,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
17
43
|
- Release CI moved to GitLab CI (`.gitlab-ci.yml`): tag-triggered `npm stage
|
|
18
44
|
publish` with OIDC trusted publishing — no tokens anywhere; a maintainer
|
|
19
45
|
still approves every release with 2FA. The GitHub mirror is distribution-only.
|
|
20
|
-
-
|
|
21
|
-
public
|
|
46
|
+
- Provenance-ready: trusted publishing is configured and the source repository
|
|
47
|
+
is public; whether attestations survive the staged-approval flow gets proven
|
|
48
|
+
by the pipeline's `--provenance` flag at the next release.
|
|
22
49
|
- Package metadata points to the canonical GitLab source; GitHub remains the
|
|
23
50
|
distribution mirror.
|
|
24
51
|
|
|
@@ -86,6 +113,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
86
113
|
- Opt-in helpers: `.mote-container`, `.mote-muted`, `.mote-note` surfaces.
|
|
87
114
|
- Element gallery demo page (`demo.html`).
|
|
88
115
|
|
|
116
|
+
[0.3.0]: https://gitlab.com/abmach/mote/compare/v0.2.1...v0.3.0
|
|
89
117
|
[0.2.1]: https://gitlab.com/abmach/mote/compare/v0.2.0...v0.2.1
|
|
90
118
|
[0.2.0]: https://gitlab.com/abmach/mote/compare/v0.1.0...v0.2.0
|
|
91
119
|
[0.1.0]: https://gitlab.com/abmach/mote/-/tags/v0.1.0
|
package/README.md
CHANGED
|
@@ -139,12 +139,14 @@ mote is classless by design; these are the only escape hatches, plus status clas
|
|
|
139
139
|
|
|
140
140
|
| Component | Hook |
|
|
141
141
|
|---|---|
|
|
142
|
+
| Document layout (landmark grid) | `.mote-doc` on `<body>` — `:has()` reads your `header`/`nav`/`main`/`aside`/`footer` |
|
|
143
|
+
| Sticky site header / nav pills | `body > header` — classless; `.mote-header`/`.mote-nav` only for shells wrapped in a `<div>` |
|
|
144
|
+
| Breadcrumbs | `nav[aria-label="breadcrumb"]` — semantic, no class |
|
|
145
|
+
| Card grids | `.mote-grid` — auto-fill columns from the container, no breakpoints |
|
|
142
146
|
| Cards | `.mote-card` |
|
|
143
147
|
| Badges | `.mote-badge` + optional status class |
|
|
144
148
|
| Avatars | `.mote-avatar` |
|
|
145
149
|
| Skeleton / spinner | `.mote-skeleton`, `.mote-spinner` |
|
|
146
|
-
| Sticky site header / nav pills | `.mote-header`, `.mote-nav` |
|
|
147
|
-
| Breadcrumbs | `nav[aria-label="breadcrumb"]` — semantic, no class |
|
|
148
150
|
| Tooltips | `[popover].mote-tooltip` + `popovertarget` button |
|
|
149
151
|
| Menus | `menu[popover]` + `popovertarget` button |
|
|
150
152
|
| Toasts | `[popover].mote-toast` + status class |
|
package/mote.components.css
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/*!
|
|
2
2
|
* mote.components.css — opt-in components for mote.css.
|
|
3
|
-
* v0.
|
|
3
|
+
* v0.3.0 · MIT
|
|
4
4
|
* https://gitlab.com/abmach/mote · mirror: https://github.com/abmach/mote
|
|
5
5
|
*
|
|
6
6
|
* Requires mote.css loaded first (provides the --mote-* tokens).
|
|
@@ -105,9 +105,15 @@
|
|
|
105
105
|
|
|
106
106
|
/* ---------------------------------------------------------------------------
|
|
107
107
|
* 6. Site header and nav
|
|
108
|
+
*
|
|
109
|
+
* The page shell is styled classlessly: a header that is a direct
|
|
110
|
+
* child of <body> is the site bar, its nav the pill row. The classes
|
|
111
|
+
* exist for the one case landmarks cannot express — a shell wrapped
|
|
112
|
+
* in a <div> (common with frameworks), where body > header cannot
|
|
113
|
+
* see it. All selectors keep :where() specificity so overrides win.
|
|
108
114
|
* ------------------------------------------------------------------------- */
|
|
109
115
|
|
|
110
|
-
.mote-header {
|
|
116
|
+
:where(body > header, .mote-header) {
|
|
111
117
|
position: sticky;
|
|
112
118
|
top: 0;
|
|
113
119
|
z-index: 10;
|
|
@@ -116,7 +122,7 @@
|
|
|
116
122
|
border-block-end: var(--mote-border-width) solid var(--mote-border);
|
|
117
123
|
}
|
|
118
124
|
|
|
119
|
-
.mote-nav ul {
|
|
125
|
+
:where(body > header nav, body > nav, .mote-nav) ul {
|
|
120
126
|
display: flex;
|
|
121
127
|
flex-wrap: wrap;
|
|
122
128
|
gap: 0.25rem;
|
|
@@ -125,7 +131,7 @@
|
|
|
125
131
|
list-style: none;
|
|
126
132
|
}
|
|
127
133
|
|
|
128
|
-
.mote-nav a {
|
|
134
|
+
:where(body > header nav, body > nav, .mote-nav) a {
|
|
129
135
|
display: inline-block;
|
|
130
136
|
padding: 0.35rem 0.8rem;
|
|
131
137
|
border-radius: 999px;
|
|
@@ -134,12 +140,12 @@
|
|
|
134
140
|
transition: background var(--mote-transition), color var(--mote-transition);
|
|
135
141
|
}
|
|
136
142
|
|
|
137
|
-
.mote-nav a:hover {
|
|
143
|
+
:where(body > header nav, body > nav, .mote-nav) a:hover {
|
|
138
144
|
background: var(--mote-accent-soft);
|
|
139
145
|
color: var(--mote-accent-deep);
|
|
140
146
|
}
|
|
141
147
|
|
|
142
|
-
.mote-nav a[aria-current="page"] {
|
|
148
|
+
:where(body > header nav, body > nav, .mote-nav) a[aria-current="page"] {
|
|
143
149
|
background: var(--mote-accent);
|
|
144
150
|
color: var(--mote-on-accent);
|
|
145
151
|
}
|
|
@@ -370,3 +376,99 @@ details[name] > :not(summary) {
|
|
|
370
376
|
}
|
|
371
377
|
}
|
|
372
378
|
}
|
|
379
|
+
|
|
380
|
+
/* ---------------------------------------------------------------------------
|
|
381
|
+
* 12. Layout — document shell and card grids
|
|
382
|
+
*
|
|
383
|
+
* The document layout is opted in with a single class on <body> (or any
|
|
384
|
+
* wrapper): .mote-doc. The landmarks you already write — header, nav,
|
|
385
|
+
* main, aside, footer — become the layout; no classes on the landmarks.
|
|
386
|
+
* A nav becomes a left rail, an aside a right rail, and everything
|
|
387
|
+
* collapses to a single column under 50rem.
|
|
388
|
+
*
|
|
389
|
+
* All :has() guards sit in :where(), so the rules carry zero specificity
|
|
390
|
+
* weight — your own styles on the same landmarks always win.
|
|
391
|
+
* ------------------------------------------------------------------------- */
|
|
392
|
+
|
|
393
|
+
.mote-doc {
|
|
394
|
+
display: grid;
|
|
395
|
+
column-gap: 1.5rem;
|
|
396
|
+
grid-template-rows: auto 1fr auto;
|
|
397
|
+
grid-template-columns: 1fr;
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
/* On <body>, the middle row stretches the page so the footer pins to
|
|
401
|
+
the viewport bottom even when content is short. :where() keeps this
|
|
402
|
+
at base specificity; wrappers (demo boxes, embeds) stay natural-size. */
|
|
403
|
+
:where(body).mote-doc {
|
|
404
|
+
min-height: 100svh;
|
|
405
|
+
}
|
|
406
|
+
|
|
407
|
+
.mote-doc > header { grid-row: 1; grid-column: 1 / -1; }
|
|
408
|
+
.mote-doc > footer { grid-row: 3; grid-column: 1 / -1; }
|
|
409
|
+
|
|
410
|
+
.mote-doc > main { grid-row: 2; grid-column: 1; }
|
|
411
|
+
|
|
412
|
+
/* nav = left rail */
|
|
413
|
+
.mote-doc > nav {
|
|
414
|
+
grid-row: 2;
|
|
415
|
+
grid-column: 1;
|
|
416
|
+
align-self: start;
|
|
417
|
+
position: sticky;
|
|
418
|
+
top: 1rem;
|
|
419
|
+
max-height: calc(100svh - 2rem);
|
|
420
|
+
overflow: auto;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
.mote-doc:where(:has(> nav)) {
|
|
424
|
+
grid-template-columns: minmax(12rem, 16rem) 1fr;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
.mote-doc:where(:has(> nav)) > main {
|
|
428
|
+
grid-column: 2;
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
/* aside = right rail (or the main column when there is no nav) */
|
|
432
|
+
.mote-doc > aside {
|
|
433
|
+
grid-row: 2;
|
|
434
|
+
grid-column: 2;
|
|
435
|
+
align-self: start;
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
.mote-doc:where(:has(> nav)) > aside {
|
|
439
|
+
grid-column: 3;
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
.mote-doc:where(:has(> aside)) {
|
|
443
|
+
grid-template-columns: 1fr minmax(10rem, 14rem);
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
.mote-doc:where(:has(> nav)):where(:has(> aside)) {
|
|
447
|
+
grid-template-columns: minmax(12rem, 16rem) 1fr minmax(10rem, 14rem);
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
@media (width < 50rem) {
|
|
451
|
+
.mote-doc:where(:has(> nav)),
|
|
452
|
+
.mote-doc:where(:has(> aside)),
|
|
453
|
+
.mote-doc:where(:has(> nav)):where(:has(> aside)) {
|
|
454
|
+
grid-template-columns: 1fr;
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
.mote-doc > :is(nav, aside, main) {
|
|
458
|
+
grid-column: 1 / -1;
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
.mote-doc > nav {
|
|
462
|
+
position: static;
|
|
463
|
+
max-height: none;
|
|
464
|
+
overflow: visible;
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
/* Card grids: one class, no breakpoints, no column utilities.
|
|
469
|
+
Columns are computed from the container: as many as fit in 16rem. */
|
|
470
|
+
.mote-grid {
|
|
471
|
+
display: grid;
|
|
472
|
+
gap: 1.25rem;
|
|
473
|
+
grid-template-columns: repeat(auto-fill, minmax(min(16rem, 100%), 1fr));
|
|
474
|
+
}
|
package/mote.css
CHANGED