独立成篇、可单独发布的内容使用 article
サクラノ詩
连载中转学第一天,我在天台遇见了那个抱着旧相机的少女。
全 12 卷
<script setup lang="ts">
import { Button, Card, Divider, Heading, Inline, Stack, Tag, Text } from '@hina-ui/vue'
</script>
<template>
<Card class="w-full max-w-sm">
<Stack>
<Stack gap="xs">
<Inline justify="between" align="start" :wrap="false">
<Heading :level="3" size="md">サクラノ詩</Heading>
<Tag tone="success">连载中</Tag>
</Inline>
<Text tone="muted" size="sm">转学第一天,我在天台遇见了那个抱着旧相机的少女。</Text>
</Stack>
<Divider />
<Inline justify="between">
<Text tone="faint" size="sm">全 12 卷</Text>
<Button variant="ghost" tone="neutral" size="sm">查看</Button>
</Inline>
</Stack>
</Card>
</template>
用法
import { Card } from '@hina-ui/vue'
卡片由三部分构成视觉:自身的背景色、一条细边框,以及一层静止状态的阴影,三者共同使它比页面底色高出一层。内容置于默认插槽中。
卡片自带背景色、一条细边框与一层阴影,内容置于默认插槽中。
<script setup lang="ts">
import { Card, Text } from '@hina-ui/vue'
</script>
<template>
<Card class="w-full max-w-sm">
<Text>卡片自带背景色、一条细边框与一层阴影,内容置于默认插槽中。</Text>
</Card>
</template>
卡片只负责这一层容器,不决定其中内容如何排布。内容的方向与间距应交由 Stack、Inline 等布局组件处理。
示例
内边距
卡片默认带有内边距,取值随密度变化。图片、表格等需要贴合卡片边缘的内容,应将 padded 设为 false,再由内部容器提供内边距。此时卡片会裁去溢出的部分,贴边内容的直角不会盖住卡片的圆角。
通向车站的那条坡道
图片贴合卡片边缘,内边距改由内部容器提供。
<script setup lang="ts">
import { Card, Heading, Image, Stack, Text } from '@hina-ui/vue'
</script>
<template>
<Card :padded="false" class="w-full max-w-sm overflow-hidden">
<Image src="/sample.webp" alt="夏日午后的坡道" class="h-32 w-full" />
<Stack gap="xs" class="p-[var(--hn-panel-p)]">
<Heading :level="3" size="base">通向车站的那条坡道</Heading>
<Text tone="muted" size="sm">图片贴合卡片边缘,内边距改由内部容器提供。</Text>
</Stack>
</Card>
</template>
若内容需要随圆角一同裁切,为卡片添加 overflow-hidden。
语义标签
as 用于指定渲染的标签,默认为 div,仅在需要更准确的语义时替换:独立成篇的内容使用 article,页面中的一个区块使用 section;一组卡片构成列表时,容器使用 ul,每张卡片使用 li。
页面中的一个区块使用 section
<script setup lang="ts">
import { Card, Stack, Text } from '@hina-ui/vue'
</script>
<template>
<Stack class="w-full max-w-sm">
<Card as="article">
<Text>独立成篇、可单独发布的内容使用 article</Text>
</Card>
<Card as="section">
<Text>页面中的一个区块使用 section</Text>
</Card>
</Stack>
</template>
可点击的卡片
卡片自身不带任何可点击的样式,既不会在悬停时改变颜色,也不会提升阴影层级。需要整张卡片可点击时,由调用方组合实现:as="button" 替换标签,hn-interactive 提供指针样式与焦点环,hn-state-layer 提供悬停时的状态层,hn-press-lg 将按压时的缩放幅度调整为适合大面积元素的档位,另置入一个 Ripple。
<script setup lang="ts">
import { Card, Heading, Ripple, Stack, Text } from '@hina-ui/vue'
</script>
<template>
<Card as="button" class="hn-interactive hn-state-layer hn-press-lg w-full max-w-sm text-start">
<Ripple />
<Stack gap="xs">
<Heading :level="3" size="base">整张卡片都是可点击区域</Heading>
<Text tone="muted" size="sm">悬停时的状态层与按下时的波纹均由调用方添加。</Text>
</Stack>
</Card>
</template>
若卡片中仅有局部可点击,则不应如此处理:应在该处放置 Button 或 Link,卡片本身保持静态。
密度
内边距取自密度 token,因此在任意祖先元素上设置 data-density="compact",其范围内的卡片都会随之收紧,无需向卡片传入参数。
comfortable
内边距 20px
compact
内边距 14px
<script setup lang="ts">
import { Card, Inline, Stack, Text } from '@hina-ui/vue'
</script>
<template>
<Inline align="start" class="w-full max-w-lg">
<Card class="flex-1">
<Stack gap="xs">
<Text size="sm" tone="faint">comfortable</Text>
<Text>内边距 20px</Text>
</Stack>
</Card>
<Card data-density="compact" class="flex-1">
<Stack gap="xs">
<Text size="sm" tone="faint">compact</Text>
<Text>内边距 14px</Text>
</Stack>
</Card>
</Inline>
</template>
无障碍
- 卡片默认渲染为
div,不带角色,屏幕阅读器按普通内容朗读。 - 整张卡片可点击时必须替换为
button或链接。不应为div绑定点击事件,那样键盘无法触达,屏幕阅读器也无法识别其为控件。 - 卡片内的标题使用
Heading,并选择恰当的level,使其衔接页面已有的标题层级。
API
Props
| 属性 | 类型 | 默认值 | 说明 |
|---|---|---|---|
padded | boolean | true | 是否带内边距,取值随密度变化;关闭时裁去溢出 |
as | string | 'div' | 渲染的标签 |
as-child | boolean | false | 不渲染自身标签,把样式合并到唯一的子元素 |
class | string | — | 追加至根元素的类名 |
Slots
| 插槽 | 说明 |
|---|---|
default | 卡片的内容 |