refactor: Slider support css var (#45866)

This commit is contained in:
MadCcc 2023-11-14 15:59:23 +08:00 committed by GitHub
parent b2300fa2d3
commit 48402ca44f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 95 additions and 86 deletions

View File

@ -10,6 +10,7 @@ import DisabledContext from '../config-provider/DisabledContext';
import type { AbstractTooltipProps, TooltipPlacement } from '../tooltip'; import type { AbstractTooltipProps, TooltipPlacement } from '../tooltip';
import SliderTooltip from './SliderTooltip'; import SliderTooltip from './SliderTooltip';
import useStyle from './style'; import useStyle from './style';
import useCSSVar from './style/cssVar';
export type SliderMarks = RcSliderProps['marks']; export type SliderMarks = RcSliderProps['marks'];
@ -158,7 +159,8 @@ const Slider = React.forwardRef<SliderRef, SliderSingleProps | SliderRangeProps>
const prefixCls = getPrefixCls('slider', customizePrefixCls); const prefixCls = getPrefixCls('slider', customizePrefixCls);
const [wrapSSR, hashId] = useStyle(prefixCls); const [, hashId] = useStyle(prefixCls);
const wrapCSSVar = useCSSVar(prefixCls);
const cls = classNames( const cls = classNames(
className, className,
@ -255,7 +257,7 @@ const Slider = React.forwardRef<SliderRef, SliderSingleProps | SliderRangeProps>
const mergedStyle: React.CSSProperties = { ...slider?.style, ...style }; const mergedStyle: React.CSSProperties = { ...slider?.style, ...style };
return wrapSSR( return wrapCSSVar(
<RcSlider <RcSlider
{...restProps} {...restProps}
step={restProps.step} step={restProps.step}

View File

@ -0,0 +1,4 @@
import { genCSSVarRegister } from '../../theme/internal';
import { prepareComponentToken } from '.';
export default genCSSVarRegister('Slider', prepareComponentToken);

View File

@ -3,8 +3,9 @@ import type { CSSObject } from '@ant-design/cssinjs';
import { TinyColor } from '@ctrl/tinycolor'; import { TinyColor } from '@ctrl/tinycolor';
import { resetComponent } from '../../style'; import { resetComponent } from '../../style';
import type { FullToken, GenerateStyle } from '../../theme/internal'; import type { FullToken, GenerateStyle, GetDefaultToken } from '../../theme/internal';
import { genComponentStyleHook, mergeToken } from '../../theme/internal'; import { genComponentStyleHook, mergeToken } from '../../theme/internal';
import { unit } from '@ant-design/cssinjs';
// Direction naming standard: // Direction naming standard:
// Horizontal base: // Horizontal base:
@ -60,9 +61,9 @@ export interface ComponentToken {
} }
interface SliderToken extends FullToken<'Slider'> { interface SliderToken extends FullToken<'Slider'> {
marginFull: number; marginFull: number | string;
marginPart: number; marginPart: number | string;
marginPartWithMark: number; marginPartWithMark: number | string;
} }
// =============================== Base =============================== // =============================== Base ===============================
@ -75,6 +76,7 @@ const genBaseStyle: GenerateStyle<SliderToken> = (token) => {
marginFull, marginFull,
marginPart, marginPart,
colorFillContentHover, colorFillContentHover,
calc,
} = token; } = token;
return { return {
@ -83,13 +85,13 @@ const genBaseStyle: GenerateStyle<SliderToken> = (token) => {
position: 'relative', position: 'relative',
height: controlSize, height: controlSize,
margin: `${marginPart}px ${marginFull}px`, margin: `${unit(marginPart)} ${unit(marginFull)}`,
padding: 0, padding: 0,
cursor: 'pointer', cursor: 'pointer',
touchAction: 'none', touchAction: 'none',
[`&-vertical`]: { [`&-vertical`]: {
margin: `${marginFull}px ${marginPart}px`, margin: `${unit(marginFull)} ${unit(marginPart)}`,
}, },
[`${componentCls}-rail`]: { [`${componentCls}-rail`]: {
@ -129,7 +131,7 @@ const genBaseStyle: GenerateStyle<SliderToken> = (token) => {
}, },
[`${componentCls}-handle::after`]: { [`${componentCls}-handle::after`]: {
boxShadow: `0 0 0 ${token.handleLineWidth}px ${token.colorPrimaryBorderHover}`, boxShadow: `0 0 0 ${unit(token.handleLineWidth)} ${token.colorPrimaryBorderHover}`,
}, },
[`${componentCls}-dot-active`]: { [`${componentCls}-dot-active`]: {
@ -147,10 +149,10 @@ const genBaseStyle: GenerateStyle<SliderToken> = (token) => {
'&::before': { '&::before': {
content: '""', content: '""',
position: 'absolute', position: 'absolute',
insetInlineStart: -token.handleLineWidth, insetInlineStart: calc(token.handleLineWidth).mul(-1).equal(),
insetBlockStart: -token.handleLineWidth, insetBlockStart: calc(token.handleLineWidth).mul(-1).equal(),
width: token.handleSize + token.handleLineWidth * 2, width: calc(token.handleSize).add(calc(token.handleLineWidth).mul(2)).equal(),
height: token.handleSize + token.handleLineWidth * 2, height: calc(token.handleSize).add(calc(token.handleLineWidth).mul(2)).equal(),
backgroundColor: 'transparent', backgroundColor: 'transparent',
}, },
@ -162,7 +164,7 @@ const genBaseStyle: GenerateStyle<SliderToken> = (token) => {
width: token.handleSize, width: token.handleSize,
height: token.handleSize, height: token.handleSize,
backgroundColor: token.colorBgElevated, backgroundColor: token.colorBgElevated,
boxShadow: `0 0 0 ${token.handleLineWidth}px ${token.handleColor}`, boxShadow: `0 0 0 ${unit(token.handleLineWidth)} ${token.handleColor}`,
borderRadius: '50%', borderRadius: '50%',
cursor: 'pointer', cursor: 'pointer',
transition: ` transition: `
@ -176,24 +178,38 @@ const genBaseStyle: GenerateStyle<SliderToken> = (token) => {
'&:hover, &:active, &:focus': { '&:hover, &:active, &:focus': {
'&::before': { '&::before': {
insetInlineStart: -( // -(
(token.handleSizeHover - token.handleSize) / 2 + // (token.handleSizeHover - token.handleSize) / 2 +
token.handleLineWidthHover // token.handleLineWidthHover
), // ),
insetBlockStart: -( insetInlineStart: calc(token.handleSizeHover)
(token.handleSizeHover - token.handleSize) / 2 + .sub(token.handleSize)
token.handleLineWidthHover .div(2)
), .add(token.handleLineWidthHover)
width: token.handleSizeHover + token.handleLineWidthHover * 2, .mul(-1)
height: token.handleSizeHover + token.handleLineWidthHover * 2, .equal(),
insetBlockStart: calc(token.handleSizeHover)
.sub(token.handleSize)
.div(2)
.add(token.handleLineWidthHover)
.mul(-1)
.equal(),
width: calc(token.handleSizeHover).add(calc(token.handleLineWidthHover).mul(2)).equal(),
height: calc(token.handleSizeHover)
.add(calc(token.handleLineWidthHover).mul(2))
.equal(),
}, },
'&::after': { '&::after': {
boxShadow: `0 0 0 ${token.handleLineWidthHover}px ${token.handleActiveColor}`, boxShadow: `0 0 0 ${unit(token.handleLineWidthHover)} ${token.handleActiveColor}`,
width: token.handleSizeHover, width: token.handleSizeHover,
height: token.handleSizeHover, height: token.handleSizeHover,
insetInlineStart: (token.handleSize - token.handleSizeHover) / 2, insetInlineStart: token
insetBlockStart: (token.handleSize - token.handleSizeHover) / 2, .calc(token.handleSize)
.sub(token.handleSizeHover)
.div(2)
.equal(),
insetBlockStart: token.calc(token.handleSize).sub(token.handleSizeHover).div(2).equal(),
}, },
}, },
}, },
@ -228,7 +244,7 @@ const genBaseStyle: GenerateStyle<SliderToken> = (token) => {
width: dotSize, width: dotSize,
height: dotSize, height: dotSize,
backgroundColor: token.colorBgElevated, backgroundColor: token.colorBgElevated,
border: `${token.handleLineWidth}px solid ${token.dotBorderColor}`, border: `${unit(token.handleLineWidth)} solid ${token.dotBorderColor}`,
borderRadius: '50%', borderRadius: '50%',
cursor: 'pointer', cursor: 'pointer',
transition: `border-color ${token.motionDurationSlow}`, transition: `border-color ${token.motionDurationSlow}`,
@ -264,7 +280,7 @@ const genBaseStyle: GenerateStyle<SliderToken> = (token) => {
cursor: 'not-allowed', cursor: 'not-allowed',
width: token.handleSize, width: token.handleSize,
height: token.handleSize, height: token.handleSize,
boxShadow: `0 0 0 ${token.handleLineWidth}px ${new TinyColor(token.colorTextDisabled) boxShadow: `0 0 0 ${unit(token.handleLineWidth)} ${new TinyColor(token.colorTextDisabled)
.onBackground(token.colorBgContainer) .onBackground(token.colorBgContainer)
.toHexShortString()}`, .toHexShortString()}`,
insetInlineStart: 0, insetInlineStart: 0,
@ -288,7 +304,7 @@ const genBaseStyle: GenerateStyle<SliderToken> = (token) => {
// ============================ Horizontal ============================ // ============================ Horizontal ============================
const genDirectionStyle = (token: SliderToken, horizontal: boolean): CSSObject => { const genDirectionStyle = (token: SliderToken, horizontal: boolean): CSSObject => {
const { componentCls, railSize, handleSize, dotSize } = token; const { componentCls, railSize, handleSize, dotSize, marginFull, calc } = token;
const railPadding: keyof React.CSSProperties = horizontal ? 'paddingBlock' : 'paddingInline'; const railPadding: keyof React.CSSProperties = horizontal ? 'paddingBlock' : 'paddingInline';
const full: keyof React.CSSProperties = horizontal ? 'width' : 'height'; const full: keyof React.CSSProperties = horizontal ? 'width' : 'height';
@ -296,22 +312,22 @@ const genDirectionStyle = (token: SliderToken, horizontal: boolean): CSSObject =
const handlePos: keyof React.CSSProperties = horizontal ? 'insetBlockStart' : 'insetInlineStart'; const handlePos: keyof React.CSSProperties = horizontal ? 'insetBlockStart' : 'insetInlineStart';
const markInset: keyof React.CSSProperties = horizontal ? 'top' : 'insetInlineStart'; const markInset: keyof React.CSSProperties = horizontal ? 'top' : 'insetInlineStart';
const handlePosSize = (railSize * 3 - handleSize) / 2; const handlePosSize = calc(railSize).mul(3).sub(handleSize).div(2).equal();
const draggableBorderSize = (handleSize - railSize) / 2; const draggableBorderSize = calc(handleSize).sub(railSize).div(2).equal();
const draggableBorder: React.CSSProperties = horizontal const draggableBorder: React.CSSProperties = horizontal
? { ? {
borderWidth: `${draggableBorderSize}px 0`, borderWidth: `${unit(draggableBorderSize)} 0`,
transform: `translateY(-${draggableBorderSize}px)`, transform: `translateY(${unit(calc(draggableBorderSize).mul(-1).equal())})`,
} }
: { : {
borderWidth: `0 ${draggableBorderSize}px`, borderWidth: `0 ${unit(draggableBorderSize)}`,
transform: `translateX(-${draggableBorderSize}px)`, transform: `translateX(${unit(token.calc(draggableBorderSize).mul(-1).equal())})`,
}; };
return { return {
[railPadding]: railSize, [railPadding]: railSize,
[part]: railSize * 3, [part]: calc(railSize).mul(3).equal(),
[`${componentCls}-rail`]: { [`${componentCls}-rail`]: {
[full]: '100%', [full]: '100%',
@ -335,7 +351,10 @@ const genDirectionStyle = (token: SliderToken, horizontal: boolean): CSSObject =
insetInlineStart: 0, insetInlineStart: 0,
top: 0, top: 0,
// https://github.com/ant-design/ant-design/issues/43731 // https://github.com/ant-design/ant-design/issues/43731
[markInset]: railSize * 3 + (horizontal ? 0 : token.marginFull), [markInset]: calc(railSize)
.mul(3)
.add(horizontal ? 0 : marginFull)
.equal(),
[full]: '100%', [full]: '100%',
}, },
@ -350,7 +369,7 @@ const genDirectionStyle = (token: SliderToken, horizontal: boolean): CSSObject =
[`${componentCls}-dot`]: { [`${componentCls}-dot`]: {
position: 'absolute', position: 'absolute',
[handlePos]: (railSize - dotSize) / 2, [handlePos]: calc(railSize).sub(dotSize).div(2).equal(),
}, },
}; };
}; };
@ -382,13 +401,40 @@ const genVerticalStyle: GenerateStyle<SliderToken> = (token) => {
}; };
// ============================== Export ============================== // ============================== Export ==============================
export const prepareComponentToken: GetDefaultToken<'Slider'> = (token) => {
// Handle line width is always width-er 1px
const increaseHandleWidth = 1;
const controlSize = token.controlHeightLG / 4;
const controlSizeHover = token.controlHeightSM / 2;
const handleLineWidth = token.lineWidth + increaseHandleWidth;
const handleLineWidthHover = token.lineWidth + increaseHandleWidth * 3;
return {
controlSize,
railSize: 4,
handleSize: controlSize,
handleSizeHover: controlSizeHover,
dotSize: 8,
handleLineWidth,
handleLineWidthHover,
railBg: token.colorFillTertiary,
railHoverBg: token.colorFillSecondary,
trackBg: token.colorPrimaryBorder,
trackHoverBg: token.colorPrimaryBorderHover,
handleColor: token.colorPrimaryBorder,
handleActiveColor: token.colorPrimary,
dotBorderColor: token.colorBorderSecondary,
dotActiveBorderColor: token.colorPrimaryBorder,
trackBgDisabled: token.colorBgContainerDisabled,
};
};
export default genComponentStyleHook( export default genComponentStyleHook(
'Slider', 'Slider',
(token) => { (token) => {
const sliderToken = mergeToken<SliderToken>(token, { const sliderToken = mergeToken<SliderToken>(token, {
marginPart: (token.controlHeight - token.controlSize) / 2, marginPart: token.calc(token.controlHeight).sub(token.controlSize).div(2).equal(),
marginFull: token.controlSize / 2, marginFull: token.calc(token.controlSize).div(2).equal(),
marginPartWithMark: token.controlHeightLG - token.controlSize, marginPartWithMark: token.calc(token.controlHeightLG).sub(token.controlSize).equal(),
}); });
return [ return [
genBaseStyle(sliderToken), genBaseStyle(sliderToken),
@ -396,30 +442,5 @@ export default genComponentStyleHook(
genVerticalStyle(sliderToken), genVerticalStyle(sliderToken),
]; ];
}, },
(token) => { prepareComponentToken,
// Handle line width is always width-er 1px
const increaseHandleWidth = 1;
const controlSize = token.controlHeightLG / 4;
const controlSizeHover = token.controlHeightSM / 2;
const handleLineWidth = token.lineWidth + increaseHandleWidth;
const handleLineWidthHover = token.lineWidth + increaseHandleWidth * 3;
return {
controlSize,
railSize: 4,
handleSize: controlSize,
handleSizeHover: controlSizeHover,
dotSize: 8,
handleLineWidth,
handleLineWidthHover,
railBg: token.colorFillTertiary,
railHoverBg: token.colorFillSecondary,
trackBg: token.colorPrimaryBorder,
trackHoverBg: token.colorPrimaryBorderHover,
handleColor: token.colorPrimaryBorder,
handleActiveColor: token.colorPrimary,
dotBorderColor: token.colorBorderSecondary,
dotActiveBorderColor: token.colorPrimaryBorder,
trackBgDisabled: token.colorBgContainerDisabled,
};
},
); );

View File

@ -28,46 +28,28 @@ console.error = (msg: any) => {
async function checkCSSVar() { async function checkCSSVar() {
const ignore = [ const ignore = [
'affix',
'alert',
'anchor', 'anchor',
'auto-complete',
'avatar',
'back-top',
'badge', 'badge',
'breadcrumb', 'breadcrumb',
'calendar', 'calendar',
'carousel',
'cascader', 'cascader',
'checkbox', 'checkbox',
'collapse', 'collapse',
'color-picker', 'color-picker',
'date-picker',
'descriptions', 'descriptions',
'divider', 'divider',
'drawer', 'drawer',
'dropdown',
'float-button', 'float-button',
'grid', 'grid',
'icon', 'icon',
'image',
'layout',
'message',
'pagination', 'pagination',
'progress',
'qr-code',
'radio', 'radio',
'select',
'slider',
'space', 'space',
'steps', 'steps',
'switch', 'switch',
'table', 'table',
'tabs',
'timeline',
'tree', 'tree',
'tree-select', 'tree-select',
'upload',
]; ];
await generateCssinjs({ await generateCssinjs({