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