@kolkrabbi/kol-framework 0.6.0 → 0.6.2
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 +13 -46
- package/package.json +2 -2
- package/src/ShellHeader.jsx +50 -29
package/kol-framework.css
CHANGED
|
@@ -17,21 +17,11 @@ html,
|
|
|
17
17
|
body {
|
|
18
18
|
background: var(--kol-surface-primary);
|
|
19
19
|
color: var(--kol-surface-on-primary);
|
|
20
|
-
|
|
21
|
-
/* Editor-style app — selection is mostly meaningless on chrome. Default
|
|
22
|
-
* to non-selectable; opt back in for prose, tables, inputs, code below. */
|
|
23
|
-
-webkit-user-select: none;
|
|
24
|
-
user-select: none;
|
|
25
20
|
}
|
|
26
21
|
|
|
27
|
-
/*
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
.kol-table, .kol-table *,
|
|
31
|
-
code, pre {
|
|
32
|
-
-webkit-user-select: text;
|
|
33
|
-
user-select: text;
|
|
34
|
-
}
|
|
22
|
+
/* The global user-select:none gate + allowlist was REMOVED 2026-07-29 (user
|
|
23
|
+
* law, brand-app ruling): text is selectable everywhere — copyability beats
|
|
24
|
+
* chrome purity. */
|
|
35
25
|
|
|
36
26
|
/* Selection highlight uses brand-primary so it reads on-brand when it appears. */
|
|
37
27
|
::selection {
|
|
@@ -87,7 +77,10 @@ code, pre {
|
|
|
87
77
|
|
|
88
78
|
@media (min-width: 1280px) { :root { --kol-container-max: 1600px; } }
|
|
89
79
|
|
|
90
|
-
:root[data-sidenav="collapsed"]
|
|
80
|
+
/* :root[data-sidenav="collapsed"] removed 2026-07-29 — the manual collapse
|
|
81
|
+
* feature died with the editor's exit (brand ruling); the responsive rail
|
|
82
|
+
* below 1024px is the surviving narrow mode. --kol-sidenav-w-collapsed stays:
|
|
83
|
+
* the rail still uses it. */
|
|
91
84
|
|
|
92
85
|
/* ───── Brand doc layout (sidebar + content) ─────
|
|
93
86
|
The grid lives in CSS for its dynamic --kol-sidenav-w + transition. */
|
|
@@ -103,7 +96,6 @@ code, pre {
|
|
|
103
96
|
User's localStorage expand preference is overridden while viewport is narrow;
|
|
104
97
|
restored once they cross back over the threshold. */
|
|
105
98
|
.kol-brand-layout { grid-template-columns: var(--kol-sidenav-w-collapsed) minmax(0, 1fr); }
|
|
106
|
-
.kol-sidenav-toggle { display: none; }
|
|
107
99
|
.kol-sidenav-hops { padding: 0 0 16px; margin-bottom: 16px; }
|
|
108
100
|
.kol-sidenav-hop { padding: 8px 0; justify-content: center; gap: 0; }
|
|
109
101
|
.kol-sidenav-hop-label { display: none; }
|
|
@@ -134,30 +126,9 @@ code, pre {
|
|
|
134
126
|
}
|
|
135
127
|
|
|
136
128
|
/* SideNav primitives (.kol-sidenav-hop, -hop-icon, -hop-label, -link,
|
|
137
|
-
* -group) promoted to kol-components-atoms.css 2026-04-30. The
|
|
138
|
-
*
|
|
139
|
-
*
|
|
140
|
-
|
|
141
|
-
/* ───── SideNav collapsed (rail mode) — overrides inlined hop padding/gap ───── */
|
|
142
|
-
|
|
143
|
-
.kol-sidenav.is-collapsed .kol-sidenav-hops {
|
|
144
|
-
padding: 0 0 16px;
|
|
145
|
-
margin-bottom: 16px;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
.kol-sidenav.is-collapsed .kol-sidenav-hop {
|
|
149
|
-
padding: 8px 0;
|
|
150
|
-
justify-content: center;
|
|
151
|
-
gap: 0;
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
.kol-sidenav.is-collapsed .kol-sidenav-hop-label {
|
|
155
|
-
display: none;
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
.kol-sidenav.is-collapsed .kol-sidenav-body {
|
|
159
|
-
display: none;
|
|
160
|
-
}
|
|
129
|
+
* -group) promoted to kol-components-atoms.css 2026-04-30. The manual
|
|
130
|
+
* collapse (.is-collapsed rail mode) was removed 2026-07-29 with the
|
|
131
|
+
* editor's exit — the ≤1024px responsive rail above is the survivor. */
|
|
161
132
|
|
|
162
133
|
/* ───── Page scaffold ───── */
|
|
163
134
|
|
|
@@ -807,13 +778,9 @@ code, pre {
|
|
|
807
778
|
}
|
|
808
779
|
|
|
809
780
|
/* SideNav collapsibleSections chrome — inert unless that mode renders.
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
.kol-sidenav.is-collapsed .kol-sidenav-section-toggle {
|
|
814
|
-
display: none;
|
|
815
|
-
}
|
|
816
|
-
|
|
781
|
+
The forced rail (≤1024px) hides count/toggle with the labels; the open
|
|
782
|
+
≤767px drawer restores them, mirroring -hop-label. (Manual .is-collapsed
|
|
783
|
+
removed 2026-07-29.) */
|
|
817
784
|
@media (max-width: 1024px) {
|
|
818
785
|
.kol-sidenav-hop-count,
|
|
819
786
|
.kol-sidenav-section-toggle {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kolkrabbi/kol-framework",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.2",
|
|
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",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
],
|
|
29
29
|
"dependencies": {
|
|
30
30
|
"@kolkrabbi/kol-component": "0.12.19",
|
|
31
|
-
"@kolkrabbi/kol-icons": "0.8.
|
|
31
|
+
"@kolkrabbi/kol-icons": "0.8.10"
|
|
32
32
|
},
|
|
33
33
|
"peerDependencies": {
|
|
34
34
|
"react": "^18.3.0 || ^19.0.0",
|
package/src/ShellHeader.jsx
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Icon } from '@kolkrabbi/kol-icons'
|
|
2
|
-
import { SearchInput } from '@kolkrabbi/kol-component'
|
|
2
|
+
import { SearchInput, Tooltip } from '@kolkrabbi/kol-component'
|
|
3
3
|
import ThemeToggle from './ThemeToggle.jsx'
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -21,6 +21,11 @@ import ThemeToggle from './ThemeToggle.jsx'
|
|
|
21
21
|
* Tab-strip chrome (mono type, active underline, hidden scrollbar, wide-
|
|
22
22
|
* viewport bumps) lives in kol-framework.css under kol-shell-header-*.
|
|
23
23
|
*
|
|
24
|
+
* Every icon-only control is Tooltip-wrapped and aria-labelled, the bar is a
|
|
25
|
+
* real `<header>` landmark, and the theme toggle steps up a rung at lg+ —
|
|
26
|
+
* folded in from the kol-website workshop fork (2026-07-30), which existed
|
|
27
|
+
* only to add these. Consumers get ONE header; the fork is retired.
|
|
28
|
+
*
|
|
24
29
|
* @param {ReactNode} brand Row-1 left slot — logo/wordmark + link, consumer-supplied
|
|
25
30
|
* @param {Array} nav section tabs: [{ label, href, icon? }]
|
|
26
31
|
* @param {Function} isActive (href) => boolean — marks the active tab
|
|
@@ -58,7 +63,7 @@ export default function ShellHeader({
|
|
|
58
63
|
const hasTabRow = nav.length > 0 || Boolean(search) || Boolean(onNavToggle) || Boolean(onTocToggle)
|
|
59
64
|
|
|
60
65
|
return (
|
|
61
|
-
<
|
|
66
|
+
<header className={`kol-shell-header sticky top-0 z-50 shrink-0 bg-surface-primary ${className}`.trim()}>
|
|
62
67
|
{/* Row 1: brand block + controls */}
|
|
63
68
|
<div className="border-b border-fg-08">
|
|
64
69
|
<div className="w-full px-4 py-4 md:px-5 lg:px-6">
|
|
@@ -70,16 +75,25 @@ export default function ShellHeader({
|
|
|
70
75
|
</div>
|
|
71
76
|
<div className="flex shrink-0 items-center gap-1">
|
|
72
77
|
{actions}
|
|
73
|
-
{showThemeToggle &&
|
|
78
|
+
{showThemeToggle && (
|
|
79
|
+
<Tooltip label="Toggle theme">
|
|
80
|
+
{/* one rung up at lg+ — the bar has room, and the toggle is
|
|
81
|
+
* the most-used control in the row */}
|
|
82
|
+
<span className="hidden lg:inline-flex"><ThemeToggle size="lg" /></span>
|
|
83
|
+
<span className="lg:hidden"><ThemeToggle /></span>
|
|
84
|
+
</Tooltip>
|
|
85
|
+
)}
|
|
74
86
|
{onMenuClick && (
|
|
75
|
-
<
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
87
|
+
<Tooltip label="Open navigation menu">
|
|
88
|
+
<button
|
|
89
|
+
type="button"
|
|
90
|
+
className={`${iconBtnCls} text-fg-64`}
|
|
91
|
+
onClick={onMenuClick}
|
|
92
|
+
aria-label="Open navigation menu"
|
|
93
|
+
>
|
|
94
|
+
<Icon name="hamburger" size={18} />
|
|
95
|
+
</button>
|
|
96
|
+
</Tooltip>
|
|
83
97
|
)}
|
|
84
98
|
</div>
|
|
85
99
|
</div>
|
|
@@ -98,7 +112,7 @@ export default function ShellHeader({
|
|
|
98
112
|
<a
|
|
99
113
|
key={item.href ?? item.label}
|
|
100
114
|
href={item.href}
|
|
101
|
-
className="kol-shell-header-tab"
|
|
115
|
+
className="kol-shell-header-tab kol-mono-14"
|
|
102
116
|
aria-current={active ? 'page' : undefined}
|
|
103
117
|
onClick={onNavigate ? (event) => onNavigate(event, item) : undefined}
|
|
104
118
|
>
|
|
@@ -111,30 +125,37 @@ export default function ShellHeader({
|
|
|
111
125
|
{search && (
|
|
112
126
|
<SearchInput
|
|
113
127
|
className="shrink-0 self-center"
|
|
128
|
+
aria-label="Search"
|
|
114
129
|
{...(search === true ? {} : search)}
|
|
115
130
|
/>
|
|
116
131
|
)}
|
|
117
132
|
{(onNavToggle || onTocToggle) && (
|
|
118
133
|
<div className="hidden lg:flex items-center gap-1 pb-2">
|
|
119
134
|
{onNavToggle && (
|
|
120
|
-
<
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
135
|
+
<Tooltip label="Toggle navigation sidebar">
|
|
136
|
+
<button
|
|
137
|
+
type="button"
|
|
138
|
+
className={`${iconBtnCls} ${navCollapsed ? 'text-fg-32' : 'text-fg-64'}`}
|
|
139
|
+
onClick={onNavToggle}
|
|
140
|
+
aria-label="Toggle navigation sidebar"
|
|
141
|
+
aria-pressed={!navCollapsed}
|
|
142
|
+
>
|
|
143
|
+
<Icon name="panel-left" size={18} />
|
|
144
|
+
</button>
|
|
145
|
+
</Tooltip>
|
|
128
146
|
)}
|
|
129
147
|
{onTocToggle && (
|
|
130
|
-
<
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
148
|
+
<Tooltip label="Toggle table of contents sidebar">
|
|
149
|
+
<button
|
|
150
|
+
type="button"
|
|
151
|
+
className={`${iconBtnCls} ${tocCollapsed ? 'text-fg-32' : 'text-fg-64'}`}
|
|
152
|
+
onClick={onTocToggle}
|
|
153
|
+
aria-label="Toggle table of contents sidebar"
|
|
154
|
+
aria-pressed={!tocCollapsed}
|
|
155
|
+
>
|
|
156
|
+
<Icon name="panel-right" size={18} />
|
|
157
|
+
</button>
|
|
158
|
+
</Tooltip>
|
|
138
159
|
)}
|
|
139
160
|
</div>
|
|
140
161
|
)}
|
|
@@ -142,6 +163,6 @@ export default function ShellHeader({
|
|
|
142
163
|
</div>
|
|
143
164
|
</div>
|
|
144
165
|
)}
|
|
145
|
-
</
|
|
166
|
+
</header>
|
|
146
167
|
)
|
|
147
168
|
}
|