mirror of
https://gitee.com/ant-design/ant-design.git
synced 2024-11-30 11:08:45 +08:00
refactor: Simplify Button Group Style (#35175)
* chore: refactor grp with context * test: Update snapshot * chore: clean up * test: fix test case * chore: clean up * test: fix test
This commit is contained in:
parent
e14ec001a1
commit
f8e7cba353
@ -1,8 +0,0 @@
|
||||
import UnreachableException from '../unreachableException';
|
||||
|
||||
describe('UnreachableException', () => {
|
||||
it('error thrown matches snapshot', () => {
|
||||
const exception = new UnreachableException('some value');
|
||||
expect(exception.error.message).toMatchInlineSnapshot(`"unreachable case: \\"some value\\""`);
|
||||
});
|
||||
});
|
@ -1,7 +0,0 @@
|
||||
export default class UnreachableException {
|
||||
error: Error;
|
||||
|
||||
constructor(value: never) {
|
||||
this.error = new Error(`unreachable case: ${JSON.stringify(value)}`);
|
||||
}
|
||||
}
|
@ -1016,7 +1016,7 @@ Array [
|
||||
class="ant-btn-group ant-btn-group-sm"
|
||||
>
|
||||
<button
|
||||
class="ant-btn ant-btn-primary"
|
||||
class="ant-btn ant-btn-primary ant-btn-sm"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
@ -1024,7 +1024,7 @@ Array [
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
class="ant-btn ant-btn-primary"
|
||||
class="ant-btn ant-btn-primary ant-btn-sm"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
@ -1036,7 +1036,7 @@ Array [
|
||||
style="display:inline-block;cursor:not-allowed"
|
||||
>
|
||||
<button
|
||||
class="ant-btn ant-btn-primary ant-btn-icon-only"
|
||||
class="ant-btn ant-btn-primary ant-btn-sm ant-btn-icon-only"
|
||||
disabled=""
|
||||
style="pointer-events:none"
|
||||
type="button"
|
||||
@ -1087,7 +1087,7 @@ Array [
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
class="ant-btn ant-btn-primary ant-btn-icon-only"
|
||||
class="ant-btn ant-btn-primary ant-btn-sm ant-btn-icon-only"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
@ -1268,7 +1268,7 @@ Array [
|
||||
class="ant-btn-group ant-btn-group-lg"
|
||||
>
|
||||
<button
|
||||
class="ant-btn ant-btn-primary"
|
||||
class="ant-btn ant-btn-primary ant-btn-lg"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
@ -1276,7 +1276,7 @@ Array [
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
class="ant-btn ant-btn-primary"
|
||||
class="ant-btn ant-btn-primary ant-btn-lg"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
@ -1288,7 +1288,7 @@ Array [
|
||||
style="display:inline-block;cursor:not-allowed"
|
||||
>
|
||||
<button
|
||||
class="ant-btn ant-btn-primary ant-btn-icon-only"
|
||||
class="ant-btn ant-btn-primary ant-btn-lg ant-btn-icon-only"
|
||||
disabled=""
|
||||
style="pointer-events:none"
|
||||
type="button"
|
||||
@ -1339,7 +1339,7 @@ Array [
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
class="ant-btn ant-btn-primary ant-btn-icon-only"
|
||||
class="ant-btn ant-btn-primary ant-btn-lg ant-btn-icon-only"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
|
@ -824,7 +824,7 @@ Array [
|
||||
class="ant-btn-group ant-btn-group-sm"
|
||||
>
|
||||
<button
|
||||
class="ant-btn ant-btn-primary"
|
||||
class="ant-btn ant-btn-primary ant-btn-sm"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
@ -832,7 +832,7 @@ Array [
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
class="ant-btn ant-btn-primary"
|
||||
class="ant-btn ant-btn-primary ant-btn-sm"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
@ -844,7 +844,7 @@ Array [
|
||||
style="display:inline-block;cursor:not-allowed"
|
||||
>
|
||||
<button
|
||||
class="ant-btn ant-btn-primary ant-btn-icon-only"
|
||||
class="ant-btn ant-btn-primary ant-btn-sm ant-btn-icon-only"
|
||||
disabled=""
|
||||
style="pointer-events:none"
|
||||
type="button"
|
||||
@ -871,7 +871,7 @@ Array [
|
||||
</button>
|
||||
</span>
|
||||
<button
|
||||
class="ant-btn ant-btn-primary ant-btn-icon-only"
|
||||
class="ant-btn ant-btn-primary ant-btn-sm ant-btn-icon-only"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
@ -980,7 +980,7 @@ Array [
|
||||
class="ant-btn-group ant-btn-group-lg"
|
||||
>
|
||||
<button
|
||||
class="ant-btn ant-btn-primary"
|
||||
class="ant-btn ant-btn-primary ant-btn-lg"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
@ -988,7 +988,7 @@ Array [
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
class="ant-btn ant-btn-primary"
|
||||
class="ant-btn ant-btn-primary ant-btn-lg"
|
||||
type="button"
|
||||
>
|
||||
<span>
|
||||
@ -1000,7 +1000,7 @@ Array [
|
||||
style="display:inline-block;cursor:not-allowed"
|
||||
>
|
||||
<button
|
||||
class="ant-btn ant-btn-primary ant-btn-icon-only"
|
||||
class="ant-btn ant-btn-primary ant-btn-lg ant-btn-icon-only"
|
||||
disabled=""
|
||||
style="pointer-events:none"
|
||||
type="button"
|
||||
@ -1027,7 +1027,7 @@ Array [
|
||||
</button>
|
||||
</span>
|
||||
<button
|
||||
class="ant-btn ant-btn-primary ant-btn-icon-only"
|
||||
class="ant-btn ant-btn-primary ant-btn-lg ant-btn-icon-only"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
|
@ -36,14 +36,13 @@ describe('Button', () => {
|
||||
});
|
||||
|
||||
it('warns if size is wrong', () => {
|
||||
const mockWarn = jest.fn();
|
||||
jest.spyOn(console, 'warn').mockImplementation(mockWarn);
|
||||
resetWarned();
|
||||
const mockWarn = jest.spyOn(console, 'error').mockImplementation(() => {});
|
||||
const size = 'who am I' as any as SizeType;
|
||||
mount(<Button.Group size={size} />);
|
||||
expect(mockWarn).toHaveBeenCalledTimes(1);
|
||||
expect(mockWarn.mock.calls[0][0]).toMatchObject({
|
||||
message: 'unreachable case: "who am I"',
|
||||
});
|
||||
render(<Button.Group size={size} />);
|
||||
expect(mockWarn).toHaveBeenCalledWith('Warning: [antd: Button.Group] Invalid prop `size`.');
|
||||
|
||||
mockWarn.mockRestore();
|
||||
});
|
||||
|
||||
it('renders Chinese characters correctly', () => {
|
||||
|
@ -1,8 +1,8 @@
|
||||
import * as React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import { SizeType } from '../config-provider/SizeContext';
|
||||
import { ConfigConsumer, ConfigConsumerProps } from '../config-provider';
|
||||
import UnreachableException from '../_util/unreachableException';
|
||||
import { ConfigContext } from '../config-provider';
|
||||
import devWarning from '../_util/devWarning';
|
||||
|
||||
export interface ButtonGroupProps {
|
||||
size?: SizeType;
|
||||
@ -12,42 +12,45 @@ export interface ButtonGroupProps {
|
||||
children?: React.ReactNode;
|
||||
}
|
||||
|
||||
const ButtonGroup: React.FC<ButtonGroupProps> = props => (
|
||||
<ConfigConsumer>
|
||||
{({ getPrefixCls, direction }: ConfigConsumerProps) => {
|
||||
const { prefixCls: customizePrefixCls, size, className, ...others } = props;
|
||||
const prefixCls = getPrefixCls('btn-group', customizePrefixCls);
|
||||
export const GroupSizeContext = React.createContext<SizeType | undefined>(undefined);
|
||||
|
||||
// large => lg
|
||||
// small => sm
|
||||
let sizeCls = '';
|
||||
switch (size) {
|
||||
case 'large':
|
||||
sizeCls = 'lg';
|
||||
break;
|
||||
case 'small':
|
||||
sizeCls = 'sm';
|
||||
break;
|
||||
case 'middle':
|
||||
case undefined:
|
||||
break;
|
||||
default:
|
||||
// eslint-disable-next-line no-console
|
||||
console.warn(new UnreachableException(size).error);
|
||||
}
|
||||
const ButtonGroup: React.FC<ButtonGroupProps> = props => {
|
||||
const { getPrefixCls, direction } = React.useContext(ConfigContext);
|
||||
|
||||
const classes = classNames(
|
||||
prefixCls,
|
||||
{
|
||||
[`${prefixCls}-${sizeCls}`]: sizeCls,
|
||||
[`${prefixCls}-rtl`]: direction === 'rtl',
|
||||
},
|
||||
className,
|
||||
);
|
||||
const { prefixCls: customizePrefixCls, size, className, ...others } = props;
|
||||
const prefixCls = getPrefixCls('btn-group', customizePrefixCls);
|
||||
|
||||
return <div {...others} className={classes} />;
|
||||
}}
|
||||
</ConfigConsumer>
|
||||
);
|
||||
// large => lg
|
||||
// small => sm
|
||||
let sizeCls = '';
|
||||
switch (size) {
|
||||
case 'large':
|
||||
sizeCls = 'lg';
|
||||
break;
|
||||
case 'small':
|
||||
sizeCls = 'sm';
|
||||
break;
|
||||
case 'middle':
|
||||
case undefined:
|
||||
break;
|
||||
default:
|
||||
devWarning(!size, 'Button.Group', 'Invalid prop `size`.');
|
||||
}
|
||||
|
||||
const classes = classNames(
|
||||
prefixCls,
|
||||
{
|
||||
[`${prefixCls}-${sizeCls}`]: sizeCls,
|
||||
[`${prefixCls}-rtl`]: direction === 'rtl',
|
||||
},
|
||||
className,
|
||||
);
|
||||
|
||||
return (
|
||||
<GroupSizeContext.Provider value={size}>
|
||||
<div {...others} className={classes} />
|
||||
</GroupSizeContext.Provider>
|
||||
);
|
||||
};
|
||||
|
||||
export default ButtonGroup;
|
||||
|
@ -3,7 +3,7 @@ import * as React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import omit from 'rc-util/lib/omit';
|
||||
|
||||
import Group from './button-group';
|
||||
import Group, { GroupSizeContext } from './button-group';
|
||||
import { ConfigContext } from '../config-provider';
|
||||
import Wave from '../_util/wave';
|
||||
import { tuple } from '../_util/type';
|
||||
@ -18,7 +18,7 @@ function isString(str: any) {
|
||||
return typeof str === 'string';
|
||||
}
|
||||
|
||||
function isUnborderedButtonType(type: ButtonType | undefined) {
|
||||
function isUnBorderedButtonType(type: ButtonType | undefined) {
|
||||
return type === 'text' || type === 'link';
|
||||
}
|
||||
|
||||
@ -94,7 +94,11 @@ export function convertLegacyProps(type?: LegacyButtonType): ButtonProps {
|
||||
export interface BaseButtonProps {
|
||||
type?: ButtonType;
|
||||
icon?: React.ReactNode;
|
||||
/** @default default */
|
||||
/**
|
||||
* Shape of Button
|
||||
*
|
||||
* @default default
|
||||
*/
|
||||
shape?: ButtonShape;
|
||||
size?: SizeType;
|
||||
loading?: boolean | { delay?: number };
|
||||
@ -152,13 +156,14 @@ const InternalButton: React.ForwardRefRenderFunction<unknown, ButtonProps> = (pr
|
||||
} = props;
|
||||
|
||||
const size = React.useContext(SizeContext);
|
||||
const groupSize = React.useContext(GroupSizeContext);
|
||||
const [innerLoading, setLoading] = React.useState<Loading>(!!loading);
|
||||
const [hasTwoCNChar, setHasTwoCNChar] = React.useState(false);
|
||||
const { getPrefixCls, autoInsertSpaceInButton, direction } = React.useContext(ConfigContext);
|
||||
const buttonRef = (ref as any) || React.createRef<HTMLElement>();
|
||||
|
||||
const isNeedInserted = () =>
|
||||
React.Children.count(children) === 1 && !icon && !isUnborderedButtonType(type);
|
||||
React.Children.count(children) === 1 && !icon && !isUnBorderedButtonType(type);
|
||||
|
||||
const fixTwoCNChar = () => {
|
||||
// Fix for HOC usage like <FormatMessage />
|
||||
@ -220,7 +225,7 @@ const InternalButton: React.ForwardRefRenderFunction<unknown, ButtonProps> = (pr
|
||||
);
|
||||
|
||||
devWarning(
|
||||
!(ghost && isUnborderedButtonType(type)),
|
||||
!(ghost && isUnBorderedButtonType(type)),
|
||||
'Button',
|
||||
"`link` or `text` button can't be a `ghost` button.",
|
||||
);
|
||||
@ -229,7 +234,7 @@ const InternalButton: React.ForwardRefRenderFunction<unknown, ButtonProps> = (pr
|
||||
const autoInsertSpace = autoInsertSpaceInButton !== false;
|
||||
|
||||
const sizeClassNameMap = { large: 'lg', small: 'sm', middle: undefined };
|
||||
const sizeFullname = customizeSize || size;
|
||||
const sizeFullname = groupSize || customizeSize || size;
|
||||
const sizeCls = sizeFullname ? sizeClassNameMap[sizeFullname] || '' : '';
|
||||
|
||||
const iconType = innerLoading ? 'loading' : icon;
|
||||
@ -241,7 +246,7 @@ const InternalButton: React.ForwardRefRenderFunction<unknown, ButtonProps> = (pr
|
||||
[`${prefixCls}-${type}`]: type,
|
||||
[`${prefixCls}-${sizeCls}`]: sizeCls,
|
||||
[`${prefixCls}-icon-only`]: !children && children !== 0 && !!iconType,
|
||||
[`${prefixCls}-background-ghost`]: ghost && !isUnborderedButtonType(type),
|
||||
[`${prefixCls}-background-ghost`]: ghost && !isUnBorderedButtonType(type),
|
||||
[`${prefixCls}-loading`]: innerLoading,
|
||||
[`${prefixCls}-two-chinese-chars`]: hasTwoCNChar && autoInsertSpace,
|
||||
[`${prefixCls}-block`]: block,
|
||||
@ -286,7 +291,7 @@ const InternalButton: React.ForwardRefRenderFunction<unknown, ButtonProps> = (pr
|
||||
</button>
|
||||
);
|
||||
|
||||
if (isUnborderedButtonType(type)) {
|
||||
if (isUnBorderedButtonType(type)) {
|
||||
return buttonNode;
|
||||
}
|
||||
|
||||
|
@ -210,28 +210,6 @@
|
||||
.@{btnClassName}-icon-only {
|
||||
font-size: @font-size-base;
|
||||
}
|
||||
// size
|
||||
&-lg > .@{btnClassName},
|
||||
&-lg > span > .@{btnClassName} {
|
||||
.button-size(@btn-height-lg; @btn-padding-horizontal-lg; @btn-font-size-lg; 0);
|
||||
}
|
||||
&-lg .@{btnClassName}.@{btnClassName}-icon-only {
|
||||
.square(@btn-height-lg);
|
||||
padding-right: 0;
|
||||
padding-left: 0;
|
||||
}
|
||||
&-sm > .@{btnClassName},
|
||||
&-sm > span > .@{btnClassName} {
|
||||
.button-size(@btn-height-sm; @btn-padding-horizontal-sm; @font-size-base; 0);
|
||||
> .@{iconfont-css-prefix} {
|
||||
font-size: @font-size-base;
|
||||
}
|
||||
}
|
||||
&-sm .@{btnClassName}.@{btnClassName}-icon-only {
|
||||
.square(@btn-height-sm);
|
||||
padding-right: 0;
|
||||
padding-left: 0;
|
||||
}
|
||||
}
|
||||
// Base styles of buttons
|
||||
// --------------------------------------------------
|
||||
|
@ -5170,7 +5170,7 @@ exports[`renders ./components/dropdown/demo/loading.md extend context correctly
|
||||
class="ant-btn-group ant-btn-group-sm ant-dropdown-button"
|
||||
>
|
||||
<button
|
||||
class="ant-btn ant-btn-primary ant-btn-loading"
|
||||
class="ant-btn ant-btn-primary ant-btn-sm ant-btn-loading"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
@ -5201,7 +5201,7 @@ exports[`renders ./components/dropdown/demo/loading.md extend context correctly
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
class="ant-btn ant-btn-primary ant-btn-icon-only ant-dropdown-trigger"
|
||||
class="ant-btn ant-btn-primary ant-btn-sm ant-btn-icon-only ant-dropdown-trigger"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
|
@ -534,7 +534,7 @@ exports[`renders ./components/dropdown/demo/loading.md correctly 1`] = `
|
||||
class="ant-btn-group ant-btn-group-sm ant-dropdown-button"
|
||||
>
|
||||
<button
|
||||
class="ant-btn ant-btn-primary ant-btn-loading"
|
||||
class="ant-btn ant-btn-primary ant-btn-sm ant-btn-loading"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
@ -565,7 +565,7 @@ exports[`renders ./components/dropdown/demo/loading.md correctly 1`] = `
|
||||
</span>
|
||||
</button>
|
||||
<button
|
||||
class="ant-btn ant-btn-primary ant-btn-icon-only ant-dropdown-trigger"
|
||||
class="ant-btn ant-btn-primary ant-btn-sm ant-btn-icon-only ant-dropdown-trigger"
|
||||
type="button"
|
||||
>
|
||||
<span
|
||||
|
Loading…
Reference in New Issue
Block a user