@kolkrabbi/kol-framework 0.11.1 → 0.13.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.
Files changed (2) hide show
  1. package/package.json +3 -3
  2. package/src/ShellHeader.jsx +59 -25
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kolkrabbi/kol-framework",
3
- "version": "0.11.1",
3
+ "version": "0.13.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",
@@ -27,8 +27,8 @@
27
27
  "app-shell"
28
28
  ],
29
29
  "dependencies": {
30
- "@kolkrabbi/kol-component": "0.19.0",
31
- "@kolkrabbi/kol-icons": "0.8.11"
30
+ "@kolkrabbi/kol-component": "0.24.0",
31
+ "@kolkrabbi/kol-icons": "0.10.0"
32
32
  },
33
33
  "peerDependencies": {
34
34
  "react": "^18.3.0 || ^19.0.0",
@@ -1,5 +1,5 @@
1
1
  import { Icon } from '@kolkrabbi/kol-icons'
2
- import { SearchInput, Tooltip } from '@kolkrabbi/kol-component'
2
+ import { IconFrame, SearchInput, Tooltip, glyphSize } from '@kolkrabbi/kol-component'
3
3
  import ThemeToggle from './ThemeToggle.jsx'
4
4
 
5
5
  /**
@@ -45,12 +45,32 @@ import ThemeToggle from './ThemeToggle.jsx'
45
45
  /* ONE header-action glyph size (user 2026-08-01: "icon in navbar is small and
46
46
  * wrong"). The row mixed sizes: the ThemeToggle draws its solo glyph at 24 on
47
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. */
48
+ * controls, two scales, in a row eight inches wide.
49
+ *
50
+ * It is NOT an independent number. Every header control is a `lg` rung, and
51
+ * `SOLO.lg` (hooks/glyphLadders.js) is 24 — this constant is that ladder rung
52
+ * under a name the chrome can import. Naming it once was not enough on its own:
53
+ * it shipped exported and the two rail toggles still hardcoded 18 three rows
54
+ * below it, which is the whole reason the row looked wrong after the fix. The
55
+ * durable answer is that no header control writes a glyph size at all — it
56
+ * writes `size="lg"` and the ladder resolves it.
57
+ *
58
+ * @deprecated 2026-08-01 — **zero consumers as of this change.** Every header
59
+ * control now names its rung and takes the glyph from `SOLO`. Kept exported
60
+ * because it is public API of a published package (breaking an export needs a
61
+ * changeset + major bump); a consumer still importing it gets the right number,
62
+ * it is just no longer how the chrome decides. Passing it as `iconSize` is the
63
+ * anti-pattern this whole change removes: it pins the glyph while leaving the
64
+ * SQUARE on whatever rung the call site forgot to set, which is precisely how
65
+ * the search trigger ended up drawing an lg glyph in an md box. */
50
66
  export const HEADER_ICON = 24
51
67
 
52
- const iconBtnCls =
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'
68
+ /* `iconBtnCls` lived here — a private class string re-implementing the icon
69
+ * button box (h-9 w-9, rounded, transparent, hover wash) on three call sites,
70
+ * with a near-duplicate of it hand-written in the showcase's GitHub link. Four
71
+ * containers, one job. Deleted 2026-08-01: the box has an owner, and it is
72
+ * `Button variant="ghost" quiet iconOnly` — the shape the search trigger in
73
+ * ShellLayout had been calling correctly the entire time. */
54
74
 
55
75
  export default function ShellHeader({
56
76
  brand,
@@ -93,19 +113,24 @@ export default function ShellHeader({
93
113
  * quiet square = button geometry + fill none + no label
94
114
  * (was the old `icon` variant default). */}
95
115
  <span className="hidden lg:inline-flex"><ThemeToggle fill="none" label={false} size="lg" /></span>
96
- <span className="lg:hidden"><ThemeToggle fill="none" label={false} /></span>
116
+ <span className="lg:hidden"><ThemeToggle fill="none" label={false} size="lg" /></span>
97
117
  </Tooltip>
98
118
  )}
99
119
  {onMenuClick && (
100
120
  <Tooltip label="Open navigation menu">
101
- <button
102
- type="button"
103
- className={`${iconBtnCls} text-fg-64`}
121
+ {/* IconFrame, not Button (user ruling 2026-08-01). Header
122
+ * chrome takes a click but must not light up; the frame has
123
+ * no state rules at all, which is the property Button can
124
+ * only approximate by dropping its own. `nav` rests at
125
+ * oq-64 — the `text-fg-64` this control hand-wrote for
126
+ * months. */}
127
+ <IconFrame
128
+ name="hamburger"
129
+ variant="nav"
130
+ size="lg"
104
131
  onClick={onMenuClick}
105
132
  aria-label="Open navigation menu"
106
- >
107
- <Icon name="hamburger" size={HEADER_ICON} />
108
- </button>
133
+ />
109
134
  </Tooltip>
110
135
  )}
111
136
  </div>
@@ -129,7 +154,12 @@ export default function ShellHeader({
129
154
  aria-current={active ? 'page' : undefined}
130
155
  onClick={onNavigate ? (event) => onNavigate(event, item) : undefined}
131
156
  >
132
- {item.icon && <Icon name={item.icon} size={14} />}
157
+ {/* The ladder, not a literal (2026-08-01). This hardcoded
158
+ * 14 — the same value ADJACENT.sm carries, but written
159
+ * out, so the tab could not follow the rule it was
160
+ * meant to. The tab's own type is 14/18, which is that
161
+ * rung. */}
162
+ {item.icon && <Icon name={item.icon} size={glyphSize('sm')} />}
133
163
  {item.label}
134
164
  </a>
135
165
  )
@@ -146,28 +176,32 @@ export default function ShellHeader({
146
176
  <div className="hidden lg:flex items-center gap-1 pb-2">
147
177
  {onNavToggle && (
148
178
  <Tooltip label="Toggle navigation sidebar">
149
- <button
150
- type="button"
151
- className={`${iconBtnCls} ${navCollapsed ? 'text-fg-32' : 'text-fg-64'}`}
179
+ {/* The collapsed tint is a VARIANT SWAP, not a state:
180
+ * `ghost` rests at oq-48, `nav` at oq-64, and both are
181
+ * static classes with no rules to fire. That is the only
182
+ * honest way to express it on a frame — Button's `quiet`
183
+ * is an opacity transition, i.e. exactly the kind of
184
+ * behaviour this control was ruled out of. */}
185
+ <IconFrame
186
+ name="panel-left"
187
+ variant={navCollapsed ? 'ghost' : 'nav'}
188
+ size="sm"
152
189
  onClick={onNavToggle}
153
190
  aria-label="Toggle navigation sidebar"
154
191
  aria-pressed={!navCollapsed}
155
- >
156
- <Icon name="panel-left" size={18} />
157
- </button>
192
+ />
158
193
  </Tooltip>
159
194
  )}
160
195
  {onTocToggle && (
161
196
  <Tooltip label="Toggle table of contents sidebar">
162
- <button
163
- type="button"
164
- className={`${iconBtnCls} ${tocCollapsed ? 'text-fg-32' : 'text-fg-64'}`}
197
+ <IconFrame
198
+ name="panel-right"
199
+ variant={tocCollapsed ? 'ghost' : 'nav'}
200
+ size="sm"
165
201
  onClick={onTocToggle}
166
202
  aria-label="Toggle table of contents sidebar"
167
203
  aria-pressed={!tocCollapsed}
168
- >
169
- <Icon name="panel-right" size={18} />
170
- </button>
204
+ />
171
205
  </Tooltip>
172
206
  )}
173
207
  </div>