feat: desc support root level label & content style (#28613)

This commit is contained in:
二货机器人 2020-12-30 17:08:43 +08:00 committed by GitHub
parent 6ae70059c9
commit a211756e6b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 274 additions and 56 deletions

View File

@ -1,6 +1,7 @@
import * as React from 'react';
import { DescriptionsItemProps } from './Item';
import Cell from './Cell';
import { DescriptionsContext, DescriptionsContextProps } from '.';
interface CellConfig {
component: string | [string, string];
@ -12,7 +13,14 @@ interface CellConfig {
function renderCells(
items: React.ReactElement<DescriptionsItemProps>[],
{ colon, prefixCls, bordered }: RowProps,
{ component, type, showLabel, showContent }: CellConfig,
{
component,
type,
showLabel,
showContent,
labelStyle: rootLabelStyle,
contentStyle: rootContentStyle,
}: CellConfig & DescriptionsContextProps,
) {
return items.map(
(
@ -37,8 +45,8 @@ function renderCells(
key={`${type}-${key || index}`}
className={className}
style={style}
labelStyle={labelStyle}
contentStyle={contentStyle}
labelStyle={{ ...rootLabelStyle, ...labelStyle }}
contentStyle={{ ...rootContentStyle, ...contentStyle }}
span={span}
colon={colon}
component={component}
@ -54,7 +62,7 @@ function renderCells(
<Cell
key={`label-${key || index}`}
className={className}
style={{ ...style, ...labelStyle }}
style={{ ...rootLabelStyle, ...style, ...labelStyle }}
span={1}
colon={colon}
component={component[0]}
@ -65,7 +73,7 @@ function renderCells(
<Cell
key={`content-${key || index}`}
className={className}
style={{ ...style, ...contentStyle }}
style={{ ...rootContentStyle, ...style, ...contentStyle }}
span={span * 2 - 1}
component={component[1]}
itemPrefixCls={itemPrefixCls}
@ -87,18 +95,26 @@ export interface RowProps {
}
const Row: React.FC<RowProps> = props => {
const descContext = React.useContext(DescriptionsContext);
const { prefixCls, vertical, row, index, bordered } = props;
if (vertical) {
return (
<>
<tr key={`label-${index}`} className={`${prefixCls}-row`}>
{renderCells(row, props, { component: 'th', type: 'label', showLabel: true })}
{renderCells(row, props, {
component: 'th',
type: 'label',
showLabel: true,
...descContext,
})}
</tr>
<tr key={`content-${index}`} className={`${prefixCls}-row`}>
{renderCells(row, props, {
component: 'td',
type: 'content',
showContent: true,
...descContext,
})}
</tr>
</>
@ -112,6 +128,7 @@ const Row: React.FC<RowProps> = props => {
type: 'item',
showLabel: true,
showContent: true,
...descContext,
})}
</tr>
);

View File

@ -960,6 +960,165 @@ Array [
</table>
</div>
</div>,
<div
class="ant-divider ant-divider-horizontal"
role="separator"
/>,
<div
class="ant-descriptions"
>
<div
class="ant-descriptions-header"
>
<div
class="ant-descriptions-title"
>
Root style
</div>
</div>
<div
class="ant-descriptions-view"
>
<table>
<tbody>
<tr
class="ant-descriptions-row"
>
<td
class="ant-descriptions-item"
colspan="1"
>
<div
class="ant-descriptions-item-container"
>
<span
class="ant-descriptions-item-label"
style="background:red"
>
Product
</span>
<span
class="ant-descriptions-item-content"
style="background:green"
>
Cloud Database
</span>
</div>
</td>
<td
class="ant-descriptions-item"
colspan="1"
>
<div
class="ant-descriptions-item-container"
>
<span
class="ant-descriptions-item-label"
style="background:red"
>
Billing Mode
</span>
<span
class="ant-descriptions-item-content"
style="background:green"
>
Prepaid
</span>
</div>
</td>
<td
class="ant-descriptions-item"
colspan="1"
>
<div
class="ant-descriptions-item-container"
>
<span
class="ant-descriptions-item-label"
style="background:red;color:orange"
>
Automatic Renewal
</span>
<span
class="ant-descriptions-item-content"
style="background:green;color:blue"
>
YES
</span>
</div>
</td>
</tr>
</tbody>
</table>
</div>
</div>,
<div
class="ant-descriptions ant-descriptions-bordered"
>
<div
class="ant-descriptions-header"
>
<div
class="ant-descriptions-title"
>
Root style
</div>
</div>
<div
class="ant-descriptions-view"
>
<table>
<tbody>
<tr
class="ant-descriptions-row"
>
<th
class="ant-descriptions-item-label"
colspan="1"
style="background:red"
>
Product
</th>
<td
class="ant-descriptions-item-content"
colspan="1"
style="background:green"
>
Cloud Database
</td>
<th
class="ant-descriptions-item-label"
colspan="1"
style="background:red"
>
Billing Mode
</th>
<td
class="ant-descriptions-item-content"
colspan="1"
style="background:green"
>
Prepaid
</td>
<th
class="ant-descriptions-item-label"
colspan="1"
style="background:red;color:orange"
>
Automatic Renewal
</th>
<td
class="ant-descriptions-item-content"
colspan="1"
style="background:green;color:blue"
>
YES
</td>
</tr>
</tbody>
</table>
</div>
</div>,
]
`;

View File

@ -15,28 +15,53 @@ debug: true
Customize label & wrapper style
```tsx
import { Descriptions } from 'antd';
import { Descriptions, Divider } from 'antd';
const labelStyle: React.CSSProperties = { background: 'red' };
const contentStyle: React.CSSProperties = { background: 'green' };
function renderCelledDesc(bordered?: boolean) {
return (
<Descriptions title="User Info" bordered={bordered}>
<Descriptions.Item label="Product" labelStyle={labelStyle} contentStyle={contentStyle}>
Cloud Database
</Descriptions.Item>
<Descriptions.Item label="Billing Mode">Prepaid</Descriptions.Item>
<Descriptions.Item label="Automatic Renewal">YES</Descriptions.Item>
</Descriptions>
);
}
function renderRootDesc(bordered?: boolean) {
return (
<Descriptions
title="Root style"
labelStyle={labelStyle}
contentStyle={contentStyle}
bordered={bordered}
>
<Descriptions.Item label="Product">Cloud Database</Descriptions.Item>
<Descriptions.Item label="Billing Mode">Prepaid</Descriptions.Item>
<Descriptions.Item
label="Automatic Renewal"
labelStyle={{ color: 'orange' }}
contentStyle={{ color: 'blue' }}
>
YES
</Descriptions.Item>
</Descriptions>
);
}
ReactDOM.render(
<>
<Descriptions title="User Info">
<Descriptions.Item label="Product" labelStyle={labelStyle} contentStyle={contentStyle}>
Cloud Database
</Descriptions.Item>
<Descriptions.Item label="Billing Mode">Prepaid</Descriptions.Item>
<Descriptions.Item label="Automatic Renewal">YES</Descriptions.Item>
</Descriptions>
{renderCelledDesc()}
{renderCelledDesc(true)}
<Descriptions title="User Info" bordered>
<Descriptions.Item label="Product" labelStyle={labelStyle} contentStyle={contentStyle}>
Cloud Database
</Descriptions.Item>
<Descriptions.Item label="Billing Mode">Prepaid</Descriptions.Item>
<Descriptions.Item label="Automatic Renewal">YES</Descriptions.Item>
</Descriptions>
<Divider />
{renderRootDesc()}
{renderRootDesc(true)}
</>,
mountNode,
);

View File

@ -21,7 +21,9 @@ Commonly displayed on the details page.
| bordered | Whether to display the border | boolean | false | |
| colon | Change default props `colon` value of Descriptions.Item | boolean | true | |
| column | The number of `DescriptionItems` in a row,could be a number or a object like `{ xs: 8, sm: 16, md: 24}`,(Only set `bordered={true}` to take effect) | number | 3 | |
| contentStyle | Customize label style | CSSProperties | - | 4.10.0 |
| extra | The action area of the description list, placed at the top-right | ReactNode | - | 4.5.0 |
| labelStyle | Customize label style | CSSProperties | - | 4.10.0 |
| layout | Define description layout | `horizontal` \| `vertical` | `horizontal` | |
| size | Set the size of the list. Can be set to `middle`,`small`, or not filled | `default` \| `middle` \| `small` | - | |
| title | The title of the description list, placed at the top | ReactNode | - | |

View File

@ -13,6 +13,13 @@ import Row from './Row';
import DescriptionsItem from './Item';
import { cloneElement } from '../_util/reactNode';
export interface DescriptionsContextProps {
labelStyle?: React.CSSProperties;
contentStyle?: React.CSSProperties;
}
export const DescriptionsContext = React.createContext<DescriptionsContextProps>({});
const DEFAULT_COLUMN_MAP: Record<Breakpoint, number> = {
xxl: 3,
xl: 3,
@ -104,6 +111,8 @@ export interface DescriptionsProps {
column?: number | Partial<Record<Breakpoint, number>>;
layout?: 'horizontal' | 'vertical';
colon?: boolean;
labelStyle?: React.CSSProperties;
contentStyle?: React.CSSProperties;
}
function Descriptions({
@ -118,6 +127,8 @@ function Descriptions({
className,
style,
size,
labelStyle,
contentStyle,
}: DescriptionsProps) {
const { getPrefixCls, direction } = React.useContext(ConfigContext);
const prefixCls = getPrefixCls('descriptions', customizePrefixCls);
@ -142,43 +153,45 @@ function Descriptions({
const rows = getRows(children, mergedColumn);
return (
<div
className={classNames(
prefixCls,
{
[`${prefixCls}-${size}`]: size && size !== 'default',
[`${prefixCls}-bordered`]: !!bordered,
[`${prefixCls}-rtl`]: direction === 'rtl',
},
className,
)}
style={style}
>
{(title || extra) && (
<div className={`${prefixCls}-header`}>
{title && <div className={`${prefixCls}-title`}>{title}</div>}
{extra && <div className={`${prefixCls}-extra`}>{extra}</div>}
</div>
)}
<DescriptionsContext.Provider value={{ labelStyle, contentStyle }}>
<div
className={classNames(
prefixCls,
{
[`${prefixCls}-${size}`]: size && size !== 'default',
[`${prefixCls}-bordered`]: !!bordered,
[`${prefixCls}-rtl`]: direction === 'rtl',
},
className,
)}
style={style}
>
{(title || extra) && (
<div className={`${prefixCls}-header`}>
{title && <div className={`${prefixCls}-title`}>{title}</div>}
{extra && <div className={`${prefixCls}-extra`}>{extra}</div>}
</div>
)}
<div className={`${prefixCls}-view`}>
<table>
<tbody>
{rows.map((row, index) => (
<Row
key={index}
index={index}
colon={colon}
prefixCls={prefixCls}
vertical={layout === 'vertical'}
bordered={bordered}
row={row}
/>
))}
</tbody>
</table>
<div className={`${prefixCls}-view`}>
<table>
<tbody>
{rows.map((row, index) => (
<Row
key={index}
index={index}
colon={colon}
prefixCls={prefixCls}
vertical={layout === 'vertical'}
bordered={bordered}
row={row}
/>
))}
</tbody>
</table>
</div>
</div>
</div>
</DescriptionsContext.Provider>
);
}

View File

@ -22,7 +22,9 @@ cover: https://gw.alipayobjects.com/zos/alicdn/MjtG9_FOI/Descriptions.svg
| bordered | 是否展示边框 | boolean | false | |
| colon | 配置 `Descriptions.Item``colon` 的默认值 | boolean | true | |
| column | 一行的 `DescriptionItems` 数量,可以写成像素值或支持响应式的对象写法 `{ xs: 8, sm: 16, md: 24}` | number | 3 | |
| contentStyle | 自定义内容样式 | CSSProperties | - | 4.10.0 |
| extra | 描述列表的操作区域,显示在右上方 | ReactNode | - | 4.5.0 |
| labelStyle | 自定义标签样式 | CSSProperties | - | 4.10.0 |
| layout | 描述布局 | `horizontal` \| `vertical` | `horizontal` | |
| size | 设置列表的大小。可以设置为 `middle` 、`small`, 或不填(只有设置 `bordered={true}` 生效) | `default` \| `middle` \| `small` | - | |
| title | 描述列表的标题,显示在最顶部 | ReactNode | - | |