KQ-2099 · WORKSPACE/LIFT

Workspace Lift

An app frame with a narrow strip of workspace icons at its far left, where the rest of the frame — sidebar, header and page — is one car: choosing another workspace runs it like an elevator on springs.glide, the current car and the next travelling together as one shaft so the seam between them passes through the frame, the new one arriving from below when it sits lower in the strip and from above when higher. The strip's indicator slides on springs.snap, the frame takes the new workspace's colour on a short tween, the header's floor number rolls one face the way the car went, and inside a workspace the nav tree's current pill travels on snap while pages cross-fade with a 4px rise. The strip is a vertical tablist whose Up and Down walk it with the car riding along, Cmd or Ctrl with 1 to 9 switches from anywhere in the frame, and in a narrow container the strip becomes a sheet dropping from the header.

KQ-2099 · WORKSPACE/LIFT
Signed in as Ines Carvalho

Inbox

12 open · oldest waiting 38 min

  • Order 4471 marked delivered, not receivedInes · 4 min
  • Refund for a double chargeTomas · 12 min
  • Can I change the delivery address?Mei · 21 min
  • Invoice for SeptemberArjun · 38 min

Coldbrook · Inbox · 15 unread

Install

One command — the source lands in your repo. Or copy it from the Code tab.

$ pnpm dlx shadcn@latest add @kinetiq/workspace-lift

Props

workspaces
LiftWorkspace[]
default defaultLiftWorkspaces
The workspaces in strip order: { id, name, initials, color, kind?, nav: { id, label, items: { id, label, unread?, icon?, page: { title, summary, rows } }[] }[], status?: ready | loading | locked }.
workspace / defaultWorkspace
string
default the first workspace
The open workspace, controlled or initial. A host change rides the lift too.
onSwitchWorkspace
(id: string, workspace: LiftWorkspace) => void
default —
Fires from the strip, the sheet, an arrow key or Cmd/Ctrl+number that chose a workspace.
page / defaultPage
string
default each workspace's first page
The page within the current workspace, controlled or initial; every workspace remembers its own page for the trip back.
onNavigate
(workspaceId: string, pageId: string) => void
default —
Fires when a nav item is chosen.
onAddWorkspace
() => void
default —
The strip's + button (or the sheet's Add a workspace) was pressed. Omit it and there is no + button.
onRequestAccess
(workspaceId: string) => void
default —
“Ask for access” was pressed on a locked workspace; the button then reads “Request sent”.
user
{ name: string; initials: string }
default { name: "Ines Carvalho", initials: "IC" }
The person signed in, for the header avatar.
title
string
default "Workspaces"
The frame's accessible name.
frameHeight
number
default 520
The frame's height in px; pages scroll inside it.
liftDirection
"auto" | "up" | "down"
default "auto"
Where a new workspace arrives from: by its place in the strip, always rising from below, or always dropping from above.
stripWidth
number
default 56
The strip's width in px; its icons, badges and indicator scale with it.
accent
"cobalt" | "plum" | "mint" | "ink" | string
default "cobalt"
Selection colour for the nav pill and unread counts; each workspace keeps its own colour for the frame.
shortcuts
boolean
default true
Cmd or Ctrl with 1 to 9 switches workspace while focus is in the frame.
disabled
boolean
default false
Read only: nothing can be switched or opened.
className
string
default —
Classes for the frame.