feat(radio): add 'block' argument for Radio.Group (#50828)

Co-authored-by: afc163 <afc163@gmail.com>
Co-authored-by: liuyuan <yuanliu147@qq.com>
This commit is contained in:
yuanliu 2024-09-16 17:21:55 +08:00 committed by GitHub
parent 7a521ab908
commit 5a2818600c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 444 additions and 2 deletions

View File

@ -1000,6 +1000,201 @@ exports[`renders components/radio/demo/radiogroup.tsx extend context correctly 1
exports[`renders components/radio/demo/radiogroup.tsx extend context correctly 2`] = `[]`; exports[`renders components/radio/demo/radiogroup.tsx extend context correctly 2`] = `[]`;
exports[`renders components/radio/demo/radiogroup-block.tsx extend context correctly 1`] = `
<div
class="ant-flex ant-flex-align-stretch ant-flex-gap-middle ant-flex-vertical"
>
<div
class="ant-radio-group ant-radio-group-outline ant-radio-group-block"
>
<label
class="ant-radio-wrapper ant-radio-wrapper-checked ant-radio-wrapper-block"
>
<span
class="ant-radio ant-wave-target ant-radio-checked"
>
<input
checked=""
class="ant-radio-input"
type="radio"
value="Apple"
/>
<span
class="ant-radio-inner"
/>
</span>
<span>
Apple
</span>
</label>
<label
class="ant-radio-wrapper ant-radio-wrapper-block"
>
<span
class="ant-radio ant-wave-target"
>
<input
class="ant-radio-input"
type="radio"
value="Pear"
/>
<span
class="ant-radio-inner"
/>
</span>
<span>
Pear
</span>
</label>
<label
class="ant-radio-wrapper ant-radio-wrapper-block"
>
<span
class="ant-radio ant-wave-target"
>
<input
class="ant-radio-input"
type="radio"
value="Orange"
/>
<span
class="ant-radio-inner"
/>
</span>
<span>
Orange
</span>
</label>
</div>
<div
class="ant-radio-group ant-radio-group-solid ant-radio-group-block"
>
<label
class="ant-radio-button-wrapper ant-radio-button-wrapper-checked ant-radio-button-wrapper-block"
>
<span
class="ant-radio-button ant-radio-button-checked"
>
<input
checked=""
class="ant-radio-button-input"
type="radio"
value="Apple"
/>
<span
class="ant-radio-button-inner"
/>
</span>
<span>
Apple
</span>
</label>
<label
class="ant-radio-button-wrapper ant-radio-button-wrapper-block"
>
<span
class="ant-radio-button"
>
<input
class="ant-radio-button-input"
type="radio"
value="Pear"
/>
<span
class="ant-radio-button-inner"
/>
</span>
<span>
Pear
</span>
</label>
<label
class="ant-radio-button-wrapper ant-radio-button-wrapper-block"
>
<span
class="ant-radio-button"
>
<input
class="ant-radio-button-input"
type="radio"
value="Orange"
/>
<span
class="ant-radio-button-inner"
/>
</span>
<span>
Orange
</span>
</label>
</div>
<div
class="ant-radio-group ant-radio-group-outline ant-radio-group-block"
>
<label
class="ant-radio-button-wrapper ant-radio-button-wrapper-block"
>
<span
class="ant-radio-button"
>
<input
class="ant-radio-button-input"
type="radio"
value="Apple"
/>
<span
class="ant-radio-button-inner"
/>
</span>
<span>
Apple
</span>
</label>
<label
class="ant-radio-button-wrapper ant-radio-button-wrapper-checked ant-radio-button-wrapper-block"
>
<span
class="ant-radio-button ant-radio-button-checked"
>
<input
checked=""
class="ant-radio-button-input"
type="radio"
value="Pear"
/>
<span
class="ant-radio-button-inner"
/>
</span>
<span>
Pear
</span>
</label>
<label
class="ant-radio-button-wrapper ant-radio-button-wrapper-block"
>
<span
class="ant-radio-button"
>
<input
class="ant-radio-button-input"
type="radio"
value="Orange"
/>
<span
class="ant-radio-button-inner"
/>
</span>
<span>
Orange
</span>
</label>
</div>
</div>
`;
exports[`renders components/radio/demo/radiogroup-block.tsx extend context correctly 2`] = `[]`;
exports[`renders components/radio/demo/radiogroup-more.tsx extend context correctly 1`] = ` exports[`renders components/radio/demo/radiogroup-more.tsx extend context correctly 1`] = `
<div <div
class="ant-radio-group ant-radio-group-outline" class="ant-radio-group ant-radio-group-outline"

View File

@ -986,6 +986,199 @@ exports[`renders components/radio/demo/radiogroup.tsx correctly 1`] = `
</div> </div>
`; `;
exports[`renders components/radio/demo/radiogroup-block.tsx correctly 1`] = `
<div
class="ant-flex ant-flex-align-stretch ant-flex-gap-middle ant-flex-vertical"
>
<div
class="ant-radio-group ant-radio-group-outline ant-radio-group-block"
>
<label
class="ant-radio-wrapper ant-radio-wrapper-checked ant-radio-wrapper-block"
>
<span
class="ant-radio ant-wave-target ant-radio-checked"
>
<input
checked=""
class="ant-radio-input"
type="radio"
value="Apple"
/>
<span
class="ant-radio-inner"
/>
</span>
<span>
Apple
</span>
</label>
<label
class="ant-radio-wrapper ant-radio-wrapper-block"
>
<span
class="ant-radio ant-wave-target"
>
<input
class="ant-radio-input"
type="radio"
value="Pear"
/>
<span
class="ant-radio-inner"
/>
</span>
<span>
Pear
</span>
</label>
<label
class="ant-radio-wrapper ant-radio-wrapper-block"
>
<span
class="ant-radio ant-wave-target"
>
<input
class="ant-radio-input"
type="radio"
value="Orange"
/>
<span
class="ant-radio-inner"
/>
</span>
<span>
Orange
</span>
</label>
</div>
<div
class="ant-radio-group ant-radio-group-solid ant-radio-group-block"
>
<label
class="ant-radio-button-wrapper ant-radio-button-wrapper-checked ant-radio-button-wrapper-block"
>
<span
class="ant-radio-button ant-radio-button-checked"
>
<input
checked=""
class="ant-radio-button-input"
type="radio"
value="Apple"
/>
<span
class="ant-radio-button-inner"
/>
</span>
<span>
Apple
</span>
</label>
<label
class="ant-radio-button-wrapper ant-radio-button-wrapper-block"
>
<span
class="ant-radio-button"
>
<input
class="ant-radio-button-input"
type="radio"
value="Pear"
/>
<span
class="ant-radio-button-inner"
/>
</span>
<span>
Pear
</span>
</label>
<label
class="ant-radio-button-wrapper ant-radio-button-wrapper-block"
>
<span
class="ant-radio-button"
>
<input
class="ant-radio-button-input"
type="radio"
value="Orange"
/>
<span
class="ant-radio-button-inner"
/>
</span>
<span>
Orange
</span>
</label>
</div>
<div
class="ant-radio-group ant-radio-group-outline ant-radio-group-block"
>
<label
class="ant-radio-button-wrapper ant-radio-button-wrapper-block"
>
<span
class="ant-radio-button"
>
<input
class="ant-radio-button-input"
type="radio"
value="Apple"
/>
<span
class="ant-radio-button-inner"
/>
</span>
<span>
Apple
</span>
</label>
<label
class="ant-radio-button-wrapper ant-radio-button-wrapper-checked ant-radio-button-wrapper-block"
>
<span
class="ant-radio-button ant-radio-button-checked"
>
<input
checked=""
class="ant-radio-button-input"
type="radio"
value="Pear"
/>
<span
class="ant-radio-button-inner"
/>
</span>
<span>
Pear
</span>
</label>
<label
class="ant-radio-button-wrapper ant-radio-button-wrapper-block"
>
<span
class="ant-radio-button"
>
<input
class="ant-radio-button-input"
type="radio"
value="Orange"
/>
<span
class="ant-radio-button-inner"
/>
</span>
<span>
Orange
</span>
</label>
</div>
</div>
`;
exports[`renders components/radio/demo/radiogroup-more.tsx correctly 1`] = ` exports[`renders components/radio/demo/radiogroup-more.tsx correctly 1`] = `
<div <div
class="ant-radio-group ant-radio-group-outline" class="ant-radio-group ant-radio-group-outline"

View File

@ -0,0 +1,7 @@
## zh-CN
`block` 属性将使 Radio.Group 撑满父容器。
## en-US
The `block` property will make a Radio.Group fit to its parent width.

View File

@ -0,0 +1,24 @@
import React from 'react';
import { Flex, Radio } from 'antd';
const options = [
{ label: 'Apple', value: 'Apple' },
{ label: 'Pear', value: 'Pear' },
{ label: 'Orange', value: 'Orange' },
];
const App: React.FC = () => (
<Flex vertical gap="middle">
<Radio.Group block options={options} defaultValue="Apple" />
<Radio.Group
block
options={options}
defaultValue="Apple"
optionType="button"
buttonStyle="solid"
/>
<Radio.Group block options={options} defaultValue="Pear" optionType="button" />
</Flex>
);
export default App;

View File

@ -34,6 +34,7 @@ const RadioGroup = React.forwardRef<HTMLDivElement, RadioGroupProps>((props, ref
name, name,
defaultValue, defaultValue,
value: customizedValue, value: customizedValue,
block = false,
onChange, onChange,
onMouseEnter, onMouseEnter,
onMouseLeave, onMouseLeave,
@ -111,6 +112,7 @@ const RadioGroup = React.forwardRef<HTMLDivElement, RadioGroupProps>((props, ref
{ {
[`${groupPrefixCls}-${mergedSize}`]: mergedSize, [`${groupPrefixCls}-${mergedSize}`]: mergedSize,
[`${groupPrefixCls}-rtl`]: direction === 'rtl', [`${groupPrefixCls}-rtl`]: direction === 'rtl',
[`${groupPrefixCls}-block`]: block,
}, },
className, className,
rootClassName, rootClassName,
@ -120,8 +122,8 @@ const RadioGroup = React.forwardRef<HTMLDivElement, RadioGroupProps>((props, ref
); );
const memoizedValue = React.useMemo<RadioGroupContextProps>( const memoizedValue = React.useMemo<RadioGroupContextProps>(
() => ({ onChange: onRadioChange, value, disabled, name, optionType }), () => ({ onChange: onRadioChange, value, disabled, name, optionType, block }),
[onRadioChange, value, disabled, name, optionType], [onRadioChange, value, disabled, name, optionType, block],
); );
return wrapCSSVar( return wrapCSSVar(

View File

@ -21,6 +21,7 @@ demo:
<code src="./demo/disabled.tsx">disabled</code> <code src="./demo/disabled.tsx">disabled</code>
<code src="./demo/radiogroup.tsx">Radio Group</code> <code src="./demo/radiogroup.tsx">Radio Group</code>
<code src="./demo/radiogroup-more.tsx">Vertical Radio.Group</code> <code src="./demo/radiogroup-more.tsx">Vertical Radio.Group</code>
<code src="./demo/radiogroup-block.tsx" version="5.21.0">Block Radio.Group</code>
<code src="./demo/radiogroup-options.tsx">Radio.Group group - optional</code> <code src="./demo/radiogroup-options.tsx">Radio.Group group - optional</code>
<code src="./demo/radiobutton.tsx">radio style</code> <code src="./demo/radiobutton.tsx">radio style</code>
<code src="./demo/radiogroup-with-name.tsx">Radio.Group with name</code> <code src="./demo/radiogroup-with-name.tsx">Radio.Group with name</code>
@ -59,6 +60,7 @@ Radio group can wrap a group of `Radio`。
| optionType | Set Radio optionType | `default` \| `button` | `default` | 4.4.0 | | optionType | Set Radio optionType | `default` \| `button` | `default` | 4.4.0 |
| size | The size of radio button style | `large` \| `middle` \| `small` | - | | | size | The size of radio button style | `large` \| `middle` \| `small` | - | |
| value | Used for setting the currently selected value | any | - | | | value | Used for setting the currently selected value | any | - | |
| block | Option to fit RadioGroup width to its parent width | boolean | false | 5.21.0 |
| onChange | The callback function that is triggered when the state changes | function(e:Event) | - | | | onChange | The callback function that is triggered when the state changes | function(e:Event) | - | |
### CheckboxOptionType ### CheckboxOptionType

View File

@ -22,6 +22,7 @@ demo:
<code src="./demo/disabled.tsx">不可用</code> <code src="./demo/disabled.tsx">不可用</code>
<code src="./demo/radiogroup.tsx">单选组合</code> <code src="./demo/radiogroup.tsx">单选组合</code>
<code src="./demo/radiogroup-more.tsx">Radio.Group 垂直</code> <code src="./demo/radiogroup-more.tsx">Radio.Group 垂直</code>
<code src="./demo/radiogroup-block.tsx" version="5.21.0">Block 单选组合</code>
<code src="./demo/radiogroup-options.tsx">Radio.Group 组合 - 配置方式</code> <code src="./demo/radiogroup-options.tsx">Radio.Group 组合 - 配置方式</code>
<code src="./demo/radiobutton.tsx">按钮样式</code> <code src="./demo/radiobutton.tsx">按钮样式</code>
<code src="./demo/radiogroup-with-name.tsx">单选组合 - 配合 name 使用</code> <code src="./demo/radiogroup-with-name.tsx">单选组合 - 配合 name 使用</code>
@ -62,6 +63,7 @@ demo:
| optionType | 用于设置 Radio `options` 类型 | `default` \| `button` | `default` | 4.4.0 | | | optionType | 用于设置 Radio `options` 类型 | `default` \| `button` | `default` | 4.4.0 | |
| size | 大小,只对按钮样式生效 | `large` \| `middle` \| `small` | - | | | | size | 大小,只对按钮样式生效 | `large` \| `middle` \| `small` | - | | |
| value | 用于设置当前选中的值 | any | - | | | | value | 用于设置当前选中的值 | any | - | | |
| block | 将 RadioGroup 宽度调整为其父宽度的选项 | boolean | false | 5.21.0 | |
| onChange | 选项变化时的回调函数 | function(e:Event) | - | | | | onChange | 选项变化时的回调函数 | function(e:Event) | - | | |
### CheckboxOptionType ### CheckboxOptionType

View File

@ -23,6 +23,7 @@ export interface RadioGroupProps extends AbstractCheckboxGroupProps {
buttonStyle?: RadioGroupButtonStyle; buttonStyle?: RadioGroupButtonStyle;
onFocus?: React.FocusEventHandler<HTMLDivElement>; onFocus?: React.FocusEventHandler<HTMLDivElement>;
onBlur?: React.FocusEventHandler<HTMLDivElement>; onBlur?: React.FocusEventHandler<HTMLDivElement>;
block?: boolean;
} }
export interface RadioGroupContextProps { export interface RadioGroupContextProps {
@ -37,6 +38,7 @@ export interface RadioGroupContextProps {
* @internal * @internal
*/ */
optionType?: RadioGroupOptionType; optionType?: RadioGroupOptionType;
block?: boolean;
} }
export interface RadioProps extends AbstractCheckboxProps<RadioChangeEvent> { export interface RadioProps extends AbstractCheckboxProps<RadioChangeEvent> {

View File

@ -72,6 +72,7 @@ const InternalRadio: React.ForwardRefRenderFunction<RadioRef, RadioProps> = (pro
[`${prefixCls}-wrapper-disabled`]: radioProps.disabled, [`${prefixCls}-wrapper-disabled`]: radioProps.disabled,
[`${prefixCls}-wrapper-rtl`]: direction === 'rtl', [`${prefixCls}-wrapper-rtl`]: direction === 'rtl',
[`${prefixCls}-wrapper-in-form-item`]: isFormItemInput, [`${prefixCls}-wrapper-in-form-item`]: isFormItemInput,
[`${prefixCls}-wrapper-block`]: !!groupContext?.block,
}, },
radio?.className, radio?.className,
className, className,

View File

@ -120,6 +120,10 @@ const getGroupRadioStyle: GenerateStyle<RadioToken> = (token) => {
direction: 'rtl', direction: 'rtl',
}, },
[`&${groupPrefixCls}-block`]: {
display: 'flex',
},
[`${antCls}-badge ${antCls}-badge-count`]: { [`${antCls}-badge ${antCls}-badge-count`]: {
zIndex: 1, zIndex: 1,
}, },
@ -185,6 +189,11 @@ const getRadioBasicStyle: GenerateStyle<RadioToken> = (token) => {
content: '"\\a0"', content: '"\\a0"',
}, },
'&-block': {
flex: 1,
justifyContent: 'center',
},
// hashId 在 wrapper 上,只能铺平 // hashId 在 wrapper 上,只能铺平
[`${componentCls}-checked::after`]: { [`${componentCls}-checked::after`]: {
position: 'absolute', position: 'absolute',
@ -543,6 +552,11 @@ const getRadioButtonStyle: GenerateStyle<RadioToken> = (token) => {
borderColor: colorBorder, borderColor: colorBorder,
boxShadow: 'none', boxShadow: 'none',
}, },
'&-block': {
flex: 1,
textAlign: 'center',
},
}, },
}; };
}; };