@kolkrabbi/kol-component 0.327.0 → 0.328.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 +1 -1
- package/src/organisms/NavRail.jsx +35 -2
package/package.json
CHANGED
|
@@ -82,6 +82,7 @@ import NavRailSite from './NavRailSite.jsx'
|
|
|
82
82
|
* EXPANDS (its rows open under it in place) and COLLAPSES. No other words, in code or docs.
|
|
83
83
|
*
|
|
84
84
|
* @param {'app'|'site'|'workshop'} preset which rail (default `app`); `variant="site"` is the old spelling of `preset="site"`
|
|
85
|
+
* @param {'top'} variant `top` — the horizontal top rail (TopRail): logomark · items · `actions` (the right slot)
|
|
85
86
|
* @param {Array} items `{ icon, path, label, sub?: [{ icon?, path, label }] }`
|
|
86
87
|
* a section (`sub`) with `to` is a FOLDER NOTE: its icon and label open `to`, its chevron expands or enters
|
|
87
88
|
* @param {Array} bottomItems pinned below the rule (Settings)
|
|
@@ -133,8 +134,8 @@ const openWidth = () => {
|
|
|
133
134
|
* a snap reports its target once at the start of the tween (as before) — the sub rows render only while it is true,
|
|
134
135
|
* because closed they would still take their height and push the rungs below them.
|
|
135
136
|
*
|
|
136
|
-
* ONE AXIS: the gesture reads `pos` and `size` only. A side rail reads x and width; a top rail (variant="top"
|
|
137
|
-
*
|
|
137
|
+
* ONE AXIS: the gesture reads `pos` and `size` only. A side rail reads x and width; a top rail (variant="top" — built
|
|
138
|
+
* 2026-10-31 as `TopRail`, without a drag) would swap them for y and height — nothing else in here assumes a side. */
|
|
138
139
|
const RAIL_MAX = 560
|
|
139
140
|
const RAIL_LABELS = 160
|
|
140
141
|
function useRailDrag(railRef, grabRef, onSnap, snapRef, enabled = true) {
|
|
@@ -321,6 +322,7 @@ export const RAIL_PRESETS = {
|
|
|
321
322
|
export function registerRailPreset(name, Component) { RAIL_PRESETS[name] = { ...(RAIL_PRESETS[name] ?? {}), component: Component } }
|
|
322
323
|
|
|
323
324
|
export default function NavRail({ variant, preset, ...props }) {
|
|
325
|
+
if (variant === 'top') return <TopRail {...props} />
|
|
324
326
|
const name = preset ?? (variant === 'site' ? 'site' : 'app')
|
|
325
327
|
if (name === 'app') return <AppRail {...props} sections={props.sections ?? RAIL_PRESETS.app.sections} />
|
|
326
328
|
const Named = RAIL_PRESETS[name]?.component
|
|
@@ -328,6 +330,37 @@ export default function NavRail({ variant, preset, ...props }) {
|
|
|
328
330
|
return <Named {...props} />
|
|
329
331
|
}
|
|
330
332
|
|
|
333
|
+
/* THE TOP RAIL (`variant="top"`, 2026-10-31 — user: *"it would have to be a TopNavRail? and completely rebuilt with Rail
|
|
334
|
+
* Component? so we wouldnt ever import this, but make something in its stead"*). Replaces Atlas's /lab header ("Lab bar"
|
|
335
|
+
* in Figma): the rail's own parts laid out on a row, 48 tall — the mark and the app name (the side rail's logomark row),
|
|
336
|
+
* the items as rail rows (a nav Button rung + the rail label), then `actions` on the right (views / menus — a `Menu` with
|
|
337
|
+
* a `MenuTrigger`). Same type and inks as the side rail; no grab, no drag. A row's `sub` is not drawn here. */
|
|
338
|
+
function TopRail({ items = [], logomark, currentPath = '', onNavigate, iconComponent, actions, hidden = false, className = '' }) {
|
|
339
|
+
if (hidden) return null
|
|
340
|
+
return (
|
|
341
|
+
<header className={`kol-shell-rail kol-shell-rail--top bg-surface-primary sticky top-0 flex h-12 w-full items-center gap-6 px-4 border-b border-fg-08 ${className}`.trim()}>
|
|
342
|
+
{logomark && (
|
|
343
|
+
<div onClick={() => onNavigate?.('/')} className="text-oq-96 cursor-pointer flex items-center gap-3 shrink-0">
|
|
344
|
+
{logomark.svgUrl && <VectorLoader src={logomark.svgUrl} size={20} />}
|
|
345
|
+
<span className="kol-helper-12 uppercase">{logomark.title}</span>
|
|
346
|
+
</div>
|
|
347
|
+
)}
|
|
348
|
+
<nav className="flex min-w-0 flex-1 items-center gap-2 overflow-x-auto">
|
|
349
|
+
{items.map(({ icon, path, label }) => {
|
|
350
|
+
const active = path === '/' ? currentPath === '/' : currentPath.startsWith(path)
|
|
351
|
+
return (
|
|
352
|
+
<div key={path} className="flex items-center gap-2 shrink-0 cursor-pointer" onClick={() => onNavigate?.(path)}>
|
|
353
|
+
{icon && <Button iconOnly={icon} iconSize={RAIL_ROW.glyph} iconComponent={iconComponent} variant="nav" size="md" aria-current={active ? 'page' : undefined} aria-label={label} />}
|
|
354
|
+
<span className={`${RAIL_ROW.label} text-oq-96`}>{label}</span>
|
|
355
|
+
</div>
|
|
356
|
+
)
|
|
357
|
+
})}
|
|
358
|
+
</nav>
|
|
359
|
+
{actions && <div className="flex shrink-0 items-center gap-2">{actions}</div>}
|
|
360
|
+
</header>
|
|
361
|
+
)
|
|
362
|
+
}
|
|
363
|
+
|
|
331
364
|
function AppRail({
|
|
332
365
|
items = [],
|
|
333
366
|
bottomItems = [],
|