生态产品多个设计器现已发布正式版

查看生态总览
跳转到内容

Card 卡片 ​

用于组织相关内容与操作的中性表面。

用法 ​

Header 放标题与说明,Content 放主体

本月账单

账期 7 月 1 日至 7 月 31 日

共 128 笔支出,合计 3,240.00 元。

组件结构 ​

加粗的是必需部件。

data-scope="card":root · header · title · trigger · description · content · footer

示例 ​

变体 ​

outline 为默认卡面,subtle 淡底嵌入,ghost 用于嵌套

outline

一段用来看表面层级的正文。

subtle

一段用来看表面层级的正文。

ghost

一段用来看表面层级的正文。

横向布局 ​

Card 只提供内容面,方向和媒体尺寸由使用场景决定

七月总结

收入与支出趋势已生成

更新于今天 09:30

带媒体 ​

图片或自绘媒体作为普通子节点放入,由内容自己决定比例与圆角

七月总结

媒体与文字共享卡片的统一节奏

本月共完成 18 个里程碑。

整卡可点 ​

interactive 加标题里的 trigger:整张卡片都是点击区,读屏只读到一个链接

季度报告

2026 年第三季度 · 财务部

营收同比增长 12%,毛利率持平。

设计指引 ​

何时使用 ​

  • 把一组相关信息收成一个可以整体感知的单元。
  • 内容块之间需要视觉边界。

何时不用 ​

  • 页面上每一块都使用卡片会使边界失效。
  • 只需要一条分隔时,使用分隔线。

特性 ​

  • root 必需;header、title、description、content、footer 按内容组合。
  • outline 是默认卡面,subtle 用淡底嵌在别的面里,ghost 用于嵌套内容不再画面。
  • 根取 surface 圆角、1px 装饰边、无影,自己不留内衬:放在根下的 header 是一条头部条(一行标题时高 46px、紧凑密度 40px,横向内距 16px,底边一道 1px 内部分隔线),标题取区块标题档、正文色;content 四边内距 16px(紧凑密度纵向 12px)、14px 次级色;footer 与正文同起点、底边留同档内距。直接放进根的媒体贴边铺满;横向布局与媒体比例由使用场景决定。
  • 整卡可点用 interactive 加标题里的 trigger:trigger 是原生链接(给了 href)或 <button type="button">,路由链接等作者自己的节点用 asChild。它的点击区由伪元素铺满整张卡片,卡片里任一处点下去都是在点它;可及名只取 trigger 自己的文字,Tab 位也只有它这一个。不把整张卡片包进 <a>:那样读屏会把标题、说明、正文连成一整串链接名逐字念完,卡片里也不能再放按钮(交互元素不能嵌套)。
  • 可交互卡片的反馈按根面分:outline 是抬起面,悬停抬高一档海拔(raised → lifted),按下落回 raised 并换到白底阶梯第一档;subtle 悬停淡底 200、按下 300;ghost 悬停 100、按下 200。抬起只走影、不走位移,减弱动效下仍是淡变。按下只认 trigger 自己的按下,脚部按钮按下时整卡不跟着换面。
  • 键盘聚焦 trigger 时焦点环画在整张卡片外沿,与点击区是同一块轮廓;trigger 自己不再画环。
  • 脚部叠在点击区之上:里面另放的按钮照常可点、不触发整卡,脚部的空白处也不触发。其余部件都在点击区之下。
  • data-material="liquid" 下,可交互卡片在细指针悬停时描边扫过一道交互光,只播一遍,与 Button 实心钮同一配方;standard 档、粗指针与强制色下不画。时长槽 --xh-card-glint-duration。
  • 不写结构时按标准结构铺(Vue 不写默认插槽、React 不给 children、Web Components 不写部件或只写 root),三端出自同一个结构函数:给了标题或说明才铺页头(标题在前),给了正文、页脚才铺对应一段,内容都归作者。Vue 是 title、description、content、footer 四个具名插槽,React 是同名的四个属性,Web Components 是宿主直接子节点上的同名 slot。整卡可交互的 trigger 要用时手写结构。

组合 ​

最佳实践 ​

  • 整卡可点时用 interactive 加 trigger,不要自己给根加 tabindex 与点击处理:那样根没有可及名,读屏只报一个“组”。
  • trigger 与根之间的祖先不要再建定位上下文(position: relative 等),否则点击区只铺到那一层。
  • 同组卡片保持相同宽度和内容节奏。

反模式 ​

  • 卡片嵌套卡片,两层边界互相削弱。
  • 整卡可点的同时在正文里再放按钮或链接:它们被点击区盖住,点下去触发的是整卡。另有操作时放进脚部。
  • 静态卡片也挂悬停反馈:没有 trigger 的卡片悬停抬起,读者会以为能点。

API 参考 ​

产物 ​

层值
自定义元素<xh-card>
Vue 组件XhCardContent XhCardDescription XhCardFooter XhCardHeader XhCardRoot XhCardTitle XhCardTrigger
状态机无,connect 直接由 props 算属性
皮肤@xihan-ui/styles/card.css

Props ​

属性类型必填说明
interactiveboolean整卡可交互:标题里的 trigger(链接或按钮)把点击区铺满整张卡片,悬停抬起、按下换面, 焦点环沿卡片外沿画在卡片盒内。可及名只取 trigger 自己的文字,卡片里的其余内容不进链接名。 默认 false。
variantControlVariant形态:outline 为带影的抬起面,subtle 为淡底,ghost 无底无影。默认 outline。

插槽 ​

仅列出带载荷的插槽。

Vue 组件插槽载荷说明
XhCardRootdefault—
XhCardRoottitle—
XhCardRootdescription—
XhCardRootcontent—
XhCardRootfooter—

React 适配器 props ​

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

React 组件属性类型必填说明
XhCardRoottitleReactNode标题。不给 children 时铺进页头的 title 部件。
XhCardRootdescriptionReactNode标题下的说明。不给 children 时铺进页头的 description 部件。
XhCardRootcontentReactNode正文。不给 children 时铺进 content 部件。
XhCardRootfooterReactNode页脚,通常放操作。不给 children 时铺进 footer 部件。

connect API ​

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

成员类型说明
getRootProps() => T['element']
getHeaderProps() => T['element']
getTitleProps() => T['element']
getTriggerProps() => T['element']整卡的触发器:放在 title 里的链接或按钮,interactive 时它的点击区铺满整张卡片。
getDescriptionProps() => T['element']
getContentProps() => T['element']
getFooterProps() => T['element']

无障碍 ​

键盘 ​

规格出处:W3C APG

按键生效条件行为
Enter / Spacefocus on trigger原生激活:链接只认 Enter 并跳转,按钮 Enter 与 Space 都认;整张卡片只有 trigger 这一个 Tab 位
  • 可交互卡片的语义就是一个链接或按钮加一段普通内容:根不写 role、不拿焦点,读屏按文档序读到标题里的链接,再读说明与正文。
  • trigger 必须有可见文字,它就是可及名;只放图标时补 aria-label。
  • 点击区盖在内容之上,内容里的文字不能再拖选;需要复制的内容(编号、地址)不要放进可交互卡片,或放进脚部。

样式参考 ​

皮肤 ​

@xihan-ui/styles/card.css 按 [data-scope="card"][data-part="root"] 部件选择器书写,发布产物以挂载类 .xh-scope-card 代替其中的 data-scope(特异性相同),位于 xihan.components 层。覆盖样式使用 xihan.overrides,部件选择器照常可用。

forced-colors: active 下另有一套规则:颜色交给系统,边框与状态标记改用系统色关键字。

CSS 变量 ​

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

变量部件CSS 属性状态默认来源说明
--xh-card-bgrootbackgrounddefault
variant=subtle
--xh-bg-subtle
--xh-bg-surface
card 的 root 部件 background 覆盖槽。
--xh-card-bg-hoverrootbackgroundhover
interactive
variant=ghost
variant=subtle
--xh-_card-host-bg-hover
--xh-bg-subtle
card 的 root 部件 background 覆盖槽。
--xh-card-bg-pressedrootbackgroundactive
interactive
not(:has([data-scope='card'][data-part='footer']:active)
variant=ghost
variant=outline
variant=subtle
--xh-_card-host-bg-pressed
--xh-bg-subtle-hover
--xh-bg-subtle-hover-opaque
card 的 root 部件 background 覆盖槽。
--xh-card-borderrootborderdefault--xh-border-defaultcard 的 root 部件 border 覆盖槽。
--xh-card-content-fgcontentcolordefault--xh-fg-mutedcard 的 content 部件 color 覆盖槽。
--xh-card-content-font-sizecontentfont-sizedefault--xh-text-body-sizecard 的 content 部件 font-size 覆盖槽。
--xh-card-content-gapcontentgapdefault--xh-space-1card 的 content 部件 gap 覆盖槽。
--xh-card-description-fgdescriptioncolordefault--xh-fg-mutedcard 的 description 部件 color 覆盖槽。
--xh-card-description-font-sizedescriptionfont-sizedefault--xh-text-secondary-sizecard 的 description 部件 font-size 覆盖槽。
--xh-card-description-leadingdescriptionline-heightdefault--xh-leading-normalcard 的 description 部件 line-height 覆盖槽。
--xh-card-fgrootcolordefault--xh-fg-defaultcard 的 root 部件 color 覆盖槽。
--xh-card-font-sizerootfont-sizedefault--xh-text-label-sizecard 的 root 部件 font-size 覆盖槽。
--xh-card-footer-gapfootergapdefault--xh-space-2card 的 footer 部件 gap 覆盖槽。
--xh-card-gaprootgapdefault0card 的 root 部件 gap 覆盖槽。
--xh-card-glint-durationrootanimation@media (hover: hover) and (pointer: fine) and (forced-colors: none)
hover
interactive
material=liquid
where([data-material='liquid'])
--xh-motion-duration-glintcard 的 root 部件 animation 覆盖槽。
--xh-card-header-borderheader
root
border-block-enddefault--xh-border-subtlecard 的 header、root 部件 border-block-end 覆盖槽。
--xh-card-header-hheader
root
min-block-sizedefault--xh-surface-header-hcard 的 header、root 部件 min-block-size 覆盖槽。
--xh-card-header-pyheader
root
padding-blockdefault--xh-space-2card 的 header、root 部件 padding-block 覆盖槽。
--xh-card-leadingrootline-heightdefault--xh-text-body-leadingcard 的 root 部件 line-height 覆盖槽。
--xh-card-pcontent
footer
header
root
padding
padding-block-end
padding-inline
default--xh-space-4
--xh-surface-pad-lg
card 的 content、footer、header、root 部件 padding、padding-block-end、padding-inline 覆盖槽。
--xh-card-radiusroot
trigger
border-radiusdefault
interactive
--xh-shape-surfacecard 的 root、trigger 部件 border-radius 覆盖槽。
--xh-card-shadowrootbox-shadowdefault
variant=ghost
variant=subtle
--xh-elevation-raised
none
card 的 root 部件 box-shadow 覆盖槽。
--xh-card-shadow-hoverrootbox-shadowhover
interactive
variant=outline
--xh-elevation-liftedcard 的 root 部件 box-shadow 覆盖槽。
--xh-card-title-fgtitlecolordefault--xh-fg-defaultcard 的 title 部件 color 覆盖槽。
--xh-card-title-font-sizetitlefont-sizedefault--xh-text-heading-3-sizecard 的 title 部件 font-size 覆盖槽。
--xh-card-title-font-weighttitlefont-weightdefault--xh-text-heading-3-weightcard 的 title 部件 font-weight 覆盖槽。
--xh-card-title-leadingtitleline-heightdefault--xh-leading-tightcard 的 title 部件 line-height 覆盖槽。

动效 ​

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

可覆盖的动效槽:--xh-card-glint-duration。

background-color · box-shadow 走 transition 过渡。时长与缓动读动效令牌,改令牌即改全局节奏。

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

响应式 ​

皮肤另按输入能力分档:hover: hover:同一份皮肤在触屏与带指针的设备上不一样,与视口宽度无关。

RTL ​

皮肤用逻辑属性排布(inline-start 一族),dir="rtl" 下自动镜像;只认物理方向的量乘 --xh-direction-sign 换向,按就近的 dir 走。

Released under The MIT License