@kolkrabbi/kol-framework 0.23.0 → 0.25.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/kol-framework.css +19 -0
- package/package.json +16 -14
- package/src/SideNav.jsx +66 -26
package/kol-framework.css
CHANGED
|
@@ -150,6 +150,16 @@ body {
|
|
|
150
150
|
gap: 0.125rem;
|
|
151
151
|
margin-bottom: 0.5rem;
|
|
152
152
|
}
|
|
153
|
+
/* A nested route GROUP's header (sidenav-nested-groups, kol-studio
|
|
154
|
+
* 2026-08-26): a non-routing label sitting where a leaf sits, its rows one
|
|
155
|
+
* step further in. Type and colour ride the element as utilities
|
|
156
|
+
* (kol-helper-10; text-subtle, text-emphasis when a leaf beneath it is the
|
|
157
|
+
* route); the box lives here. No text-transform — the retired fork's
|
|
158
|
+
* `uppercase` does not return (type law: only the display voice carries one). */
|
|
159
|
+
.kol-sidenav-group {
|
|
160
|
+
display: block;
|
|
161
|
+
padding: 0.25rem 1.5rem 0.25rem 3.5rem;
|
|
162
|
+
}
|
|
153
163
|
.kol-sidenav-footer { padding-inline: 1.5rem 1rem; }
|
|
154
164
|
|
|
155
165
|
/* The aside's OWN box (SideNavMobilePosition, kol-website 2026-08-25) — the
|
|
@@ -493,6 +503,15 @@ body {
|
|
|
493
503
|
width: clamp(320px, 72vw, 900px);
|
|
494
504
|
}
|
|
495
505
|
|
|
506
|
+
/* fullWidth (FeaturedCarouselFullWidth, kol-website 2026-08-26): the slide
|
|
507
|
+
* fills its container. The prop only ever dropped the section's own padding —
|
|
508
|
+
* the slide stayed the 72vw peek width, so a 1440 viewport showed 270px of
|
|
509
|
+
* the neighbours on both sides and every neighbour's video autoplayed. Peek
|
|
510
|
+
* is still the default; nothing existing moves. */
|
|
511
|
+
.kol-featured-carousel.is-full .kol-embla-slide {
|
|
512
|
+
width: 100%;
|
|
513
|
+
}
|
|
514
|
+
|
|
496
515
|
.kol-embla-controls {
|
|
497
516
|
display: flex;
|
|
498
517
|
gap: 8px;
|
package/package.json
CHANGED
|
@@ -1,20 +1,28 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kolkrabbi/kol-framework",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.25.0",
|
|
4
4
|
"description": "KOL app shell — sidenav, layout, theme toggle, footer, heroes + brand color layer. SideNav takes nav data as props so the tree stays app-local.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"main": "./src/index.js",
|
|
8
8
|
"module": "./src/index.js",
|
|
9
|
-
"sideEffects": [
|
|
10
|
-
"*.css"
|
|
11
|
-
],
|
|
12
9
|
"exports": {
|
|
13
10
|
".": "./src/index.js",
|
|
14
11
|
"./src/*": "./src/*",
|
|
15
12
|
"./kol-framework.css": "./kol-framework.css",
|
|
16
13
|
"./kol-brand-color.css": "./kol-brand-color.css"
|
|
17
14
|
},
|
|
15
|
+
"peerDependencies": {
|
|
16
|
+
"@kolkrabbi/kol-component": ">=0.70.0",
|
|
17
|
+
"@kolkrabbi/kol-icons": ">=0.18.0",
|
|
18
|
+
"react": "^18.3.0 || ^19.0.0",
|
|
19
|
+
"react-dom": "^18.3.0 || ^19.0.0",
|
|
20
|
+
"react-router-dom": "^6.0.0 || ^7.0.0"
|
|
21
|
+
},
|
|
22
|
+
"devDependencies": {
|
|
23
|
+
"@kolkrabbi/kol-component": "^0.70.0",
|
|
24
|
+
"@kolkrabbi/kol-icons": "^0.18.0"
|
|
25
|
+
},
|
|
18
26
|
"files": [
|
|
19
27
|
"src",
|
|
20
28
|
"*.css",
|
|
@@ -27,15 +35,6 @@
|
|
|
27
35
|
"react",
|
|
28
36
|
"app-shell"
|
|
29
37
|
],
|
|
30
|
-
"dependencies": {
|
|
31
|
-
"@kolkrabbi/kol-icons": "^0.18.0",
|
|
32
|
-
"@kolkrabbi/kol-component": "^0.68.1"
|
|
33
|
-
},
|
|
34
|
-
"peerDependencies": {
|
|
35
|
-
"react": "^18.3.0 || ^19.0.0",
|
|
36
|
-
"react-dom": "^18.3.0 || ^19.0.0",
|
|
37
|
-
"react-router-dom": "^6.0.0 || ^7.0.0"
|
|
38
|
-
},
|
|
39
38
|
"repository": {
|
|
40
39
|
"type": "git",
|
|
41
40
|
"url": "git+https://github.com/Tor-Grimsson/kol-ds.git",
|
|
@@ -43,5 +42,8 @@
|
|
|
43
42
|
},
|
|
44
43
|
"publishConfig": {
|
|
45
44
|
"access": "public"
|
|
46
|
-
}
|
|
45
|
+
},
|
|
46
|
+
"sideEffects": [
|
|
47
|
+
"*.css"
|
|
48
|
+
]
|
|
47
49
|
}
|
package/src/SideNav.jsx
CHANGED
|
@@ -13,14 +13,26 @@ import useDragResize from './useDragResize'
|
|
|
13
13
|
* better version in kol-website apps:brand") — the brand app's evolved fork
|
|
14
14
|
* folded back into the package, generic seams kept.
|
|
15
15
|
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
* `pages` (Home) renders as a plain link row — it has nothing to disclose.
|
|
16
|
+
* A category is a grouping LABEL — a disclosure <button> with a trailing
|
|
17
|
+
* caret, no route. A page is a route. The ONE exception: a category with `to`
|
|
18
|
+
* and no `pages` (Home) renders as a plain link row — it has nothing to
|
|
19
|
+
* disclose.
|
|
21
20
|
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
21
|
+
* The 2026-08-01 "TWO LEVELS ONLY" ruling was the BRAND APP's, about its
|
|
22
|
+
* scroll-spied `#anchor` section layer — that layer stays dead (an `{ id }`
|
|
23
|
+
* leaf is dropped). It was inscribed here as a law for every consumer, and
|
|
24
|
+
* kol-studio lost two groups and six routes from its rail on adopting 0.23.0.
|
|
25
|
+
* User, 2026-08-26, verbatim: "ok that is such a problem, sometimes Im
|
|
26
|
+
* talking about a specific thing and it gets applied as a literal fit-all
|
|
27
|
+
* rule, which isnt the case. its very hard to work in such uncertainty."
|
|
28
|
+
* Re-scoped (sidenav-nested-groups, 0.24.0): nested ROUTE groups are
|
|
29
|
+
* supported. A `{ label, children }` node inside a category renders as a
|
|
30
|
+
* non-routing group header with its rows indented one step under it,
|
|
31
|
+
* recursively. The tree shape is the opt-in — there is no prop — and a tree
|
|
32
|
+
* with no group nodes renders byte-for-byte as before.
|
|
33
|
+
*
|
|
34
|
+
* navTree: [{ id, label, icon, to?, pages?: [{ label, to } | { label, children }] }]
|
|
35
|
+
* (legacy `children` on a category is read as `pages`; section anchors are not.)
|
|
24
36
|
*
|
|
25
37
|
* Collapse: the pill-marked grab edge is THE single control (user build
|
|
26
38
|
* order 2026-08-09, completing SideNavGrabResize — the chip Button is gone
|
|
@@ -47,9 +59,17 @@ const pageStyle = { '--kol-sidenav-dot-left': '2.625rem' }
|
|
|
47
59
|
const pageCls = `${pageBase} text-strong hover:text-emphasis`
|
|
48
60
|
const pageActiveCls = `${pageBase} is-active`
|
|
49
61
|
|
|
50
|
-
/*
|
|
51
|
-
* leaves
|
|
52
|
-
|
|
62
|
+
/* A category's rows: route leaves (`to`) and route groups (`children`).
|
|
63
|
+
* `#anchor` leaves (`id` only) are dropped — that layer died with the brand
|
|
64
|
+
* app's 2026-08-01 ruling and is not reopened here. */
|
|
65
|
+
const rowsOf = (nodes) => nodes.filter((c) => c.to || c.children)
|
|
66
|
+
const pagesOf = (cat) => rowsOf(cat.pages ?? cat.children ?? [])
|
|
67
|
+
/* Every route leaf under a set of rows, through any depth of groups. */
|
|
68
|
+
const leavesOf = (rows) => rows.flatMap((r) => (r.children ? leavesOf(rowsOf(r.children)) : [r]))
|
|
69
|
+
/* A nested row sits one --kol-spacing-3 step further in per depth. Inline,
|
|
70
|
+
* not a rule: `pl-14` rides the leaf as a utility and outranks anything in
|
|
71
|
+
* this layer. Depth 0 carries no indent so a flat tree renders unchanged. */
|
|
72
|
+
const indentOf = (depth) => `calc(3.5rem + ${depth} * var(--kol-spacing-3))`
|
|
53
73
|
|
|
54
74
|
export default function SideNav({
|
|
55
75
|
drawerOpen = false,
|
|
@@ -61,7 +81,7 @@ export default function SideNav({
|
|
|
61
81
|
}) {
|
|
62
82
|
const { pathname } = useLocation()
|
|
63
83
|
const isPageActive = (to) => (isActive ? isActive(to) : pathname === to)
|
|
64
|
-
const isActiveCat = (cat) => pagesOf(cat).some((p) => isPageActive(p.to))
|
|
84
|
+
const isActiveCat = (cat) => leavesOf(pagesOf(cat)).some((p) => isPageActive(p.to))
|
|
65
85
|
|
|
66
86
|
/* Every navigation closes the mobile drawer — the prop sat accepted-but-
|
|
67
87
|
* unread until the kol-website session flagged it (2026-08-09) — and, from
|
|
@@ -90,6 +110,40 @@ export default function SideNav({
|
|
|
90
110
|
const asideRef = useRef(null)
|
|
91
111
|
const { collapsed, toggleCollapsed, grabProps } = useDragResize(asideRef)
|
|
92
112
|
|
|
113
|
+
/* Rows under a category: a leaf is a NavLink; a group is a non-routing
|
|
114
|
+
* header over its own rows, one step further in (recursive). A group lights
|
|
115
|
+
* up the way a category does — when one of its leaves is the current route. */
|
|
116
|
+
const renderRows = (rows, depth) => rows.map((row, i) => {
|
|
117
|
+
if (row.children) {
|
|
118
|
+
const lit = leavesOf(rowsOf(row.children)).some((l) => isPageActive(l.to))
|
|
119
|
+
return (
|
|
120
|
+
<li key={row.id ?? `${row.label}-${i}`}>
|
|
121
|
+
<div
|
|
122
|
+
className={`kol-sidenav-group kol-helper-10${lit ? ' text-emphasis' : ' text-subtle'}`}
|
|
123
|
+
style={depth ? { paddingLeft: indentOf(depth) } : undefined}
|
|
124
|
+
>
|
|
125
|
+
{row.label}
|
|
126
|
+
</div>
|
|
127
|
+
<ul className="kol-sidenav-list">{renderRows(rowsOf(row.children), depth + 1)}</ul>
|
|
128
|
+
</li>
|
|
129
|
+
)
|
|
130
|
+
}
|
|
131
|
+
return (
|
|
132
|
+
<li key={row.to}>
|
|
133
|
+
<NavLink
|
|
134
|
+
to={row.to}
|
|
135
|
+
end
|
|
136
|
+
/* the dot keeps its 0.875rem lead on the text at every depth */
|
|
137
|
+
style={depth ? { paddingLeft: indentOf(depth), '--kol-sidenav-dot-left': `calc(2.625rem + ${depth} * var(--kol-spacing-3))` } : pageStyle}
|
|
138
|
+
className={({ isActive: navActive }) => ((isActive ? isActive(row.to) : navActive) ? pageActiveCls : pageCls)}
|
|
139
|
+
onClick={handleNavigate}
|
|
140
|
+
>
|
|
141
|
+
{row.label}
|
|
142
|
+
</NavLink>
|
|
143
|
+
</li>
|
|
144
|
+
)
|
|
145
|
+
})
|
|
146
|
+
|
|
93
147
|
return (
|
|
94
148
|
<aside
|
|
95
149
|
ref={asideRef}
|
|
@@ -174,21 +228,7 @@ export default function SideNav({
|
|
|
174
228
|
) : head}
|
|
175
229
|
|
|
176
230
|
{!isLink && isOpen && (
|
|
177
|
-
<ul className="kol-sidenav-list">
|
|
178
|
-
{pages.map((page) => (
|
|
179
|
-
<li key={page.to}>
|
|
180
|
-
<NavLink
|
|
181
|
-
to={page.to}
|
|
182
|
-
end
|
|
183
|
-
style={pageStyle}
|
|
184
|
-
className={({ isActive: navActive }) => ((isActive ? isActive(page.to) : navActive) ? pageActiveCls : pageCls)}
|
|
185
|
-
onClick={handleNavigate}
|
|
186
|
-
>
|
|
187
|
-
{page.label}
|
|
188
|
-
</NavLink>
|
|
189
|
-
</li>
|
|
190
|
-
))}
|
|
191
|
-
</ul>
|
|
231
|
+
<ul className="kol-sidenav-list">{renderRows(pages, 0)}</ul>
|
|
192
232
|
)}
|
|
193
233
|
</li>
|
|
194
234
|
)
|