跳转到内容

Collapsible 折叠区域 ​

一块可以展开与收起的单块内容。

用法 ​

不传 open 即为非受控,defaultOpen 只提供初始值,之后由组件自行维护开合

defaultOpen 只影响初始状态。

组件结构 ​

加粗的是必需部件。

data-scope="collapsible":root · header · trigger · content · indicator

示例 ​

受控 ​

传入 open 后由宿主决定,组件自身不再修改状态,只发 open-change 报告意图

禁用 ​

disabled 把触发器整个关停,点击与键盘都不再改变开合,已展开的内容维持原样

内容停在展开态,收不上。

尺寸 ​

size 改变触发按钮的高度、内边距与字号,三档并排对照

按钮最矮,字号也最小。
不写 size 就是这一档。
按钮最高,字号也最大。

自定义展开标记 ​

在指示符部件中放置自己的图形,转向仍由皮肤按 open 接管

展开动画 ​

收起时节点不卸载,作者接管内容区的 display,用一条行高过渡即可平滑展开

颜色 ​

tone 落在触发按钮的展开态上,六种颜色各展开一份做对照

收起后触发按钮保持默认颜色。
收起后触发按钮保持默认颜色。
收起后触发按钮保持默认颜色。
收起后触发按钮保持默认颜色。
收起后触发按钮保持默认颜色。
收起后触发按钮保持默认颜色。

设计指引 ​

何时使用 ​

  • 高级选项、补充说明等默认不需要显示的单块内容。

何时不用 ​

  • 有多块并列的可折叠内容时,使用手风琴,它负责互斥与整组语义。
  • 内容需要浮在页面之上时,使用气泡卡片。

特性 ​

  • 触发器与内容通过 aria-controls 与 aria-expanded 关联。
  • 展开动画由皮肤提供,内容高度由组件测量。
  • 指示符部件留空时由皮肤绘制箭头,放入图形时以作者提供的为准,两种情形的转向都由皮肤处理。

组合 ​

最佳实践 ​

  • 触发器文字说明内容是什么,不只写“展开”。
  • 收起时内容退出 Tab 序列,焦点不落到不可见的位置。

反模式 ​

  • 把必填字段放进折叠区,用户提交失败时无法定位错误。

API 参考 ​

产物 ​

层值
自定义元素<xh-collapsible>
Vue 组件XhCollapsibleContent XhCollapsibleHeader XhCollapsibleIndicator XhCollapsibleRoot XhCollapsibleTrigger
组合式函数useCollapsible
状态机collapsibleMachine
皮肤@xihan-ui/styles/collapsible.css

Props ​

属性类型必填说明
openboolean
defaultOpenboolean
disabledboolean
toneTone颜色:brand / neutral / success / warning / danger / info,决定使用哪组状态色。
sizeSize尺寸:sm / md / lg。
dirDirection文字方向,只作用于排版;作者未提供时不写入。
onOpenChange(details: CollapsibleOpenChangeDetails) => voidopen 变化意图回调;受控时是唯一出口,非受控时随内部转移一并通知。

事件 ​

自定义元素将载荷放在 detail;Vue 使用同名 emit。

事件载荷说明
open-changeCollapsibleOpenChangeDetailsopen 状态变化;detail 为 { open: boolean }

React 适配器 props ​

只列各组件自己声明的那些:继承自 ComponentPropsWithRef 的 DOM 属性不在其中,根组件上与上面 Props 表同名的也不重复列。Vue 的对应物是上面的插槽表。

React 组件属性类型必填说明
XhCollapsibleRootchildrenReactNode

状态 ​

公开状态写入 data-state。

部件取值
root'open' | 'closed'
header'open' | 'closed'
trigger'open' | 'closed'
content'open' | 'closed'
indicator'open' | 'closed'

以下名称仅用于内部状态机。

状态:open · closed

事件:OPEN · CLOSE · TOGGLE · CONTROLLED.OPEN · CONTROLLED.CLOSE · PRESS.START · PRESS.END

判据:isOpenControlled · canPress

connect API ​

getXxxProps() 返回对应部件的宿主属性。

成员类型说明
openboolean
setOpen(next: boolean) => void
getRootProps() => T['element']
getHeaderProps() => T['element']
getTriggerProps() => T['button']
getContentProps() => T['element']
getIndicatorProps() => T['element']

无障碍 ​

键盘 ​

规格出处:W3C APG

按键生效条件行为
Space / Enterfocus in trigger, not disabled展开/收起 content
Enter / Spaceheld in trigger, not disabled按住期间 trigger 投影 data-pressed,与指针 :active 同一副按压面(disclosure trigger 只换面不缩放);抬起、失焦或转禁用撤下

ARIA ​

以下属性由 connect 生成。

部件属性值
triggeraria-controlscontent 部件的 id
triggeraria-expanded'true' | 'false'
indicatoraria-hidden'true'

样式参考 ​

皮肤 ​

@xihan-ui/styles/collapsible.css 使用 [data-scope="collapsible"][data-part="root"] 部件选择器,位于 xihan.components 与 xihan.motion 层。覆盖样式使用 xihan.overrides。

数据属性 ​

由 connect 生成;条件不成立时不输出无值属性。

部件属性值
rootdata-disabled''(条件成立时才出现)
rootdata-sizeprops.size
rootdata-state'open' | 'closed'
rootdata-toneprops.tone
headerdata-disabled''(条件成立时才出现)
headerdata-state'open' | 'closed'
triggerdata-disabled''(条件成立时才出现)
triggerdata-pressed''(条件成立时才出现)
triggerdata-state'open' | 'closed'
triggerdata-xh-action-control''
triggerdata-xh-action-display'always'
triggerdata-xh-action-profile'disclosure-trigger'
triggerdata-xh-action-sizeprops.size
triggerdata-xh-action-variant'ghost'
contentdata-instant''(条件成立时才出现)
contentdata-state'open' | 'closed'
indicatordata-disabled''(条件成立时才出现)
indicatordata-instant''(条件成立时才出现)
indicatordata-state'open' | 'closed'

CSS 变量 ​

本组件公开覆盖槽由独立皮肤的实际消费位生成;默认来源、作用部件和状态均与 CSS 同源。

变量部件CSS 属性状态默认来源说明
--xh-collapsible-content-fgcontentcolordefault--xh-fg-mutedcollapsible 的 content 部件 color 覆盖槽。
--xh-collapsible-content-font-sizecontentfont-sizedefault--xh-text-secondary-sizecollapsible 的 content 部件 font-size 覆盖槽。
--xh-collapsible-content-pbcontentpadding-block-end@keyframes xh-disclosure-collapse
@keyframes xh-disclosure-expand
default
--xh-_collapsible-content-pbcollapsible 的 content 部件 padding-block-end 覆盖槽。
--xh-collapsible-content-pxcontentpadding-inlinedefault--xh-_collapsible-content-pxcollapsible 的 content 部件 padding-inline 覆盖槽。
--xh-collapsible-header-gapheadergapdefault--xh-_collapsible-trigger-gapcollapsible 的 header 部件 gap 覆盖槽。
--xh-collapsible-icon-sizeroot
trigger
--xh-icon-sizedefault--xh-_action-profile-glyph-size
--xh-glyph-size-md
collapsible 的 root、trigger 部件 --xh-icon-size 覆盖槽。
--xh-collapsible-indicator-fgindicatorcolordefault--xh-fg-mutedcollapsible 的 indicator 部件 color 覆盖槽。
--xh-collapsible-trigger-bgtrigger--xh-ink-surface
background-color
default
xh-ink-surface
--xh-_action-variant-bg-restcollapsible 的 trigger 部件 --xh-ink-surface、background-color 覆盖槽。
--xh-collapsible-trigger-bg-hovertriggerbackground-colordisabled
hover
loading
not([data-disabled])
not([data-loading])
--xh-_action-variant-bg-hovercollapsible 的 trigger 部件 background-color 覆盖槽。
--xh-collapsible-trigger-fgtriggercolordefault
disabled
hover
is(:active, [data-pressed])
loading
not([data-disabled])
not([data-loading])
pressed
--xh-_action-variant-fg-hover
--xh-_action-variant-fg-pressed
--xh-_action-variant-fg-rest
collapsible 的 trigger 部件 color 覆盖槽。
--xh-collapsible-trigger-fg-disabledtriggercolordisabled--xh-_action-variant-fg-disabledcollapsible 的 trigger 部件 color 覆盖槽。
--xh-collapsible-trigger-fg-opentriggercolordisabled
hover
is(:active, [data-pressed])
loading
not([data-disabled])
not([data-loading])
pressed
state=open
--xh-_collapsible-open-fgcollapsible 的 trigger 部件 color 覆盖槽。
--xh-collapsible-trigger-font-sizetriggerfont-sizedefault--xh-_action-profile-font-sizecollapsible 的 trigger 部件 font-size 覆盖槽。
--xh-collapsible-trigger-font-weighttriggerfont-weightdefault--xh-text-label-weightcollapsible 的 trigger 部件 font-weight 覆盖槽。
--xh-collapsible-trigger-gaptriggergapdefault--xh-_action-profile-gapcollapsible 的 trigger 部件 gap 覆盖槽。
--xh-collapsible-trigger-htriggerblock-size
min-block-size
default
xh-action-profile=disclosure-trigger
--xh-_action-profile-visual-sizecollapsible 的 trigger 部件 block-size、min-block-size 覆盖槽。
--xh-collapsible-trigger-pxtriggerpadding-inlinedefault--xh-_action-profile-padding-inlinecollapsible 的 trigger 部件 padding-inline 覆盖槽。
--xh-collapsible-trigger-pytriggerpadding-blockxh-action-profile=disclosure-trigger--xh-_action-profile-padding-blockcollapsible 的 trigger 部件 padding-block 覆盖槽。
--xh-collapsible-trigger-radiustriggerborder-radiusdefault--xh-_action-profile-radiuscollapsible 的 trigger 部件 border-radius 覆盖槽。

动效 ​

动效角色:按压 · 状态 · 披露(见动效规范)。

共享关键帧 xh-disclosure-collapse · xh-disclosure-expand 由 family/motion.css 提供,皮肤 @import 它,单独引入仍成立;rotate 走 transition 过渡。时长与缓动读动效令牌,改令牌即改全局节奏。

皮肤之外还有一段:退场由适配器的退场闸门把关,动画播完才真收起。

系统开启减弱动效时由令牌层统一收敛,皮肤不另作判断。

RTL ​

皮肤用逻辑属性排布(inline-start 一族),dir="rtl" 下自动镜像。

Released under The MIT License