ant-design/components/segmented/style/index.ts
二货爱吃白萝卜 ec25f2230c
Merge pull request #46937 from ant-design/master
chore: feature merge master
2024-01-12 13:50:02 +08:00

289 lines
8.2 KiB
TypeScript

import type { CSSObject } from '@ant-design/cssinjs';
import { resetComponent, textEllipsis } from '../../style';
import type { FullToken, GenerateStyle, GetDefaultToken } from '../../theme/internal';
import { genStyleHooks, mergeToken } from '../../theme/internal';
import { unit } from '@ant-design/cssinjs';
export interface ComponentToken {
/**
* @desc 选项文本颜色
* @descEN Text color of item
*/
itemColor: string;
/**
* @desc 选项悬浮态文本颜色
* @descEN Text color of item when hover
*/
itemHoverColor: string;
/**
* @desc 选项悬浮态背景颜色
* @descEN Background color of item when hover
*/
itemHoverBg: string;
/**
* @desc 选项激活态背景颜色
* @descEN Background color of item when active
*/
itemActiveBg: string;
/**
* @desc 选项选中时背景颜色
* @descEN Background color of item when selected
*/
itemSelectedBg: string;
/**
* @desc 选项选中时文字颜色
* @descEN Text color of item when selected
*/
itemSelectedColor: string;
/**
* @desc Segmented 控件容器的 padding
* @descEN Padding of Segmented container
*/
trackPadding: string | number;
/**
* @desc Segmented 控件容器背景色
* @descEN Background of Segmented container
*/
trackBg: string;
}
interface SegmentedToken extends FullToken<'Segmented'> {
segmentedPaddingHorizontal: number | string;
segmentedPaddingHorizontalSM: number | string;
}
// ============================== Mixins ==============================
function getItemDisabledStyle(cls: string, token: SegmentedToken): CSSObject {
return {
[`${cls}, ${cls}:hover, ${cls}:focus`]: {
color: token.colorTextDisabled,
cursor: 'not-allowed',
},
};
}
function getItemSelectedStyle(token: SegmentedToken): CSSObject {
return {
backgroundColor: token.itemSelectedBg,
boxShadow: token.boxShadowTertiary,
};
}
const segmentedTextEllipsisCss: CSSObject = {
overflow: 'hidden',
// handle text ellipsis
...textEllipsis,
};
// ============================== Styles ==============================
const genSegmentedStyle: GenerateStyle<SegmentedToken> = (token: SegmentedToken) => {
const { componentCls } = token;
const labelHeight = token
.calc(token.controlHeight)
.sub(token.calc(token.trackPadding).mul(2))
.equal();
const labelHeightLG = token
.calc(token.controlHeightLG)
.sub(token.calc(token.trackPadding).mul(2))
.equal();
const labelHeightSM = token
.calc(token.controlHeightSM)
.sub(token.calc(token.trackPadding).mul(2))
.equal();
return {
[componentCls]: {
...resetComponent(token),
display: 'inline-block',
padding: token.trackPadding,
color: token.itemColor,
background: token.trackBg,
borderRadius: token.borderRadius,
transition: `all ${token.motionDurationMid} ${token.motionEaseInOut}`,
[`${componentCls}-group`]: {
position: 'relative',
display: 'flex',
alignItems: 'stretch',
justifyItems: 'flex-start',
width: '100%',
},
// RTL styles
[`&${componentCls}-rtl`]: {
direction: 'rtl',
},
// block styles
[`&${componentCls}-block`]: {
display: 'flex',
},
[`&${componentCls}-block ${componentCls}-item`]: {
flex: 1,
minWidth: 0,
},
// item styles
[`${componentCls}-item`]: {
position: 'relative',
textAlign: 'center',
cursor: 'pointer',
transition: `color ${token.motionDurationMid} ${token.motionEaseInOut}`,
borderRadius: token.borderRadiusSM,
// Fix Safari render bug
// https://github.com/ant-design/ant-design/issues/45250
transform: 'translateZ(0)',
'&-selected': {
...getItemSelectedStyle(token),
color: token.itemSelectedColor,
},
'&::after': {
content: '""',
position: 'absolute',
zIndex: -1,
width: '100%',
height: '100%',
top: 0,
insetInlineStart: 0,
borderRadius: 'inherit',
transition: `background-color ${token.motionDurationMid}`,
// This is mandatory to make it not clickable or hoverable
// Ref: https://github.com/ant-design/ant-design/issues/40888
pointerEvents: 'none',
},
[`&:hover:not(${componentCls}-item-selected):not(${componentCls}-item-disabled)`]: {
color: token.itemHoverColor,
'&::after': {
backgroundColor: token.itemHoverBg,
},
},
[`&:active:not(${componentCls}-item-selected):not(${componentCls}-item-disabled)`]: {
color: token.itemHoverColor,
'&::after': {
backgroundColor: token.itemActiveBg,
},
},
'&-label': {
minHeight: labelHeight,
lineHeight: unit(labelHeight),
padding: `0 ${unit(token.segmentedPaddingHorizontal)}`,
...segmentedTextEllipsisCss,
},
// syntactic sugar to add `icon` for Segmented Item
'&-icon + *': {
marginInlineStart: token.calc(token.marginSM).div(2).equal(),
},
'&-input': {
position: 'absolute',
insetBlockStart: 0,
insetInlineStart: 0,
width: 0,
height: 0,
opacity: 0,
pointerEvents: 'none',
},
},
// thumb styles
[`${componentCls}-thumb`]: {
...getItemSelectedStyle(token),
position: 'absolute',
insetBlockStart: 0,
insetInlineStart: 0,
width: 0,
height: '100%',
padding: `${unit(token.paddingXXS)} 0`,
borderRadius: token.borderRadiusSM,
[`& ~ ${componentCls}-item:not(${componentCls}-item-selected):not(${componentCls}-item-disabled)::after`]:
{
backgroundColor: 'transparent',
},
},
// size styles
[`&${componentCls}-lg`]: {
borderRadius: token.borderRadiusLG,
[`${componentCls}-item-label`]: {
minHeight: labelHeightLG,
lineHeight: unit(labelHeightLG),
padding: `0 ${unit(token.segmentedPaddingHorizontal)}`,
fontSize: token.fontSizeLG,
},
[`${componentCls}-item, ${componentCls}-thumb`]: {
borderRadius: token.borderRadius,
},
},
[`&${componentCls}-sm`]: {
borderRadius: token.borderRadiusSM,
[`${componentCls}-item-label`]: {
minHeight: labelHeightSM,
lineHeight: unit(labelHeightSM),
padding: `0 ${unit(token.segmentedPaddingHorizontalSM)}`,
},
[`${componentCls}-item, ${componentCls}-thumb`]: {
borderRadius: token.borderRadiusXS,
},
},
// disabled styles
...getItemDisabledStyle(`&-disabled ${componentCls}-item`, token),
...getItemDisabledStyle(`${componentCls}-item-disabled`, token),
// transition effect when `appear-active`
[`${componentCls}-thumb-motion-appear-active`]: {
transition: `transform ${token.motionDurationSlow} ${token.motionEaseInOut}, width ${token.motionDurationSlow} ${token.motionEaseInOut}`,
willChange: 'transform, width',
},
},
};
};
// ============================== Export ==============================
export const prepareComponentToken: GetDefaultToken<'Segmented'> = (token) => {
const {
colorTextLabel,
colorText,
colorFillSecondary,
colorBgElevated,
colorFill,
lineWidthBold,
colorBgLayout,
} = token;
return {
trackPadding: lineWidthBold,
trackBg: colorBgLayout,
itemColor: colorTextLabel,
itemHoverColor: colorText,
itemHoverBg: colorFillSecondary,
itemSelectedBg: colorBgElevated,
itemActiveBg: colorFill,
itemSelectedColor: colorText,
};
};
export default genStyleHooks(
'Segmented',
(token) => {
const { lineWidth, calc } = token;
const segmentedToken = mergeToken<SegmentedToken>(token, {
segmentedPaddingHorizontal: calc(token.controlPaddingHorizontal).sub(lineWidth).equal(),
segmentedPaddingHorizontalSM: calc(token.controlPaddingHorizontalSM).sub(lineWidth).equal(),
});
return [genSegmentedStyle(segmentedToken)];
},
prepareComponentToken,
);