@kolkrabbi/kol-framework 0.10.2 → 0.11.1

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 CHANGED
@@ -31,8 +31,21 @@ body {
31
31
 
32
32
  :root {
33
33
  --kol-topnav-h: 0px;
34
- --kol-sidenav-w: 260px;
34
+ /* 16rem — the rail width, one number (2026-07-31). It read 260 while every
35
+ grid track that had to line up with it read 256, so the shell header's
36
+ brand block sat 4 off the sidebar column it exists to align to. */
37
+ --kol-sidenav-w: 16rem;
35
38
  --kol-sidenav-w-collapsed: 56px;
39
+ /* The workshop shell's RIGHT rail. EQUAL TO THE LEFT (user ruling
40
+ 2026-08-01) — the two rails frame the same content and a lopsided frame is
41
+ a frame nobody drew on purpose; it read 14rem against the left's 16rem.
42
+ Kept as its own token rather than aliased: the right rail can be ruled
43
+ different later without touching the sidenav.
44
+ The track is RESERVED whether or not the rail has anything in it — a rail
45
+ that vanishes on a heading-less page re-flows main, so the same shell
46
+ renders at two widths. Distinct from --kol-toc-w further down, which is
47
+ the BRAND layout's rail: same concept, two shells, two numbers. */
48
+ --kol-shell-toc-w: 16rem;
36
49
  --kol-container-max: 100%;
37
50
 
38
51
  /* Opacity tokens (--kol-fg-*) + text-role tokens (--kol-text-*) live in
@@ -44,6 +57,15 @@ body {
44
57
  Intentional: site chrome uses browser-ease for a softer feel. */
45
58
  --kol-t-btn: background 200ms ease, color 200ms ease, border-color 200ms ease;
46
59
 
60
+ /* Shell CHROME inset (2026-07-31, user ruling: "24, it's what lives in
61
+ kolkrabbi") — a separate concern from the page ladder below, and
62
+ deliberately tighter: chrome is not page content. The shell header and the
63
+ shell content frame both read this, so they cannot disagree; before it,
64
+ the header carried bare Tailwind steps and the frame carried the page ramp.
65
+ FLAT, not stepped — one value at every width, on the user's word.
66
+ Do NOT reach for this on page containers — that is --kol-pad-section-x. */
67
+ --kol-pad-chrome-x: var(--kol-spacing-6);
68
+
47
69
  /* Stepped page / section / band padding tokens.
48
70
  Used by chrome (topnav, sidenav) and landing bands. Scaled at 768 / 1024
49
71
  breakpoints so one set of rules covers mobile → desktop without clamp(). */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kolkrabbi/kol-framework",
3
- "version": "0.10.2",
3
+ "version": "0.11.1",
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",
@@ -27,7 +27,7 @@
27
27
  "app-shell"
28
28
  ],
29
29
  "dependencies": {
30
- "@kolkrabbi/kol-component": "0.15.1",
30
+ "@kolkrabbi/kol-component": "0.19.0",
31
31
  "@kolkrabbi/kol-icons": "0.8.11"
32
32
  },
33
33
  "peerDependencies": {
package/src/AppShell.jsx CHANGED
@@ -53,7 +53,7 @@ export default function AppShell({ navTree = [], getActivePage, header, footer,
53
53
  </button>
54
54
 
55
55
  <div
56
- className="kol-sidenav-backdrop fixed inset-0 z-20 bg-black/50 opacity-0 pointer-events-none transition-opacity duration-200 md:hidden"
56
+ className="kol-sidenav-backdrop fixed inset-0 z-20 kol-overlay-scrim opacity-0 pointer-events-none transition-opacity duration-200 md:hidden"
57
57
  onClick={() => setDrawerOpen(false)}
58
58
  aria-hidden="true"
59
59
  />
@@ -42,6 +42,13 @@ import ThemeToggle from './ThemeToggle.jsx'
42
42
  * @param {string} className extra classes on the outer bar
43
43
  */
44
44
 
45
+ /* ONE header-action glyph size (user 2026-08-01: "icon in navbar is small and
46
+ * wrong"). The row mixed sizes: the ThemeToggle draws its solo glyph at 24 on
47
+ * the `lg` rung while search, GitHub and the hamburger sat at 18 — four
48
+ * controls, two scales, in a row eight inches wide. Named once here so a new
49
+ * control cannot pick its own. */
50
+ export const HEADER_ICON = 24
51
+
45
52
  const iconBtnCls =
46
53
  'flex h-9 w-9 items-center justify-center rounded p-0 bg-transparent border-0 cursor-pointer transition-colors hover:bg-fg-08 hover:text-emphasis'
47
54
 
@@ -66,7 +73,11 @@ export default function ShellHeader({
66
73
  <header className={`kol-shell-header sticky top-0 z-50 shrink-0 bg-surface-primary ${className}`.trim()}>
67
74
  {/* Row 1: brand block + controls */}
68
75
  <div className="border-b border-fg-08">
69
- <div className="w-full px-4 py-4 md:px-5 lg:px-6">
76
+ {/* Chrome inset from --kol-pad-chrome-x, not Tailwind steps
77
+ * (2026-07-31): the header sat on its own improvised steps while the
78
+ * shell content frame sat on the page ramp, so the sidebar hung right
79
+ * of the wordmark above it. One token, both surfaces. */}
80
+ <div className="w-full py-4" style={{ paddingInline: 'var(--kol-pad-chrome-x)' }}>
70
81
  <div className="flex items-center justify-between">
71
82
  {/* kol-shell-header-brand reserves the nav-column width at lg+ so
72
83
  * the Row-2 tabs align to the shell grid. */}
@@ -93,7 +104,7 @@ export default function ShellHeader({
93
104
  onClick={onMenuClick}
94
105
  aria-label="Open navigation menu"
95
106
  >
96
- <Icon name="hamburger" size={18} />
107
+ <Icon name="hamburger" size={HEADER_ICON} />
97
108
  </button>
98
109
  </Tooltip>
99
110
  )}
@@ -105,7 +116,7 @@ export default function ShellHeader({
105
116
  {/* Row 2: section tabs + inline search + rail toggles */}
106
117
  {hasTabRow && (
107
118
  <div className="border-b border-fg-08">
108
- <div className="w-full px-4 md:px-5 lg:px-6">
119
+ <div className="w-full" style={{ paddingInline: 'var(--kol-pad-chrome-x)' }}>
109
120
  <div className="kol-shell-header-tabs">
110
121
  <nav className="flex flex-1 gap-6" aria-label="Sections">
111
122
  {nav.map((item) => {
@@ -43,7 +43,8 @@ import { useTheme } from './theme.js'
43
43
  * no consumer shifts a pixel; migrate at your own pace:
44
44
  * icon → button + fill none + label off
45
45
  * hop → button + fill subtle + fullWidth (old: chrome pinned md)
46
- * hop-bare → flush + fullWidth (old: 6/24 padding kept)
46
+ * hop-bare → flush + fullWidth. Horizontal pad stays 24px (sidenav gutter);
47
+ * vertical pad, type and glyph honour `size` since 2026-07-30.
47
48
  *
48
49
  * Theme state lives in useTheme (./theme.js); this component is only the
49
50
  * glyph-roll UI on top of it.
@@ -145,13 +146,24 @@ export default function ThemeToggle({
145
146
  }
146
147
  if (variant === 'hop' || variant === 'hop-bare') {
147
148
  const bare = variant === 'hop-bare'
149
+ /* hop-bare HONOURS `size` (user ruling 2026-07-30). It used to hardcode
150
+ * kol-mono-14 while its glyph still tracked `size`, so size="lg" produced a
151
+ * 24px glyph beside 14px text — and it took the SOLO glyph ladder despite
152
+ * carrying a label, against the glyph law in this docstring.
153
+ *
154
+ * One container across all three rungs: same bare full-width row, only the
155
+ * vertical pad, the type and the glyph move (4/6/8 · 12/14/16 · 14/16/18).
156
+ * The 24px horizontal gutter is FIXED at every size — it aligns the row with
157
+ * the sidenav's own pl-6, which is the whole reason this alias exists.
158
+ * `hop` stays pinned to md: its docstring promises old chrome verbatim. */
159
+ const barePadY = size === 'sm' ? 'py-1' : size === 'lg' ? 'py-2' : 'py-1.5'
148
160
  const chromeCls = bare
149
- ? 'w-full inline-flex items-center justify-start gap-2 py-1.5 px-6 kol-mono-14 bg-transparent text-emphasis'
161
+ ? `w-full inline-flex items-center justify-start gap-2 ${barePadY} px-6 ${mono} bg-transparent text-emphasis`
150
162
  : 'kol-theme-toggle kol-theme-toggle-subtle kol-btn-md kol-mono-14 w-full justify-start gap-2'
151
163
  return (
152
164
  <button {...shared} className={`${chromeCls} ${className}`.trim()}>
153
165
  <span className="inline-flex items-center justify-center shrink-0" aria-hidden="true">
154
- {iconSwap(glyphSolo)}
166
+ {iconSwap(bare ? glyphWithText : glyphSolo)}
155
167
  </span>
156
168
  <span className="kol-sidenav-hop-label flex-1 min-w-0 text-left">
157
169
  {MODE_LABEL[shown]}
package/src/index.js CHANGED
@@ -10,7 +10,7 @@
10
10
  export { default as AppShell } from './AppShell.jsx'
11
11
  export { ShellTocContext, ShellTocCollapsedContext } from './AppShell.jsx'
12
12
  export { default as SideNav } from './SideNav.jsx'
13
- export { default as ShellHeader } from './ShellHeader.jsx'
13
+ export { default as ShellHeader, HEADER_ICON } from './ShellHeader.jsx'
14
14
  export { default as ThemeToggle } from './ThemeToggle.jsx'
15
15
  export { useTheme, applyTheme, getInitialTheme, THEME_STORAGE_KEY } from './theme.js'
16
16
  export { default as Layout } from './Layout.jsx'