@refrakt-md/lumina 0.14.2 → 0.14.4
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/index.css +1 -0
- package/package.json +4 -4
- package/styles/layouts/blog.css +10 -0
- package/styles/layouts/docs.css +32 -12
- package/styles/layouts/mobile.css +43 -39
- package/styles/layouts/plan.css +1 -1
- package/styles/runes/badge.css +33 -0
- package/styles/runes/hint.css +0 -1
- package/styles/runes/nav.css +313 -9
package/index.css
CHANGED
|
@@ -41,6 +41,7 @@
|
|
|
41
41
|
@import './styles/runes/annotate.css';
|
|
42
42
|
@import './styles/runes/audio.css';
|
|
43
43
|
@import './styles/runes/api.css';
|
|
44
|
+
@import './styles/runes/badge.css';
|
|
44
45
|
@import './styles/runes/bento.css';
|
|
45
46
|
@import './styles/runes/blog.css';
|
|
46
47
|
@import './styles/runes/bond.css';
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@refrakt-md/lumina",
|
|
3
3
|
"description": "Lumina theme for refrakt.md — design tokens, CSS, identity transform, and layout configs",
|
|
4
|
-
"version": "0.14.
|
|
4
|
+
"version": "0.14.4",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"repository": {
|
|
@@ -83,9 +83,9 @@
|
|
|
83
83
|
"build": "tsc"
|
|
84
84
|
},
|
|
85
85
|
"dependencies": {
|
|
86
|
-
"@refrakt-md/runes": "0.14.
|
|
87
|
-
"@refrakt-md/transform": "0.14.
|
|
88
|
-
"@refrakt-md/types": "0.14.
|
|
86
|
+
"@refrakt-md/runes": "0.14.4",
|
|
87
|
+
"@refrakt-md/transform": "0.14.4",
|
|
88
|
+
"@refrakt-md/types": "0.14.4"
|
|
89
89
|
},
|
|
90
90
|
"devDependencies": {
|
|
91
91
|
"postcss": "^8.4.0"
|
package/styles/layouts/blog.css
CHANGED
|
@@ -1,7 +1,17 @@
|
|
|
1
1
|
/* Blog layout */
|
|
2
2
|
|
|
3
|
+
/* The blog header chrome is taller (1.125rem padding + 2rem logo), so
|
|
4
|
+
tell the mobile panel where the header ends. The variable lives on the
|
|
5
|
+
layout root so the panel — a sibling of the header — inherits it. */
|
|
6
|
+
.rf-layout-blog-article {
|
|
7
|
+
--rf-header-height: 4.25rem;
|
|
8
|
+
}
|
|
3
9
|
/* ---- Header ---- */
|
|
4
10
|
.rf-blog-header {
|
|
11
|
+
position: sticky;
|
|
12
|
+
top: 0;
|
|
13
|
+
z-index: 100;
|
|
14
|
+
background: var(--rf-color-bg);
|
|
5
15
|
border-bottom: 1px solid var(--rf-color-border);
|
|
6
16
|
}
|
|
7
17
|
.rf-blog-header__inner {
|
package/styles/layouts/docs.css
CHANGED
|
@@ -75,13 +75,25 @@
|
|
|
75
75
|
vertical-align: -0.15em;
|
|
76
76
|
}
|
|
77
77
|
|
|
78
|
-
/* ----
|
|
78
|
+
/* ---- Body wrapper: sidebar + content row ----
|
|
79
|
+
* The `body` slot in docsLayout groups sidebar + main so `position: sticky`
|
|
80
|
+
* on the sidebar has a containing block that ends *before* the footer.
|
|
81
|
+
* When the user scrolls past the wrapper's bottom (i.e. when the footer
|
|
82
|
+
* comes into view) sticky releases and the sidebar scrolls away with the
|
|
83
|
+
* page rather than overlaying the footer. */
|
|
84
|
+
.rf-docs-body {
|
|
85
|
+
display: flex;
|
|
86
|
+
align-items: flex-start;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/* ---- Sticky sidebar ---- */
|
|
79
90
|
.rf-docs-sidebar {
|
|
80
|
-
position:
|
|
81
|
-
left: 0;
|
|
91
|
+
position: sticky;
|
|
82
92
|
top: 3.125rem;
|
|
83
|
-
|
|
93
|
+
align-self: flex-start;
|
|
94
|
+
flex-shrink: 0;
|
|
84
95
|
width: 240px;
|
|
96
|
+
height: calc(100vh - 3.125rem);
|
|
85
97
|
overflow-y: auto;
|
|
86
98
|
padding: 1.5rem;
|
|
87
99
|
border-right: 1px solid var(--rf-color-border);
|
|
@@ -94,13 +106,12 @@
|
|
|
94
106
|
|
|
95
107
|
/* ---- Content area ---- */
|
|
96
108
|
.rf-docs-content {
|
|
109
|
+
flex: 1;
|
|
110
|
+
min-width: 0;
|
|
97
111
|
padding-top: 4.75rem;
|
|
98
112
|
padding-bottom: 4rem;
|
|
99
113
|
container-type: inline-size;
|
|
100
114
|
}
|
|
101
|
-
.rf-docs-content--has-nav {
|
|
102
|
-
margin-left: 240px;
|
|
103
|
-
}
|
|
104
115
|
.rf-docs-content__inner {
|
|
105
116
|
max-width: 60rem;
|
|
106
117
|
margin: 0 auto;
|
|
@@ -226,16 +237,28 @@ html:has(.rf-docs-header) {
|
|
|
226
237
|
/* ---- Mobile overrides ---- */
|
|
227
238
|
@media (max-width: 768px) {
|
|
228
239
|
.rf-docs-header {
|
|
229
|
-
position:
|
|
240
|
+
position: sticky;
|
|
241
|
+
top: 0;
|
|
230
242
|
}
|
|
231
243
|
.rf-docs-header__inner p ~ p {
|
|
232
244
|
display: none;
|
|
233
245
|
}
|
|
246
|
+
/* The toolbar is sticky directly below the header so the hamburger —
|
|
247
|
+
which doubles as the open/close trigger for the sidebar-nav panel —
|
|
248
|
+
stays reachable while the panel is open or the page is scrolled.
|
|
249
|
+
`top` is 1px less than the header height so the two bars overlap by
|
|
250
|
+
a pixel — sub-pixel rounding during scroll can otherwise leave a
|
|
251
|
+
hairline gap that lets page content shine through.
|
|
252
|
+
z-index sits above the .rf-mobile-panel (99) so the hamburger
|
|
253
|
+
stays clickable while the panel is open. */
|
|
234
254
|
.rf-docs-toolbar {
|
|
235
255
|
display: flex;
|
|
256
|
+
position: sticky;
|
|
257
|
+
top: calc(3.5rem - 1px);
|
|
258
|
+
z-index: 100;
|
|
236
259
|
}
|
|
237
260
|
.rf-mobile-panel--nav {
|
|
238
|
-
top: 6.25rem;
|
|
261
|
+
top: calc(6.25rem - 1px);
|
|
239
262
|
}
|
|
240
263
|
.rf-docs-sidebar {
|
|
241
264
|
display: none;
|
|
@@ -243,9 +266,6 @@ html:has(.rf-docs-header) {
|
|
|
243
266
|
.rf-docs-content {
|
|
244
267
|
padding-top: 2rem;
|
|
245
268
|
}
|
|
246
|
-
.rf-docs-content--has-nav {
|
|
247
|
-
margin-left: 0;
|
|
248
|
-
}
|
|
249
269
|
.rf-docs-content__inner {
|
|
250
270
|
--rf-content-padding: 1.5rem;
|
|
251
271
|
--rf-docs-wide-inset: 1.5rem;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/* Shared mobile UI — menu button,
|
|
1
|
+
/* Shared mobile UI — menu button, panel docked below header, close */
|
|
2
2
|
|
|
3
3
|
/* ---- Mobile menu button (hidden on desktop) ---- */
|
|
4
4
|
.rf-mobile-menu-btn {
|
|
@@ -13,42 +13,41 @@
|
|
|
13
13
|
.rf-mobile-menu-btn:hover {
|
|
14
14
|
color: var(--rf-color-text);
|
|
15
15
|
}
|
|
16
|
+
/* Dots/X toggle — the SVG has both icons stacked; we show one at a time
|
|
17
|
+
based on the button's aria-expanded state. */
|
|
18
|
+
.rf-mobile-menu-btn__icon-close {
|
|
19
|
+
display: none;
|
|
20
|
+
}
|
|
21
|
+
.rf-mobile-menu-btn[aria-expanded="true"] .rf-mobile-menu-btn__icon-open {
|
|
22
|
+
display: none;
|
|
23
|
+
}
|
|
24
|
+
.rf-mobile-menu-btn[aria-expanded="true"] .rf-mobile-menu-btn__icon-close {
|
|
25
|
+
display: inline;
|
|
26
|
+
}
|
|
16
27
|
|
|
17
|
-
/* ----
|
|
28
|
+
/* ---- Mobile panel — docks below the header ----
|
|
29
|
+
The header height is fixed by --rf-header-height (default 3.5rem to
|
|
30
|
+
match the rendered chrome height — 0.625rem padding + 2rem logo +
|
|
31
|
+
line-box rounding). Layouts with a taller header set the variable on
|
|
32
|
+
their layout root so the panel — a sibling of the header — inherits. */
|
|
18
33
|
.rf-mobile-panel {
|
|
19
34
|
display: none;
|
|
20
35
|
position: fixed;
|
|
21
|
-
|
|
22
|
-
|
|
36
|
+
top: var(--rf-header-height, 3.5rem);
|
|
37
|
+
right: 0;
|
|
38
|
+
bottom: 0;
|
|
39
|
+
left: 0;
|
|
40
|
+
width: 100%;
|
|
41
|
+
max-width: 100vw;
|
|
42
|
+
z-index: 99;
|
|
23
43
|
background: var(--rf-color-bg, #fff);
|
|
44
|
+
overflow-x: hidden;
|
|
24
45
|
overflow-y: auto;
|
|
25
46
|
-webkit-overflow-scrolling: touch;
|
|
26
47
|
}
|
|
27
|
-
.
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
justify-content: space-between;
|
|
31
|
-
padding: 1.125rem 1.5rem;
|
|
32
|
-
border-bottom: 1px solid var(--rf-color-border);
|
|
33
|
-
}
|
|
34
|
-
.rf-mobile-panel__title {
|
|
35
|
-
font-size: 0.85rem;
|
|
36
|
-
font-weight: 600;
|
|
37
|
-
text-transform: uppercase;
|
|
38
|
-
letter-spacing: 0.05em;
|
|
39
|
-
color: var(--rf-color-muted);
|
|
40
|
-
}
|
|
41
|
-
.rf-mobile-panel__close {
|
|
42
|
-
background: none;
|
|
43
|
-
border: none;
|
|
44
|
-
padding: 0.25rem;
|
|
45
|
-
cursor: pointer;
|
|
46
|
-
color: var(--rf-color-muted);
|
|
47
|
-
line-height: 0;
|
|
48
|
-
}
|
|
49
|
-
.rf-mobile-panel__close:hover {
|
|
50
|
-
color: var(--rf-color-text);
|
|
51
|
-
}
|
|
48
|
+
/* Layout-specific panels (e.g. the docs sidebar-nav panel that sits
|
|
49
|
+
under the docs header *and* toolbar) override `top` in their own
|
|
50
|
+
layout CSS. */
|
|
52
51
|
.rf-mobile-panel__nav {
|
|
53
52
|
padding: 1.5rem;
|
|
54
53
|
}
|
|
@@ -59,15 +58,16 @@
|
|
|
59
58
|
display: none;
|
|
60
59
|
}
|
|
61
60
|
/* Panel items — top-level links and group items render uniformly. The
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
61
|
+
selectors below need to beat nav.css's nested-columns mobile overrides
|
|
62
|
+
((0,4,0)) on equal source position (nav.css is imported later than
|
|
63
|
+
mobile.css in index.css), so the columns-context selectors carry
|
|
64
|
+
(0,5,0) by including `.rf-nav-group__panel` in the chain. */
|
|
66
65
|
.rf-mobile-panel__nav a,
|
|
67
66
|
.rf-mobile-panel .rf-nav--menubar .rf-nav__top-level .rf-nav-item__link,
|
|
68
|
-
.rf-mobile-panel .rf-nav--menubar .rf-nav-group .rf-nav-item__link
|
|
67
|
+
.rf-mobile-panel .rf-nav--menubar .rf-nav-group .rf-nav-item__link,
|
|
68
|
+
.rf-mobile-panel .rf-nav--menubar .rf-nav-group__panel .rf-nav--columns .rf-nav-item__link {
|
|
69
69
|
display: block;
|
|
70
|
-
padding: 0
|
|
70
|
+
padding: 0;
|
|
71
71
|
font-size: 1.5rem;
|
|
72
72
|
font-weight: 700;
|
|
73
73
|
color: var(--rf-color-text);
|
|
@@ -77,7 +77,8 @@
|
|
|
77
77
|
}
|
|
78
78
|
.rf-mobile-panel__nav a:hover,
|
|
79
79
|
.rf-mobile-panel .rf-nav--menubar .rf-nav__top-level .rf-nav-item__link:hover,
|
|
80
|
-
.rf-mobile-panel .rf-nav--menubar .rf-nav-group .rf-nav-item__link:hover
|
|
80
|
+
.rf-mobile-panel .rf-nav--menubar .rf-nav-group .rf-nav-item__link:hover,
|
|
81
|
+
.rf-mobile-panel .rf-nav--menubar .rf-nav-group__panel .rf-nav--columns .rf-nav-item__link:hover {
|
|
81
82
|
color: var(--rf-color-primary, var(--rf-color-text));
|
|
82
83
|
background: transparent;
|
|
83
84
|
text-decoration: none;
|
|
@@ -88,6 +89,9 @@
|
|
|
88
89
|
.rf-mobile-panel .rf-nav--menubar .rf-nav-group h3 {
|
|
89
90
|
padding: 1.5rem 0 0.25rem;
|
|
90
91
|
}
|
|
92
|
+
/* Nested column collapse for the menubar drawer is handled in nav.css's
|
|
93
|
+
≤768px block (it already resets grid-template-columns and the rich-panel
|
|
94
|
+
min-width rules). */
|
|
91
95
|
.rf-mobile-panel__body {
|
|
92
96
|
padding: 1rem 1.5rem;
|
|
93
97
|
}
|
|
@@ -101,7 +105,7 @@
|
|
|
101
105
|
.rf-mobile-menu-btn {
|
|
102
106
|
display: block;
|
|
103
107
|
}
|
|
104
|
-
/* The inline menubar collapses behind the
|
|
108
|
+
/* The inline menubar collapses behind the kebab on mobile — the
|
|
105
109
|
.rf-mobile-panel duplicates the same nav and styles it as a flat
|
|
106
110
|
vertical list (see nav.css's rf-nav--menubar mobile rules). */
|
|
107
111
|
.rf-header__inner > rf-nav,
|
|
@@ -109,8 +113,8 @@
|
|
|
109
113
|
.rf-blog-header__inner > rf-nav {
|
|
110
114
|
display: none;
|
|
111
115
|
}
|
|
112
|
-
/* Hide the duplicated brand line inside the mobile panel — the
|
|
113
|
-
|
|
116
|
+
/* Hide the duplicated brand line inside the mobile panel — the header
|
|
117
|
+
above the panel already shows it. */
|
|
114
118
|
.rf-mobile-panel__nav > p:first-child {
|
|
115
119
|
display: none;
|
|
116
120
|
}
|
package/styles/layouts/plan.css
CHANGED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/* Badge rune — standalone inline pill that visually stands out from prose.
|
|
2
|
+
*
|
|
3
|
+
* Unlike the metadata badges that appear inside card chrome (plan items,
|
|
4
|
+
* recipe meta, work item headers), standalone {% badge %} runes are meant
|
|
5
|
+
* to pop. They reuse the universal `--meta-color` set by
|
|
6
|
+
* dimensions/metadata.css's sentiment rules, applied as a sentiment-tinted
|
|
7
|
+
* border, a low-opacity sentiment-tinted background, and sentiment-coloured
|
|
8
|
+
* text. The leading sentiment dot from metadata.css is dropped — the
|
|
9
|
+
* background tint already carries the sentiment cue.
|
|
10
|
+
*
|
|
11
|
+
* rank="primary" boosts emphasis with a heavier background tint and a
|
|
12
|
+
* bolder weight, useful for "Popular" / "Featured" labels that should
|
|
13
|
+
* dominate over their neighbours.
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
.rf-badge {
|
|
17
|
+
vertical-align: baseline;
|
|
18
|
+
border-color: var(--meta-color, var(--rf-color-border));
|
|
19
|
+
background: color-mix(in srgb, var(--meta-color, transparent) 12%, transparent);
|
|
20
|
+
color: var(--meta-color, var(--rf-color-text));
|
|
21
|
+
font-weight: 500;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.rf-badge[data-meta-rank="primary"] {
|
|
25
|
+
background: color-mix(in srgb, var(--meta-color, transparent) 22%, transparent);
|
|
26
|
+
font-weight: 600;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/* Drop the sentiment dot — the background tint carries the cue for
|
|
30
|
+
* standalone badges, and the dot competes visually with adjacent prose. */
|
|
31
|
+
.rf-badge::before {
|
|
32
|
+
display: none;
|
|
33
|
+
}
|
package/styles/runes/hint.css
CHANGED
package/styles/runes/nav.css
CHANGED
|
@@ -48,11 +48,19 @@
|
|
|
48
48
|
color: var(--rf-color-text);
|
|
49
49
|
text-decoration: none;
|
|
50
50
|
}
|
|
51
|
-
|
|
51
|
+
/* SPEC-055: current page receives aria-current="page" at build time
|
|
52
|
+
* (replaces the legacy --active modifier set at runtime by rf-nav). */
|
|
53
|
+
.rf-nav-item__link[aria-current="page"] {
|
|
52
54
|
background: color-mix(in srgb, var(--rf-color-primary) 8%, transparent);
|
|
53
55
|
color: var(--rf-color-primary);
|
|
54
56
|
font-weight: 600;
|
|
55
57
|
}
|
|
58
|
+
/* SPEC-055: ancestor-of-current-page link — subtler treatment than the
|
|
59
|
+
* exact-match aria-current state. Themes can collapse the two into a
|
|
60
|
+
* single style if they prefer. */
|
|
61
|
+
.rf-nav-item__link[data-active="ancestor"] {
|
|
62
|
+
color: var(--rf-color-primary);
|
|
63
|
+
}
|
|
56
64
|
.rf-nav-item {
|
|
57
65
|
padding: 0.375rem 0.75rem;
|
|
58
66
|
font-size: 0.85rem;
|
|
@@ -90,11 +98,16 @@
|
|
|
90
98
|
transition: transform 200ms ease;
|
|
91
99
|
margin-right: 0.25rem;
|
|
92
100
|
}
|
|
101
|
+
/* SPEC-054 wraps the group body in `<div data-name="panel">`. Animate that
|
|
102
|
+
* wrapper; keep the direct ul/ol selectors as a fallback for older trees
|
|
103
|
+
* that haven't picked up the panel structure. */
|
|
104
|
+
.rf-nav--collapsible .rf-nav-group > .rf-nav-group__panel,
|
|
93
105
|
.rf-nav--collapsible .rf-nav-group > ul,
|
|
94
106
|
.rf-nav--collapsible .rf-nav-group > ol {
|
|
95
107
|
overflow: hidden;
|
|
96
108
|
transition: height 200ms ease;
|
|
97
109
|
}
|
|
110
|
+
.rf-nav--collapsible .rf-nav-group[data-collapsed="true"] > .rf-nav-group__panel,
|
|
98
111
|
.rf-nav--collapsible .rf-nav-group[data-collapsed="true"] > ul,
|
|
99
112
|
.rf-nav--collapsible .rf-nav-group[data-collapsed="true"] > ol {
|
|
100
113
|
height: 0;
|
|
@@ -105,6 +118,7 @@
|
|
|
105
118
|
}
|
|
106
119
|
|
|
107
120
|
@media (prefers-reduced-motion: reduce) {
|
|
121
|
+
.rf-nav--collapsible .rf-nav-group > .rf-nav-group__panel,
|
|
108
122
|
.rf-nav--collapsible .rf-nav-group > ul,
|
|
109
123
|
.rf-nav--collapsible .rf-nav-group > ol,
|
|
110
124
|
.rf-nav--collapsible .rf-nav-group h2::after,
|
|
@@ -134,6 +148,7 @@
|
|
|
134
148
|
}
|
|
135
149
|
.rf-nav--menubar > .rf-nav__top-level li {
|
|
136
150
|
padding: 0;
|
|
151
|
+
margin: 0;
|
|
137
152
|
}
|
|
138
153
|
.rf-nav--menubar > .rf-nav__top-level .rf-nav-item__link {
|
|
139
154
|
display: inline-block;
|
|
@@ -159,6 +174,7 @@
|
|
|
159
174
|
padding: 0.375rem 0.75rem;
|
|
160
175
|
font-size: 0.9rem;
|
|
161
176
|
font-weight: 500;
|
|
177
|
+
line-height: inherit;
|
|
162
178
|
text-transform: none;
|
|
163
179
|
letter-spacing: normal;
|
|
164
180
|
color: var(--rf-color-muted);
|
|
@@ -174,13 +190,17 @@
|
|
|
174
190
|
background: var(--rf-color-surface);
|
|
175
191
|
color: var(--rf-color-text);
|
|
176
192
|
}
|
|
177
|
-
|
|
193
|
+
/* The dropdown panel is the <div data-name="panel"> wrapper added by the
|
|
194
|
+
* nav schema's buildGroupTag. Positioning + visibility live on this
|
|
195
|
+
* wrapper so the rule works equally well for simple <ul> dropdowns and
|
|
196
|
+
* rich panels containing nested navs / intro / footer slots. */
|
|
197
|
+
.rf-nav--menubar .rf-nav-group > .rf-nav-group__panel {
|
|
178
198
|
display: block;
|
|
179
199
|
position: absolute;
|
|
180
200
|
top: 100%;
|
|
181
201
|
right: 0;
|
|
182
202
|
left: auto;
|
|
183
|
-
min-width:
|
|
203
|
+
min-width: 14rem;
|
|
184
204
|
padding: 0.5rem;
|
|
185
205
|
background: var(--rf-color-bg);
|
|
186
206
|
border: 1px solid var(--rf-color-border);
|
|
@@ -193,14 +213,33 @@
|
|
|
193
213
|
transform: translateY(-4px);
|
|
194
214
|
transition: opacity 150ms ease, visibility 150ms ease, transform 150ms ease;
|
|
195
215
|
}
|
|
196
|
-
.rf-nav--menubar .rf-nav-group:hover >
|
|
197
|
-
.rf-nav--menubar .rf-nav-group:focus-within >
|
|
198
|
-
.rf-nav--menubar .rf-nav-group[data-open="true"] >
|
|
216
|
+
.rf-nav--menubar .rf-nav-group:hover > .rf-nav-group__panel,
|
|
217
|
+
.rf-nav--menubar .rf-nav-group:focus-within > .rf-nav-group__panel,
|
|
218
|
+
.rf-nav--menubar .rf-nav-group[data-open="true"] > .rf-nav-group__panel {
|
|
199
219
|
opacity: 1;
|
|
200
220
|
visibility: visible;
|
|
201
221
|
pointer-events: auto;
|
|
202
222
|
transform: translateY(0);
|
|
203
223
|
}
|
|
224
|
+
/* Inside the panel, lists render naturally (no extra positioning). */
|
|
225
|
+
.rf-nav--menubar .rf-nav-group__panel ul {
|
|
226
|
+
list-style: none;
|
|
227
|
+
padding: 0;
|
|
228
|
+
margin: 0;
|
|
229
|
+
}
|
|
230
|
+
.rf-nav--menubar .rf-nav-group__panel li {
|
|
231
|
+
padding: 0;
|
|
232
|
+
}
|
|
233
|
+
/* Flat dropdown items: force the link to fill the panel's content width so
|
|
234
|
+
* the hover hit-area is the whole row rather than just the text. Scoped to
|
|
235
|
+
* `> ul > li > a` so it only catches flat panels — nested columns navs
|
|
236
|
+
* (which sit inside `.rf-nav--columns`) keep their own item styling. */
|
|
237
|
+
.rf-nav--menubar .rf-nav-group__panel > ul > li > .rf-nav-item__link {
|
|
238
|
+
display: block;
|
|
239
|
+
width: 100%;
|
|
240
|
+
box-sizing: border-box;
|
|
241
|
+
padding: 0.5rem 0.75rem;
|
|
242
|
+
}
|
|
204
243
|
.rf-nav--menubar .rf-nav-group .rf-nav-item__link {
|
|
205
244
|
font-size: 0.85rem;
|
|
206
245
|
font-weight: 400;
|
|
@@ -265,7 +304,7 @@
|
|
|
265
304
|
background: transparent;
|
|
266
305
|
color: var(--rf-color-muted);
|
|
267
306
|
}
|
|
268
|
-
.rf-nav--menubar .rf-nav-group
|
|
307
|
+
.rf-nav--menubar .rf-nav-group > .rf-nav-group__panel {
|
|
269
308
|
position: static;
|
|
270
309
|
display: block;
|
|
271
310
|
min-width: 0;
|
|
@@ -312,11 +351,24 @@
|
|
|
312
351
|
background: transparent;
|
|
313
352
|
color: var(--rf-color-text);
|
|
314
353
|
}
|
|
354
|
+
/* Standalone columns (footer, section landing) use a text-only treatment
|
|
355
|
+
* for the active item — the generic `.rf-nav-item__link[aria-current="page"]`
|
|
356
|
+
* surface tint would compete with the column layout's quiet rhythm. The
|
|
357
|
+
* nested-in-menubar case re-enables the tint below at higher specificity. */
|
|
358
|
+
.rf-nav--columns .rf-nav-item__link[aria-current="page"] {
|
|
359
|
+
background: transparent;
|
|
360
|
+
}
|
|
315
361
|
|
|
316
362
|
@media (max-width: 600px) {
|
|
317
363
|
.rf-nav--columns {
|
|
318
|
-
|
|
319
|
-
|
|
364
|
+
/* Keep two columns on mobile. `minmax(0, 1fr)` lets columns shrink
|
|
365
|
+
* below their min-content width so long link labels don't push the
|
|
366
|
+
* grid wider than the viewport and trigger horizontal scroll. */
|
|
367
|
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
368
|
+
gap: 1.25rem 1.5rem;
|
|
369
|
+
}
|
|
370
|
+
.rf-nav--columns .rf-nav-item__link {
|
|
371
|
+
overflow-wrap: anywhere;
|
|
320
372
|
}
|
|
321
373
|
}
|
|
322
374
|
|
|
@@ -401,3 +453,255 @@
|
|
|
401
453
|
grid-template-columns: 1fr;
|
|
402
454
|
}
|
|
403
455
|
}
|
|
456
|
+
|
|
457
|
+
/* ─── Per-item description (SPEC-054, any layout) ─────────────────────── */
|
|
458
|
+
|
|
459
|
+
.rf-nav-item__description {
|
|
460
|
+
display: block;
|
|
461
|
+
font-size: 0.8125rem;
|
|
462
|
+
color: var(--rf-color-muted);
|
|
463
|
+
line-height: 1.4;
|
|
464
|
+
margin-top: 0.125rem;
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
/* ─── Menubar group slots (SPEC-054 rich panel content) ──────────────── */
|
|
468
|
+
|
|
469
|
+
/* Rich menubar panels: when the panel contains intro / nested nav / footer
|
|
470
|
+
* blocks, it auto-sizes to fit content rather than the narrow flat dropdown
|
|
471
|
+
* default. */
|
|
472
|
+
.rf-nav--menubar .rf-nav-group__panel:has(.rf-nav-group__intro),
|
|
473
|
+
.rf-nav--menubar .rf-nav-group__panel:has(.rf-nav-group__footer),
|
|
474
|
+
.rf-nav--menubar .rf-nav-group__panel:has(.rf-nav) {
|
|
475
|
+
min-width: 20rem;
|
|
476
|
+
max-width: 36rem;
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
/* When the panel contains a nested columns nav with explicit column wrappers,
|
|
480
|
+
* widen the cap so each column has room for a one-line description rather
|
|
481
|
+
* than wrapping to three or four. */
|
|
482
|
+
.rf-nav--menubar .rf-nav-group__panel:has(.rf-nav--columns > div[data-name="column"]) {
|
|
483
|
+
min-width: 36rem;
|
|
484
|
+
max-width: 56rem;
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
/* Nested columns nav inside a menubar panel: render as a distinct surface
|
|
488
|
+
* card so the column grid reads as a grouped block rather than bleeding
|
|
489
|
+
* into the panel's chrome. Resets the standalone columns padding (which
|
|
490
|
+
* assumes a footer-like context) and tightens the gap for the tighter
|
|
491
|
+
* dropdown box. */
|
|
492
|
+
.rf-nav--menubar .rf-nav-group__panel .rf-nav--columns {
|
|
493
|
+
padding: 0.75rem;
|
|
494
|
+
gap: 1rem;
|
|
495
|
+
background: var(--rf-color-surface);
|
|
496
|
+
border: 1px solid var(--rf-color-border);
|
|
497
|
+
border-radius: var(--rf-radius-sm);
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
/* Items inside a nested menubar columns nav: render the whole link as one
|
|
501
|
+
* generously padded click target with the title on top in regular text
|
|
502
|
+
* colour and the description stacked below in muted colour. The description
|
|
503
|
+
* `<span>` lives inside the `<a>` (see navItem transform), so styling on
|
|
504
|
+
* the link covers both lines. */
|
|
505
|
+
.rf-nav--menubar .rf-nav-group__panel .rf-nav--columns .rf-nav-item {
|
|
506
|
+
padding: 0;
|
|
507
|
+
}
|
|
508
|
+
.rf-nav--menubar .rf-nav-group__panel .rf-nav--columns .rf-nav-item__link {
|
|
509
|
+
display: block;
|
|
510
|
+
padding: 0.75rem;
|
|
511
|
+
color: var(--rf-color-text);
|
|
512
|
+
font-weight: 500;
|
|
513
|
+
border-radius: var(--rf-radius-sm);
|
|
514
|
+
}
|
|
515
|
+
.rf-nav--menubar .rf-nav-group__panel .rf-nav--columns .rf-nav-item__link:hover {
|
|
516
|
+
background: var(--rf-color-surface-hover);
|
|
517
|
+
color: var(--rf-color-text);
|
|
518
|
+
}
|
|
519
|
+
/* Re-enable a neutral surface tint on the active item inside a menubar
|
|
520
|
+
* dropdown — the standalone-columns override above zeroes the background,
|
|
521
|
+
* but here it helps the current page stand out from peers in a tight
|
|
522
|
+
* panel. Uses the purpose-built interactive-surface tokens so the contrast
|
|
523
|
+
* direction stays correct in dark mode. */
|
|
524
|
+
.rf-nav--menubar .rf-nav-group__panel .rf-nav--columns .rf-nav-item__link[aria-current="page"] {
|
|
525
|
+
background: var(--rf-color-surface-active);
|
|
526
|
+
}
|
|
527
|
+
.rf-nav--menubar .rf-nav-group__panel .rf-nav--columns .rf-nav-item__link .rf-nav-item__description {
|
|
528
|
+
font-weight: 400;
|
|
529
|
+
color: var(--rf-color-muted);
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
/* Intro / footer slots inside a menubar panel get airy padding so the
|
|
533
|
+
* eyebrow / "see all" links breathe inside the dropdown frame. */
|
|
534
|
+
.rf-nav--menubar .rf-nav-group__panel > .rf-nav-group__intro {
|
|
535
|
+
margin: 0 0 0.75rem;
|
|
536
|
+
padding: 0.5rem 0.75rem 0;
|
|
537
|
+
}
|
|
538
|
+
.rf-nav--menubar .rf-nav-group__panel > .rf-nav-group__footer {
|
|
539
|
+
margin: 0.75rem 0 0;
|
|
540
|
+
padding: 0 0.75rem 0.5rem;
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
.rf-nav-group__intro {
|
|
544
|
+
margin: 0 0 0.75rem;
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
/* Eyebrow intro: a plain paragraph in the intro slot renders as a small
|
|
548
|
+
* muted lead-in above the panel content. */
|
|
549
|
+
.rf-nav-group__intro p:only-child {
|
|
550
|
+
margin: 0;
|
|
551
|
+
font-size: 0.75rem;
|
|
552
|
+
color: var(--rf-color-muted);
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
.rf-nav-group__footer {
|
|
556
|
+
margin: 0.75rem 0 0;
|
|
557
|
+
}
|
|
558
|
+
.rf-nav-group__footer p {
|
|
559
|
+
margin: 0;
|
|
560
|
+
font-size: 0.8125rem;
|
|
561
|
+
color: var(--rf-color-muted);
|
|
562
|
+
}
|
|
563
|
+
.rf-nav-group__footer a {
|
|
564
|
+
color: var(--rf-color-primary);
|
|
565
|
+
font-weight: 500;
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
/* ─── Multi-section columns (SPEC-054 columns flow rule) ──────────────── */
|
|
569
|
+
|
|
570
|
+
/* When the columns layout has <hr> separators, groups are bucketed into
|
|
571
|
+
* .rf-nav-group__column wrappers (or .rf-nav__column at the nav level for
|
|
572
|
+
* headingless mode). Each column stacks one or more sections vertically. */
|
|
573
|
+
.rf-nav--columns .rf-nav-group__column,
|
|
574
|
+
.rf-nav--columns .rf-nav__column,
|
|
575
|
+
.rf-nav--columns > div[data-name="column"] {
|
|
576
|
+
display: flex;
|
|
577
|
+
flex-direction: column;
|
|
578
|
+
gap: 1.25rem;
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
/* Multi-section columns mode: when the author has placed explicit `---`
|
|
582
|
+
* dividers, the structure already declares the column count. Use
|
|
583
|
+
* grid-auto-flow:column so each `data-name="column"` wrapper becomes its own
|
|
584
|
+
* track — this expands the container to fit the tracks rather than
|
|
585
|
+
* collapsing to one column when the container is narrow (e.g. nested inside
|
|
586
|
+
* a menubar panel at its min-width). */
|
|
587
|
+
.rf-nav--columns:has(> div[data-name="column"]) {
|
|
588
|
+
display: grid;
|
|
589
|
+
grid-template-columns: unset;
|
|
590
|
+
grid-auto-flow: column;
|
|
591
|
+
grid-auto-columns: minmax(14rem, 1fr);
|
|
592
|
+
}
|
|
593
|
+
|
|
594
|
+
/* Stepped collapse: at four columns × 14rem min + gaps the grid needs ~62rem
|
|
595
|
+
* of width, so below ~900px the explicit-column flow would overflow. Step
|
|
596
|
+
* down to a 2×N grid before going single-column at the narrowest breakpoint. */
|
|
597
|
+
@media (max-width: 900px) {
|
|
598
|
+
.rf-nav--columns:has(> div[data-name="column"]) {
|
|
599
|
+
grid-auto-flow: row;
|
|
600
|
+
grid-auto-columns: unset;
|
|
601
|
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
@media (max-width: 600px) {
|
|
606
|
+
.rf-nav--columns:has(> div[data-name="column"]) {
|
|
607
|
+
grid-auto-flow: row;
|
|
608
|
+
grid-auto-columns: unset;
|
|
609
|
+
/* Keep two columns on mobile. `minmax(0, 1fr)` lets columns shrink
|
|
610
|
+
* below their min-content width so long link labels don't push the
|
|
611
|
+
* grid wider than the viewport and trigger horizontal scroll. */
|
|
612
|
+
grid-template-columns: repeat(2, minmax(0, 1fr));
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
|
|
616
|
+
/* ─── Strip layout (SPEC-054 compact secondary nav) ───────────────────── */
|
|
617
|
+
|
|
618
|
+
.rf-nav--strip {
|
|
619
|
+
display: flex;
|
|
620
|
+
flex-wrap: wrap;
|
|
621
|
+
gap: 0.5rem 1rem;
|
|
622
|
+
padding: 0.5rem 0;
|
|
623
|
+
font-size: 0.8125rem;
|
|
624
|
+
}
|
|
625
|
+
.rf-nav--strip ul {
|
|
626
|
+
display: flex;
|
|
627
|
+
flex-wrap: wrap;
|
|
628
|
+
gap: 0.5rem 1rem;
|
|
629
|
+
list-style: none;
|
|
630
|
+
padding: 0;
|
|
631
|
+
margin: 0;
|
|
632
|
+
}
|
|
633
|
+
.rf-nav--strip li {
|
|
634
|
+
padding: 0;
|
|
635
|
+
}
|
|
636
|
+
.rf-nav--strip .rf-nav-item__link {
|
|
637
|
+
display: inline-block;
|
|
638
|
+
padding: 0.25rem 0;
|
|
639
|
+
color: var(--rf-color-muted);
|
|
640
|
+
font-size: 0.8125rem;
|
|
641
|
+
border-radius: 0;
|
|
642
|
+
background: transparent;
|
|
643
|
+
}
|
|
644
|
+
.rf-nav--strip .rf-nav-item__link:hover {
|
|
645
|
+
color: var(--rf-color-text);
|
|
646
|
+
background: transparent;
|
|
647
|
+
}
|
|
648
|
+
.rf-nav--strip .rf-nav-item__link[aria-current="page"] {
|
|
649
|
+
color: var(--rf-color-primary);
|
|
650
|
+
background: transparent;
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
/* When a strip nav is nested inside a menubar panel footer slot, render
|
|
654
|
+
* compact-but-still-tap-friendly. */
|
|
655
|
+
.rf-nav-group__footer .rf-nav--strip {
|
|
656
|
+
padding: 0;
|
|
657
|
+
font-size: 0.75rem;
|
|
658
|
+
}
|
|
659
|
+
|
|
660
|
+
/* ─── Mobile menubar: nested columns collapse ─────────────────────────── */
|
|
661
|
+
|
|
662
|
+
/* Placed at the end of the file so the source order beats the desktop
|
|
663
|
+
* nested-columns rules at equal specificity. On a collapsed menubar
|
|
664
|
+
* drawer (≤ 768px), drop the columns nav's surface card chrome and
|
|
665
|
+
* flatten to a single-column flow so each item visually matches a
|
|
666
|
+
* regular flat-dropdown item rather than a card-styled grid cell. */
|
|
667
|
+
@media (max-width: 768px) {
|
|
668
|
+
.rf-nav--menubar .rf-nav-group__panel .rf-nav--columns {
|
|
669
|
+
padding: 0;
|
|
670
|
+
gap: 0;
|
|
671
|
+
background: transparent;
|
|
672
|
+
border: 0;
|
|
673
|
+
border-radius: 0;
|
|
674
|
+
grid-auto-flow: row;
|
|
675
|
+
grid-auto-columns: unset;
|
|
676
|
+
grid-template-columns: 1fr;
|
|
677
|
+
}
|
|
678
|
+
/* Tighter padding + bolder weight matches the visual rhythm of the
|
|
679
|
+
* regular flat menubar group items above. Hover swaps to a text-colour
|
|
680
|
+
* change rather than a surface tint so the drawer doesn't fill with
|
|
681
|
+
* highlighted bands as the user scrolls. */
|
|
682
|
+
.rf-nav--menubar .rf-nav-group__panel .rf-nav--columns .rf-nav-item__link {
|
|
683
|
+
padding: 0.25rem 0.75rem;
|
|
684
|
+
font-weight: 500;
|
|
685
|
+
}
|
|
686
|
+
.rf-nav--menubar .rf-nav-group__panel .rf-nav--columns .rf-nav-item__link:hover {
|
|
687
|
+
background: transparent;
|
|
688
|
+
color: var(--rf-color-primary);
|
|
689
|
+
}
|
|
690
|
+
/* Descriptions are space-eaters in a vertical drawer — hide them and let
|
|
691
|
+
* the link title carry the line on its own. */
|
|
692
|
+
.rf-nav--menubar .rf-nav-group__panel .rf-nav--columns .rf-nav-item__description {
|
|
693
|
+
display: none;
|
|
694
|
+
}
|
|
695
|
+
/* Rich-panel min-widths (20rem / 36rem) above aren't viewport-gated and
|
|
696
|
+
* would push the drawer wider than the mobile viewport. The drawer
|
|
697
|
+
* renders the menubar as a flat vertical list, so no min-width is
|
|
698
|
+
* needed — clamp to fit. Placed after the rich-panel rules so source
|
|
699
|
+
* order wins the cascade at equal specificity. */
|
|
700
|
+
.rf-nav--menubar .rf-nav-group__panel:has(.rf-nav-group__intro),
|
|
701
|
+
.rf-nav--menubar .rf-nav-group__panel:has(.rf-nav-group__footer),
|
|
702
|
+
.rf-nav--menubar .rf-nav-group__panel:has(.rf-nav),
|
|
703
|
+
.rf-nav--menubar .rf-nav-group__panel:has(.rf-nav--columns > div[data-name="column"]) {
|
|
704
|
+
min-width: 0;
|
|
705
|
+
max-width: 100%;
|
|
706
|
+
}
|
|
707
|
+
}
|