From eee3b50727a9e2cc57095a422c75ca4ecfbfe67b Mon Sep 17 00:00:00 2001 From: vagusX Date: Thu, 28 Apr 2022 19:39:52 +0800 Subject: [PATCH] feat: support icon only in segmented (#35256) * feat: support icon only with segmented * fix: lint issue * chore: update * test: fix * test: update snapshot --- .../__snapshots__/demo-extend.test.ts.snap | 78 ++++++++++++++++++ .../__tests__/__snapshots__/demo.test.js.snap | 78 ++++++++++++++++++ .../__snapshots__/index.test.tsx.snap | 81 +++++++++++++++++++ components/segmented/__tests__/index.test.tsx | 28 ++++++- components/segmented/demo/block.md | 2 +- components/segmented/demo/controlled.md | 2 +- components/segmented/demo/custom.md | 2 +- components/segmented/demo/disabled.md | 2 +- components/segmented/demo/dynamic.md | 2 +- components/segmented/demo/icon-only.md | 34 ++++++++ components/segmented/demo/size.md | 2 +- components/segmented/demo/with-icon.md | 2 +- components/segmented/index.tsx | 27 +++++-- components/segmented/style/index.less | 4 +- 14 files changed, 325 insertions(+), 19 deletions(-) create mode 100644 components/segmented/demo/icon-only.md diff --git a/components/segmented/__tests__/__snapshots__/demo-extend.test.ts.snap b/components/segmented/__tests__/__snapshots__/demo-extend.test.ts.snap index d9d5a2f118..76c58f48c2 100644 --- a/components/segmented/__tests__/__snapshots__/demo-extend.test.ts.snap +++ b/components/segmented/__tests__/__snapshots__/demo-extend.test.ts.snap @@ -644,6 +644,84 @@ Array [ ] `; +exports[`renders ./components/segmented/demo/icon-only.md extend context correctly 1`] = ` +
+ + +
+`; + exports[`renders ./components/segmented/demo/size.md extend context correctly 1`] = ` Array [
+ + +
+`; + exports[`renders ./components/segmented/demo/size.md correctly 1`] = ` Array [
`; +exports[`Segmented render with icons 1`] = ` +
+ + +
+`; + exports[`Segmented rtl render component should be rendered correctly in RTL direction 1`] = `
{ it('render segmented with string options', () => { const handleValueChange = jest.fn(); const wrapper = mount( - , + , ); expect(wrapper.render()).toMatchSnapshot(); @@ -356,4 +355,25 @@ describe('Segmented', () => { expect(wrapper.find(`.${prefixCls}`).at(0).hasClass(`${prefixCls}-lg`)).toBeTruthy(); }); + + it('render with icons', () => { + const wrapper = mount( + , + }, + { + value: 'Kanban', + label: 'KanbanYes', + icon: , + }, + ]} + />, + ); + expect(wrapper.render()).toMatchSnapshot(); + expect(wrapper.find(`span.${prefixCls}-item-icon`).length).toBe(2); + expect(wrapper.find(`div.${prefixCls}-item-label`).at(1).contains('KanbanYes')).toBeTruthy(); + }); }); diff --git a/components/segmented/demo/block.md b/components/segmented/demo/block.md index ab2bdced3e..16335a173a 100644 --- a/components/segmented/demo/block.md +++ b/components/segmented/demo/block.md @@ -1,5 +1,5 @@ --- -order: 10 +order: 1 title: zh-CN: Block 分段选择器 en-US: Block Segmented diff --git a/components/segmented/demo/controlled.md b/components/segmented/demo/controlled.md index 48092ecd19..0f051d366e 100644 --- a/components/segmented/demo/controlled.md +++ b/components/segmented/demo/controlled.md @@ -1,5 +1,5 @@ --- -order: 0 +order: 3 title: zh-CN: 受控模式 en-US: Controlled mode diff --git a/components/segmented/demo/custom.md b/components/segmented/demo/custom.md index e88b41d1c8..21c4880080 100644 --- a/components/segmented/demo/custom.md +++ b/components/segmented/demo/custom.md @@ -1,5 +1,5 @@ --- -order: 1 +order: 4 title: zh-CN: 自定义渲染 en-US: Custom Render diff --git a/components/segmented/demo/disabled.md b/components/segmented/demo/disabled.md index df9699a279..cc0875bd4e 100644 --- a/components/segmented/demo/disabled.md +++ b/components/segmented/demo/disabled.md @@ -1,5 +1,5 @@ --- -order: 0 +order: 2 title: zh-CN: 不可用 en-US: Basic diff --git a/components/segmented/demo/dynamic.md b/components/segmented/demo/dynamic.md index 47ecdf2173..f03475e036 100644 --- a/components/segmented/demo/dynamic.md +++ b/components/segmented/demo/dynamic.md @@ -1,5 +1,5 @@ --- -order: 0 +order: 5 title: zh-CN: 动态数据 en-US: Dynamic diff --git a/components/segmented/demo/icon-only.md b/components/segmented/demo/icon-only.md new file mode 100644 index 0000000000..62cd10e0c9 --- /dev/null +++ b/components/segmented/demo/icon-only.md @@ -0,0 +1,34 @@ +--- +order: 8 +title: + zh-CN: 只设置图标 + en-US: With Icon only +--- + +## zh-CN + +在 Segmented Item 选项中只设置 Icon。 + +## en-US + +Set `icon` without `label` for Segmented Item. + +```jsx +import { Segmented } from 'antd'; +import { AppstoreOutlined, BarsOutlined } from '@ant-design/icons'; + +export default () => ( + , + }, + { + value: 'Kanban', + icon: , + }, + ]} + /> +); +``` diff --git a/components/segmented/demo/size.md b/components/segmented/demo/size.md index 92fe41dfc0..d9fa0cb760 100644 --- a/components/segmented/demo/size.md +++ b/components/segmented/demo/size.md @@ -1,5 +1,5 @@ --- -order: 1 +order: 6 title: zh-CN: 三种大小 en-US: Three sizes of Segmented diff --git a/components/segmented/demo/with-icon.md b/components/segmented/demo/with-icon.md index 7d4855c3e8..20214c7e22 100644 --- a/components/segmented/demo/with-icon.md +++ b/components/segmented/demo/with-icon.md @@ -1,5 +1,5 @@ --- -order: 0 +order: 7 title: zh-CN: 设置图标 en-US: With Icon diff --git a/components/segmented/index.tsx b/components/segmented/index.tsx index da17860bcb..5ea98b9cc7 100644 --- a/components/segmented/index.tsx +++ b/components/segmented/index.tsx @@ -12,12 +12,27 @@ import SizeContext, { SizeType } from '../config-provider/SizeContext'; export type { SegmentedValue } from 'rc-segmented'; -export interface SegmentedLabeledOption extends RcSegmentedLabeledOption { - /** Set icon for Segmented item */ - icon?: React.ReactNode; +interface SegmentedLabeledOptionWithoutIcon extends RcSegmentedLabeledOption { + label: RcSegmentedLabeledOption['label']; } -export interface SegmentedProps extends Omit { +interface SegmentedLabeledOptionWithIcon extends Omit { + label?: RcSegmentedLabeledOption['label']; + /** Set icon for Segmented item */ + icon: React.ReactNode; +} + +function isSegmentedLabeledOptionWithIcon( + option: SegmentedRawOption | SegmentedLabeledOptionWithIcon | SegmentedLabeledOptionWithoutIcon, +): option is SegmentedLabeledOptionWithIcon { + return typeof option === 'object' && !!(option as SegmentedLabeledOptionWithIcon)?.icon; +} + +export type SegmentedLabeledOption = + | SegmentedLabeledOptionWithIcon + | SegmentedLabeledOptionWithoutIcon; + +export interface SegmentedProps extends Omit { options: (SegmentedRawOption | SegmentedLabeledOption)[]; /** Option to fit width to its parent's width */ block?: boolean; @@ -46,14 +61,14 @@ const Segmented = React.forwardRef((props, ref) const extendedOptions = React.useMemo( () => options.map(option => { - if (typeof option === 'object' && option?.icon) { + if (isSegmentedLabeledOptionWithIcon(option)) { const { icon, label, ...restOption } = option; return { ...restOption, label: ( <> {icon} - {label} + {label && {label}} ), }; diff --git a/components/segmented/style/index.less b/components/segmented/style/index.less index c3d83b726a..06b3936135 100644 --- a/components/segmented/style/index.less +++ b/components/segmented/style/index.less @@ -61,8 +61,8 @@ } // syntactic sugar to add `icon` for Segmented Item - &-icon { - margin-right: 6px; + &-icon + * { + margin-left: 6px; } &-input {