feat(card): css in js (#231)

* feat(card): css in js

* fix(card): code review

* chore: fix code review

Co-authored-by: Lecong Zhang <50313260+tskirby@users.noreply.github.com>
This commit is contained in:
HaiboTang 2020-08-08 19:11:57 +08:00 committed by 07akioni
parent e7fa600355
commit 58f35bd857
13 changed files with 560 additions and 201 deletions

View File

@ -1,7 +0,0 @@
import Card from './src/main.vue'
Card.install = function (Vue) {
Vue.component(Card.name, Card)
}
export default Card

View File

@ -80,7 +80,7 @@
<script>
import NScrollbar from '../../Scrollbar'
import NConfirm from '../../Confirm/src/Confirm'
import NCard from '../../Card'
import NCard from '../../card'
import themeable from '../../_mixins/themeable'
import presetProps from './presetProps'

View File

@ -64,7 +64,7 @@ function setupMutableStyle (
process.env.NODE_ENV !== 'production' &&
(dependencyValue === null || dependencyValue === undefined)
) {
console.error(`[naive-ui/mixins/usecssr]: dependency key ${name}.${dependencyKey} should be nullable`)
console.error(`[naive-ui/mixins/usecssr]: dependency key ${name}.${dependencyKey} should not be nullable`)
}
const mountId = createMutableStyleId(
id,

View File

@ -1,191 +1,191 @@
@import './mixins/mixins.scss';
// @import './mixins/mixins.scss';
@mixin card-size-mixin ($size) {
@include m($size + '-size') {
@include m(content-segmented) {
& > {
@include e(content) {
padding-top: map-get($--n-card-margin-bottom, $size);
}
}
}
@include m(content-soft-segmented) {
& > {
@include e(content) {
margin: 0 map-get($--n-card-margin-left, $size);
padding: map-get($--n-card-margin-bottom, $size) 0;
}
}
}
@include m(footer-segmented) {
& > {
@include e(footer) {
padding-top: map-get($--n-card-margin-bottom, $size);
}
}
}
@include m(footer-soft-segmented) {
& > {
@include e(footer) {
padding: map-get($--n-card-margin-bottom, $size) 0;
margin: 0 map-get($--n-card-margin-left, $size);
}
}
}
& > {
@include b(card-header) {
padding:
map-get($--n-card-margin-top, $size)
map-get($--n-card-margin-left, $size)
map-get($--n-card-margin-bottom, $size)
map-get($--n-card-margin-left, $size);
@include e(main) {
font-size: map-get($--n-card-font-size, $size);
}
@include e(extra) {
font-size: 14px;
}
}
@include e(content, footer) {
&:first-child {
padding-top: map-get($--n-card-margin-bottom, $size);
}
padding: 0 map-get($--n-card-margin-left, $size) map-get($--n-card-margin-bottom, $size) map-get($--n-card-margin-left, $size) ;
font-size: 14px;
}
@include e(action) {
background-color: $--card-action-background-color;
padding: map-get($--n-card-margin-bottom, $size) map-get($--n-card-margin-left, $size);
font-size: 14px;
}
}
}
}
// @mixin card-size-mixin ($size) {
// @include m($size + '-size') {
// @include m(content-segmented) {
// & > {
// @include e(content) {
// padding-top: map-get($--n-card-margin-bottom, $size);
// }
// }
// }
// @include m(content-soft-segmented) {
// & > {
// @include e(content) {
// margin: 0 map-get($--n-card-margin-left, $size);
// padding: map-get($--n-card-margin-bottom, $size) 0;
// }
// }
// }
// @include m(footer-segmented) {
// & > {
// @include e(footer) {
// padding-top: map-get($--n-card-margin-bottom, $size);
// }
// }
// }
// @include m(footer-soft-segmented) {
// & > {
// @include e(footer) {
// padding: map-get($--n-card-margin-bottom, $size) 0;
// margin: 0 map-get($--n-card-margin-left, $size);
// }
// }
// }
// & > {
// @include b(card-header) {
// padding:
// map-get($--n-card-margin-top, $size)
// map-get($--n-card-margin-left, $size)
// map-get($--n-card-margin-bottom, $size)
// map-get($--n-card-margin-left, $size);
// @include e(main) {
// font-size: map-get($--n-card-font-size, $size);
// }
// @include e(extra) {
// font-size: 14px;
// }
// }
// @include e(content, footer) {
// &:first-child {
// padding-top: map-get($--n-card-margin-bottom, $size);
// }
// padding: 0 map-get($--n-card-margin-left, $size) map-get($--n-card-margin-bottom, $size) map-get($--n-card-margin-left, $size) ;
// font-size: 14px;
// }
// @include e(action) {
// background-color: $--card-action-background-color;
// padding: map-get($--n-card-margin-bottom, $size) map-get($--n-card-margin-left, $size);
// font-size: 14px;
// }
// }
// }
// }
@include themes-mixin {
@include b(card) {
@include once {
display: block;
width: 100%;
box-sizing: border-box;
position: relative;
transition: color .3s $--n-ease-in-out-cubic-bezier, background-color .3s $--n-ease-in-out-cubic-bezier, border-color .3s $--n-ease-in-out-cubic-bezier;
border-radius: $--n-card-border-radius;
@include card-size-mixin('small');
@include card-size-mixin('medium');
@include card-size-mixin('large');
@include card-size-mixin('huge');
@include b(card-cover) {
$border-radius: $--n-card-border-radius - 1px;
overflow: hidden;
border-radius: $border-radius $border-radius 0 0;
width: 100%;
img {
display: block;
width: 100%;
}
}
}
background-color: $--card-background-color;
color: $--card-text-color;
@include m(bordered) {
border: 1px solid $--card-border-color;
}
@include m(action-segmented) {
& > {
@include e(action) {
&:not(:first-child) {
border-top: 1px solid $--card-border-color;
}
}
}
}
@include m(content-segmented, content-soft-segmented) {
& > {
@include e(content) {
@include once {
transition: border-color .3s $--n-ease-in-out-cubic-bezier;
}
&:not(:first-child) {
border-top: 1px solid $--card-border-color;
}
}
}
}
@include m(footer-segmented, footer-soft-segmented) {
& > {
@include e(footer) {
@include once {
transition: border-color .3s $--n-ease-in-out-cubic-bezier;
}
&:not(:first-child) {
border-top: 1px solid $--card-border-color;
}
}
}
}
@include once {
& > {
@include e(content) {
box-sizing: border-box;
line-height: 1.75;
font-size: 14px;
}
@include e(footer) {
box-sizing: border-box;
line-height: 1.75;
font-size: 14px;
}
}
}
& > {
@include b(card-header) {
@include once {
box-sizing: border-box;
display: flex;
align-items: center;
}
@include e(main) {
@include once {
font-weight: $--n-strong-weight;
font-size: 18px;
transition: color .3s $--n-ease-in-out-cubic-bezier;
flex: 1;
}
color: $--card-title-text-color;
}
@include e(extra) {
@include once {
font-weight: 400;
font-size: 14px;
transition: color .3s $--n-ease-in-out-cubic-bezier;
}
color: $--card-text-color;
}
@include e(close-mark) {
@include once {
cursor: pointer;
transition: fill .3s $--n-ease-in-out-cubic-bezier;
}
fill: map-get($--card-close-color, 'default');
&:hover {
fill: map-get($--card-close-color, 'hover');
}
&:active {
fill: map-get($--card-close-color, 'active');
}
}
}
@include e(action) {
@include once {
box-sizing: border-box;
transition: background-color .3s $--n-ease-in-out-cubic-bezier, border-color .3s $--n-ease-in-out-cubic-bezier;
line-height: 1.75;
font-size: 14px;
background-clip: padding-box;
}
background-color: $--card-action-background-color;
}
}
}
}
// @include themes-mixin {
// @include b(card) {
// @include once {
// display: block;
// width: 100%;
// box-sizing: border-box;
// position: relative;
// transition: color .3s $--n-ease-in-out-cubic-bezier, background-color .3s $--n-ease-in-out-cubic-bezier, border-color .3s $--n-ease-in-out-cubic-bezier;
// border-radius: $--n-card-border-radius;
// @include card-size-mixin('small');
// @include card-size-mixin('medium');
// @include card-size-mixin('large');
// @include card-size-mixin('huge');
// @include b(card-cover) {
// $border-radius: $--n-card-border-radius - 1px;
// overflow: hidden;
// border-radius: $border-radius $border-radius 0 0;
// width: 100%;
// img {
// display: block;
// width: 100%;
// }
// }
// }
// background-color: $--card-background-color;
// color: $--card-text-color;
// @include m(bordered) {
// border: 1px solid $--card-border-color;
// }
// @include m(action-segmented) {
// & > {
// @include e(action) {
// &:not(:first-child) {
// border-top: 1px solid $--card-border-color;
// }
// }
// }
// }
// @include m(content-segmented, content-soft-segmented) {
// & > {
// @include e(content) {
// @include once {
// transition: border-color .3s $--n-ease-in-out-cubic-bezier;
// }
// &:not(:first-child) {
// border-top: 1px solid $--card-border-color;
// }
// }
// }
// }
// @include m(footer-segmented, footer-soft-segmented) {
// & > {
// @include e(footer) {
// @include once {
// transition: border-color .3s $--n-ease-in-out-cubic-bezier;
// }
// &:not(:first-child) {
// border-top: 1px solid $--card-border-color;
// }
// }
// }
// }
// @include once {
// & > {
// @include e(content) {
// box-sizing: border-box;
// line-height: 1.75;
// font-size: 14px;
// }
// @include e(footer) {
// box-sizing: border-box;
// line-height: 1.75;
// font-size: 14px;
// }
// }
// }
// & > {
// @include b(card-header) {
// @include once {
// box-sizing: border-box;
// display: flex;
// align-items: center;
// }
// @include e(main) {
// @include once {
// font-weight: $--n-strong-weight;
// font-size: 18px;
// transition: color .3s $--n-ease-in-out-cubic-bezier;
// flex: 1;
// }
// color: $--card-title-text-color;
// }
// @include e(extra) {
// @include once {
// font-weight: 400;
// font-size: 14px;
// transition: color .3s $--n-ease-in-out-cubic-bezier;
// }
// color: $--card-text-color;
// }
// @include e(close-mark) {
// @include once {
// cursor: pointer;
// transition: fill .3s $--n-ease-in-out-cubic-bezier;
// }
// fill: map-get($--card-close-color, 'default');
// &:hover {
// fill: map-get($--card-close-color, 'hover');
// }
// &:active {
// fill: map-get($--card-close-color, 'active');
// }
// }
// }
// @include e(action) {
// @include once {
// box-sizing: border-box;
// transition: background-color .3s $--n-ease-in-out-cubic-bezier, border-color .3s $--n-ease-in-out-cubic-bezier;
// line-height: 1.75;
// font-size: 14px;
// background-clip: padding-box;
// }
// background-color: $--card-action-background-color;
// }
// }
// }
// }

7
src/card/index.js Normal file
View File

@ -0,0 +1,7 @@
import Card from './src/Card.vue'
Card.install = function (Vue, naive) {
Vue.component(naive.componentPrefix + Card.name, Card)
}
export default Card

View File

@ -50,14 +50,16 @@ import withapp from '../../_mixins/withapp'
import themeable from '../../_mixins/themeable'
import NIcon from '../../Icon'
import mdClose from '../../_icons/md-close'
import usecssr from '../../_mixins/usecssr'
import styles from './styles'
export default {
name: 'NCard',
name: 'Card',
components: {
mdClose,
NIcon
},
mixins: [withapp, themeable],
mixins: [withapp, themeable, usecssr(styles)],
props: {
title: {
type: String,

View File

@ -0,0 +1,20 @@
import sizeStyle from './themed-size.cssr.js'
import baseStyle from './themed-base.cssr.js'
export default [
{
key: 'size',
watch: [
'size',
'syntheticTheme'
],
CNode: sizeStyle
},
{
key: 'syntheticTheme',
watch: [
'syntheticTheme'
],
CNode: baseStyle
}
]

View File

@ -0,0 +1,161 @@
import { c, cTB, cB, cE, cM } from '../../../_utils/cssr'
export default c([
({ props }) => {
const base = props.$base
const easeInOutCubicBezier = base.easeInOutCubicBezier
const {
cardBackgroundColor,
cardTextColor,
cardTitleTextColor,
cardBorderColor,
cardActionBackgroundColor,
cardCloseColor,
strongFontWeight,
borderRadius,
smallBorderRadius
} = props.$local
const {
default: defaultCardCloseColor,
hover: hoverCardCloseColor,
active: activeCardCloseColor
} = cardCloseColor
return cTB(
'card',
{
raw: `
display: block;
width: 100%;
box-sizing: border-box;
position: relative;
border-radius: ${borderRadius};
backgroundColor: ${cardBackgroundColor};
color: ${cardTextColor};
`,
transition: `
color .3s ${easeInOutCubicBezier},
background-color .3s ${easeInOutCubicBezier},
border-color .3s ${easeInOutCubicBezier}
`
},
[
cB('card-cover', {
raw: `
overflow: hidden;
width: 100%;
`,
borderRadius: `${smallBorderRadius} ${smallBorderRadius} 0 0;`
},
[
c('img', {
raw: `
display: block;
width: 100%;
`
})
]),
cM('bordered', {
border: `1px solid ${cardBorderColor}`
}),
cM('action-segmented', [
c('& >', [
cE('action', [
c('&:not(:first-child)', {
borderTop: `1px solid ${cardBorderColor}`
})
])
])
]),
cM('content-segmented, content-soft-segmented', [
c('& >', [
cE('content', {
transition: `border-color 0.3s ${easeInOutCubicBezier}`
}, [
c('&:not(:first-child)', {
borderTop: `1px solid ${cardBorderColor}`
})
])
])
]),
cM('footer-segmented, footer-soft-segmented', [
c('& >', [
cE('footer', {
transition: `border-color 0.3s ${easeInOutCubicBezier}`
}, [
c('&:not(:first-child)', {
borderTop: `1px solid ${cardBorderColor}`
})
])
])
]),
c('& >', [
cE('content', {
raw: `
box-sizing: border-box;
line-height: 1.75;
font-size: 14px;
`
}),
cE('footer', {
raw: `
box-sizing: border-box;
line-height: 1.75;
font-size: 14px;
`
})
]),
c('& >', [
cB('card-header', {
raw: `
box-sizing: border-box;
display: flex;
align-items: center;
`
}, [
cE('main', {
raw: `
font-weight: ${strongFontWeight};
font-size: 18px;
transition: color .3s ${easeInOutCubicBezier};
flex: 1;
color: ${cardTitleTextColor};
`
}),
cE('extra', {
raw: `
font-weight: 400;
font-size: 14px;
transition: color .3s ${easeInOutCubicBezier};
color: ${cardTextColor};
`
}),
cE('close-mark', {
raw: `
cursor: pointer;
transition: fill .3s ${easeInOutCubicBezier};
fill: ${defaultCardCloseColor};
`
}, [
c('&:hover', {
fill: hoverCardCloseColor
}),
c('&:active', {
fill: activeCardCloseColor
})
])
]),
cE('action', {
raw: `
box-sizing: border-box;
transition: background-color .3s ${easeInOutCubicBezier}, border-color .3s ${easeInOutCubicBezier};
line-height: 1.75;
font-size: 14px;
background-clip: padding-box;
background-color: ${cardActionBackgroundColor};
`
})
])
]
)
}
])

View File

@ -0,0 +1,88 @@
import { c, cB, cTB, cE, cM } from '../../../_utils/cssr'
export default c([
({ props }) => {
const {
fontSize,
marginLeft,
marginTop,
marginBottom
} = props.$local
const { cardActionBackgroundColor } = props.$local
const { size } = props.$instance
const marginBottomSize = marginBottom[size]
const marginLeftSize = marginLeft[size]
const marginTopSize = marginTop[size]
return cTB(
'card',
[
cM(`${size}-size`, {
}, [
cM('content-segmented', [
c('& >', [
cE('content', {
paddingTop: marginBottomSize
})
])
]),
cM('content-soft-segmented', [
c('& >', [
cE('content', {
raw: `
margin: 0 ${marginLeftSize};
padding: ${marginBottomSize} 0;
`
})
])
]),
cM('footer-segmented', [
c('& >', [
cE('footer', {
paddingTop: marginBottomSize
})
])
]),
cM('footer-soft-segmented', [
c('& >', [
cE('footer', {
raw: `
padding: ${marginBottomSize} 0;
margin: 0 ${marginLeftSize};
`
})
])
]),
c('& >', [
cB('card-header', {
raw: `
padding: ${marginTopSize} ${marginLeftSize} ${marginBottomSize} ${marginLeftSize};
`
}, [
cE('main', {
fontSize: fontSize[size]
}),
cE('extra', {
fontSize: '14px'
})
]),
cE('content, footer', {
padding: `0 ${marginLeftSize} ${marginBottomSize} ${marginLeftSize}`,
fontSize: '14px'
}, [
c('$:first-child', {
paddingTop: marginBottomSize
})
]),
cE('action', {
raw: `
background-color: ${cardActionBackgroundColor};
padding: ${marginBottomSize} ${marginLeftSize};
font-size: 14px;
`
})
])
])
]
)
}
])

26
src/card/styles/card.js Normal file
View File

@ -0,0 +1,26 @@
export default {
marginLeft: {
'small': '16px',
'medium': '24px',
'large': '32px',
'huge': '40px'
},
marginTop: {
'small': '12px',
'medium': '19px',
'large': '23px',
'huge': '27px'
},
marginBottom: {
'small': '12px',
'medium': '20px',
'large': '24px',
'huge': '28px'
},
fontSize: {
'small': '16px',
'medium': '18px',
'large': '18px',
'huge': '18px'
}
}

29
src/card/styles/dark.js Normal file
View File

@ -0,0 +1,29 @@
import create from '../../styles/_utils/create-component-base'
import sizeVariable from './card'
export default create({
theme: 'dark',
name: 'Card',
getDerivedVariables ({ base, derived }) {
const {
borderRadius,
smallBorderRadius
} = base
return {
...sizeVariable,
cardBackgroundColor: derived.cardBackgroundColor,
cardTextColor: derived.secondaryTextOverlayColor,
cardTitleTextColor: derived.primaryTextOverlayColor,
cardBorderColor: derived.dividerOverlayColor,
cardActionBackgroundColor: derived.actionBackgroundOverlayColor,
strongFontWeight: base.strongFontWeight,
cardCloseColor: {
default: derived.closeOverlayColor,
hover: derived.closeHoverOverlayColor,
active: derived.closeOverlayColor
},
borderRadius,
smallBorderRadius
}
}
})

29
src/card/styles/light.js Normal file
View File

@ -0,0 +1,29 @@
import create from '../../styles/_utils/create-component-base'
import sizeVariable from './card'
export default create({
theme: 'light',
name: 'Card',
getDerivedVariables ({ base, derived }) {
const {
borderRadius,
smallBorderRadius
} = base
return {
...sizeVariable,
cardBackgroundColor: derived.cardBackgroundColor,
cardTextColor: derived.secondaryTextColor,
cardTitleTextColor: derived.primaryTextColor,
cardBorderColor: derived.dividerOverlayColor,
cardActionBackgroundColor: derived.actionBackgroundOverlayColor,
strongFontWeight: base.strongFontWeight,
cardCloseColor: {
default: derived.closeColor,
hover: derived.closeHoverColor,
active: derived.closeColor
},
borderRadius,
smallBorderRadius
}
}
})

View File

@ -1,4 +1,4 @@
import Card from './Card'
import Card from './card'
import Icon from './Icon'
import GradientText from './GradientText'
import Table from './Table'
@ -113,6 +113,8 @@ import autoComplateLightStyle from './auto-complete/styles/light'
import autoComplateDarkStyle from './auto-complete/styles/dark'
import codeLightStyle from './code/styles/light'
import codeDarkStyle from './code/styles/dark'
import cardDarkStyle from './card/styles/dark'
import cardLightStyle from './card/styles/light'
import anchorDarkStyle from './anchor/styles/dark'
import anchorLightStyle from './anchor/styles/light'
import breadcrumbDarkStyle from './breadcrumb/styles/dark'
@ -252,6 +254,8 @@ export default create({
backTopDarkStyle,
codeLightStyle,
codeDarkStyle,
cardDarkStyle,
cardLightStyle,
anchorDarkStyle,
anchorLightStyle,
breadcrumbDarkStyle,