@kolkrabbi/kol-shell 0.59.1 → 0.61.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,8 +1,8 @@
1
1
  {
2
2
  "name": "@kolkrabbi/kol-shell",
3
- "version": "0.59.1",
3
+ "version": "0.61.0",
4
4
  "private": false,
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}.",
5
+ "description": "The application shell",
6
6
  "license": "MIT",
7
7
  "type": "module",
8
8
  "main": "./src/index.js",
@@ -14,16 +14,16 @@
14
14
  "peerDependencies": {
15
15
  "@kolkrabbi/kol-component": ">=0.229.0",
16
16
  "@kolkrabbi/kol-icons": ">=0.16.0",
17
- "@kolkrabbi/kol-theme": ">=0.156.0",
17
+ "@kolkrabbi/kol-theme": ">=0.165.0",
18
18
  "gsap": "^3.13.0",
19
19
  "react": "^18.3.0 || ^19.0.0",
20
20
  "react-dom": "^18.3.0 || ^19.0.0"
21
21
  },
22
22
  "devDependencies": {
23
- "@kolkrabbi/kol-framework": "^0.46.0",
24
- "@kolkrabbi/kol-component": "^0.230.0",
25
- "@kolkrabbi/kol-icons": "^0.29.1",
26
- "@kolkrabbi/kol-theme": "^0.157.0"
23
+ "@kolkrabbi/kol-component": "^0.239.0",
24
+ "@kolkrabbi/kol-framework": "^0.49.0",
25
+ "@kolkrabbi/kol-icons": "^0.33.0",
26
+ "@kolkrabbi/kol-theme": "^0.165.0"
27
27
  },
28
28
  "files": [
29
29
  "src",
package/src/AppHub.jsx CHANGED
@@ -7,7 +7,7 @@ import { ShortcutsOverlay } from '@kolkrabbi/kol-component'
7
7
  /* taxonomy-ok: organism — nests AppShell / HubHome / HubSettings / ShortcutsOverlay (relative) */
8
8
 
9
9
  /**
10
- * AppHub — Shell + Hub in one call; the app passes its Tool as children (the app anatomy,
10
+ * AppHub — An app's shell and hub in one. Shell + Hub in one call; the app passes its Tool as children (the app anatomy,
11
11
  * `docs/documentation/04-compositions/16-app-anatomy.md`, 2026-09-26).
12
12
  *
13
13
  * monitor, mirror and fxr each assembled this by hand: the same AppShell props, the same
package/src/AppShell.jsx CHANGED
@@ -42,6 +42,7 @@ import { TABBAR_H, MastheadContext } from '@kolkrabbi/kol-component'
42
42
  * open/close is the consumer's `onNavigate` (kol-mirror's model: navigating to
43
43
  * `/settings` while already there returns to the last page), and the theme
44
44
  * toggle lives on the settings page, not in the rail (user, 2026-08-28).
45
+ * @param {boolean} [props.railFade=true] the rail's list fades out at its foot (`NavRail fade`); `false` opts out
45
46
  * @param {string} props.railToggleKey a key that toggles the rail (e.g. '\\') — ignored while typing in a field;
46
47
  * the rail comes back on every `currentPath` change (ShellHomeSystem, 2026-08-27)
47
48
  * @param {'shell'|'bare'|'overlay'|'drawer'|'bar'} props.touch the touch-primary policy (default 'shell' = the rail regardless):
@@ -130,6 +131,7 @@ export default function AppShell({
130
131
  onNavigate,
131
132
  iconComponent,
132
133
  railComponent: Rail = NavRail,
134
+ railFade = true,
133
135
  railToggleKey,
134
136
  touch = 'shell',
135
137
  appName,
@@ -370,6 +372,7 @@ export default function AppShell({
370
372
  onNavigate={navigate}
371
373
  iconComponent={iconComponent}
372
374
  drawer={drawer}
375
+ fade={railFade}
373
376
  />
374
377
  )}
375
378
  {/* THE BACK OF THE BACK — surface-primary, always, in every app; the
package/src/AppStudio.jsx CHANGED
@@ -6,7 +6,7 @@ import PageShell from './PageShell.jsx'
6
6
  /* taxonomy-ok: organism — nests AppHub / CatalogPage / PageShell (relative) + kol-component's PageHeader */
7
7
 
8
8
  /**
9
- * AppStudio — the WORKSTATION: the Hub plus a fixed page set (apps review §6c-4, 2026-09-29).
9
+ * AppStudio — The studio workstation. the WORKSTATION: the Hub plus a fixed page set (apps review §6c-4, 2026-09-29).
10
10
  *
11
11
  * fxr, mirror and monitor each hand-build the same shape — a landing Catalog, a Library of what the
12
12
  * tool makes, a page that composes a new one, the tool itself full-bleed, a page or two of their own,
@@ -7,7 +7,7 @@ import WalkthroughPanel from './WalkthroughPanel.jsx'
7
7
  /* taxonomy-ok: organism — nests PageShell / PageHeader / WalkthroughPanel (relative) + kol-component's ContentFilters + ContentCard / ContentRow */
8
8
 
9
9
  /**
10
- * CatalogPage — the app tier's Home / Library page, shipped once (ShellHomeSystem,
10
+ * CatalogPage — An app's home or library page. the app tier's Home / Library page, shipped once (ShellHomeSystem,
11
11
  * kol-fxr 2026-08-27 — fxr's HomePage / LibraryPage and monitor's HomePage were
12
12
  * the same page written three times): `PageHeader` → `ContentFilters` (title ·
13
13
  * filter · search, the view strip in the header, LIST / GRID below the divider)
package/src/HubHome.jsx CHANGED
@@ -5,7 +5,7 @@ import CatalogPage from './CatalogPage.jsx'
5
5
  /* taxonomy-ok: organism — nests CatalogPage (relative) + kol-component's Button */
6
6
 
7
7
  /**
8
- * HubHome — the Hub's Home: a Catalog under the app's masthead (the Hub, 2026-09-26).
8
+ * HubHome — A hub's home page. the Hub's Home: a Catalog under the app's masthead (the Hub, 2026-09-26).
9
9
  * monitor, mirror and fxr each wrote this page on `CatalogPage` with the same five
10
10
  * decisions — the mono masthead, RECENT · SAVED, a walkthrough opened by a button,
11
11
  * that button's Close label, a "Get started" last step — and the case of the view
@@ -71,7 +71,7 @@ export default function HubHome({
71
71
  <>
72
72
  {actions}
73
73
  {steps.length > 0 && (
74
- <Button variant="grey" size="md" onClick={() => setTouring((t) => !t)}>
74
+ <Button tone="grey" size="md" onClick={() => setTouring((t) => !t)}>
75
75
  {touring ? 'Close' : 'Walkthrough'}
76
76
  </Button>
77
77
  )}
@@ -7,7 +7,7 @@ import SettingsLinks, { SettingsColophon } from './SettingsLinks.jsx'
7
7
  /* taxonomy-ok: organism — nests SettingsScaffold / SettingsShortcuts / SettingsLinks (relative) + kol-component's SettingsPanel / SettingsSections */
8
8
 
9
9
  /**
10
- * HubSettings — the Hub's Settings page (the Hub, 2026-09-26). monitor, mirror and fxr
10
+ * HubSettings — A hub's settings page. the Hub's Settings page (the Hub, 2026-09-26). monitor, mirror and fxr
11
11
  * each put the same page on `SettingsScaffold`: SETTINGS · ABOUT · REPO with the same
12
12
  * three subtitles, the same theme toggle in the masthead, About as the app's prose over
13
13
  * the colophon, Repo as a link list, and the keyboard shortcuts from the one array the
package/src/Logomark.jsx CHANGED
@@ -1,7 +1,7 @@
1
1
  import { useState, useEffect } from 'react'
2
2
 
3
3
  /**
4
- * Logomark — fetches and INLINES an SVG so currentColor theming works: an
4
+ * Logomark — An inlined SVG mark. fetches and INLINES an SVG so currentColor theming works: an
5
5
  * <img> renders a currentColor mark black in dark mode (invisible). Ported
6
6
  * verbatim from the kol-mirror cut (module-level cache; async resolve even on
7
7
  * cache hit — sync setState in an effect cascades renders).
package/src/NavRail.jsx CHANGED
@@ -70,6 +70,10 @@ import Logomark from './Logomark.jsx'
70
70
  * @param {boolean} drawer off-canvas mode: no grab, no drag, no token writes, rows always
71
71
  * labelled, and the rail sizes itself from `--kol-shell-drawer-width` (default 240px).
72
72
  * AppShell sets this from `touch="drawer"` — see ShellRailNoDrawerOnMobile, 2026-08-31.
73
+ * @param {boolean} [fade=true] the list fades out at its foot — the workshop rail's fade
74
+ * (2026-10-01), here too on the user's word (2026-10-02). The rows sit in their own scroll
75
+ * region between the mark and the pinned bottom rows, so a list longer than the window scrolls
76
+ * and runs out under the fade instead of being cut by the edge. `false` draws the list plain.
73
77
  */
74
78
  const RAIL_W = '--kol-shell-rail-width'
75
79
  const CLOSED = 48
@@ -277,6 +281,7 @@ export default function NavRail({
277
281
  iconComponent,
278
282
  hidden = false,
279
283
  drawer = false,
284
+ fade = true,
280
285
  }) {
281
286
  const railRef = useRef(null)
282
287
  const grabRef = useRef(null)
@@ -340,9 +345,12 @@ export default function NavRail({
340
345
  </div>
341
346
  </Tooltip>
342
347
  )}
343
- {items.map(row)}
344
- {/* the spacer IS the layout */}
345
- <div className="flex-1" />
348
+ {/* THE LIST IS ITS OWN REGION (2026-10-02): it takes the room between the mark and the pinned
349
+ * bottom rows — what the bare spacer used to hold — scrolls when the rows outrun the window,
350
+ * and fades at its foot unless `fade={false}`. Same column, same gap, as the rail's own. */}
351
+ <div className={`kol-shell-rail-list flex min-h-0 w-full flex-1 flex-col items-start gap-2 overflow-y-auto overflow-x-hidden ${fade ? 'kol-shell-rail-list--fade' : ''}`.trim()}>
352
+ {items.map(row)}
353
+ </div>
346
354
  {/* the rule runs the full rail width, out past the px-2 */}
347
355
  {bottomItems.length > 0 && <div className="self-stretch -mx-2 border-t border-fg-08" />}
348
356
  {bottomItems.map(row)}
package/src/PageShell.jsx CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * PageShell — the page scaffold every shell page re-declared by hand (6 pages
2
+ * PageShell — The page scaffold of an app. the page scaffold every shell page re-declared by hand (6 pages
3
3
  * in monitor, 4 in mirror — the most-duplicated block in both repos).
4
4
  *
5
5
  * `mode="scroll"` (default): min-height 100vh, natural page scroll.
package/src/PhoneNav.jsx CHANGED
@@ -4,7 +4,7 @@ import { Button, MobileTabBar } from '@kolkrabbi/kol-component'
4
4
  /* taxonomy-ok: molecule — MobileTabBar + a More sheet of Buttons */
5
5
 
6
6
  /**
7
- * PhoneNav — the rail, on a phone, as a bottom bar (AppShell `touch="bar"`, apps review
7
+ * PhoneNav — The rail as a phone tab bar. the rail, on a phone, as a bottom bar (AppShell `touch="bar"`, apps review
8
8
  * 2026-09-29). The user: *"what about when there are like 10 pages? … this seems like something
9
9
  * shell or hub should account for and ship, but not have per app fixes."*
10
10
  *
@@ -1,5 +1,5 @@
1
1
  /**
2
- * SettingsLinks — the About / Repo link list every app hand-wrote (ShellHomeSystem,
2
+ * SettingsLinks — The links block of a settings page. the About / Repo link list every app hand-wrote (ShellHomeSystem,
3
3
  * kol-fxr 2026-08-27): label `kol-helper-12 text-fg-32` at 72px, the URL as an
4
4
  * external link `text-fg-64 hover:text-fg-96 hover:underline`.
5
5
  *
@@ -18,7 +18,7 @@ export default function SettingsLinks({ links = [], className = '' }) {
18
18
  )
19
19
  }
20
20
 
21
- /** SettingsColophon — the "Kolkrabbi Vinnustofa / 2026" foot under a settings scaffold. */
21
+ /** SettingsColophon — The foot of a settings page. the "Kolkrabbi Vinnustofa / 2026" foot under a settings scaffold. */
22
22
  export function SettingsColophon({ name = 'Kolkrabbi Vinnustofa', year = new Date().getFullYear(), className = '' }) {
23
23
  return (
24
24
  <div className={className} style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
@@ -4,7 +4,7 @@ import PageShell from './PageShell.jsx'
4
4
  import { PageHeader } from '@kolkrabbi/kol-component'
5
5
 
6
6
  /**
7
- * SettingsScaffold — the settings-page idiom both shells re-implemented inline:
7
+ * SettingsScaffold — The settings page scaffold. the settings-page idiom both shells re-implemented inline:
8
8
  * fixed PageShell, a PageHeader masthead, one header row, then a scrolling body.
9
9
  * Content is consumer-authored via `renderContent` — sections/rows are content,
10
10
  * not markup.
@@ -7,7 +7,7 @@ import { SettingsRow } from '@kolkrabbi/kol-component'
7
7
  * baseline row did. */
8
8
 
9
9
  /**
10
- * SettingsShortcuts — the keyboard-shortcuts block of a settings page
10
+ * SettingsShortcuts — The shortcuts block of a settings page. the keyboard-shortcuts block of a settings page
11
11
  * (ShellHomeSystem, kol-fxr 2026-08-27): the same `[{ section, items: [{ id,
12
12
  * label, combo }] }]` array `ShortcutsOverlay` takes, laid out UP TO six columns ×
13
13
  * two sections per column, filled column-first (user, 2026-08-27) — each
package/src/TabStrip.jsx CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * TabStrip — the flat text-tab idiom both shells use twice (ContentFilters
2
+ * TabStrip — A row of text tabs. the flat text-tab idiom both shells use twice (ContentFilters
3
3
  * view-mode/layout spans, Settings tabs): `kol-helper-14`, active
4
4
  * `text-fg-96`, rest `text-fg-32 hover:text-fg-48`.
5
5
  *
@@ -17,20 +17,24 @@ export function useTouchPrimary() {
17
17
  }
18
18
 
19
19
  /**
20
- * TouchDeviceOverlay — "Desktop recommended", once, on a touch-primary device
20
+ * TouchDeviceOverlay — A desktop-recommended note on touch devices. "Desktop recommended", once, on a touch-primary device
21
21
  * (kol-monitor's overlay, promoted 2026-08-27 — ShellHomeSystem; `AppShell
22
22
  * touch="overlay"` mounts it). Dismissal is remembered in localStorage.
23
23
  *
24
24
  * @param {string} appName the sentence's subject ("Monitor is built for mouse and keyboard…")
25
25
  * @param {string} message override the sentence whole
26
+ * @param {boolean} force show it whatever the pointer and whatever was dismissed — for a preview
27
+ * or a settings "show it again"; dismissing a forced note stores nothing
26
28
  */
27
- export default function TouchDeviceOverlay({ appName = 'This app', message }) {
29
+ export default function TouchDeviceOverlay({ appName = 'This app', message, force = false }) {
28
30
  const coarse = useTouchPrimary()
29
31
  const [dismissed, setDismissed] = useState(() => {
30
32
  try { return localStorage.getItem(STORAGE_KEY) === '1' } catch { return false }
31
33
  })
32
- if (!coarse || dismissed) return null
34
+ const [closed, setClosed] = useState(false)
35
+ if (force ? closed : !coarse || dismissed) return null
33
36
  const dismiss = () => {
37
+ if (force) { setClosed(true); return }
34
38
  try { localStorage.setItem(STORAGE_KEY, '1') } catch { /* storage blocked */ }
35
39
  setDismissed(true)
36
40
  }
@@ -2,7 +2,7 @@ import { useState } from 'react'
2
2
  import { Button } from '@kolkrabbi/kol-component'
3
3
 
4
4
  /**
5
- * WalkthroughPanel — the absolutely-centred stepped intro card (both repos'
5
+ * WalkthroughPanel — A stepped intro card. the absolutely-centred stepped intro card (both repos'
6
6
  * HomePage): chevron Buttons either side, text column + illustration pane.
7
7
  *
8
8
  * Steps are content: `[{ title, text: [..], illustration?, actions? }]` —
@@ -27,7 +27,7 @@ export default function WalkthroughPanel({ steps = [], iconComponent, onClose })
27
27
  maxWidth: 960, width: '100%', zIndex: 10,
28
28
  }}>
29
29
  <Button
30
- variant="grey"
30
+ tone="grey"
31
31
  size="md"
32
32
  iconOnly="chevron-left"
33
33
  iconComponent={iconComponent}
@@ -76,7 +76,7 @@ export default function WalkthroughPanel({ steps = [], iconComponent, onClose })
76
76
  </div>
77
77
 
78
78
  <Button
79
- variant="grey"
79
+ tone="grey"
80
80
  size="md"
81
81
  iconOnly="chevron-right"
82
82
  iconComponent={iconComponent}