Sidebar 侧边栏
可组合、可主题化的应用侧边栏(shadcn-vue Sidebar)。空间足够时停靠在内容旁边,不够时变成侧边面板——依据自身容器测量,没有断点。可以带宽度动画地折叠为图标栏或完全收起。
演练场
拖动宽度滑块,试试各种变体与折叠模式。
SSidebarProvider({ variant: 'sidebar', collapsible: 'icon', value: this.page!! }) {
SSidebar() {
SSidebarHeader() { Brand() }
SSidebarContent() {
SSidebarGroup() {
SSidebarGroupLabel({ text: 'Platform' })
SSidebarMenu() {
SSidebarMenuItem() {
SSidebarMenuButton({ value: 'inbox', icon: 'inbox', text: 'Inbox', badge: '24' })
}
SSidebarMenuItem() {
SSidebarMenuButton({ value: 'calendar', icon: 'calendar', text: 'Calendar' })
}
}
}
}
SSidebarFooter() { UserRow() }
}
SSidebarInset() {
STopbar({ title: 'Inbox' }) // leading SSidebarTrigger appears automatically
SPage() { ... }
}
}
// Wide container: docked; the trigger folds it to an icon rail (animated width).
// Narrow container: the sidebar becomes a sheet opened by the trigger. No breakpoints to declare.网页近似预览,真机效果以 HarmonyOS 渲染为准。
结构
SSidebarProvider 持有状态(open、openMobile、value),并排布 SSidebar + SSidebarInset。组成部分:SSidebarHeader、SSidebarContent(可滚动)、SSidebarFooter、SSidebarGroup、SSidebarGroupLabel、SSidebarMenu、SSidebarMenuItem、SSidebarMenuButton(icon、text、badge、isActive 或 value)、SSidebarSeparator、SSidebarTrigger。
Token
外观可通过 --sidebar-* 组件 Token(ADR D13)在语义色 --sidebar / --sidebar-accent 之上主题化:背景、边框、宽度、菜单圆角 / 高度 / 激活与悬停颜色、分组标签颜色、浮动与内嵌框。可按实例设置:SSidebarProvider({ tokens })。开关会写入主题变量,因此会同时改变上方的演练场与本画廊自身的侧边栏。
// theme-wide (exported with the theme)
SparkUI.themes.setVariable('--sidebar-background', 'transparent');
SparkUI.themes.setVariable('--sidebar-menu-radius', '999px');
SparkUI.themes.setVariable('--sidebar-menu-active-background',
'color-mix(in oklab, var(--primary) 12%, transparent)');
SparkUI.themes.setVariable('--sidebar-menu-active-foreground', 'var(--primary)');
// one sidebar only
SSidebarProvider({ tokens: { background: 'transparent', menuRadius: 999, borderColor: 'transparent' } }) { ... }网页近似预览,真机效果以 HarmonyOS 渲染为准。
API
从组件库源码中的 @Param / @Event / @BuilderParam 声明自动提取。
SSidebarProvider
shadcn-vue 的 SidebarProvider:并排排布 SSidebar 与 SSidebarInset,并持有侧边栏状态。无断点的响应式:layoutPolicy 根据 provider 自身的宽度决定侧边栏是停靠、图标栏还是浮层面板(默认:展开的侧边栏放不下且与内容区至少保持 minInsetWidth 时使用侧边面板;sparkSidebarRailPolicy() 增加图标栏这一档)。
属性:variant 取 'sidebar' | 'floating' | 'inset';collapsible 取 'offcanvas' | 'icon' | 'none';side 取 'left' | 'right'(渲染顺序会自动翻转)。open / defaultOpen / onOpenChange 控制停靠状态(把存储的值传给 defaultOpen,并在 onOpenChange 中保存即可持久化);value / defaultValue / onValueChange / onNavigate 控制当前激活的菜单值(内置无路由功能:把任意路由器接到 value + onNavigate)。controller 允许你自行持有状态对象。
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
controller | SparkSidebarState | undefined | undefined | 你自己的状态对象(无头控制);省略时会自动创建 |
open!! | boolean | undefined | undefined | |
defaultOpen | boolean | true | |
value!! | string | undefined | undefined | |
defaultValue | string | '' | |
variant | SidebarVariantSidebarVariant = 'sidebar' | 'floating' | 'inset' | 'sidebar' | |
collapsible | SidebarCollapsibleSidebarCollapsible = 'offcanvas' | 'icon' | 'none' | 'offcanvas' | |
side | SidebarSideSidebarSide = 'left' | 'right' | 'left' | |
sidebarWidth | number | 0 | 停靠宽度(vp);0 表示使用 --sidebar-width 令牌,否则为 256(shadcn 的 16rem) |
sidebarWidthMobile | number | 0 | 侧边面板宽度(vp);0 表示使用 --sidebar-width-mobile 令牌,否则为 288 |
sidebarWidthIcon | number | 0 | 图标栏宽度(vp);0 表示使用 --sidebar-width-icon 令牌,否则为 48 |
tokens | SidebarTokens | {} | 实例级外观(ADR D13):实例 → --sidebar-* 组件令牌 → shadcn 配方 |
minInsetWidth | number | 360 | 主区域至少应保持的宽度(vp);layoutPolicy 的输入 |
safeArea | boolean | false | 为窗口安全区留出内边距(沉浸式页面,参见 SparkProvider 的 immersive) |
closeOnSelect | boolean | true | 点击菜单按钮时关闭侧边面板 |
motionKey | string | 'sidebar' | 折叠动画与侧边面板所用的动效 key |
| 事件 | 类型 | 默认值 | 说明 |
|---|---|---|---|
onOpenChange | (open: boolean) => void | () => { } | |
onValueChange | (value: string) => void | () => { } | |
onNavigate | (value: string) => void | () => { } | 每次激活菜单值都会触发,即使是当前项(路由钩子:再次点击 = 弹回根页面) |
onOpenMobileChange | (open: boolean) => void | () => { } | 浮层侧边面板打开 / 关闭时触发 |
onPresentationChange | (presentation: SidebarPresentation) => voidSidebarPresentation = 'docked' | 'rail' | 'sheet' | () => { } | 布局策略在停靠 / 图标栏 / 侧边面板之间切换时触发 |
layoutPolicy | SparkSidebarLayoutPolicy | sparkSidebarDefaultPolicy | 根据测得的宽度决定停靠 / 图标栏 / 侧边面板(可替换) |
插槽: 子组件(尾随闭包)
SSidebar
shadcn-vue 的 Sidebar。停靠时:一列,宽度在展开 / 图标栏 / 隐藏之间做动画(由 provider 的 motionKey 决定,默认为 'sidebar')。图标栏:仅显示图标栏;切换后可把完整侧边栏以侧边面板的形式打开。侧边面板:从 side 方向滑出的浮层面板(使用 SparkUI 的浮层基础,因此返回手势、点击遮罩和焦点的行为与 SSheet 一致)。
插槽: 子组件(尾随闭包)
SSidebarHeader
顶部区域(品牌、团队切换器等):flex flex-col gap-2 p-2。
插槽: 子组件(尾随闭包)
SSidebarFooter
插槽: 子组件(尾随闭包)
SSidebarContent
可滚动的中间区域;占据头部与页脚之间的剩余高度。
插槽: 子组件(尾随闭包)
SSidebarGroup
插槽: 子组件(尾随闭包)
SSidebarGroupContent
插槽: 子组件(尾随闭包)
SSidebarGroupLabel
h-8 px-2 text-xs font-medium text-sidebar-foreground/70;在图标栏中会被收起。
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
text | ResourceStr | '' |
SSidebarMenu
插槽: 子组件(尾随闭包)
SSidebarMenuItem
插槽: 子组件(尾随闭包)
SSidebarMenuButton
shadcn-vue 的 SidebarMenuButton:图标 + 文本(+ 徽标,+ 尾部插槽)。当 isActive 为 true,或 value 与 provider 的 value 相等时处于激活状态。激活时调用 onSelect,更新 provider 的值,并关闭移动端的侧边面板。在图标栏中只保留图标可见(文字会被随宽度动画裁剪掉)。
按下的反馈来自系统的按下状态(SparkRowPressModifier.applyPressedAttribute),激活高亮则立即切换,从不做动画。
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
text | ResourceStr | '' | |
icon | string | undefined | undefined | |
value | string | '' | 用于在 provider 的 value 中标识该按钮 |
isActive | boolean | undefined | undefined | 显式的激活状态(优先于 value 匹配) |
badge | string | undefined | undefined | 位于尾部的计数或标签(shadcn 的 SidebarMenuBadge) |
sizing | SidebarMenuButtonSizeSidebarMenuButtonSize = 'default' | 'sm' | 'lg' | 'default' | |
variant | SidebarMenuButtonVariantSidebarMenuButtonVariant = 'default' | 'outline' | 'default' | |
disabled | boolean | false |
| 事件 | 类型 | 默认值 | 说明 |
|---|---|---|---|
onSelect | () => void | () => { } |
插槽: 子组件(尾随闭包)
SSidebarSeparator
h-px mx-2 bg-sidebar-border
无属性。
SSidebarTrigger
shadcn-vue 的 SidebarTrigger:幽灵风格的图标按钮,用于切换侧边栏(窄屏时打开侧边面板,否则折叠停靠的侧边栏)。可在 provider 内任意位置使用(例如 STopbar 中)。
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
label | ResourceStr | $r('app.string.spark_toggle_sidebar') | |
icon | string | undefined | undefined | lucide 图标;默认根据 side 取 panel-left / panel-right |
controller | SparkSidebarState | undefined | undefined | 控制该控制器而不是最近的 provider(用于 provider 外部的触发器) |
SSidebarInset
shadcn-vue 的 SidebarInset:侧边栏旁边的主区域。占据剩余宽度;variant 为 'inset' 时,它会成为侧边栏配色外框内一张带圆角、略微抬起的卡片。
插槽: 子组件(尾随闭包)