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: Descriptions items.span support responsive config #44534

Merged
merged 6 commits into from
Aug 30, 2023
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
12 changes: 12 additions & 0 deletions components/_util/responsiveObserver.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React from 'react';

import type { GlobalToken } from '../theme/interface';
import { useToken } from '../theme/internal';

Expand Down Expand Up @@ -124,3 +125,14 @@ export default function useResponsiveObserver() {
};
}, [token]);
}

export const matchScreen = (screens: ScreenMap, screenSizes?: ScreenSizeMap) => {
if (screenSizes && typeof screenSizes === 'object') {
for (let i = 0; i < responsiveArray.length; i++) {
const breakpoint: Breakpoint = responsiveArray[i];
if (screens[breakpoint] && screenSizes[breakpoint] !== undefined) {
return screenSizes[breakpoint];
}
}
}
};
7 changes: 4 additions & 3 deletions components/descriptions/Row.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as React from 'react';
import type { DescriptionsItemType } from '.';

import type { InternalDescriptionsItemType } from '.';
import Cell from './Cell';
import type { DescriptionsContextProps } from './DescriptionsContext';
import DescriptionsContext from './DescriptionsContext';
Expand All @@ -12,7 +13,7 @@ interface CellConfig {
}

function renderCells(
items: DescriptionsItemType[],
items: InternalDescriptionsItemType[],
{ colon, prefixCls, bordered }: RowProps,
{
component,
Expand Down Expand Up @@ -87,7 +88,7 @@ function renderCells(
export interface RowProps {
prefixCls: string;
vertical: boolean;
row: DescriptionsItemType[];
row: InternalDescriptionsItemType[];
bordered?: boolean;
colon: boolean;
index: number;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1116,13 +1116,32 @@ exports[`renders components/descriptions/demo/responsive.tsx extend context corr
Database version: 3.4
<br />
Package: dds.mongo.mid
</span>
</td>
</tr>
<tr
class="ant-descriptions-row"
>
<th
class="ant-descriptions-item-label"
colspan="1"
>
<span>
Hardware Info
</span>
</th>
<td
class="ant-descriptions-item-content"
colspan="1"
>
<span>
CPU: 6 Core 3.5 GHz
<br />
Storage space: 10 GB
<br />
Replication factor: 3
<br />
Region: East China 1
<br />
</span>
</td>
</tr>
Expand Down
19 changes: 17 additions & 2 deletions components/descriptions/__tests__/__snapshots__/demo.test.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -1004,21 +1004,36 @@ exports[`renders components/descriptions/demo/responsive.tsx correctly 1`] = `
</th>
<td
class="ant-descriptions-item-content"
colspan="5"
colspan="1"
>
<span>
Data disk type: MongoDB
<br />
Database version: 3.4
<br />
Package: dds.mongo.mid
</span>
</td>
<th
class="ant-descriptions-item-label"
colspan="1"
>
<span>
Hardware Info
</span>
</th>
<td
class="ant-descriptions-item-content"
colspan="3"
>
<span>
CPU: 6 Core 3.5 GHz
<br />
Storage space: 10 GB
<br />
Replication factor: 3
<br />
Region: East China 1
<br />
</span>
</td>
</tr>
Expand Down
39 changes: 35 additions & 4 deletions components/descriptions/__tests__/index.test.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import MockDate from 'mockdate';
import React from 'react';
import MockDate from 'mockdate';

import Descriptions from '..';
import { resetWarned } from '../../_util/warning';
import mountTest from '../../../tests/shared/mountTest';
import { render } from '../../../tests/utils';
import { resetWarned } from '../../_util/warning';
import ConfigProvider from '../../config-provider';

describe('Descriptions', () => {
Expand All @@ -20,7 +21,7 @@ describe('Descriptions', () => {
errorSpy.mockRestore();
});

it('when max-width: 575pxcolumn=1', () => {
it('when max-width: 575px, column=1', () => {
const wrapper = render(
<Descriptions>
<Descriptions.Item label="Product">Cloud Database</Descriptions.Item>
Expand All @@ -35,7 +36,7 @@ describe('Descriptions', () => {
wrapper.unmount();
});

it('when max-width: 575pxcolumn=2', () => {
it('when max-width: 575px, column=2', () => {
// eslint-disable-next-line global-require
const wrapper = render(
<Descriptions column={{ xs: 2 }}>
Expand All @@ -49,6 +50,36 @@ describe('Descriptions', () => {
wrapper.unmount();
});

it('when max-width: 575px, column=2, span=2', () => {
// eslint-disable-next-line global-require
const { container } = render(
<Descriptions
column={{ xs: 2 }}
items={[
{
label: 'Product',
children: 'Cloud Database',
span: { xs: 2 },
},
{
label: 'Billing',
children: 'Prepaid',
span: { xs: 1 },
},
{
label: 'Time',
children: '18:00:00',
span: { xs: 1 },
},
]}
/>,
);

expect(container.querySelectorAll('.ant-descriptions-item')[0]).toHaveAttribute('colSpan', '2');
expect(container.querySelectorAll('.ant-descriptions-item')[1]).toHaveAttribute('colSpan', '1');
expect(container.querySelectorAll('.ant-descriptions-item')[2]).toHaveAttribute('colSpan', '1');
});

it('column is number', () => {
// eslint-disable-next-line global-require
const wrapper = render(
Expand Down
12 changes: 12 additions & 0 deletions components/descriptions/constant.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import type { Breakpoint } from '../_util/responsiveObserver';

const DEFAULT_COLUMN_MAP: Record<Breakpoint, number> = {
xxl: 3,
xl: 3,
lg: 3,
md: 3,
sm: 2,
xs: 1,
};

export default DEFAULT_COLUMN_MAP;
22 changes: 13 additions & 9 deletions components/descriptions/demo/responsive.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,52 +4,56 @@ import type { DescriptionsProps } from 'antd';

const items: DescriptionsProps['items'] = [
{
key: '1',
label: 'Product',
children: 'Cloud Database',
},
{
key: '2',
label: 'Billing',
children: 'Prepaid',
},
{
key: '3',
label: 'Time',
children: '18:00:00',
},
{
key: '4',
label: 'Amount',
children: '$80.00',
},
{
key: '5',
label: 'Discount',
span: { xl: 2, xxl: 2 },
children: '$20.00',
},
{
key: '6',
label: 'Official',
span: { xl: 2, xxl: 2 },
children: '$60.00',
},
{
key: '7',
label: 'Config Info',
span: { xs: 1, sm: 2, md: 3, lg: 3, xl: 2, xxl: 2 },
children: (
<>
Data disk type: MongoDB
<br />
Database version: 3.4
<br />
Package: dds.mongo.mid
</>
),
},
{
label: 'Hardware Info',
span: { xs: 1, sm: 2, md: 3, lg: 3, xl: 2, xxl: 2 },
children: (
<>
CPU: 6 Core 3.5 GHz
<br />
Storage space: 10 GB
<br />
Replication factor: 3
<br />
Region: East China 1
<br />
</>
),
},
Expand All @@ -59,7 +63,7 @@ const App: React.FC = () => (
<Descriptions
title="Responsive Descriptions"
bordered
column={{ xxl: 4, xl: 3, lg: 3, md: 3, sm: 2, xs: 1 }}
column={{ xs: 1, sm: 2, md: 3, lg: 3, xl: 4, xxl: 4 }}
items={items}
/>
);
Expand Down
33 changes: 33 additions & 0 deletions components/descriptions/hooks/useItems.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import * as React from 'react';
import toArray from 'rc-util/lib/Children/toArray';

import type { DescriptionsItemType, InternalDescriptionsItemType } from '..';
import { matchScreen, type ScreenMap } from '../../_util/responsiveObserver';

// Convert children into items
const transChildren2Items = (childNodes?: React.ReactNode) =>
toArray(childNodes).map((node) => ({ ...node?.props }));

export default function useItems(
screens: ScreenMap,
items?: DescriptionsItemType[],
children?: React.ReactNode,
) {
const mergedItems = React.useMemo<DescriptionsItemType[]>(
() =>
// Take `items` first or convert `children` into items
items || transChildren2Items(children),
[items, children],
);

const responsiveItems = React.useMemo<InternalDescriptionsItemType[]>(
() =>
mergedItems.map(({ span, ...restItem }) => ({
...restItem,
span: typeof span === 'number' ? span : matchScreen(screens, span),
})),
[mergedItems, screens],
);

return responsiveItems;
}
32 changes: 9 additions & 23 deletions components/descriptions/hooks/useRow.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import toArray from 'rc-util/lib/Children/toArray';
import type React from 'react';
import { useMemo } from 'react';
import type { DescriptionsItemType } from '..';

import type { InternalDescriptionsItemType } from '..';
import warning from '../../_util/warning';

function getFilledItem(
rowItem: DescriptionsItemType,
rowItem: InternalDescriptionsItemType,
rowRestCol: number,
span?: number,
): DescriptionsItemType {
): InternalDescriptionsItemType {
let clone = rowItem;

if (span === undefined || span > rowRestCol) {
Expand All @@ -25,14 +24,10 @@ function getFilledItem(
return clone;
}

// Convert children into items
const transChildren2Items = (childNodes?: React.ReactNode) =>
toArray(childNodes).map((node) => ({ ...node?.props }));

// Calculate the sum of span in a row
function getCalcRows(rowItems: DescriptionsItemType[], mergedColumn: number) {
const rows: DescriptionsItemType[][] = [];
let tmpRow: DescriptionsItemType[] = [];
function getCalcRows(rowItems: InternalDescriptionsItemType[], mergedColumn: number) {
const rows: InternalDescriptionsItemType[][] = [];
let tmpRow: InternalDescriptionsItemType[] = [];
let rowRestCol = mergedColumn;

rowItems
Expand Down Expand Up @@ -62,17 +57,8 @@ function getCalcRows(rowItems: DescriptionsItemType[], mergedColumn: number) {
return rows;
}

const useRow = (
mergedColumn: number,
items?: DescriptionsItemType[],
children?: React.ReactNode,
) => {
const rows = useMemo(() => {
if (Array.isArray(items)) {
return getCalcRows(items, mergedColumn);
}
return getCalcRows(transChildren2Items(children), mergedColumn);
}, [items, children, mergedColumn]);
const useRow = (mergedColumn: number, items: InternalDescriptionsItemType[]) => {
const rows = useMemo(() => getCalcRows(items, mergedColumn), [items, mergedColumn]);

return rows;
};
Expand Down
12 changes: 6 additions & 6 deletions components/descriptions/index.en-US.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,12 +93,12 @@ Common props ref:[Common props](/docs/react/common-props)

### DescriptionItem

| Property | Description | Type | Default | Version |
| ------------ | ------------------------------ | ------------- | ------- | ------- |
| contentStyle | Customize content style | CSSProperties | - | 4.9.0 |
| label | The description of the content | ReactNode | - | |
| labelStyle | Customize label style | CSSProperties | - | 4.9.0 |
| span | The number of columns included | number | 1 | |
| Property | Description | Type | Default | Version |
| --- | --- | --- | --- | --- |
| contentStyle | Customize content style | CSSProperties | - | 4.9.0 |
| label | The description of the content | ReactNode | - | |
| labelStyle | Customize label style | CSSProperties | - | 4.9.0 |
| span | The number of columns included | number \| [Screens](/components/grid#col) | 1 | `screens: 5.9.0` |

> The number of span Description.Item. Span={2} takes up the width of two DescriptionItems. When both `style` and `labelStyle`(or `contentStyle`) configured, both of them will work. And next one will overwrite first when conflict.

Expand Down
Loading