From 7a34c99935a8ea40aea9d6147654201310b5e20a Mon Sep 17 00:00:00 2001 From: bqy_fe <1743369777@qq.com> Date: Sun, 12 Feb 2023 14:34:58 +0800 Subject: [PATCH] refactor(layout): less to cssinjs (#6249) --- components/layout/layout.tsx | 12 +- components/layout/style/index.less | 145 --------------- components/layout/style/index.ts | 225 +++++++++++++++++++++++ components/layout/style/index.tsx | 2 - components/layout/style/light.less | 11 -- components/layout/style/light.ts | 27 +++ components/layout/style/rtl.less | 10 - components/style.ts | 2 +- components/theme/interface/components.ts | 4 +- 9 files changed, 263 insertions(+), 175 deletions(-) delete mode 100644 components/layout/style/index.less create mode 100644 components/layout/style/index.ts delete mode 100644 components/layout/style/index.tsx delete mode 100644 components/layout/style/light.less create mode 100644 components/layout/style/light.ts delete mode 100644 components/layout/style/rtl.less diff --git a/components/layout/layout.tsx b/components/layout/layout.tsx index 82d7e2129..a07507e58 100644 --- a/components/layout/layout.tsx +++ b/components/layout/layout.tsx @@ -2,6 +2,7 @@ import type { ExtractPropTypes, HTMLAttributes } from 'vue'; import { computed, createVNode, defineComponent, provide, ref } from 'vue'; import useConfigInject from '../config-provider/hooks/useConfigInject'; import { SiderHookProviderKey } from './injectionKey'; +import useStyle from './style'; export const basicProps = () => ({ prefixCls: String, @@ -18,7 +19,7 @@ type GeneratorArgument = { }; function generator({ suffixCls, tagName, name }: GeneratorArgument) { - return (BasicComponent: typeof Basic) => { + return (BasicComponent: typeof BasicLayout) => { const Adapter = defineComponent({ compatConfig: { MODE: 3 }, name, @@ -49,9 +50,11 @@ const Basic = defineComponent({ const BasicLayout = defineComponent({ compatConfig: { MODE: 3 }, + inheritAttrs: false, props: basicProps(), - setup(props, { slots }) { - const { direction } = useConfigInject('', props); + setup(props, { slots, attrs }) { + const { prefixCls, direction } = useConfigInject('', props); + const [wrapSSR, hashId] = useStyle(prefixCls); const siders = ref([]); const siderHookProvider = { addSider: (id: string) => { @@ -66,6 +69,7 @@ const BasicLayout = defineComponent({ const divCls = computed(() => { const { prefixCls, hasSider } = props; return { + [hashId.value]: true, [`${prefixCls}`]: true, [`${prefixCls}-has-sider`]: typeof hasSider === 'boolean' ? hasSider : siders.value.length > 0, @@ -74,7 +78,7 @@ const BasicLayout = defineComponent({ }); return () => { const { tagName } = props; - return createVNode(tagName, { class: divCls.value }, slots); + return wrapSSR(createVNode(tagName, { ...attrs, class: [divCls.value, attrs.class] }, slots)); }; }, }); diff --git a/components/layout/style/index.less b/components/layout/style/index.less deleted file mode 100644 index f699c0b45..000000000 --- a/components/layout/style/index.less +++ /dev/null @@ -1,145 +0,0 @@ -@import '../../style/themes/index'; -@import '../../style/mixins/index'; - -@layout-prefix-cls: ~'@{ant-prefix}-layout'; -@layout-menu-prefix-cls: ~'@{ant-prefix}-menu'; - -.@{layout-prefix-cls} { - display: flex; - flex: auto; - flex-direction: column; - - /* fix firefox can't set height smaller than content on flex item */ - min-height: 0; - background: @layout-body-background; - - &, - * { - box-sizing: border-box; - } - - &&-has-sider { - flex-direction: row; - - > .@{layout-prefix-cls}, - > .@{layout-prefix-cls}-content { - width: 0; // https://segmentfault.com/a/1190000019498300 - } - } - - &-header, - &-footer { - flex: 0 0 auto; - } - - &-header { - height: @layout-header-height; - padding: @layout-header-padding; - color: @layout-header-color; - line-height: @layout-header-height; - background: @layout-header-background; - } - - &-footer { - padding: @layout-footer-padding; - color: @text-color; - font-size: @font-size-base; - background: @layout-footer-background; - } - - &-content { - flex: auto; - - /* fix firefox can't set height smaller than content on flex item */ - min-height: 0; - } - - &-sider { - position: relative; - - /* fix firefox can't set width smaller than content on flex item */ - min-width: 0; - background: @layout-sider-background; - transition: all 0.2s; - - &-children { - height: 100%; - margin-top: -0.1px; - // Hack for fixing margin collaspe bug - // https://github.com/ant-design/ant-design/issues/7967 - // solution from https://stackoverflow.com/a/33132624/3040605 - padding-top: 0.1px; - - .@{layout-menu-prefix-cls}.@{layout-menu-prefix-cls}-inline-collapsed { - width: auto; - } - } - - &-has-trigger { - padding-bottom: @layout-trigger-height; - } - - &-right { - order: 1; - } - - &-trigger { - position: fixed; - bottom: 0; - z-index: 1; - height: @layout-trigger-height; - color: @layout-trigger-color; - line-height: @layout-trigger-height; - text-align: center; - background: @layout-trigger-background; - cursor: pointer; - transition: all 0.2s; - } - - &-zero-width { - > * { - overflow: hidden; - } - - &-trigger { - position: absolute; - top: @layout-header-height; - right: -@layout-zero-trigger-width; - z-index: 1; - width: @layout-zero-trigger-width; - height: @layout-zero-trigger-height; - color: @layout-trigger-color; - font-size: (@layout-zero-trigger-width / 2); - line-height: @layout-zero-trigger-height; - text-align: center; - background: @layout-sider-background; - border-radius: 0 @border-radius-base @border-radius-base 0; - cursor: pointer; - transition: background 0.3s ease; - - &::after { - position: absolute; - top: 0; - right: 0; - bottom: 0; - left: 0; - background: transparent; - transition: all 0.3s; - content: ''; - } - - &:hover::after { - background: rgba(255, 255, 255, 0.1); - } - - &-right { - left: -@layout-zero-trigger-width; - border-radius: @border-radius-base 0 0 @border-radius-base; - } - } - } - } -} - -@import './light'; -@import './rtl'; diff --git a/components/layout/style/index.ts b/components/layout/style/index.ts new file mode 100644 index 000000000..cd8fabc65 --- /dev/null +++ b/components/layout/style/index.ts @@ -0,0 +1,225 @@ +import type { CSSObject } from '../../_util/cssinjs'; +import type { FullToken, GenerateStyle } from '../../theme/internal'; +import { genComponentStyleHook, mergeToken } from '../../theme/internal'; +import genLayoutLightStyle from './light'; + +export interface ComponentToken { + colorBgHeader: string; + colorBgBody: string; + colorBgTrigger: string; +} + +export interface LayoutToken extends FullToken<'Layout'> { + // Layout + layoutHeaderHeight: number; + layoutHeaderPaddingInline: number; + layoutHeaderColor: string; + layoutFooterPadding: string; + layoutTriggerHeight: number; + layoutZeroTriggerSize: number; +} + +const genLayoutStyle: GenerateStyle = token => { + const { + antCls, // .ant + componentCls, // .ant-layout + colorText, + colorTextLightSolid, + colorBgHeader, + colorBgBody, + colorBgTrigger, + layoutHeaderHeight, + layoutHeaderPaddingInline, + layoutHeaderColor, + layoutFooterPadding, + layoutTriggerHeight, + layoutZeroTriggerSize, + motionDurationMid, + motionDurationSlow, + fontSize, + borderRadius, + } = token; + + return { + [componentCls]: { + display: 'flex', + flex: 'auto', + flexDirection: 'column', + + /* fix firefox can't set height smaller than content on flex item */ + minHeight: 0, + background: colorBgBody, + + '&, *': { + boxSizing: 'border-box', + }, + + [`&${componentCls}-has-sider`]: { + flexDirection: 'row', + [`> ${componentCls}, > ${componentCls}-content`]: { + // https://segmentfault.com/a/1190000019498300 + width: 0, + }, + }, + + [`${componentCls}-header, &${componentCls}-footer`]: { + flex: '0 0 auto', + }, + + [`${componentCls}-header`]: { + height: layoutHeaderHeight, + paddingInline: layoutHeaderPaddingInline, + color: layoutHeaderColor, + lineHeight: `${layoutHeaderHeight}px`, + background: colorBgHeader, + // Other components/menu/style/index.less line:686 + // Integration with header element so menu items have the same height + [`${antCls}-menu`]: { + lineHeight: 'inherit', + }, + }, + + [`${componentCls}-footer`]: { + padding: layoutFooterPadding, + color: colorText, + fontSize, + background: colorBgBody, + }, + + [`${componentCls}-content`]: { + flex: 'auto', + + // fix firefox can't set height smaller than content on flex item + minHeight: 0, + }, + + [`${componentCls}-sider`]: { + position: 'relative', + + // fix firefox can't set width smaller than content on flex item + minWidth: 0, + background: colorBgHeader, + transition: `all ${motionDurationMid}`, + + '&-children': { + height: '100%', + // Hack for fixing margin collapse bug + // https://github.com/ant-design/ant-design/issues/7967 + // solution from https://stackoverflow.com/a/33132624/3040605 + marginTop: -0.1, + paddingTop: 0.1, + + [`${antCls}-menu${antCls}-menu-inline-collapsed`]: { + width: 'auto', + }, + }, + + '&-has-trigger': { + paddingBottom: layoutTriggerHeight, + }, + + '&-right': { + order: 1, + }, + + '&-trigger': { + position: 'fixed', + bottom: 0, + zIndex: 1, + height: layoutTriggerHeight, + color: colorTextLightSolid, + lineHeight: `${layoutTriggerHeight}px`, + textAlign: 'center', + background: colorBgTrigger, + cursor: 'pointer', + transition: `all ${motionDurationMid}`, + }, + + '&-zero-width': { + '> *': { + overflow: 'hidden', + }, + + '&-trigger': { + position: 'absolute', + top: layoutHeaderHeight, + insetInlineEnd: -layoutZeroTriggerSize, + zIndex: 1, + width: layoutZeroTriggerSize, + height: layoutZeroTriggerSize, + color: colorTextLightSolid, + fontSize: token.fontSizeXL, + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + background: colorBgHeader, + borderStartStartRadius: 0, + borderStartEndRadius: borderRadius, + borderEndEndRadius: borderRadius, + borderEndStartRadius: 0, + + cursor: 'pointer', + transition: `background ${motionDurationSlow} ease`, + + '&::after': { + position: 'absolute', + inset: 0, + background: 'transparent', + transition: `all ${motionDurationSlow}`, + content: '""', + }, + + '&:hover::after': { + // FIXME: Hardcode, but seems no need to create a token for this + background: `rgba(255, 255, 255, 0.2)`, + }, + + '&-right': { + insetInlineStart: -layoutZeroTriggerSize, + borderStartStartRadius: borderRadius, + borderStartEndRadius: 0, + borderEndEndRadius: 0, + borderEndStartRadius: borderRadius, + }, + }, + }, + }, + // Light + ...genLayoutLightStyle(token), + // RTL + '&-rtl': { + direction: 'rtl', + }, + }, + }; +}; + +// ============================== Export ============================== +export default genComponentStyleHook( + 'Layout', + token => { + const { colorText, controlHeightSM, controlHeight, controlHeightLG, marginXXS } = token; + const layoutHeaderPaddingInline = controlHeightLG * 1.25; + + const layoutToken = mergeToken(token, { + // Layout + layoutHeaderHeight: controlHeight * 2, + layoutHeaderPaddingInline, + layoutHeaderColor: colorText, + layoutFooterPadding: `${controlHeightSM}px ${layoutHeaderPaddingInline}px`, + layoutTriggerHeight: controlHeightLG + marginXXS * 2, // = item height + margin + layoutZeroTriggerSize: controlHeightLG, + }); + + return [genLayoutStyle(layoutToken)]; + }, + token => { + const { colorBgLayout } = token; + + return { + colorBgHeader: '#001529', + colorBgBody: colorBgLayout, + colorBgTrigger: '#002140', + }; + }, +); diff --git a/components/layout/style/index.tsx b/components/layout/style/index.tsx deleted file mode 100644 index 3a3ab0de5..000000000 --- a/components/layout/style/index.tsx +++ /dev/null @@ -1,2 +0,0 @@ -import '../../style/index.less'; -import './index.less'; diff --git a/components/layout/style/light.less b/components/layout/style/light.less deleted file mode 100644 index 35d636df1..000000000 --- a/components/layout/style/light.less +++ /dev/null @@ -1,11 +0,0 @@ -.@{layout-prefix-cls}-sider-light { - background: @layout-sider-background-light; - .@{layout-prefix-cls}-sider-trigger { - color: @layout-trigger-color-light; - background: @layout-trigger-background-light; - } - .@{layout-prefix-cls}-sider-zero-width-trigger { - color: @layout-trigger-color-light; - background: @layout-trigger-background-light; - } -} diff --git a/components/layout/style/light.ts b/components/layout/style/light.ts new file mode 100644 index 000000000..ed66f9ed0 --- /dev/null +++ b/components/layout/style/light.ts @@ -0,0 +1,27 @@ +import type { CSSObject } from '../../_util/cssinjs'; +import type { LayoutToken } from '.'; +import type { GenerateStyle } from '../../theme/internal'; + +const genLayoutLightStyle: GenerateStyle = token => { + const { componentCls, colorBgContainer, colorBgBody, colorText } = token; + + return { + [`${componentCls}-sider-light`]: { + background: colorBgContainer, + + [`${componentCls}-sider-trigger`]: { + color: colorText, + background: colorBgContainer, + }, + + [`${componentCls}-sider-zero-width-trigger`]: { + color: colorText, + background: colorBgContainer, + border: `1px solid ${colorBgBody}`, // Safe to modify to any other color + borderInlineStart: 0, + }, + }, + }; +}; + +export default genLayoutLightStyle; diff --git a/components/layout/style/rtl.less b/components/layout/style/rtl.less deleted file mode 100644 index da7aca0dd..000000000 --- a/components/layout/style/rtl.less +++ /dev/null @@ -1,10 +0,0 @@ -@import '../../style/themes/index'; -@import '../../style/mixins/index'; - -@layout-prefix-cls: ~'@{ant-prefix}-layout'; - -.@{layout-prefix-cls} { - &-rtl { - direction: rtl; - } -} diff --git a/components/style.ts b/components/style.ts index b2d119dea..619d6af19 100644 --- a/components/style.ts +++ b/components/style.ts @@ -44,7 +44,7 @@ import './input-number/style'; import './transfer/style'; import './tree/style'; import './upload/style'; -import './layout/style'; +// import './layout/style'; // import './anchor/style'; // import './list/style'; import './tree-select/style'; diff --git a/components/theme/interface/components.ts b/components/theme/interface/components.ts index ca1fa3dcf..689022d5e 100644 --- a/components/theme/interface/components.ts +++ b/components/theme/interface/components.ts @@ -17,7 +17,7 @@ import type { ComponentToken as DropdownComponentToken } from '../../dropdown/st import type { ComponentToken as EmptyComponentToken } from '../../empty/style'; // import type { ComponentToken as ImageComponentToken } from '../../image/style'; // import type { ComponentToken as InputNumberComponentToken } from '../../input-number/style'; -// import type { ComponentToken as LayoutComponentToken } from '../../layout/style'; +import type { ComponentToken as LayoutComponentToken } from '../../layout/style'; import type { ComponentToken as ListComponentToken } from '../../list/style'; // import type { ComponentToken as MentionsComponentToken } from '../../mentions/style'; import type { ComponentToken as MenuComponentToken } from '../../menu/style'; @@ -77,7 +77,7 @@ export interface ComponentTokenMap { // Image?: ImageComponentToken; Input?: {}; // InputNumber?: InputNumberComponentToken; - // Layout?: LayoutComponentToken; + Layout?: LayoutComponentToken; List?: ListComponentToken; // Mentions?: MentionsComponentToken; Notification?: NotificationComponentToken;