Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(Card): icon prop #6683

Merged
merged 1 commit into from
Jul 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/components/card/card.less
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
display: flex;
justify-content: space-between;
align-items: center;
gap: var(--adm-card-header-gap, 8px);
box-sizing: border-box;
padding: var(--adm-card-header-padding-block, 12px) 0;
&:not(:last-child) {
Expand Down
6 changes: 6 additions & 0 deletions src/components/card/card.patch.less
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,12 @@
&-title {
font-size: 15px;
}
&-icon {
margin-right: 8px;
}
&-extra {
margin-left: 8px;
}
}
&-body {
padding: 12px 0;
Expand Down
12 changes: 9 additions & 3 deletions src/components/card/card.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import React from 'react'
import type { FC, ReactNode, CSSProperties } from 'react'
import classNames from 'classnames'
import type { CSSProperties, FC, ReactNode } from 'react'
import React from 'react'
import { NativeProps, withNativeProps } from '../../utils/native-props'

const classPrefix = `adm-card`

export type CardProps = {
title?: ReactNode
icon?: ReactNode
extra?: ReactNode
headerStyle?: CSSProperties
headerClassName?: string
Expand All @@ -29,8 +30,13 @@ export const Card: FC<CardProps> = props => {
style={props.headerStyle}
onClick={props.onHeaderClick}
>
{props.icon && (
<div className={`${classPrefix}-header-icon`}>{props.icon}</div>
)}
<div className={`${classPrefix}-header-title`}>{props.title}</div>
{props.extra}
{props.extra && (
<div className={`${classPrefix}-header-extra`}>{props.extra}</div>
)}
</div>
)
}
Expand Down
14 changes: 5 additions & 9 deletions src/components/card/demos/demo1.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from 'react'
import { Card, Toast, Button } from 'antd-mobile'
import { DemoBlock } from 'demos'
import { Button, Card, Toast } from 'antd-mobile'
import { AntOutline, RightOutline } from 'antd-mobile-icons'
import { DemoBlock } from 'demos'
import React from 'react'

import styles from './demo1.less'

Expand Down Expand Up @@ -35,12 +35,8 @@ export default () => {

<DemoBlock title='自定义卡片内容' background='gray'>
<Card
title={
<div style={{ fontWeight: 'normal' }}>
<AntOutline style={{ marginRight: '4px', color: '#1677ff' }} />
卡片标题
</div>
}
icon={<AntOutline style={{ color: '#1677ff' }} />}
title={<div style={{ fontWeight: 'normal' }}>卡片标题</div>}
extra={<RightOutline />}
onBodyClick={onBodyClick}
onHeaderClick={onHeaderClick}
Expand Down
40 changes: 21 additions & 19 deletions src/components/card/index.en.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,25 +14,27 @@ It can carry text, lists, pictures, paragraphs, etc., which is convenient for us

### Props

| Name | Description | Type | Default |
| --- | --- | --- | --- |
| bodyClassName | The custom class name of the body | `string` | - |
| bodyStyle | The custom style of the body | `React.CSSProperties` | - |
| extra | The right area of the header | `ReactNode` | - |
| headerClassName | The custom class name of the header | `string` | - |
| headerStyle | The custom style of the header | `React.CSSProperties` | - |
| onBodyClick | The click event of the body area | `(event: React.MouseEvent<HTMLDivElement, MouseEvent>) => void` | - |
| onClick | The click event of the Card | `(event: React.MouseEvent<HTMLDivElement, MouseEvent>) => void` | - |
| onHeaderClick | The click event of the header area | `(event: React.MouseEvent<HTMLDivElement, MouseEvent>) => void` | - |
| title | The left area of the header | `ReactNode` | - |
| Name | Description | Type | Default | Version |
| --- | --- | --- | --- | --- |
| bodyClassName | The custom class name of the body | `string` | - | |
| bodyStyle | The custom style of the body | `React.CSSProperties` | - | |
| extra | The right area of the header | `ReactNode` | - | |
| headerClassName | The custom class name of the header | `string` | - | |
| headerStyle | The custom style of the header | `React.CSSProperties` | - | |
| icon | The left icon of the header | `ReactNode` | - | 5.38.0 |
| onBodyClick | The click event of the body area | `(event: React.MouseEvent<HTMLDivElement, MouseEvent>) => void` | - | |
| onClick | The click event of the Card | `(event: React.MouseEvent<HTMLDivElement, MouseEvent>) => void` | - | |
| onHeaderClick | The click event of the header area | `(event: React.MouseEvent<HTMLDivElement, MouseEvent>) => void` | - | |
| title | The left area of the header | `ReactNode` | - | |

### CSS Variables

| Name | Description | Default | Global |
| --- | --- | --- | --- |
| `--adm-card-border-radius` | Border radius of the button. | `8px` | `--adm-card-border-radius` |
| `--adm-card-padding-inline` | Horizontal padding of the card. | `12px` | `--adm-card-padding-inline` |
| `--adm-card-header-border-width` | Bottom border width of the card header. | `0.5px` | `--adm-card-header-border-width` |
| `--adm-card-header-border-color` | Bottom border color of the card header. | `var(--adm-color-border)` | `--adm-card-header-border-color` |
| `--adm-card-header-padding-block` | Vertical of the card header. | `12px` | `--adm-card-header-padding-block` |
| `--adm-card-body-padding-block` | Vertical padding of the card body. | `12px` | `--adm-card-body-padding-block` |
| Name | Description | Default | Global | Version |
| --- | --- | --- | --- | --- |
| `--adm-card-border-radius` | Border radius of the button. | `8px` | `--adm-card-border-radius` | |
| `--adm-card-padding-inline` | Horizontal padding of the card. | `12px` | `--adm-card-padding-inline` | |
| `--adm-card-header-border-width` | Bottom border width of the card header. | `0.5px` | `--adm-card-header-border-width` | |
| `--adm-card-header-border-color` | Bottom border color of the card header. | `var(--adm-color-border)` | `--adm-card-header-border-color` | |
| `--adm-card-header-gap` | Horizontal gap of the card header. | `8px` | `--adm-card-header-gap` | 5.38.0 |
| `--adm-card-header-padding-block` | Vertical of the card header. | `12px` | `--adm-card-header-padding-block` | |
| `--adm-card-body-padding-block` | Vertical padding of the card body. | `12px` | `--adm-card-body-padding-block` | |
40 changes: 21 additions & 19 deletions src/components/card/index.zh.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,25 +14,27 @@

### 属性

| 属性 | 说明 | 类型 | 默认值 |
| --- | --- | --- | --- |
| bodyClassName | body 自定义类名 | `string` | - |
| bodyStyle | body 自定义样式 | `React.CSSProperties` | - |
| extra | header 右边区域 | `ReactNode` | - |
| headerClassName | header 自定义类名 | `string` | - |
| headerStyle | header 自定义样式 | `React.CSSProperties` | - |
| onBodyClick | body 区域点击事件 | `(event: React.MouseEvent<HTMLDivElement, MouseEvent>) => void` | - |
| onClick | 卡片点击事件 | `(event: React.MouseEvent<HTMLDivElement, MouseEvent>) => void` | - |
| onHeaderClick | header 区域点击事件 | `(event: React.MouseEvent<HTMLDivElement, MouseEvent>) => void` | - |
| title | header 左边区域 | `ReactNode` | - |
| 属性 | 说明 | 类型 | 默认值 | 版本 |
| --- | --- | --- | --- | --- |
| bodyClassName | body 自定义类名 | `string` | - | |
| bodyStyle | body 自定义样式 | `React.CSSProperties` | - | |
| extra | header 右边区域 | `ReactNode` | - | |
| headerClassName | header 自定义类名 | `string` | - | |
| headerStyle | header 自定义样式 | `React.CSSProperties` | - | |
| icon | header 左边图标 | `ReactNode` | - | 5.38.0 |
| onBodyClick | body 区域点击事件 | `(event: React.MouseEvent<HTMLDivElement, MouseEvent>) => void` | - | |
| onClick | 卡片点击事件 | `(event: React.MouseEvent<HTMLDivElement, MouseEvent>) => void` | - | |
| onHeaderClick | header 区域点击事件 | `(event: React.MouseEvent<HTMLDivElement, MouseEvent>) => void` | - | |
| title | header 左边区域 | `ReactNode` | - | |

### CSS 变量

| 属性 | 说明 | 默认值 | 全局变量 |
| --- | --- | --- | --- |
| `--adm-card-border-radius` | 圆角大小 | `8px` | `--adm-card-border-radius` |
| `--adm-card-padding-inline` | 水平内边距 | `12px` | `--adm-card-padding-inline` |
| `--adm-card-header-border-width` | header 分割线宽度 | `0.5px` | `--adm-card-header-border-width` |
| `--adm-card-header-border-color` | header 分割线颜色 | `var(--adm-color-border)` | `--adm-card-header-border-color` |
| `--adm-card-header-padding-block` | header 垂直内边距 | `12px` | `--adm-card-header-padding-block` |
| `--adm-card-body-padding-block` | body 垂直内边距 | `12px` | `--adm-card-body-padding-block` |
| 属性 | 说明 | 默认值 | 全局变量 | 版本 |
| --- | --- | --- | --- | --- |
| `--adm-card-border-radius` | 圆角大小 | `8px` | `--adm-card-border-radius` | |
| `--adm-card-padding-inline` | 水平内边距 | `12px` | `--adm-card-padding-inline` | |
| `--adm-card-header-border-width` | header 分割线宽度 | `0.5px` | `--adm-card-header-border-width` | |
| `--adm-card-header-border-color` | header 分割线颜色 | `var(--adm-color-border)` | `--adm-card-header-border-color` | |
| `--adm-card-header-gap` | header 水平间隙 | `8px` | `--adm-card-header-gap` | 5.38.0 |
| `--adm-card-header-padding-block` | header 垂直内边距 | `12px` | `--adm-card-header-padding-block` | |
| `--adm-card-body-padding-block` | body 垂直内边距 | `12px` | `--adm-card-body-padding-block` | |
25 changes: 11 additions & 14 deletions src/components/card/tests/card.test.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { RightOutline } from 'antd-mobile-icons'
import * as React from 'react'
import { fireEvent, render, testA11y, waitFor } from 'testing'
import { AppOutline, RightOutline } from 'antd-mobile-icons'
import Card from '../'

const classPrefix = `adm-card`
Expand All @@ -10,9 +10,9 @@ it('passes a11y test', async () => {
})

test('renders with title', () => {
const { getByText } = render(<Card title='title'>Card</Card>)
const { getByText } = render(<Card title='title'>body</Card>)
expect(getByText('title')).toHaveClass(`${classPrefix}-header-title`)
expect(getByText('Card')).toHaveClass(`${classPrefix}-body`)
expect(getByText('body')).toHaveClass(`${classPrefix}-body`)
})

test('renders with event', async () => {
Expand All @@ -21,32 +21,29 @@ test('renders with event', async () => {

const { getByText } = render(
<Card
title={
<div style={{ fontWeight: 'normal' }}>
<AppOutline style={{ marginRight: '4px', color: '#1677ff' }} />
卡片标题
</div>
}
icon='icon'
title='title'
extra={<RightOutline />}
onBodyClick={onBodyClick}
onHeaderClick={onHeaderClick}
>
Card
body
</Card>
)
fireEvent.click(getByText('卡片标题'))
fireEvent.click(getByText('title'))
fireEvent.click(getByText('icon'))
await waitFor(() => {
expect(onHeaderClick).toBeCalledTimes(1)
expect(onHeaderClick).toBeCalledTimes(2)
})
fireEvent.click(getByText('Card'))
fireEvent.click(getByText('body'))
await waitFor(() => {
expect(onBodyClick).toBeCalledTimes(1)
})
})

test('renders without children', async () => {
const { getByTestId } = render(
<Card title={'标题'} data-testid='test-card-id' />
<Card title='title' data-testid='test-card-id' />
)
expect(getByTestId('test-card-id')).not.toHaveClass(`${classPrefix}-body`)
})
Loading