From c4ac778ac8520660da539485ba80768fd51f5f1b Mon Sep 17 00:00:00 2001 From: HaiboTang <42064613+gtangxiaobo@users.noreply.github.com> Date: Mon, 31 Aug 2020 22:00:48 +0800 Subject: [PATCH] feat(layout): css in js (#275) * feat(layout): css in js * chore: fix code review * fix: code review --- src/Layout/index.js | 15 - src/_styles/index.scss | 2 +- src/index.js | 6 +- src/layout/index.js | 15 + src/{Layout => layout}/src/Layout.vue | 11 +- src/{Layout => layout}/src/LayoutFooter.vue | 2 +- src/{Layout => layout}/src/LayoutHeader.vue | 2 +- src/{Layout => layout}/src/LayoutSider.vue | 2 +- src/{Layout => layout}/src/ToggleBar.vue | 0 src/{Layout => layout}/src/ToggleButton.vue | 0 src/{Layout => layout}/src/layoutModeMixin.js | 0 src/layout/src/styles/index.js | 9 + src/layout/src/styles/themed-base.cssr.js | 287 ++++++++++++++++++ src/layout/styles/dark.js | 35 +++ src/layout/styles/light.js | 35 +++ 15 files changed, 399 insertions(+), 22 deletions(-) delete mode 100644 src/Layout/index.js create mode 100644 src/layout/index.js rename src/{Layout => layout}/src/Layout.vue (93%) rename src/{Layout => layout}/src/LayoutFooter.vue (96%) rename src/{Layout => layout}/src/LayoutHeader.vue (96%) rename src/{Layout => layout}/src/LayoutSider.vue (99%) rename src/{Layout => layout}/src/ToggleBar.vue (100%) rename src/{Layout => layout}/src/ToggleButton.vue (100%) rename src/{Layout => layout}/src/layoutModeMixin.js (100%) create mode 100644 src/layout/src/styles/index.js create mode 100644 src/layout/src/styles/themed-base.cssr.js create mode 100644 src/layout/styles/dark.js create mode 100644 src/layout/styles/light.js diff --git a/src/Layout/index.js b/src/Layout/index.js deleted file mode 100644 index 6b5d4509b..000000000 --- a/src/Layout/index.js +++ /dev/null @@ -1,15 +0,0 @@ -/* istanbul ignore file */ -import Layout from './src/Layout.vue' -import LayoutHeader from './src/LayoutHeader.vue' -import LayoutFooter from './src/LayoutFooter.vue' -import LayoutSider from './src/LayoutSider.vue' - -Layout.install = function (Vue) { - Vue.component(Layout.name, Layout) - Vue.component('NLayoutContent', Layout) - Vue.component(LayoutHeader.name, LayoutHeader) - Vue.component(LayoutFooter.name, LayoutFooter) - Vue.component(LayoutSider.name, LayoutSider) -} - -export default Layout diff --git a/src/_styles/index.scss b/src/_styles/index.scss index 6d0aea9ac..683084659 100644 --- a/src/_styles/index.scss +++ b/src/_styles/index.scss @@ -12,7 +12,7 @@ // @import './Radio.scss'; @import './Form.scss'; // @import './Grid.scss'; -@import './Layout.scss'; +// @import './Layout.scss'; @import './Message.scss'; @import './Notification.scss'; @import './Pagination.scss'; diff --git a/src/index.js b/src/index.js index 5ff4a2d0e..a8f9fa499 100644 --- a/src/index.js +++ b/src/index.js @@ -34,7 +34,7 @@ import Input from './input' import InputGroup from './input-group' import InputGroupLabelStyle from './input-group-label' import InputNumber from './input-number' -import Layout from './Layout' +import Layout from './layout' import List from './list' import LoadingBar from './loading-bar' import Log from './log' @@ -170,6 +170,8 @@ import switchLightStyle from './switch/styles/light' import switchDarkStyle from './switch/styles/dark' import radioLightStyle from './radio/styles/light' import radioDarkStyle from './radio/styles/dark' +import layoutDarkStyle from './layout/styles/dark' +import layoutLightStyle from './layout/styles/light' // Can be remove after refactoring import baseSelectionLightStyle from './_base/selection/styles/light' @@ -369,6 +371,8 @@ export default create({ switchDarkStyle, radioLightStyle, radioDarkStyle, + layoutDarkStyle, + layoutLightStyle, // Can be remove after refactoring baseSelectionLightStyle, baseSelectionDarkStyle diff --git a/src/layout/index.js b/src/layout/index.js new file mode 100644 index 000000000..34dc3dad2 --- /dev/null +++ b/src/layout/index.js @@ -0,0 +1,15 @@ +/* istanbul ignore file */ +import Layout from './src/Layout.vue' +import LayoutHeader from './src/LayoutHeader.vue' +import LayoutFooter from './src/LayoutFooter.vue' +import LayoutSider from './src/LayoutSider.vue' + +Layout.install = function (Vue, naive) { + Vue.component(naive.componentPrefix + Layout.name, Layout) + Vue.component(naive.componentPrefix + 'LayoutContent', Layout) + Vue.component(naive.componentPrefix + LayoutHeader.name, LayoutHeader) + Vue.component(naive.componentPrefix + LayoutFooter.name, LayoutFooter) + Vue.component(naive.componentPrefix + LayoutSider.name, LayoutSider) +} + +export default Layout diff --git a/src/Layout/src/Layout.vue b/src/layout/src/Layout.vue similarity index 93% rename from src/Layout/src/Layout.vue rename to src/layout/src/Layout.vue index c7a21bfce..b208eb4b0 100644 --- a/src/Layout/src/Layout.vue +++ b/src/layout/src/Layout.vue @@ -27,13 +27,20 @@ import layoutModeMixin from './layoutModeMixin' import themeable from '../../_mixins/themeable' import withapp from '../../_mixins/withapp' import NScrollbar from '../../scrollbar' +import usecssr from '../../_mixins/usecssr' +import styles from './styles' export default { - name: 'NLayout', + name: 'Layout', components: { NScrollbar }, - mixins: [ withapp, themeable, layoutModeMixin ], + mixins: [ + withapp, + themeable, + layoutModeMixin, + usecssr(styles) + ], provide () { return { NLayout: this diff --git a/src/Layout/src/LayoutFooter.vue b/src/layout/src/LayoutFooter.vue similarity index 96% rename from src/Layout/src/LayoutFooter.vue rename to src/layout/src/LayoutFooter.vue index 34c574b7c..ba012f915 100644 --- a/src/Layout/src/LayoutFooter.vue +++ b/src/layout/src/LayoutFooter.vue @@ -18,7 +18,7 @@ import withapp from '../../_mixins/withapp' import themeable from '../../_mixins/themeable' export default { - name: 'NLayoutFooter', + name: 'LayoutFooter', mixins: [ withapp, themeable, layoutModeMixin ], props: { bordered: { diff --git a/src/Layout/src/LayoutHeader.vue b/src/layout/src/LayoutHeader.vue similarity index 96% rename from src/Layout/src/LayoutHeader.vue rename to src/layout/src/LayoutHeader.vue index 0d8ef53fb..28b80007d 100644 --- a/src/Layout/src/LayoutHeader.vue +++ b/src/layout/src/LayoutHeader.vue @@ -18,7 +18,7 @@ import withapp from '../../_mixins/withapp' import themeable from '../../_mixins/themeable' export default { - name: 'NLayoutHeader', + name: 'LayoutHeader', mixins: [ withapp, themeable, layoutModeMixin ], props: { bordered: { diff --git a/src/Layout/src/LayoutSider.vue b/src/layout/src/LayoutSider.vue similarity index 99% rename from src/Layout/src/LayoutSider.vue rename to src/layout/src/LayoutSider.vue index ddb604dcb..c8b906091 100644 --- a/src/Layout/src/LayoutSider.vue +++ b/src/layout/src/LayoutSider.vue @@ -54,7 +54,7 @@ import ToggleBar from './ToggleBar' import NScrollbar from '../../scrollbar' export default { - name: 'NLayoutSider', + name: 'LayoutSider', components: { ToggleButton, ToggleBar, diff --git a/src/Layout/src/ToggleBar.vue b/src/layout/src/ToggleBar.vue similarity index 100% rename from src/Layout/src/ToggleBar.vue rename to src/layout/src/ToggleBar.vue diff --git a/src/Layout/src/ToggleButton.vue b/src/layout/src/ToggleButton.vue similarity index 100% rename from src/Layout/src/ToggleButton.vue rename to src/layout/src/ToggleButton.vue diff --git a/src/Layout/src/layoutModeMixin.js b/src/layout/src/layoutModeMixin.js similarity index 100% rename from src/Layout/src/layoutModeMixin.js rename to src/layout/src/layoutModeMixin.js diff --git a/src/layout/src/styles/index.js b/src/layout/src/styles/index.js new file mode 100644 index 000000000..958d3000d --- /dev/null +++ b/src/layout/src/styles/index.js @@ -0,0 +1,9 @@ +import baseStyle from './themed-base.cssr.js' + +export default [ + { + key: 'syntheticTheme', + watch: ['syntheticTheme'], + CNode: baseStyle + } +] diff --git a/src/layout/src/styles/themed-base.cssr.js b/src/layout/src/styles/themed-base.cssr.js new file mode 100644 index 000000000..ee88c79bf --- /dev/null +++ b/src/layout/src/styles/themed-base.cssr.js @@ -0,0 +1,287 @@ +import { cTB, c, cB, cE, cM } from '../../../_utils/cssr' + +export default c([ + ({ props }) => { + const { + textColor, + color + } = props.$local + const { + easeInOutCubicBezier + } = props.$base + return cTB('layout', { + raw: ` + color: ${textColor}; + background-color: ${color}; + box-sizing: border-box; + position: relative; + z-index: auto; + transition: + margin-left .3s ${easeInOutCubicBezier}, + background-color .3s ${easeInOutCubicBezier}, + color .3s ${easeInOutCubicBezier}; + flex: auto; + overflow-x: hidden; + ` + }, [ + cM('has-sider', { + raw: ` + display: flex; + flex-wrap: nowrap; + width: 100%; + flex-direction: row; + ` + }), + cM('absolute-positioned', { + raw: ` + position: absolute; + left: 0; + right: 0; + top: 0; + bottom: 0; + ` + }, [ + cB('layout-sider', { + raw: ` + z-index: 1; + ` + }) + ]) + ]) + }, + ({ props }) => { + const { + headerBackgroundColor, + layoutHeaderBorderColor + } = props.$local + const { + easeInOutCubicBezier + } = props.$base + return cTB('layout-header', { + raw: ` + transition: + background-color .3s ${easeInOutCubicBezier}, + box-shadow .3s ${easeInOutCubicBezier}, + border-color .3s ${easeInOutCubicBezier}; + box-sizing: border-box; + width: 100%; + background-color: ${headerBackgroundColor}; + ` + }, [ + cM('bordered', { + raw: ` + border-bottom: solid 1px ${layoutHeaderBorderColor}; + ` + }) + ]) + }, + ({ props }) => { + const { + easeInOutCubicBezier + } = props.$base + return cTB('layout-content', { + raw: ` + transition: + margin-left .3s ${easeInOutCubicBezier}, + background-color .3s ${easeInOutCubicBezier}, + color .3s ${easeInOutCubicBezier}; + box-sizing: border-box; + position: relative; + z-index: auto; + ` + }) + }, + ({ props }) => { + const { + footerBorderColor + } = props.$local + const { + easeInOutCubicBezier + } = props.$base + return cTB('layout-footer', { + raw: ` + transition: + background-color .3s ${easeInOutCubicBezier}, + border-color .3s ${easeInOutCubicBezier}; + box-sizing: border-box; + ` + }, [ + cM('absolute-positioned', { + raw: ` + position: absolute; + left: 0; + right: 0; + bottom: 0; + ` + }), + cM('bordered', { + raw: ` + border-top: solid 1px ${footerBorderColor}; + ` + }) + ]) + }, + ({ props }) => { + const { + siderBackgroundColor, + siderToggleButtonFill, + siderBorderColor, + siderToggleBarBackgroundColor + } = props.$local + const { + easeInOutCubicBezier + } = props.$base + return cTB('layout-sider', { + raw: ` + box-sizing: border-box; + position: relative; + z-index: auto; + transition: + min-width .3s ${easeInOutCubicBezier}, + max-width .3s ${easeInOutCubicBezier}, + transform .3s ${easeInOutCubicBezier}, + background-color .3s ${easeInOutCubicBezier}; + background-color: ${siderBackgroundColor}; + ` + }, [ + cB('layout-toggle-button', { + raw: ` + z-index: 1; + transition: + transform .3s ${easeInOutCubicBezier}, + fill .3s ${easeInOutCubicBezier}; + cursor: pointer; + width: 36px; + height: 36px; + position: absolute; + top: 50%; + right: 0; + transform: translateX(50%) translateY(-50%); + fill: ${siderToggleButtonFill}; + ` + }), + cE('border', { + raw: ` + position: absolute; + top: 0; + right: 0; + bottom: 0; + width: 1px; + transition: background-color .3s ${easeInOutCubicBezier}; + ` + }), + cB('layout-toggle-bar', { + raw: ` + cursor: pointer; + height: 72px; + width: 32px; + position: absolute; + top: calc(50% - 36px); + right: -28px; + ` + }, [ + cE('top, bottom', { + raw: ` + position: absolute; + width: 4px; + border-radius: 2px; + height: 38px; + left: 14px; + transition: + background-color .3s ${easeInOutCubicBezier}, + transform .3s ${easeInOutCubicBezier}; + ` + }), + cE('bottom', { + raw: ` + position: absolute; + top: 34px; + ` + }), + c('&:hover', [ + cE('top', { + raw: ` + transform: rotate(12deg) scale(1.15) translateY(-2px); + ` + }), + cE('bottom', { + raw: ` + transform: rotate(-12deg) scale(1.15) translateY(2px); + ` + }) + ]), + cM('collapsed', [ + c('&:hover', [ + cE('top', { + raw: ` + transform: rotate(-12deg) scale(1.15) translateY(-2px); + ` + }), + cE('bottom', { + raw: ` + transform: rotate(12deg) scale(1.15) translateY(2px); + ` + }) + ]) + ]), + cE('top, bottom', { + raw: ` + background-color: ${siderToggleBarBackgroundColor.default} + ` + }), + c('&:hover', [ + cE('top, bottom', { + raw: ` + background-color: ${siderToggleBarBackgroundColor.hover} + ` + }) + ]), + cE('content', { + raw: ` + opacity: 0; + transition: opacity .3s ${easeInOutCubicBezier}; + ` + }), + cM('show-content', [ + cE('content', { + raw: ` + opacity: 1; + ` + }) + ]), + cM('collapsed', [ + cB('layout-toggle-button', { + raw: ` + transform: translateX(50%) translateY(-50%) rotate(180deg); + ` + }) + ]), + cM('absolute-positioned', { + raw: ` + position: absolute; + left: 0; + top: 0; + bottom: 0; + ` + }, [ + cE('content', { + raw: ` + position: absolute; + left: 0; + right: 0; + top: 0; + bottom: 0; + ` + }) + ]), + cM('bordered', [ + cE('border', { + raw: ` + background-color: ${siderBorderColor}; + ` + }) + ]) + ]) + ]) + } +]) diff --git a/src/layout/styles/dark.js b/src/layout/styles/dark.js new file mode 100644 index 000000000..19be432f2 --- /dev/null +++ b/src/layout/styles/dark.js @@ -0,0 +1,35 @@ +import create from '../../styles/_utils/create-component-base' +import { composite } from '../../_utils/color/index' + +export default create({ + name: 'Layout', + theme: 'dark', + getDerivedVariables ({ base, derived }) { + const { + secondaryTextOverlayColor, + bodyBackgroundColor, + cardBackgroundColor, + dividerOverlayColor, + scrollbarBackgroundOverlayColor, + scrollbarHoverBackgroundOverlayColor + } = derived + const { + borderRadius + } = base + return { + borderRadius, + textColor: secondaryTextOverlayColor, + color: bodyBackgroundColor, + headerBackgroundColor: cardBackgroundColor, + headerBorderColor: dividerOverlayColor, + footerBorderColor: dividerOverlayColor, + siderBorderColor: dividerOverlayColor, + siderBackgroundColor: cardBackgroundColor, + siderToggleButtonFill: 'rgba(255, 255, 255, .3)', + siderToggleBarBackgroundColor: { + default: composite(bodyBackgroundColor, scrollbarBackgroundOverlayColor), + hover: composite(bodyBackgroundColor, scrollbarHoverBackgroundOverlayColor) + } + } + } +}) diff --git a/src/layout/styles/light.js b/src/layout/styles/light.js new file mode 100644 index 000000000..ba7383d5f --- /dev/null +++ b/src/layout/styles/light.js @@ -0,0 +1,35 @@ +import create from '../../styles/_utils/create-component-base' +import { composite } from '../../_utils/color/index' + +export default create({ + name: 'Layout', + theme: 'light', + getDerivedVariables ({ base, derived }) { + const { + secondaryTextColor, + bodyBackgroundColor, + cardBackgroundColor, + dividerOverlayColor, + scrollbarBackgroundOverlayColor, + scrollbarHoverBackgroundOverlayColor + } = derived + const { + borderRadius + } = base + return { + borderRadius, + textColor: secondaryTextColor, + color: bodyBackgroundColor, + headerBackgroundColor: cardBackgroundColor, + headerBorderColor: dividerOverlayColor, + footerBorderColor: dividerOverlayColor, + siderBorderColor: dividerOverlayColor, + siderBackgroundColor: cardBackgroundColor, + siderToggleButtonFill: 'rgba(0, 0, 0, .15)', + siderToggleBarBackgroundColor: { + default: composite(bodyBackgroundColor, scrollbarBackgroundOverlayColor), + hover: composite(bodyBackgroundColor, scrollbarHoverBackgroundOverlayColor) + } + } + } +})