kitseed.
组件

Sidebar 应用侧边栏

融合内嵌工作台布局、多级树目录、悬停槽位切换与账户状态栏的统一侧边栏组件族。

用于桌面与 Web 工作区的主导航壳层。把画布侧栏、圆角内嵌舞台、可拖拽宽度分隔条、移动端模态抽屉、多级目录树、行尾同槽位菜单切换以及底部状态与账户入口统一为一套可组合的原语。

安装

pnpm dlx shadcn@4.22.1 add http://127.0.0.1:3040/r/v0.3.0/sidebar.json

首次使用请先完成 Registry 与主题接入。

组件结构与职责

组件职责
SidebarLayout组织画布侧栏、圆角内嵌舞台(Inset Stage)、桌面折叠 inert 保护、窄窗浮动遮罩(overlay)与移动抽屉(SidebarDrawer)
SidebarResizer垂直可拖拽分隔条(默认 220px,范围 190px–300px),支持指针捕获、方向键微调与双击复位
SidebarDrawer基于 Base UI Dialog 的移动端模态导航抽屉,支持焦点恢复与 onOpenChangeComplete 关闭后延迟动作交接
SidebarRoot / SidebarHeader / SidebarBody / SidebarFooter语义化侧栏地标与四段式纵向结构,支持桌面端 titlebarInset 原生窗口拖拽留白
SidebarSearchTrigger / SidebarFilterInput全宽命令面板触发按钮(带 ⌘K 键帽)与栏内实时筛选框(带 IME 组合输入保护与 Escape 清空)
SidebarGroup统一支持可折叠分组(传入 collapsed + onToggle)与静态分组标题(省略折叠参数),右侧可挂载快捷动作
SidebarItem统一导航行:支持扁平链接、多级树状缩进(depth)与独立展开箭头(expanded)、双色徽标(neutral / brand)、桌面端悬停徽标与更多按钮同槽位无抖动切换、触屏端并排常驻以及右键上下文菜单(contextMenuContent)
SidebarSkeleton / SidebarInlineAction异步目录加载占位骨架与分组内空态/错误重试内联按钮
SidebarStatusItem / SidebarAccountTrigger / SidebarAccountSummary底部同步/离线/更新状态栏、兼容单行紧凑与双行副标题的账户菜单触发器及弹出菜单顶部身份摘要卡

核心 Props

组件与属性类型默认值说明
SidebarLayout.collapsedbooleanfalse折叠桌面侧栏并自动标记 hidden 与 inert,防止焦点泄露到不可见导航项
SidebarLayout.resizablebooleanfalse启用侧栏与舞台之间的拖拽分隔条
SidebarLayout.sidebarWidth / defaultSidebarWidthnumber220受控或非受控侧栏宽度,自动钳制在 minSidebarWidth(190)与 maxSidebarWidth(300)之间
SidebarItem.badgeTone"neutral" | "brand""neutral"neutral 用于常规条目/目录计数(静默等宽数字);brand 用于未读回执或高优待办(品牌色胶囊)
SidebarItem.depthnumber0多级目录树缩进层级(每级递增 12px)
SidebarItem.expanded / onToggleExpandboolean / () => void—传入后在行首渲染独立的子目录展开/折叠按钮,与主导航链接作为同级节点互不嵌套
SidebarItem.actions / menuOpenReactNode / boolean—行尾更多操作区;桌面端默认预留徽标槽位,悬停/聚焦或菜单打开时平滑淡入操作按钮,文字宽度零跳动
SidebarItem.contextMenuContentReactNode—为该行启用右键菜单及键盘 ContextMenu / Shift+F10 快捷唤出

键盘、触控与无障碍

  • 禁止交互控件嵌套:SidebarGroup 的折叠触发器与右侧附加动作、SidebarItem 的树展开箭头与主导航链接及行尾菜单触发器、SidebarAccountTrigger 与右侧附属按钮均为同级兄弟节点,严格避免 <button> 或 <a> 互相嵌套。
  • 桌面紧凑与触屏 44px 自适应:桌面精细指针(pointer: fine)下导航行高为 28px,并在右侧共享 24px 槽位完成徽标与操作按钮切换;在 comfortable 密度、窄容器(<= 480px)、移动端或粗指针(pointer: coarse)下,所有交互热区自动扩展至 >= 44px,且徽标与更多按钮并排常驻显示。
  • 折叠与抽屉焦点管理:侧栏折叠时设置 inert 阻断 Tab 聚焦;移动抽屉关闭后若需打开二级弹窗(如命令面板或账户设置),通过 onDrawerCloseComplete 在抽屉退场完成后接力唤起,避免焦点抢占。

来源与边界

0.3.0 本地候选,综合提炼自 Subtic、Kiipu 与 Dooset 三个 Web 项目的八处侧边栏实现。路由跳转、文件夹增删改 API、宽度持久化存储、Electron IPC 窗口桥接及业务权限判断保留在各宿主应用中。

查看由当前源码生成的类型参考

只展示 Kitseed 自身定义的属性,原生 HTML 与 Base UI 透传属性请参阅对应上游说明。

SidebarResizer

属性类型默认值
valuenumber—
min?number190
max?number300
defaultValue?number220
step?number12
label?string"调整侧栏宽度"
controls?string—
onChange(width: number) => void—
className?string—
unstyled?booleanfalse

SidebarDrawer

属性类型默认值
openboolean—
onOpenChange(open: boolean) => void—
onOpenChangeComplete?((open: boolean) => void) | undefined—
title?string | undefined"导航菜单"
description?string | undefined—
closeLabel?string | undefined"关闭导航"
showCloseButton?boolean | undefinedfalse
finalFocus?ComponentProps<typeof Dialog.Popup>["finalFocus"] | undefined—
stage?ReactNode | undefined—
childrenReactNode—
className?string | undefined—
unstyled?boolean | undefinedfalse
slotProps?| { backdrop?: ComponentProps<typeof Dialog.Backdrop>; popup?: ComponentProps<typeof Dialog.Popup>; close?: ComponentProps<typeof Dialog.Close>; } | undefined{}

SidebarLayout

属性类型默认值
sidebarReactNode—
childrenReactNode—
collapsed?booleanfalse
overlay?booleanfalse
onCloseOverlay?() => void—
overlayCloseLabel?string"关闭浮动侧栏"
inset?booleantrue
resizable?booleanfalse
sidebarWidth?number—
defaultSidebarWidth?number220
minSidebarWidth?number190
maxSidebarWidth?number300
resizerLabel?string"调整侧栏宽度"
onSidebarWidthChange?(width: number) => void—
drawerOpen?boolean—
onDrawerOpenChange?(open: boolean) => void—
onDrawerCloseComplete?(open: boolean) => void—
drawerSidebar?ReactNode—
drawerTitle?string"导航菜单"
className?string—
sidebarClassName?string—
stageClassName?string—
unstyled?booleanfalse
slotProps?{ sidebarColumn?: DivSlot; scrim?: ButtonSlot; stage?: DivSlot; }{}

SidebarRoot

属性类型默认值
label?string"主要导航"
titlebarInset?boolean | numberfalse
unstyled?booleanfalse
slotProps?{ titlebar?: DivSlot; }{}

SidebarHeader

属性类型默认值
brand?ReactNode—
actions?ReactNode—
children?ReactNode—
className?string—
unstyled?booleanfalse
slotProps?{ topRow?: DivSlot; brandSlot?: DivSlot; actionsSlot?: DivSlot; }{}

SidebarSearchTrigger

属性类型默认值
label?ReactNode"搜索…"
shortcut?ReactNode | null"⌘K"
icon?ReactNode—
active?booleanfalse
unstyled?booleanfalse
slotProps?{ icon?: SpanSlot; label?: SpanSlot; shortcut?: SpanSlot; }{}

SidebarFilterInput

属性类型默认值
valuestring—
onValueChange(value: string) => void—
label?string"筛选导航"
clearLabel?string"清除筛选"
inputRef?Ref<HTMLInputElement>—
unstyled?booleanfalse
slotProps?{ root?: DivSlot; icon?: SpanSlot; input?: ComponentProps<"input"> & DataAttributes; clearButton?: ButtonSlot; }{}

SidebarBody

属性类型默认值
label?string | undefined"主要导航"
busy?boolean | undefinedfalse
unstyled?boolean | undefinedfalse

SidebarGroup

属性类型默认值
label?ReactNode | undefined—
collapsed?boolean | undefined—
onToggle?(() => void) | undefined—
action?ReactNode | undefined—
as?"div" | "section" | undefined—
headingAs?"span" | "h2" | "p" | undefined—
headingId?string | undefined—
childrenReactNode—
className?string | undefined—
unstyled?boolean | undefinedfalse
slotProps?| { header?: DivSlot | undefined; trigger?: ButtonSlot | undefined; heading?: (SpanSlot & ComponentProps<"h2"> & ComponentProps<"p">) | undefined; indicator?: ComponentProps<typeof CaretRight> | undefined; actionSlot?: DivSlot | undefined; content?: DivSlot | undefined; } | undefined{}

SidebarItemContent

属性类型默认值
icon?ReactNode | undefined—
showIcon?boolean | undefinedfalse
labelReactNode—
badge?ReactNode | undefined—
badgeTone?SidebarBadgeTone | undefined"neutral"
badgeLabel?string | undefined—
reserveBadgeSpace?boolean | undefinedfalse
active?boolean | undefinedfalse
unstyled?boolean | undefinedfalse
slotProps?| { icon?: SpanSlot | undefined; label?: SpanSlot | undefined; badgeSlot?: SpanSlot | undefined; badge?: SpanSlot | undefined; announcement?: SpanSlot | undefined; } | undefined{}

SidebarItem

属性类型默认值
icon?ReactNode | undefined—
activeIcon?ReactNode | undefined—
labelReactNode—
active?boolean | undefinedfalse
disabled?boolean | undefinedfalse
badge?ReactNode | undefined—
badgeTone?SidebarBadgeTone | undefined"neutral"
badgeLabel?string | undefined—
reserveBadgeSpace?boolean | undefined—
depth?number | undefined0
expanded?boolean | undefined—
expandLabel?string | undefined—
onToggleExpand?(() => void) | undefined—
actions?ReactNode | undefined—
menuOpen?boolean | undefinedfalse
contextMenuContent?ReactNode | undefined—
contextMenuPopup?ReactNode | undefined—
href?string | undefined—
onClick?(ComponentProps<"button">["onClick"] & ComponentProps<"a">["onClick"]) | undefined—
render?useRender.RenderProp<{ active: boolean; disabled: boolean }> | undefined—
className?string | undefined—
unstyled?boolean | undefinedfalse
slotProps?| { row?: DivSlot | undefined; disclosure?: ButtonSlot | undefined; primary?: (ComponentProps<"button"> & ComponentProps<"a"> & DataAttributes) | undefined; content?: SpanSlot | undefined; icon?: SpanSlot | undefined; label?: SpanSlot | undefined; badgeSlot?: SpanSlot | undefined; badge?: SpanSlot | undefined; announcement?: SpanSlot | undefined; actionsSlot?: DivSlot | undefined; } | undefined{}

SidebarSkeleton

属性类型默认值
rows?number3
label?string"正在加载导航…"
className?string—
unstyled?booleanfalse

SidebarInlineAction

属性类型默认值
icon?ReactNode—
tone?"neutral" | "danger""neutral"
unstyled?booleanfalse

SidebarFooter

属性类型默认值
unstyled?booleanfalse

SidebarStatusItem

属性类型默认值
tone?SidebarStatusTone | undefined"neutral"
pulse?boolean | undefinedfalse
icon?ReactNode | undefined—
labelReactNode—
meta?ReactNode | undefined—
busy?boolean | undefinedfalse
role?ComponentProps<"div">["role"] | undefined—
"aria-label"?string | undefined—
title?string | undefined—
onClick?ComponentProps<"button">["onClick"] | undefined—
className?string | undefined—
unstyled?boolean | undefinedfalse
slotProps?| { indicator?: SpanSlot | undefined; label?: SpanSlot | undefined; meta?: SpanSlot | undefined; } | undefined{}

SidebarAccountTrigger

属性类型默认值
avatarReactNode—
nameReactNode—
subtitle?ReactNode—
indicator?"caret" | "up-down" | "dots" | "none""caret"
trailingAction?ReactNode—
render?useRender.RenderProp<Record<string, never>>—
unstyled?booleanfalse
slotProps?{ row?: DivSlot; avatar?: SpanSlot; text?: SpanSlot; name?: SpanSlot; subtitle?: SpanSlot; indicator?: SpanSlot & ComponentProps<typeof CaretDown>; trailing?: DivSlot; }{}

SidebarAccountSummary

属性类型默认值
avatarReactNode—
nameReactNode—
email?ReactNode—
badge?ReactNode—
className?string—
unstyled?boolean—
slotProps?{ avatar?: SpanSlot; body?: DivSlot; titleRow?: DivSlot; name?: SpanSlot & ComponentProps<"p">; email?: SpanSlot & ComponentProps<"p">; }{}

本页内容