ant-design/components/segmented/index.tsx
vagusX ae4e660a05
feat: add new component Segmented (#34319)
* feat: basic implements in antd

* feat: use rc-segmented

* feat: add some demos

* feat: support dark theme

* docs: add more demos

* feat: support `icon` in segmented

* docs: format content

* test: add test cases

* docs: update docs

* chore: update

* fix: lint issues

* style: add border-radius for selected effect

* style: change border-radius-base

* chore: update gitignore

* feat: segmented support block

* chore: update gitignore

* feat: support block

* feat: add test case

* feat: support size

* docs: update demos

* chore: update

* chore: update

* test: update

* style: update colors

* style: hover and focus styles

* doc: add version mark in docs

* fix: style lint issue

* fix: some lint issues

* doc: add version in demo mds

* doc: add version mark before api details

* Revert "doc: add version in demo mds"

This reverts commit 2a9e86f6ffc2331f7d73eae6edac7c889358a838.

* test: only test for thumb appear

* style: update color vars

* style: add transition

* style: text vertial align

* test: update snapshots

* feat: add preview svg and support dark theme

* fix: update test snapshot

* docs: update docs

* fix: remove useless z-index

* build: add 1kb for bundlesize of antd.variable.min.css

Co-authored-by: taian.lta <taian.lta@antgroup.com>
2022-04-11 11:13:16 +08:00

88 lines
2.4 KiB
TypeScript

import * as React from 'react';
import classNames from 'classnames';
import RcSegmented from 'rc-segmented';
import type {
SegmentedProps as RCSegmentedProps,
SegmentedRawOption,
SegmentedLabeledOption as RcSegmentedLabeledOption,
} from 'rc-segmented';
import { ConfigContext } from '../config-provider';
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;
}
export interface SegmentedProps extends Omit<RCSegmentedProps, 'size'> {
options: (SegmentedRawOption | SegmentedLabeledOption)[];
/** Option to fit width to its parent's width */
block?: boolean;
/** Option to control the display size */
size?: SizeType;
}
const Segmented = React.forwardRef<HTMLDivElement, SegmentedProps>((props, ref) => {
const {
prefixCls: customizePrefixCls,
className,
block,
options,
size: customSize = 'middle',
...restProps
} = props;
const { getPrefixCls, direction } = React.useContext(ConfigContext);
const prefixCls = getPrefixCls('segmented', customizePrefixCls);
// ===================== Size =====================
const size = React.useContext(SizeContext);
const mergedSize = customSize || size;
// syntactic sugar to support `icon` for Segmented Item
const extendedOptions = React.useMemo(
() =>
options.map(option => {
if (typeof option === 'object' && option?.icon) {
const { icon, label, ...restOption } = option;
return {
...restOption,
label: (
<>
<span className={`${prefixCls}-item-icon`}>{icon}</span>
<span>{label}</span>
</>
),
};
}
return option;
}),
[options, prefixCls],
);
return (
<RcSegmented
{...restProps}
className={classNames(className, {
[`${prefixCls}-block`]: block,
[`${prefixCls}-sm`]: mergedSize === 'small',
[`${prefixCls}-lg`]: mergedSize === 'large',
})}
options={extendedOptions}
ref={ref}
prefixCls={prefixCls}
direction={direction}
/>
);
});
Segmented.displayName = 'Segmented';
Segmented.defaultProps = {
options: [],
};
export default Segmented;