Card 卡片

Card 卡片

常规的卡片容器,可以承载标题、段落、图片、列表等内容。

支持两种使用方式:配置式(通过 props 驱动)和复合式(通过子组件组装)。

何时使用

  • 需要承载多个内容元素时。
  • 需要分组展示信息时。
  • 需要配合栅格布局展示信息卡片时。

导入

import {
  Card,
  CardHeader,
  CardTitle,
  CardDescription,
  CardContent,
  CardFooter,
  CardMeta,
  CardGroup,
} from "@reglow/reui";

两种使用方式

方式一:配置式(props 驱动)

通过 title、cover、footer 等 props 配置卡片结构,适合数据驱动的场景:

<script setup>
import { Card } from "@reglow/reui";
</script>

<template>
  <Card title="标题" header-extra-content="更多" style="max-width: 360px">
    <p>卡片内容</p>
  </Card>
</template>

方式二:复合式(子组件组装)

通过 CardHeader、CardContent 等子组件手动组装,适合自定义结构的场景:

<script setup>
import {
  Card,
  CardHeader,
  CardTitle,
  CardDescription,
  CardContent,
  CardFooter,
} from "@reglow/reui";
</script>

<template>
  <Card style="max-width: 360px">
    <CardHeader>
      <CardTitle>标题</CardTitle>
      <CardDescription>描述文字</CardDescription>
    </CardHeader>
    <CardContent>
      <p>卡片内容</p>
    </CardContent>
    <CardFooter>
      <p>页脚</p>
    </CardFooter>
  </Card>
</template>

Card 会自动检测模式:当传入 title、cover、footer、loading 等配置 props 或具名插槽时使用配置式,否则使用复合式(纯容器 + 默认插槽)。复合式默认带阴影。

代码演示

基础卡片

包含标题、内容和标题右侧额外内容。

<script setup>
import { Card } from "@reglow/reui";
</script>

<template>
  <Card
    title="Semi Design"
    style="max-width: 360px"
    header-extra-content="更多"
  >
    <p>Semi Design 是由抖音前端团队与 UED 团队共同设计开发并维护的设计系统。</p>
  </Card>
</template>

简洁卡片

只设置内容区域。

<script setup>
import { Card } from "@reglow/reui";
</script>

<template>
  <Card style="max-width: 360px">
    <p>Semi Design 是由抖音前端团队与 UED 团队共同设计开发并维护的设计系统。</p>
  </Card>
</template>

封面

通过 cover 设置封面。

<script setup>
import { Card, CardMeta } from "@reglow/reui";
import { h } from "vue";
</script>

<template>
  <Card
    style="max-width: 300px"
    :cover="h('img', { src: 'https://picsum.photos/300/200', alt: 'cover' })"
  >
    <CardMeta title="卡片封面" />
  </Card>
</template>

边线和外边框

通过 bordered 设置外边框,headerLine / footerLine 设置边线。

<script setup>
import { Card } from "@reglow/reui";
</script>

<template>
  <Card
    style="max-width: 360px"
    :bordered="false"
    :header-line="true"
    title="Semi Design"
  >
    <p>无边框卡片,标题区有边线。</p>
  </Card>
</template>

阴影

通过 shadows 设置显示阴影的时机。

<script setup>
import { Card } from "@reglow/reui";
</script>

<template>
  <!-- hover 时显示阴影 -->
  <Card shadows="hover" style="max-width: 360px">
    <p>鼠标悬停时显示阴影。</p>
  </Card>

  <!-- 始终显示阴影 -->
  <Card shadows="always" style="max-width: 360px">
    <p>始终显示阴影。</p>
  </Card>
</template>

更灵活的内容展示

利用 CardMeta 设置 title、description、avatar。

<script setup>
import { Card, CardMeta } from "@reglow/reui";
import { h } from "vue";
</script>

<template>
  <Card style="max-width: 340px">
    <CardMeta
      title="Semi Doc"
      description="全面、易用、优质"
      :avatar="
        h('img', {
          src: 'https://picsum.photos/40/40',
          class: 'w-10 h-10 rounded-full',
        })
      "
    />
  </Card>
</template>

内部卡片

卡片嵌套。

<script setup>
import { Card } from "@reglow/reui";
</script>

<template>
  <Card title="Card title">
    <Card title="Inner Card title" class="mb-4" header-extra-content="更多">
      <p>Inner Card content</p>
    </Card>
    <Card title="Inner Card title" header-extra-content="更多">
      <p>Inner Card content</p>
    </Card>
  </Card>
</template>

内置预加载

通过 loading 显示占位元素。

<script setup>
import { ref } from "vue";
import { Card, CardMeta } from "@reglow/reui";

const loading = ref(true);
</script>

<template>
  <Card :loading="loading" style="max-width: 360px">
    <CardMeta title="Semi Doc" description="全面、易用、优质" />
  </Card>
</template>

带页签的卡片

结合 Tabs 组件。

<script setup>
import { ref } from "vue";
import { Card } from "@reglow/reui";
import { Tabs } from "@reglow/reui";

const activeKey = ref("1");
const tabList = [
  { itemKey: "1", tab: "Tab 1" },
  { itemKey: "2", tab: "Tab 2" },
];
</script>

<template>
  <Card title="Card title">
    <Tabs v-model:active-key="activeKey" :tab-list="tabList">
      <div v-if="activeKey === '1'">content1</div>
      <div v-if="activeKey === '2'">content2</div>
    </Tabs>
  </Card>
</template>

卡片操作区

通过 actions 设置操作区。

<script setup>
import { h } from "vue";
import { Card, CardMeta } from "@reglow/reui";
import { Button } from "@reglow/reui";

const actions = [
  h(Button, { variant: "ghost", size: "sm" }, () => "收藏"),
  h(Button, { variant: "ghost", size: "sm" }, () => "分享"),
];
</script>

<template>
  <Card style="max-width: 300px" :actions="actions" :header-line="false">
    <CardMeta title="Semi Doc" description="全面、易用、优质" />
  </Card>
</template>

卡片组

CardGroup 中的卡片等间距排列。

<script setup>
import { ref } from "vue";
import { Card, CardGroup } from "@reglow/reui";

const spacing = ref(12);
</script>

<template>
  <CardGroup :spacing="spacing">
    <Card
      v-for="i in 8"
      :key="i"
      shadows="hover"
      title="Card title"
      :header-line="false"
      style="width: 260px"
    >
      <p>Card content</p>
    </Card>
  </CardGroup>
</template>

网格型卡片组

设置 type="grid" 将卡片组设置为网格型。

<template>
  <CardGroup type="grid" :spacing="16">
    <Card
      v-for="i in 7"
      :key="i"
      shadows="hover"
      title="Card title"
      :header-line="false"
    >
      <p>Card content</p>
    </Card>
  </CardGroup>
</template>

使用 Slot

<template>
  <Card>
    <template #header>
      <div class="flex items-center gap-2">
        <span>自定义头部</span>
      </div>
    </template>
    <template #cover>
      <img src="https://picsum.photos/360/200" alt="cover" class="w-full" />
    </template>
    <p>内容区域</p>
    <template #footer>
      <div>页脚内容</div>
    </template>
  </Card>
</template>

API

Card Props

参数说明类型默认值
title标题(配置式)VNode | string-
headerExtraContent标题右侧额外内容VNode | string-
header自定义头部(覆盖 title 和 headerExtraContent)VNode | string-
cover封面VNode | string-
footer页脚VNode | string-
actions操作区(位于内容区底部)(VNode | string)[]-
bordered是否有外边框booleantrue
headerLine标题区与内容区是否有边线booleantrue
footerLine页脚区与内容区是否有边线booleanfalse
loading加载占位booleanfalse
shadows阴影时机hover | always-
headerStyle标题区样式CSSProperties-
bodyStyle内容区样式CSSProperties-
footerStyle页脚区样式CSSProperties-
class附加类名string-
style附加样式CSSProperties-

当未传入 title、cover、footer、header、actions、headerExtraContent、loading 且未使用对应具名插槽时,Card 自动切换为复合式模式,仅渲染容器 + 默认插槽,默认带阴影。

Card Slots

名称说明
default内容(配置式为内容区,复合式为整个插槽)
header自定义头部(覆盖 title/headerExtraContent)
title标题
headerExtraContent标题右侧额外内容
cover封面
footer页脚
actions操作区

CardHeader Props

参数说明类型默认值
class附加类名string-

CardTitle Props

参数说明类型默认值
class附加类名string-

CardDescription Props

参数说明类型默认值
class附加类名string-

CardContent Props

参数说明类型默认值
class附加类名string-

CardFooter Props

参数说明类型默认值
class附加类名string-

CardGroup Props

参数说明类型默认值
spacing间距尺寸(数值或 水平, 垂直)number | number[]12
type类型,设为 grid 开启网格布局string-
class附加类名string-
style附加样式CSSProperties-

CardMeta Props

参数说明类型默认值
title标题VNode | string-
description描述VNode | string-
avatar头像VNode | string-
titleClass标题附加类名string-
descriptionClass描述附加类名string-
class附加类名string-
style附加样式CSSProperties-

CardMeta Slots

名称说明
default额外内容
title标题
description描述
avatar头像

Accessibility

  • Card 支持 aria-label 表示作用
  • loading 时开启 aria-busy
  • Card 为容器型组件,内部元素需遵循各自的可访问性指南