Browse Source

feat: token wireframe (#37507)

* feat: wireframe token

* feat: token wireframe

* feat: wireframe steps

* feat: wireframe table

* feat: wireframe modal

* feat: wireframe popover

* chore: update token collect
pull/37529/head
MadCcc 2 years ago
committed by GitHub
parent
commit
0b8c112193
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 50
      components/modal/style/index.tsx
  2. 65
      components/pagination/style/index.tsx
  3. 40
      components/popover/style/index.tsx
  4. 40
      components/radio/style/index.tsx
  5. 90
      components/steps/style/index.tsx
  6. 6
      components/steps/style/progress.ts
  7. 43
      components/table/style/index.tsx
  8. 3
      components/theme/interface.ts
  9. 3
      components/theme/themes/seed.ts
  10. 4
      components/timeline/style/index.tsx
  11. 10
      scripts/collect-token-statistic.js
  12. 8
      site/theme/template/Layout/DynamicTheme/index.tsx

50
components/modal/style/index.tsx

@ -336,6 +336,55 @@ const genRTLStyle: GenerateStyle<ModalToken> = token => {
};
};
const genWireframeStyle: GenerateStyle<ModalToken> = token => {
const { componentCls, antCls } = token;
const confirmComponentCls = `${componentCls}-confirm`;
return {
[componentCls]: {
[`${componentCls}-content`]: {
padding: 0,
},
[`${componentCls}-header`]: {
padding: token.modalHeaderPadding,
borderBottom: `${token.modalHeaderBorderWidth}px ${token.modalHeaderBorderStyle} ${token.modalHeaderBorderColorSplit}`,
marginBottom: 0,
},
[`${componentCls}-body`]: {
padding: token.modalBodyPadding,
},
[`${componentCls}-footer`]: {
padding: `${token.modalFooterPaddingVertical}px ${token.modalFooterPaddingHorizontal}px`,
borderTop: `${token.modalFooterBorderWidth}px ${token.modalFooterBorderStyle} ${token.modalFooterBorderColorSplit}`,
borderRadius: `0 0 ${token.radiusLG}px ${token.radiusLG}px`,
marginTop: 0,
},
},
[confirmComponentCls]: {
[`${antCls}-modal-body`]: {
padding: `${token.padding * 2}px ${token.padding * 2}px ${token.paddingLG}px`,
},
[`${confirmComponentCls}-body`]: {
[`> ${token.iconCls}`]: {
marginInlineEnd: token.margin,
// `content` after `icon` should set marginLeft
[`+ ${confirmComponentCls}-title + ${confirmComponentCls}-content`]: {
marginInlineStart: token.modalConfirmIconSize + token.margin,
},
},
},
[`${confirmComponentCls}-btns`]: {
marginTop: token.marginLG,
},
},
};
};
// ============================== Export ==============================
export default genComponentStyleHook('Modal', token => {
const headerPaddingVertical = token.padding;
@ -370,6 +419,7 @@ export default genComponentStyleHook('Modal', token => {
genModalConfirmStyle(modalToken),
genRTLStyle(modalToken),
genModalMaskStyle(modalToken),
token.wireframe && genWireframeStyle(modalToken),
initZoomMotion(modalToken, 'zoom'),
];
});

65
components/pagination/style/index.tsx

@ -524,6 +524,66 @@ const genPaginationStyle: GenerateStyle<PaginationToken, CSSObject> = token => {
};
};
const genBorderedStyle: GenerateStyle<PaginationToken> = token => {
const { componentCls } = token;
return {
[`${componentCls}-disabled`]: {
'&, &:hover': {
[`${componentCls}-item-link`]: {
borderColor: token.colorBorder,
},
},
'&:focus-visible': {
[`${componentCls}-item-link`]: {
borderColor: token.colorBorder,
},
},
[`${componentCls}-item`]: {
background: token.colorBgContainerDisabled,
borderColor: token.colorBorder,
},
[`${componentCls}-item-link`]: {
background: token.colorBgContainerDisabled,
borderColor: token.colorBorder,
},
},
[componentCls]: {
[`${componentCls}-prev, ${componentCls}-next`]: {
'&:hover button': {
borderColor: token.colorPrimaryHover,
},
[`${componentCls}-item-link`]: {
backgroundColor: token.paginationItemLinkBg,
borderColor: token.colorBorder,
},
[`&:hover ${componentCls}-item-link`]: {
borderColor: token.colorPrimary,
},
},
[`${componentCls}-item`]: {
backgroundColor: token.paginationItemBg,
border: `${token.controlLineWidth}px ${token.controlLineType} ${token.colorBorder}`,
'&:hover': {
borderColor: token.colorPrimary,
},
'&-active': {
borderColor: token.colorPrimary,
},
},
},
};
};
// ============================== Export ==============================
export default genComponentStyleHook('Pagination', token => {
const paginationToken = mergeToken<PaginationToken>(
@ -551,5 +611,8 @@ export default genComponentStyleHook('Pagination', token => {
},
initInputToken(token),
);
return [genPaginationStyle(paginationToken)];
return [
genPaginationStyle(paginationToken),
token.wireframe && genBorderedStyle(paginationToken),
];
});

40
components/popover/style/index.tsx

@ -118,10 +118,47 @@ const genColorStyle: GenerateStyle<PopoverToken> = token => {
};
};
const genWireframeStyle: GenerateStyle<PopoverToken> = token => {
const {
componentCls,
lineWidth,
lineType,
colorSplit,
paddingSM,
controlHeight,
fontSize,
lineHeight,
padding,
} = token;
const titlePaddingBlockDist = controlHeight - Math.round(fontSize * lineHeight);
const popoverTitlePaddingBlockTop = titlePaddingBlockDist / 2;
const popoverTitlePaddingBlockBottom = titlePaddingBlockDist / 2 - lineWidth;
const popoverPaddingHorizontal = padding;
return {
[componentCls]: {
[`${componentCls}-inner`]: {
padding: 0,
},
[`${componentCls}-title`]: {
margin: 0,
padding: `${popoverTitlePaddingBlockTop}px ${popoverPaddingHorizontal}px ${popoverTitlePaddingBlockBottom}px`,
borderBottom: `${lineWidth}px ${lineType} ${colorSplit}`,
},
[`${componentCls}-inner-content`]: {
padding: `${paddingSM}px ${popoverPaddingHorizontal}px`,
},
},
};
};
export default genComponentStyleHook(
'Popover',
token => {
const { colorBgElevated, colorText, paddingSM } = token;
const { colorBgElevated, colorText, paddingSM, wireframe } = token;
const popoverToken = mergeToken<PopoverToken>(token, {
popoverBg: colorBgElevated,
@ -132,6 +169,7 @@ export default genComponentStyleHook(
return [
genBaseStyle(popoverToken),
genColorStyle(popoverToken),
wireframe && genWireframeStyle(popoverToken),
initZoomMotion(popoverToken, 'zoom-big'),
];
},

40
components/radio/style/index.tsx

@ -14,7 +14,7 @@ interface RadioToken extends FullToken<'Radio'> {
radioTop: number;
radioDotSize: number;
radioDotDisabledSize: number;
radioDotColor: string;
radioCheckedColor: string;
radioDotDisabledColor: string;
radioSolidCheckedColor: string;
@ -67,7 +67,7 @@ const getRadioBasicStyle: GenerateStyle<RadioToken> = token => {
const {
componentCls,
radioWrapperMarginRight,
radioDotColor,
radioCheckedColor,
radioTop,
radioSize,
motionDurationSlow,
@ -84,6 +84,7 @@ const getRadioBasicStyle: GenerateStyle<RadioToken> = token => {
radioDotDisabledColor,
controlLineType,
radioDotDisabledSize,
wireframe,
} = token;
const radioInnerPrefixCls = `${componentCls}-inner`;
@ -120,7 +121,7 @@ const getRadioBasicStyle: GenerateStyle<RadioToken> = token => {
insetInlineStart: 0,
width: '100%',
height: '100%',
border: `${controlLineWidth}px ${controlLineType} ${radioDotColor}`,
border: `${controlLineWidth}px ${controlLineType} ${radioCheckedColor}`,
borderRadius: '50%',
visibility: 'hidden',
animationName: antRadioEffect,
@ -141,7 +142,7 @@ const getRadioBasicStyle: GenerateStyle<RadioToken> = token => {
[`${componentCls}-wrapper:hover &,
&:hover ${radioInnerPrefixCls}`]: {
borderColor: radioDotColor,
borderColor: radioCheckedColor,
},
[`${componentCls}-input:focus-visible + ${radioInnerPrefixCls}`]: {
@ -162,7 +163,7 @@ const getRadioBasicStyle: GenerateStyle<RadioToken> = token => {
height: radioSize,
marginBlockStart: radioSize / -2,
marginInlineStart: radioSize / -2,
backgroundColor: radioButtonBg,
backgroundColor: wireframe ? radioCheckedColor : radioButtonBg,
borderBlockStart: 0,
borderInlineStart: 0,
borderRadius: radioSize,
@ -200,8 +201,8 @@ const getRadioBasicStyle: GenerateStyle<RadioToken> = token => {
// 选中状态
[`${componentCls}-checked`]: {
[radioInnerPrefixCls]: {
borderColor: radioDotColor,
backgroundColor: radioDotColor,
borderColor: radioCheckedColor,
backgroundColor: wireframe ? radioButtonBg : radioCheckedColor,
'&::after': {
transform: `scale(${radioDotSize / radioSize})`,
@ -271,7 +272,7 @@ const getRadioButtonStyle: GenerateStyle<RadioToken> = token => {
controlRadius,
controlRadiusSM,
controlRadiusLG,
radioDotColor,
radioCheckedColor,
radioButtonCheckedBg,
radioButtonHoverColor,
radioButtonActiveColor,
@ -387,7 +388,7 @@ const getRadioButtonStyle: GenerateStyle<RadioToken> = token => {
'&:hover': {
position: 'relative',
color: radioDotColor,
color: radioCheckedColor,
},
'&:has(:focus-visible)': {
@ -403,16 +404,16 @@ const getRadioButtonStyle: GenerateStyle<RadioToken> = token => {
'&-checked:not(&-disabled)': {
zIndex: 1,
color: radioDotColor,
color: radioCheckedColor,
background: radioButtonCheckedBg,
borderColor: radioDotColor,
borderColor: radioCheckedColor,
'&::before': {
backgroundColor: radioDotColor,
backgroundColor: radioCheckedColor,
},
'&:first-child': {
borderColor: radioDotColor,
borderColor: radioCheckedColor,
},
'&:hover': {
@ -436,8 +437,8 @@ const getRadioButtonStyle: GenerateStyle<RadioToken> = token => {
[`${componentCls}-group-solid &-checked:not(&-disabled)`]: {
color: radioSolidCheckedColor,
background: radioDotColor,
borderColor: radioDotColor,
background: radioCheckedColor,
borderColor: radioCheckedColor,
'&:hover': {
color: radioSolidCheckedColor,
@ -494,6 +495,7 @@ export default genComponentStyleHook('Radio', token => {
marginXS,
controlOutlineWidth,
paddingXXS,
wireframe,
} = token;
// Radio
@ -502,9 +504,11 @@ export default genComponentStyleHook('Radio', token => {
const radioSize = fontSizeLG;
const radioTop = (Math.round(fontSize * lineHeight) - radioSize) / 2;
const radioDotSize = radioSize - (paddingXXS + controlLineWidth) * 2;
const radioDotDisabledSize = radioSize - paddingXXS * 2;
const radioDotColor = colorPrimary;
const radioDotSize = wireframe
? radioDotDisabledSize
: radioSize - (paddingXXS + controlLineWidth) * 2;
const radioCheckedColor = colorPrimary;
// Radio buttons
const radioButtonColor = colorText;
@ -521,7 +525,7 @@ export default genComponentStyleHook('Radio', token => {
radioTop,
radioDotSize,
radioDotDisabledSize,
radioDotColor,
radioCheckedColor,
radioDotDisabledColor: colorTextDisabled,
radioSolidCheckedColor: colorBgContainer,
radioButtonBg: colorBgContainer,

90
components/steps/style/index.tsx

@ -35,24 +35,28 @@ export interface StepsToken extends FullToken<'Steps'> {
processTitleColor: string;
processDescriptionColor: string;
processIconBgColor: string;
processIconBorderColor: string;
processDotColor: string;
waitIconColor: string;
waitTitleColor: string;
waitDescriptionColor: string;
waitTailColor: string;
waitIconBgColor: string;
waitIconBorderColor: string;
waitDotColor: string;
finishIconColor: string;
finishTitleColor: string;
finishDescriptionColor: string;
finishTailColor: string;
finishIconBgColor: string;
finishIconBorderColor: string;
finishDotColor: string;
errorIconColor: string;
errorTitleColor: string;
errorDescriptionColor: string;
errorTailColor: string;
errorIconBgColor: string;
errorIconBorderColor: string;
errorDotColor: string;
stepsNavActiveColor: string;
stepsProgressSize: number;
@ -72,10 +76,12 @@ const genStepsItemStatusStyle = (status: StepItemStatusEnum, token: StepsToken):
const descriptionColorKey: keyof StepsToken = `${status}DescriptionColor`;
const tailColorKey: keyof StepsToken = `${status}TailColor`;
const iconBgColorKey: keyof StepsToken = `${status}IconBgColor`;
const iconBorderColorKey: keyof StepsToken = `${status}IconBorderColor`;
const dotColorKey: keyof StepsToken = `${status}DotColor`;
return {
[`${prefix}-${status} ${prefix}-icon`]: {
backgroundColor: token[iconBgColorKey],
borderColor: token[iconBorderColorKey],
[`> ${token.componentCls}-icon`]: {
color: token[iconColorKey],
[`${token.componentCls}-icon-dot`]: {
@ -142,13 +148,13 @@ const genStepsItemStyle: GenerateStyle<StepsToken, CSSObject> = token => {
lineHeight: `${token.stepsIconSize}px`,
textAlign: 'center',
borderRadius: token.stepsIconSize,
border: `${token.controlLineWidth}px ${token.controlLineType} transparent`,
transition: `background-color ${motionDurationSlow}, border-color ${motionDurationSlow}`,
[`${componentCls}-icon`]: {
position: 'relative',
top: token.stepsIconTop,
color: token.colorPrimary,
lineHeight: 1,
verticalAlign: 'text-bottom',
},
},
[`${stepsItemCls}-tail`]: {
@ -313,50 +319,72 @@ const genStepsStyle: GenerateStyle<StepsToken, CSSObject> = token => {
export default genComponentStyleHook(
'Steps',
token => {
const {
wireframe,
colorTextDisabled,
fontSizeHeading3,
fontSize,
controlHeight,
controlHeightLG,
colorTextLightSolid,
colorText,
colorPrimary,
colorTextLabel,
colorTextDescription,
colorFillContent,
colorPrimaryBg,
colorError,
colorBgContainer,
} = token;
const stepsIconSize = token.controlHeight;
const processTailColor = token.colorSplit;
const stepsToken = mergeToken<StepsToken>(token, {
// Steps variable default.less
processTailColor,
stepsNavArrowColor: token.colorTextDisabled,
stepsNavArrowColor: colorTextDisabled,
stepsIconSize,
stepsIconCustomSize: stepsIconSize,
stepsIconCustomTop: 0,
stepsIconCustomFontSize: token.fontSizeHeading3,
stepsIconCustomFontSize: fontSizeHeading3,
stepsIconTop: -0.5, // magic for ui experience
stepsIconFontSize: token.fontSize,
stepsTitleLineHeight: token.controlHeight,
stepsSmallIconSize: token.fontSizeHeading3,
stepsDotSize: token.controlHeight / 4,
stepsCurrentDotSize: token.controlHeightLG / 4,
stepsIconFontSize: fontSize,
stepsTitleLineHeight: controlHeight,
stepsSmallIconSize: fontSizeHeading3,
stepsDotSize: controlHeight / 4,
stepsCurrentDotSize: controlHeightLG / 4,
stepsNavContentMaxWidth: 'auto',
// Steps component less variable
processIconColor: token.colorTextLightSolid,
processTitleColor: token.colorText,
processDescriptionColor: token.colorText,
processIconBgColor: token.colorPrimary,
processDotColor: token.colorPrimary,
waitIconColor: token.colorTextLabel,
waitTitleColor: token.colorTextDescription,
waitDescriptionColor: token.colorTextDescription,
processIconColor: colorTextLightSolid,
processTitleColor: colorText,
processDescriptionColor: colorText,
processIconBgColor: colorPrimary,
processIconBorderColor: colorPrimary,
processDotColor: colorPrimary,
waitIconColor: wireframe ? colorTextDisabled : colorTextLabel,
waitTitleColor: colorTextDescription,
waitDescriptionColor: colorTextDescription,
waitTailColor: processTailColor,
waitIconBgColor: token.colorFillContent,
waitDotColor: token.colorTextDisabled,
finishIconColor: token.colorPrimary,
finishTitleColor: token.colorText,
finishDescriptionColor: token.colorTextDescription,
finishTailColor: token.colorPrimary,
finishIconBgColor: token.colorPrimaryBg,
finishDotColor: token.colorPrimary,
errorIconColor: token.colorTextLightSolid,
errorTitleColor: token.colorError,
errorDescriptionColor: token.colorError,
waitIconBgColor: wireframe ? colorBgContainer : colorFillContent,
waitIconBorderColor: wireframe ? colorTextDisabled : 'transparent',
waitDotColor: colorTextDisabled,
finishIconColor: colorPrimary,
finishTitleColor: colorText,
finishDescriptionColor: colorTextDescription,
finishTailColor: colorPrimary,
finishIconBgColor: wireframe ? colorBgContainer : colorPrimaryBg,
finishIconBorderColor: wireframe ? colorPrimary : colorPrimaryBg,
finishDotColor: colorPrimary,
errorIconColor: colorTextLightSolid,
errorTitleColor: colorError,
errorDescriptionColor: colorError,
errorTailColor: processTailColor,
errorIconBgColor: token.colorError,
errorDotColor: token.colorError,
stepsNavActiveColor: token.colorPrimary,
stepsProgressSize: token.controlHeightLG,
errorIconBgColor: colorError,
errorIconBorderColor: colorError,
errorDotColor: colorError,
stepsNavActiveColor: colorPrimary,
stepsProgressSize: controlHeightLG,
});
return [genStepsStyle(stepsToken)];

6
components/steps/style/progress.ts

@ -33,8 +33,10 @@ const genStepsProgressStyle: GenerateStyle<StepsToken, CSSObject> = token => {
[`${antCls}-progress`]: {
position: 'absolute',
insetBlockStart: (token.stepsIconSize - token.stepsProgressSize) / 2,
insetInlineStart: (token.stepsIconSize - token.stepsProgressSize) / 2,
insetBlockStart:
(token.stepsIconSize - token.stepsProgressSize - token.lineWidth * 2) / 2,
insetInlineStart:
(token.stepsIconSize - token.stepsProgressSize - token.lineWidth * 2) / 2,
},
},
},

43
components/table/style/index.tsx

@ -90,6 +90,7 @@ const genTableStyle: GenerateStyle<TableToken, CSSObject> = token => {
tableSelectedRowHoverBg,
tableFooterTextColor,
tableFooterBg,
wireframe,
} = token;
const tableBorder = `${controlLineWidth}px ${controlLineType} ${tableBorderColor}`;
return {
@ -219,36 +220,38 @@ const genTableStyle: GenerateStyle<TableToken, CSSObject> = token => {
},
},
[`${componentCls}:not(${componentCls}-bordered) ${componentCls}-tbody > tr`]: {
[`&${componentCls}-row:hover, &${componentCls}-row${componentCls}-row-selected`]: {
[`+ tr${componentCls}-row > td`]: {
borderTopColor: 'transparent',
},
},
[`${componentCls}:not(${componentCls}-bordered) ${componentCls}-tbody > tr`]: wireframe
? undefined
: {
[`&${componentCls}-row:hover, &${componentCls}-row${componentCls}-row-selected`]: {
[`+ tr${componentCls}-row > td`]: {
borderTopColor: 'transparent',
},
},
[`&${componentCls}-row:last-child:hover > td,
[`&${componentCls}-row:last-child:hover > td,
&${componentCls}-row${componentCls}-row-selected:last-child > td`]: {
borderBottomColor: 'transparent',
},
borderBottomColor: 'transparent',
},
[`
[`
&${componentCls}-row:hover > td,
> td${componentCls}-cell-row-hover,
&${componentCls}-row${componentCls}-row-selected > td
`]: {
borderTopColor: 'transparent',
borderTopColor: 'transparent',
'&:first-child': {
borderStartStartRadius: tableRadius,
borderEndStartRadius: tableRadius,
},
'&:first-child': {
borderStartStartRadius: tableRadius,
borderEndStartRadius: tableRadius,
},
'&:last-child': {
borderStartEndRadius: tableRadius,
borderEndEndRadius: tableRadius,
'&:last-child': {
borderStartEndRadius: tableRadius,
borderEndEndRadius: tableRadius,
},
},
},
},
},
// ============================ Footer ============================
[`${componentCls}-footer`]: {

3
components/theme/interface.ts

@ -203,6 +203,9 @@ export interface SeedToken extends PresetColorType {
// Image
/** Define default Image opacity. Useful when in dark-like theme */
opacityImage: number;
// Wireframe
wireframe: boolean;
}
export interface NeutralColorMapToken {

3
components/theme/themes/seed.ts

@ -73,5 +73,8 @@ const seedToken: SeedToken = {
// Image
opacityImage: 1,
// Wireframe
wireframe: false,
};
export default seedToken;

4
components/timeline/style/index.tsx

@ -11,6 +11,7 @@ interface TimelineToken extends FullToken<'Timeline'> {
timeLineItemCustomHeadPaddingVertical: number;
timeLineItemTailWidth: number;
timeLinePaddingInlineEnd: number;
timeLineHeadBorderWidth: number;
}
const genTimelineStyle: GenerateStyle<TimelineToken, CSSObject> = token => {
@ -54,7 +55,7 @@ const genTimelineStyle: GenerateStyle<TimelineToken, CSSObject> = token => {
width: token.timeLineItemHeadSize,
height: token.timeLineItemHeadSize,
backgroundColor: token.colorBgContainer,
border: `${token.lineWidth * 3}px ${token.lineType} transparent`,
border: `${token.timeLineHeadBorderWidth}px ${token.lineType} transparent`,
borderRadius: '50%',
'&-blue': {
@ -219,6 +220,7 @@ export default genComponentStyleHook('Timeline', token => {
timeLineItemCustomHeadPaddingVertical: token.paddingXXS,
timeLinePaddingInlineEnd: 2,
timeLineItemTailWidth: token.lineWidthBold,
timeLineHeadBorderWidth: token.wireframe ? token.lineWidthBold : token.lineWidth * 3,
});
return [genTimelineStyle(timeLineToken)];

10
scripts/collect-token-statistic.js

@ -8,6 +8,8 @@ const glob = require('glob');
const path = require('path');
const ProgressBar = require('progress');
const { statistic } = require('../components/theme/util/statistic');
const { DesignTokenContext } = require('../components/theme');
const seedToken = require('../components/theme/themes/seed');
console.log(chalk.green(`🔥 Collecting token statistics...`));
@ -46,6 +48,14 @@ styleFiles.forEach(file => {
return EmptyElement;
};
ReactDOMServer.renderToString(React.createElement(Component));
// Render wireframe
ReactDOMServer.renderToString(
React.createElement(
DesignTokenContext.Provider,
{ value: { token: { ...seedToken, wireframe: true } } },
React.createElement(Component),
),
);
});
(async () => {

8
site/theme/template/Layout/DynamicTheme/index.tsx

@ -1,6 +1,6 @@
import { BugOutlined, EyeOutlined } from '@ant-design/icons';
import { TinyColor } from '@ctrl/tinycolor';
import { Button, Select, Checkbox, Drawer, Form, Input, InputNumber, Space } from 'antd';
import { Button, Select, Checkbox, Drawer, Form, Input, InputNumber, Space, Switch } from 'antd';
import * as React from 'react';
import { useState } from 'react';
import { useIntl } from 'react-intl';
@ -121,14 +121,16 @@ export default function DynamicTheme({
case 'number':
node = <InputNumber />;
break;
case 'boolean':
node = <Switch defaultChecked={!!originValue} />;
break;
default:
node = <Input />;
}
const rules: any[] = [{ required: key !== 'colorTextBase' && key !== 'colorBgBase' }];
const originColor = new TinyColor(originValue);
if (originValueType === 'string' && originColor.isValid) {
if (originValueType === 'string' && new TinyColor(originValue as string).isValid) {
rules.push({
validator: async (_: any, value: string) => {
if (!new TinyColor(value).isValid) {

Loading…
Cancel
Save