Skip to content

Commit

Permalink
refactor: Radio support css var (ant-design#45897)
Browse files Browse the repository at this point in the history
* refactor: Radio support css var

* refactor: Radio support css var

* refactor: Radio support css var

* refactor: Radio support css var

* refactor: Radio support css var
  • Loading branch information
JarvisArt authored Nov 16, 2023
1 parent 4f02887 commit 427d1a3
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 82 deletions.
9 changes: 7 additions & 2 deletions components/radio/group.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import { RadioGroupContextProvider } from './context';
import type { RadioChangeEvent, RadioGroupButtonStyle, RadioGroupProps } from './interface';
import Radio from './radio';
import useStyle from './style';
import useCSSVar from './style/cssVar';
import useCSSVarCls from '../config-provider/hooks/useCSSVarCls';

const RadioGroup = React.forwardRef<HTMLDivElement, RadioGroupProps>((props, ref) => {
const { getPrefixCls, direction } = React.useContext(ConfigContext);
Expand Down Expand Up @@ -49,7 +51,9 @@ const RadioGroup = React.forwardRef<HTMLDivElement, RadioGroupProps>((props, ref
const groupPrefixCls = `${prefixCls}-group`;

// Style
const [wrapSSR, hashId] = useStyle(prefixCls);
const [, hashId] = useStyle(prefixCls);
const rootCls = useCSSVarCls(prefixCls);
const wrapCSSVar = useCSSVar(rootCls);

let childrenToRender = children;
// 如果存在 options, 优先使用
Expand Down Expand Up @@ -99,8 +103,9 @@ const RadioGroup = React.forwardRef<HTMLDivElement, RadioGroupProps>((props, ref
className,
rootClassName,
hashId,
rootCls,
);
return wrapSSR(
return wrapCSSVar(
<div
{...pickAttrs(props, { aria: true, data: true })}
className={classString}
Expand Down
9 changes: 7 additions & 2 deletions components/radio/radio.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import { FormItemInputContext } from '../form/context';
import RadioGroupContext, { RadioOptionTypeContext } from './context';
import type { RadioChangeEvent, RadioProps, RadioRef } from './interface';
import useStyle from './style';
import useCSSVar from './style/cssVar';
import useCSSVarCls from '../config-provider/hooks/useCSSVarCls';

const InternalRadio: React.ForwardRefRenderFunction<RadioRef, RadioProps> = (props, ref) => {
const groupContext = React.useContext(RadioGroupContext);
Expand Down Expand Up @@ -47,7 +49,9 @@ const InternalRadio: React.ForwardRefRenderFunction<RadioRef, RadioProps> = (pro
const prefixCls = isButtonType ? `${radioPrefixCls}-button` : radioPrefixCls;

// Style
const [wrapSSR, hashId] = useStyle(radioPrefixCls);
const [, hashId] = useStyle(radioPrefixCls);
const rootCls = useCSSVarCls(radioPrefixCls);
const wrapCSSVar = useCSSVar(rootCls);

const radioProps: RadioProps = { ...restProps };

Expand All @@ -74,9 +78,10 @@ const InternalRadio: React.ForwardRefRenderFunction<RadioRef, RadioProps> = (pro
className,
rootClassName,
hashId,
rootCls,
);

return wrapSSR(
return wrapCSSVar(
<Wave component="Radio" disabled={radioProps.disabled}>
{/* eslint-disable-next-line jsx-a11y/label-has-associated-control */}
<label
Expand Down
9 changes: 9 additions & 0 deletions components/radio/style/cssVar.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { genCSSVarRegister } from '../../theme/internal';
import { prepareComponentToken } from '.';

export default genCSSVarRegister('Radio', prepareComponentToken, {
unitless: {
radioSize: true,
dotSize: true,
},
});
167 changes: 89 additions & 78 deletions components/radio/style/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { unit } from '@ant-design/cssinjs';
import { genFocusOutline, resetComponent } from '../../style';
import type { FullToken, GenerateStyle } from '../../theme/internal';
import type { FullToken, GenerateStyle, GetDefaultToken } from '../../theme/internal';
import { genComponentStyleHook, mergeToken } from '../../theme/internal';

// ============================== Tokens ==============================
Expand Down Expand Up @@ -77,10 +78,14 @@ export interface ComponentToken {
* @descEN Margin right of Radio button
*/
wrapperMarginInlineEnd: number;

/** @internal */
radioColor: string;
/** @internal */
radioBgColor: string;
}

interface RadioToken extends FullToken<'Radio'> {
radioDotDisabledSize: number;
radioFocusShadow: string;
radioButtonFocusShadow: string;
}
Expand Down Expand Up @@ -126,18 +131,21 @@ const getRadioBasicStyle: GenerateStyle<RadioToken> = (token) => {
colorBgContainer,
colorBorder,
lineWidth,
dotSize,
colorBgContainerDisabled,
colorTextDisabled,
paddingXS,
dotColorDisabled,
lineType,
radioDotDisabledSize,
wireframe,
colorWhite,
radioColor,
radioBgColor,
calc,
} = token;
const radioInnerPrefixCls = `${componentCls}-inner`;

const dotPadding = 4;
const radioDotDisabledSize = calc(radioSize).sub(calc(dotPadding).mul(2));
const radioSizeCalc = calc(1).mul(radioSize).equal();

return {
[`${componentCls}-wrapper`]: {
...resetComponent(token),
Expand Down Expand Up @@ -171,7 +179,7 @@ const getRadioBasicStyle: GenerateStyle<RadioToken> = (token) => {
insetInlineStart: 0,
width: '100%',
height: '100%',
border: `${lineWidth}px ${lineType} ${colorPrimary}`,
border: `${unit(lineWidth)} ${lineType} ${colorPrimary}`,
borderRadius: '50%',
visibility: 'hidden',
content: '""',
Expand Down Expand Up @@ -207,14 +215,14 @@ const getRadioBasicStyle: GenerateStyle<RadioToken> = (token) => {
insetBlockStart: '50%',
insetInlineStart: '50%',
display: 'block',
width: radioSize,
height: radioSize,
marginBlockStart: radioSize / -2,
marginInlineStart: radioSize / -2,
backgroundColor: wireframe ? colorPrimary : colorWhite,
width: radioSizeCalc,
height: radioSizeCalc,
marginBlockStart: calc(1).mul(radioSize).div(-2).equal(),
marginInlineStart: calc(1).mul(radioSize).div(-2).equal(),
backgroundColor: radioColor,
borderBlockStart: 0,
borderInlineStart: 0,
borderRadius: radioSize,
borderRadius: radioSizeCalc,
transform: 'scale(0)',
opacity: 0,
transition: `all ${motionDurationSlow} ${motionEaseInOutCirc}`,
Expand All @@ -226,8 +234,8 @@ const getRadioBasicStyle: GenerateStyle<RadioToken> = (token) => {
insetBlockStart: 0,
insetInlineStart: 0,
display: 'block',
width: radioSize,
height: radioSize,
width: radioSizeCalc,
height: radioSizeCalc,
backgroundColor: colorBgContainer,
borderColor: colorBorder,
borderStyle: 'solid',
Expand All @@ -248,10 +256,10 @@ const getRadioBasicStyle: GenerateStyle<RadioToken> = (token) => {
[`${componentCls}-checked`]: {
[radioInnerPrefixCls]: {
borderColor: colorPrimary,
backgroundColor: wireframe ? colorBgContainer : colorPrimary,
backgroundColor: radioBgColor,

'&::after': {
transform: `scale(${dotSize / radioSize})`,
transform: `scale(${token.calc(token.dotSize).div(radioSize).equal()})`,
opacity: 1,
transition: `all ${motionDurationSlow} ${motionEaseInOutCirc}`,
},
Expand Down Expand Up @@ -283,7 +291,9 @@ const getRadioBasicStyle: GenerateStyle<RadioToken> = (token) => {
[`&${componentCls}-checked`]: {
[radioInnerPrefixCls]: {
'&::after': {
transform: `scale(${radioDotDisabledSize / radioSize})`,
transform: `scale(${calc(radioDotDisabledSize)
.div(radioSize)
.equal({ unit: false })})`,
},
},
},
Expand Down Expand Up @@ -330,6 +340,7 @@ const getRadioButtonStyle: GenerateStyle<RadioToken> = (token) => {
buttonSolidCheckedBg,
buttonSolidCheckedHoverBg,
buttonSolidCheckedActiveBg,
calc,
} = token;
return {
[`${componentCls}-button-wrapper`]: {
Expand All @@ -341,12 +352,12 @@ const getRadioButtonStyle: GenerateStyle<RadioToken> = (token) => {
paddingBlock: 0,
color: buttonColor,
fontSize,
lineHeight: `${controlHeight - lineWidth * 2}px`,
lineHeight: unit(calc(controlHeight).sub(calc(lineWidth).mul(2)).equal()),
background: buttonBg,
border: `${lineWidth}px ${lineType} ${colorBorder}`,
border: `${unit(lineWidth)} ${lineType} ${colorBorder}`,
// strange align fix for chrome but works
// https://gw.alipayobjects.com/zos/rmsportal/VFTfKXJuogBAXcvfAUWJ.gif
borderBlockStartWidth: lineWidth + 0.02,
borderBlockStartWidth: calc(lineWidth).add(0.02).equal(),
borderInlineStartWidth: 0,
borderInlineEndWidth: lineWidth,
cursor: 'pointer',
Expand All @@ -372,8 +383,8 @@ const getRadioButtonStyle: GenerateStyle<RadioToken> = (token) => {
'&:not(:first-child)': {
'&::before': {
position: 'absolute',
insetBlockStart: -lineWidth,
insetInlineStart: -lineWidth,
insetBlockStart: calc(lineWidth).mul(-1).equal(),
insetInlineStart: calc(lineWidth).mul(-1).equal(),
display: 'block',
boxSizing: 'content-box',
width: 1,
Expand All @@ -387,7 +398,7 @@ const getRadioButtonStyle: GenerateStyle<RadioToken> = (token) => {
},

'&:first-child': {
borderInlineStart: `${lineWidth}px ${lineType} ${colorBorder}`,
borderInlineStart: `${unit(lineWidth)} ${lineType} ${colorBorder}`,
borderStartStartRadius: borderRadius,
borderEndStartRadius: borderRadius,
},
Expand All @@ -404,7 +415,7 @@ const getRadioButtonStyle: GenerateStyle<RadioToken> = (token) => {
[`${componentCls}-group-large &`]: {
height: controlHeightLG,
fontSize: fontSizeLG,
lineHeight: `${controlHeightLG - lineWidth * 2}px`,
lineHeight: unit(calc(controlHeightLG).sub(calc(lineWidth).mul(2)).equal()),

'&:first-child': {
borderStartStartRadius: borderRadiusLG,
Expand All @@ -419,9 +430,9 @@ const getRadioButtonStyle: GenerateStyle<RadioToken> = (token) => {

[`${componentCls}-group-small &`]: {
height: controlHeightSM,
paddingInline: paddingXS - lineWidth,
paddingInline: calc(paddingXS).sub(lineWidth).equal(),
paddingBlock: 0,
lineHeight: `${controlHeightSM - lineWidth * 2}px`,
lineHeight: unit(calc(controlHeightSM).sub(calc(lineWidth).mul(2)).equal()),

'&:first-child': {
borderStartStartRadius: borderRadiusSM,
Expand Down Expand Up @@ -524,23 +535,65 @@ const getRadioButtonStyle: GenerateStyle<RadioToken> = (token) => {
};
};

const getDotSize = (radioSize: number): number => {
const dotPadding = 4; // Fixed Value
return radioSize - dotPadding * 2;
// ============================== Export ==============================
export const prepareComponentToken: GetDefaultToken<'Radio'> = (token) => {
const {
wireframe,
padding,
marginXS,
lineWidth,
fontSizeLG,
colorText,
colorBgContainer,
colorTextDisabled,
controlItemBgActiveDisabled,
colorTextLightSolid,
colorPrimary,
colorPrimaryHover,
colorPrimaryActive,
colorWhite,
} = token;

const dotPadding = 4; // Fixed value
const radioSize = fontSizeLG;
const radioDotSize = wireframe
? radioSize - dotPadding * 2
: radioSize - (dotPadding + lineWidth) * 2;

return {
// Radio
radioSize,
dotSize: radioDotSize,
dotColorDisabled: colorTextDisabled,

// Radio buttons
buttonSolidCheckedColor: colorTextLightSolid,
buttonSolidCheckedBg: colorPrimary,
buttonSolidCheckedHoverBg: colorPrimaryHover,
buttonSolidCheckedActiveBg: colorPrimaryActive,
buttonBg: colorBgContainer,
buttonCheckedBg: colorBgContainer,
buttonColor: colorText,
buttonCheckedBgDisabled: controlItemBgActiveDisabled,
buttonCheckedColorDisabled: colorTextDisabled,
buttonPaddingInline: padding - lineWidth,
wrapperMarginInlineEnd: marginXS,

// internal
radioColor: wireframe ? colorPrimary : colorWhite,
radioBgColor: wireframe ? colorBgContainer : colorPrimary,
};
};

// ============================== Export ==============================
export default genComponentStyleHook(
'Radio',
(token) => {
const { controlOutline, controlOutlineWidth, radioSize } = token;
const { controlOutline, controlOutlineWidth } = token;

const radioFocusShadow = `0 0 0 ${controlOutlineWidth}px ${controlOutline}`;
const radioFocusShadow = `0 0 0 ${unit(controlOutlineWidth)} ${controlOutline}`;
const radioButtonFocusShadow = radioFocusShadow;
const radioDotDisabledSize = getDotSize(radioSize);

const radioToken = mergeToken<RadioToken>(token, {
radioDotDisabledSize,
radioFocusShadow,
radioButtonFocusShadow,
});
Expand All @@ -551,47 +604,5 @@ export default genComponentStyleHook(
getRadioButtonStyle(radioToken),
];
},
(token) => {
const {
wireframe,
padding,
marginXS,
lineWidth,
fontSizeLG,
colorText,
colorBgContainer,
colorTextDisabled,
controlItemBgActiveDisabled,
colorTextLightSolid,
colorPrimary,
colorPrimaryHover,
colorPrimaryActive,
} = token;

const dotPadding = 4; // Fixed value
const radioSize = fontSizeLG;
const radioDotSize = wireframe
? getDotSize(radioSize)
: radioSize - (dotPadding + lineWidth) * 2;

return {
// Radio
radioSize,
dotSize: radioDotSize,
dotColorDisabled: colorTextDisabled,

// Radio buttons
buttonSolidCheckedColor: colorTextLightSolid,
buttonSolidCheckedBg: colorPrimary,
buttonSolidCheckedHoverBg: colorPrimaryHover,
buttonSolidCheckedActiveBg: colorPrimaryActive,
buttonBg: colorBgContainer,
buttonCheckedBg: colorBgContainer,
buttonColor: colorText,
buttonCheckedBgDisabled: controlItemBgActiveDisabled,
buttonCheckedColorDisabled: colorTextDisabled,
buttonPaddingInline: padding - lineWidth,
wrapperMarginInlineEnd: marginXS,
};
},
prepareComponentToken,
);

0 comments on commit 427d1a3

Please sign in to comment.