@kolkrabbi/kol-shell 0.38.0 → 0.40.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kolkrabbi/kol-shell",
3
- "version": "0.38.0",
3
+ "version": "0.40.0",
4
4
  "private": false,
5
5
  "description": "KOL application shell — fixed 48px NavRail + AppShell layout root, PageShell/PageHeader scaffolds, ContentFilters catalog organism, GridCard, SettingsScaffold, WalkthroughPanel, ShortcutsOverlay. App chrome (kol-framework owns site chrome). Nav items, content, shortcuts and settings are consumer-injected. Sits above @kolkrabbi/kol-{theme,component,framework}.",
6
6
  "license": "MIT",
@@ -20,10 +20,10 @@
20
20
  "react-dom": "^18.3.0 || ^19.0.0"
21
21
  },
22
22
  "devDependencies": {
23
- "@kolkrabbi/kol-theme": "^0.123.0",
23
+ "@kolkrabbi/kol-component": "^0.162.0",
24
24
  "@kolkrabbi/kol-icons": "^0.25.0",
25
- "@kolkrabbi/kol-component": "^0.156.0",
26
- "@kolkrabbi/kol-framework": "^0.36.0"
25
+ "@kolkrabbi/kol-framework": "^0.36.0",
26
+ "@kolkrabbi/kol-theme": "^0.128.0"
27
27
  },
28
28
  "files": [
29
29
  "src",
package/src/AppShell.jsx CHANGED
@@ -194,13 +194,23 @@ export default function AppShell({
194
194
  return () => window.removeEventListener('keydown', onKey)
195
195
  }, [settingsKey, settingsPath, toggleSettings])
196
196
 
197
- /* the rail row for that path toggles too one gesture, two ways to reach it */
197
+ /* the drawer's rule for a path — matched like the rail's active row */
198
+ const opensOn = (p) => drawerOpenOn.some((x) => (x === '/' ? p === '/' : p.startsWith(x)))
199
+
200
+ /* the rail row for that path toggles too — one gesture, two ways to reach it.
201
+ * THE TAP DECIDES THE DRAWER, not only the route change
202
+ * (ShellDrawerCloseOnSamePath, kol-monitor 2026-09-02): a rung whose path is
203
+ * the one already shown — Create tapped on /create, "new case" — changes no
204
+ * pathname, so the route effect below never fires and the drawer stayed open
205
+ * over the page. The tap itself now sets the drawer to that path's rule;
206
+ * `drawerOpenOn` rungs stay open, every other rung closes it, same path or not. */
198
207
  const navigate = useCallback(
199
208
  (path, ...rest) => {
209
+ if (drawer) setDrawerOpen(opensOn(path))
200
210
  if (settingsPath && path === settingsPath) return toggleSettings()
201
211
  return onNavigate?.(path, ...rest)
202
212
  },
203
- [settingsPath, toggleSettings, onNavigate],
213
+ [settingsPath, toggleSettings, onNavigate, drawer, drawerOpenOn], // eslint-disable-line react-hooks/exhaustive-deps
204
214
  )
205
215
 
206
216
  /* THE ROUTE CHANGE MEANS THE OPPOSITE IN EACH MODE. For `railToggleKey` the
@@ -215,7 +225,7 @@ export default function AppShell({
215
225
  /* Keyed on the BOOLEAN, not the array: a consumer's inline `['/']` is a new
216
226
  * identity every render too (the showcase set passes one), and the effect
217
227
  * must fire on route entry only — never on a re-render, or it undoes the tap. */
218
- const opensHere = drawerOpenOn.some((p) => (p === '/' ? currentPath === '/' : currentPath.startsWith(p)))
228
+ const opensHere = opensOn(currentPath)
219
229
  useEffect(() => {
220
230
  if (drawer) setDrawerOpen(opensHere)
221
231
  else setNavHidden(false)
package/src/NavRail.jsx CHANGED
@@ -298,18 +298,19 @@ export default function NavRail({
298
298
  style={{ width: drawer ? 'var(--kol-shell-drawer-width, 240px)' : `var(${RAIL_W})` }}
299
299
  >
300
300
  {!drawer && (
301
- /* A BUTTON, with a glyph a thumb can find (ShellRailCollapsedWithTapOpen,
302
- * kol-mirror 2026-09-01 user: "i means collapsed variant not
303
- * expanded"): `touch="shell"` is the only mode that keeps the 48px rail
304
- * visible, and its only opener was this 8px strip, invisible until a
305
- * pointer HOVERED near it a thumb never does, so on a phone the rail
306
- * could not be opened at all. The strip already toggled on a click (a
307
- * press with no travel); it just had no affordance and no hit area on
308
- * touch. Under `(pointer: coarse)` the theme shows `.kol-rail-grab-tap`
309
- * a 24px disc on the line — and widens the strip to it; on a fine
310
- * pointer nothing changes, the ruled grab stays. The drag hook binds
311
- * pointer events, so a button works exactly as the div did, and it now
312
- * says what it is. Enter/Space toggle for the keyboard. */
301
+ /* A BUTTON, and on touch A THICKER LINE (ShellRailCollapsedWithTapOpen,
302
+ * kol-mirror 2026-09-01; corrected by RailGrabTapIsALine, kol-monitor
303
+ * 2026-09-02 — user: "it was a thicker line" · "who decided it should be
304
+ * a chevron?"): `touch="shell"` keeps the 48px rail visible and its
305
+ * only opener was this 8px strip, whose pill wakes on pointer
306
+ * PROXIMITY a thumb never hovers. The 0.38.0 answer was a disc with a
307
+ * chevron; that was the DS agent's shape, not the user's ruling. The
308
+ * opener is the strip ITSELF: under `(pointer: coarse)` the theme
309
+ * widens it to a thumb-sized hit and shows the pill thick at rest the
310
+ * same affordance a fine pointer drags, no glyph. A press with no travel
311
+ * already toggled; it just had no hit area on touch. The drag hook binds
312
+ * pointer events, so a button works exactly as the div did, and it says
313
+ * what it is. Enter/Space toggle for the keyboard. */
313
314
  <button
314
315
  type="button"
315
316
  ref={grabRef}
@@ -317,11 +318,7 @@ export default function NavRail({
317
318
  aria-label={railOpen ? 'Collapse navigation' : 'Expand navigation'}
318
319
  aria-expanded={railOpen}
319
320
  onKeyDown={(e) => { if (e.key === 'Enter' || e.key === ' ') { e.preventDefault(); snapOpenRef.current?.(!railOpen) } }}
320
- >
321
- <span className="kol-rail-grab-tap" aria-hidden="true">
322
- <IconAt name={railOpen ? 'chevron-left' : 'chevron-right'} size={12} component={iconComponent} />
323
- </span>
324
- </button>
321
+ />
325
322
  )}
326
323
  {logomark && (
327
324
  /* the mark, and the app name beside it when open — uppercase like the