Skip to content

Commit

Permalink
feat: Descriptions items.span support responsive config (ant-design…
Browse files Browse the repository at this point in the history
…#44534)

* feat: Desc items support responsive

* refactor: useBreakPoint

* docs: update docs

* test: add test case

* chore: update def

* chore: fix def
  • Loading branch information
zombieJ authored Aug 30, 2023
1 parent b0dd138 commit cbfb126
Show file tree
Hide file tree
Showing 12 changed files with 200 additions and 104 deletions.
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

0 comments on commit cbfb126

Please sign in to comment.