UNPKG

@douyinfe/semi-ui

Version:

A modern, comprehensive, flexible design system and UI library. Connect DesignOps & DevOps. Quickly build beautiful React apps. Maintained by Douyin-fe team.

731 lines (630 loc) 24 kB
--- localeCode: zh-CN order: 65 category: 展示类 title: Card 卡片 subTitle: 卡片 icon: doc-card brief: 常规的卡片容器,可以承载标题、段落、图片、列表等内容。 --- ## 代码演示 ### 如何引入 ```jsx import import { Card } from '@douyinfe/semi-ui'; ``` ### 基础卡片 基础卡片包含标题、内容等部分。 ```jsx live=true dir="column" import React from 'react'; import { Card, Typography } from '@douyinfe/semi-ui'; function Demo() { const { Text } = Typography; return ( <Card title='Semi Design' style={{ maxWidth: 360 }} headerExtraContent={ <Text link> 更多 </Text> } > Semi Design 是由抖音前端团队与 UED 团队共同设计开发并维护的设计系统。设计系统包含设计语言以及一整套可复用的前端组件,帮助设计师与开发者更容易地打造高质量的、用户体验一致的、符合设计规范的 Web 应用。 </Card> ); } ``` ### 简洁卡片 卡片可以只设置内容区域。 ```jsx live=true dir="column" import React from 'react'; import { Card, Popover, Avatar } from '@douyinfe/semi-ui'; import { IconInfoCircle } from '@douyinfe/semi-icons'; function Demo() { const { Meta } = Card; return ( <> <Card style={{ maxWidth: 360 }} > Semi Design 是由抖音前端团队与 UED 团队共同设计开发并维护的设计系统。 </Card> <br /> <Card style={{ maxWidth: 360 }} bodyStyle={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }} > <Meta title="Semi Doc" avatar={ <Avatar alt='Card meta img' size="default" src='https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/card-meta-avatar-docs-demo.jpg' /> } /> <Popover position='top' showArrow content={ <article style={{ padding: 6 }}> 这是一个 Card </article> } > <IconInfoCircle style={{ color: 'var(--semi-color-primary)' }}/> </Popover> </Card> </> ); } ``` ### 封面 可以使用 `cover` 属性设置封面。 ```jsx live=true dir="column" import React from 'react'; import { Card } from '@douyinfe/semi-ui'; function Demo() { const { Meta } = Card; return ( <Card style={{ maxWidth: 300 }} cover={ <img alt="example" src="https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/card-cover-docs-demo2.jpeg" /> } > <Meta title="卡片封面" /> </Card> ); } ``` ### 边线和外边框 可以使用 `bordered` 设置卡片是否有外边框,默认为 true 。同时,也可以使用 `headerLine` 设置内容区和标题区是否有边线, `footerLine` 设置内容区和页尾区是否有边线。 ```jsx live=true dir="column" import React from 'react'; import { Card } from '@douyinfe/semi-ui'; function Demo() { return ( <div style={{ display: 'inline-block', padding: 20, backgroundColor: 'var(--semi-color-fill-0)' }} > <Card style={{ maxWidth: 360 }} bordered={false} headerLine={true} title='Semi Design' > Semi Design 是由抖音前端团队与 UED 团队共同设计开发并维护的设计系统。设计系统包含设计语言以及一整套可复用的前端组件,帮助设计师与开发者更容易地打造高质量的、用户体验一致的、符合设计规范的 Web 应用。 </Card> </div> ); } ``` ### 阴影 可以使用 `shadows` 设置显示阴影的时机,可选值为: `hover`(hover 时显示阴影)、`always`(始终显示阴影),如果不设置该属性则没有阴影。 ```jsx live=true dir="column" import React from 'react'; import { Card, Avatar, Popover } from '@douyinfe/semi-ui'; import { IconInfoCircle } from '@douyinfe/semi-icons'; function Demo() { const { Meta } = Card; return ( <div> <Card shadows='hover' style={{ maxWidth: 360 }} bodyStyle={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }} > <Meta title="Semi Doc" avatar={ <Avatar alt='Card meta img' size="default" src='https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/card-meta-avatar-docs-demo.jpg' /> } /> <Popover position='top' showArrow content={ <article style={{ padding: 6 }}> 这是一个 Card </article> } > <IconInfoCircle style={{ color: 'var(--semi-color-primary)' }}/> </Popover> </Card> <br/> <Card shadows='always' style={{ maxWidth: 360 }} bodyStyle={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between' }} > <Meta title="Semi Doc" avatar={ <Avatar alt='Card meta img' size="default" src='https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/card-meta-avatar-docs-demo.jpg' /> } /> <Popover position='top' showArrow content={ <article style={{ padding: 6 }}> 这是一个 Card </article> } > <IconInfoCircle style={{ color: 'var(--semi-color-primary)' }}/> </Popover> </Card> </div> ); } ``` ### 更灵活的内容展示 可以利用 `Card.Meta` 支持更灵活的内容,允许设置 `title`、`avatar`、`description`。 ```jsx live=true dir="column" import React from 'react'; import { Card, Avatar, Space, Button, Typography } from '@douyinfe/semi-ui'; function Demo() { const { Meta } = Card; const { Text } = Typography; return ( <Card style={{ maxWidth: 340 }} title={ <Meta title="Semi Doc" description="全面、易用、优质" avatar={ <Avatar alt='Card meta img' size="default" src='https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/card-meta-avatar-docs-demo.jpg' /> } /> } headerExtraContent={ <Text link> More </Text> } cover={ <img alt="example" src="https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/card-cover-docs-demo.jpeg" /> } footerLine={ true } footerStyle={{ display: 'flex', justifyContent: 'flex-end' }} footer={ <Space> <Button theme='borderless' type='primary'>精选案例</Button> <Button theme='solid' type='primary'>开始使用</Button> </Space> } > Semi Design 是由抖音前端团队与 UED 团队共同设计开发并维护的设计系统。 </Card> ); } ``` ### 内部卡片 卡片内部可以嵌套其他卡片。 ```jsx live=true dir="column" import React from 'react'; import { Card, Typography } from '@douyinfe/semi-ui'; function Demo() { const { Text } = Typography; return ( <Card title='Card title' > <Card title='Inner Card title' style={{ marginBottom: 20 }} headerExtraContent={ <Text link> More </Text> } > Inner Card content </Card> <Card title='Inner Card title' headerExtraContent={ <Text link> More </Text> } > Inner Card content </Card> </Card> ); } ``` ### 栅格卡片 在系统概览页面常常和栅格进行配合。 ```jsx live=true dir="column" import React from 'react'; import { Card, Row, Col } from '@douyinfe/semi-ui'; function Demo() { return ( <div style={{ backgroundColor: 'var(--semi-color-fill-0)', padding: 20 }} > <Row gutter={[16, 16]}> <Col span={8}> <Card title='Card Title' bordered={false} > Card Content </Card> </Col> <Col span={8}> <Card title='Card Title' bordered={false} > Card Content </Card> </Col> <Col span={8}> <Card title='Card Title' bordered={false} > Card Content </Card> </Col> </Row> <Row gutter={[16, 16]}> <Col span={16}> <Card title='Card Title' bordered={false} > Card Content </Card> </Col> <Col span={8}> <Card title='Card Title' bordered={false} > Card Content </Card> </Col> </Row> </div> ); } ``` ### 内置预加载 可以使用 `Card` 的 `loading` 属性来设置卡片内容区是否显示占位元素,当它为 true 时将显示占位元素,反之则不显示。 ```jsx live=true dir="column" import React, { useState } from 'react'; import { Card, Switch } from '@douyinfe/semi-ui'; function Demo() { const [loading, setLoading] = useState(true); const { Meta } = Card; return ( <> <Switch onChange={ v => setLoading(!v) } /> <br /> <br /> <Card style={{ maxWidth: 360 }} loading={ loading } > <Meta title="Semi Doc" description="全面、易用、优质" /> </Card> </> ); } ``` ### 更丰富的预加载效果 `Card` 自带的 `loading` 属性只能设置内容区的预加载效果,如果你想要设置其他部分的预加载,或者自定义更丰富的预加载效果,你可以结合 Skeleton 组件来实现。 ```jsx live=true dir="column" import React, { useState } from 'react'; import { Card, Switch, Skeleton, Avatar, Typography } from '@douyinfe/semi-ui'; function Demo() { const [loading, setLoading] = useState(true); const { Meta } = Card; const { Title, Paragraph, Image } = Skeleton; return ( <> <Switch onChange={ v => setLoading(!v) } /> <br /> <br /> <Card style={{ maxWidth: 300 }} title={ <Meta title={ <Skeleton style={{ width: 80 }} placeholder={<Title />} loading={loading} > <Typography.Title heading={5}> Semi Doc </Typography.Title> </Skeleton> } description={ <Skeleton style={{ width: 150, marginTop: 12 }} placeholder={<Paragraph rows={1} />} loading={loading} > <Typography.Text> 全面、易用、优质 </Typography.Text> </Skeleton> } avatar={ <Skeleton placeholder={<Skeleton.Avatar />} loading={loading}> <Avatar alt='Card meta img' size="default" src='https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/card-meta-avatar-docs-demo.jpg' /> </Skeleton> } /> } headerExtraContent={ <Skeleton style={{ width: 50 }} placeholder={<Paragraph rows={1} />} loading={loading}> <Typography.Text link> More </Typography.Text> </Skeleton> } cover={ <Skeleton style={{ maxWidth: '100%', height: 220 }} placeholder={<Image />} loading={loading}> <img alt="example" src="https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/card-cover-docs-demo.jpeg" /> </Skeleton> } > </Card> </> ); } ``` ### 带页签的卡片 可以结合 Tabs 组件,实现带页签的卡片。 ```jsx live=true dir="column" import React from 'react'; import { Card, Tabs, TabPane } from '@douyinfe/semi-ui'; function demo() { return ( <Card title='Card title'> <Tabs type="line" style={{ marginTop: -20, marginBottom: -20 }} > <TabPane tab="Tab 1" itemKey="1"> <p>content1</p> <p>content1</p> <p>content1</p> </TabPane> <TabPane tab="Tab 2" itemKey="2"> <p>content2</p> <p>content2</p> <p>content2</p> </TabPane> </Tabs> </Card> ); } ``` ### 卡片操作区 `actions` 接收 ReactNode 数组,元素间将以 12px 的水平间距展示于内容区底部。 ```jsx live=true dir="column" import React from 'react'; import { Card, Rating } from '@douyinfe/semi-ui'; function Demo() { const { Meta } = Card; return ( <Card style={{ maxWidth: 300 }} actions={[ // eslint-disable-next-line react/jsx-key <Rating size='small' defaultValue={4}/> ]} headerLine={ false } cover={ <img alt="example" src="https://lf3-static.bytednsdoc.com/obj/eden-cn/ptlz_zlp/ljhwZthlaukjlkulzlp/root-web-sites/card-cover-docs-demo.jpeg" /> } > <Meta title="Semi Doc" description="全面、易用、优质" /> </Card> ); } ``` ### 卡片组 `CardGroup` 中的卡片将呈现为等间距排列,利用 `spacing` 属性可以设置卡片间距大小。 ```jsx live=true dir="column" import React, { useState } from 'react'; import { Card, CardGroup, Typography, Slider } from '@douyinfe/semi-ui'; function Demo() { const { Text } = Typography; const [ spacing, setSpacing ] = useState(12); return ( <> <Text>滑动调节 Card 间距</Text> <Slider defaultValue={12} max={40} min={10} style={{ width: 360 }} onChange={v=> setSpacing(v)} /> <br /> <CardGroup spacing={spacing}> { new Array(8).fill(null).map((v, idx)=>( <Card key={idx} shadows='hover' title='Card title' headerLine={false} style={{ width: 260 }} headerExtraContent={ <Text link> More </Text> } > <Text>Card content</Text> </Card> )) } </CardGroup> </> ); } ``` ### 网格型卡片组 使用 `CardGroup` 的 `type` 属性,可以将卡片组设置为网格型。 ```jsx live=true dir="column" import React from 'react'; import { Card, CardGroup, Typography } from '@douyinfe/semi-ui'; function Demo() { const { Text } = Typography; return ( <CardGroup type='grid'> { new Array(7).fill(null).map((v, idx)=>( <Card key={idx} shadows='hover' title='Card title' headerLine={false} style={{ width: 260 }} headerExtraContent={ <Text link> More </Text> } > <Text>Card content</Text> </Card> )) } </CardGroup> ); } ``` ### API 参考 **Card** |属性 |说明 |类型 |默认值 |版本 | |------------------|---------------------------------------------------------------|------------------|------|------| |actions |卡片操作组,位于卡片内容区的底部 |Array<ReactNode\> |- |-| |bodyStyle |卡片内容区内联样式 |CSSProperties |- |-| |bordered |是否设置卡片的外边框 |boolean |true |-| |className |卡片的样式类名 |string |- |-| |cover |卡片封面 |ReactNode |- |-| |headerExtraContent|卡片标题右侧的额外内容 |ReactNode |- |-| |footer |自定义卡片页脚 |ReactNode |- |-| |footerLine |卡片页脚区与内容区是否有边线 |boolean |false|-| |footerStyle |卡片页脚区内联样式 |CSSProperties |- |-| |header |自定义卡片头部,若传入将覆盖 `title` 和 `headerExtraContent` |ReactNode |- |-| |headerLine |卡片标题区与内容区是否有边线 |boolean |true |-| |headerStyle |卡片标题区内联样式 |CSSProperties |- |-| |loading |是否设置加载时的占位 |boolean |false |-| |shadows |设置显示阴影的时机,如果不设置该属性则没有阴影,可选值:`hover`、`always`|string |- |-| |style |卡片内联样式 |CSSProperties |- |-| |title |卡片标题 |ReactNode |- |-| **CardGroup** |属性 |说明 |类型 |默认值 |版本 | |---------|-------------------------------------------------------------------|------------------|------|------| |className|卡片组的样式类名 |string |- |-| |spacing |间距尺寸,支持数值或数组,数组形如: `[水平间距,垂直间距]` |number \| number[]|12px |-| |style |卡片组的内联样式 |CSSProperties |- |-| |type |可以把卡片组设置为网格型,设置完该属性后将覆盖 `spacing` 属性,可选值:`grid` |string |- |-| **Card.Meta** |属性 |说明 |类型 |默认值 |版本 | |-----------|------|-------------|- |------| |avatar |头像 |ReactNode |- |-| |className |类名 |string |- |-| |description|描述 |ReactNode |- |-| |style |内联样式|CSSProperties|- |-| |title |标题 |ReactNode |- |-| ## Accessibility - Card 支持传入 `aria-label` 来表示该 Card 作用 - Card loading 时,将开启 `aria-busy` - Card 为容器型组件,卡片内部的任何元素需要遵循各自的可访问性指南 ## 文案规范 - 卡片标题 - 卡片标题应具有信息描述性,聚焦最重要的信息 - 尽量将标题限制在 1 个短语或句段中 - 卡片标题应句子大小写书写 - 不要以标点符号结尾(除了问号) - 正文 - 可操作的:使用祈使句而不是“你可以”来描述正文,可以更好的告诉用户可以做什么 | ✅ 推荐用法 | ❌ 不推荐用法 | | --- | --- | | Get order progress for details | You can get order progress for details | - 总是优先说最重要的信息 - 使用 “Need to”而不是”must“ ## 设计变量 <DesignToken/> <!-- ## 相关物料 ```material 41,55,64,74,219,73,84,99,179 ``` --> ## 相关物料 <semi-material-list code="41, 179"></semi-material-list>