diff --git a/docs/src/App.vue b/docs/src/App.vue index 4aa4218..781ebc7 100644 --- a/docs/src/App.vue +++ b/docs/src/App.vue @@ -39,6 +39,10 @@ Button Toggle + + Card + + Checkbox diff --git a/docs/src/assets/avatar.png b/docs/src/assets/avatar.png new file mode 100644 index 0000000..c0924e0 Binary files /dev/null and b/docs/src/assets/avatar.png differ diff --git a/docs/src/assets/card-example.jpg b/docs/src/assets/card-example.jpg new file mode 100644 index 0000000..f83e3fe Binary files /dev/null and b/docs/src/assets/card-example.jpg differ diff --git a/docs/src/assets/card-image-1.jpg b/docs/src/assets/card-image-1.jpg new file mode 100644 index 0000000..8380353 Binary files /dev/null and b/docs/src/assets/card-image-1.jpg differ diff --git a/docs/src/assets/card-image-2.jpg b/docs/src/assets/card-image-2.jpg new file mode 100644 index 0000000..2ab8328 Binary files /dev/null and b/docs/src/assets/card-image-2.jpg differ diff --git a/docs/src/assets/card-image-3.jpg b/docs/src/assets/card-image-3.jpg new file mode 100644 index 0000000..1994ef9 Binary files /dev/null and b/docs/src/assets/card-image-3.jpg differ diff --git a/docs/src/pages/components/Card.vue b/docs/src/pages/components/Card.vue new file mode 100644 index 0000000..e97bb23 --- /dev/null +++ b/docs/src/pages/components/Card.vue @@ -0,0 +1,255 @@ + + + diff --git a/docs/src/routes.js b/docs/src/routes.js index 86e95fa..1064ba0 100644 --- a/docs/src/routes.js +++ b/docs/src/routes.js @@ -10,6 +10,7 @@ import Avatar from './pages/components/Avatar'; import BottomBar from './pages/components/BottomBar'; import Buttons from './pages/components/Buttons'; import ButtonToggle from './pages/components/ButtonToggle'; +import Card from './pages/components/Card'; import Checkbox from './pages/components/Checkbox'; import Icon from './pages/components/Icon'; import Input from './pages/components/Input'; @@ -82,6 +83,11 @@ const components = [ name: 'components:button-toggle', component: ButtonToggle }, + { + path: '/components/card', + name: 'components:card', + component: Card + }, { path: '/components/checkbox', name: 'components:checkbox', diff --git a/src/components/mdCard/index.js b/src/components/mdCard/index.js new file mode 100644 index 0000000..8c3b427 --- /dev/null +++ b/src/components/mdCard/index.js @@ -0,0 +1,20 @@ +import mdCard from './mdCard.vue'; +import mdCardMedia from './mdCardMedia.vue'; +import mdCardMediaCover from './mdCardMediaCover.vue'; +import mdCardHeader from './mdCardHeader.vue'; +import mdCardContent from './mdCardContent.vue'; +import mdCardActions from './mdCardActions.vue'; +import mdCardArea from './mdCardArea.vue'; +import mdCardTheme from './mdCard.theme'; + +export default function install(Vue) { + Vue.component('md-card', Vue.extend(mdCard)); + Vue.component('md-card-media', Vue.extend(mdCardMedia)); + Vue.component('md-card-media-cover', Vue.extend(mdCardMediaCover)); + Vue.component('md-card-header', Vue.extend(mdCardHeader)); + Vue.component('md-card-content', Vue.extend(mdCardContent)); + Vue.component('md-card-actions', Vue.extend(mdCardActions)); + Vue.component('md-card-area', Vue.extend(mdCardArea)); + + Vue.material.styles.push(mdCardTheme); +} diff --git a/src/components/mdCard/mdCard.scss b/src/components/mdCard/mdCard.scss new file mode 100644 index 0000000..13a28c8 --- /dev/null +++ b/src/components/mdCard/mdCard.scss @@ -0,0 +1,170 @@ +@import '../../core/stylesheets/variables.scss'; + +$card-radius: 2px; + +.md-card { + overflow: auto; + display: flex; + flex-direction: column; + position: relative; + z-index: 1; + border-radius: $card-radius; + box-shadow: $material-shadow-2dp; + + &.md-with-hover { + cursor: pointer; + transition: $swift-ease-out; + transition-property: box-shadow; + + &:hover { + z-index: 2; + box-shadow: $material-shadow-8dp; + } + } + + .md-card-media { + position: relative; + + + .md-card-header { + padding-top: 24px; + } + + + .md-card-content:last-child { + padding-bottom: 16px; + } + } + + .md-card-header { + padding: 16px; + + + .md-card-content { + padding-top: 0; + } + + + .md-card-actions:not(:last-child) { + padding: 0 8px; + } + + .md-avatar { + margin-right: 16px; + float: left; + + ~ .md-title { + font-size: 14px; + } + + ~ .md-title, + ~ .md-subhead { + font-weight: 500; + line-height: 20px; + } + } + } + + .md-subhead, + .md-title, + .md-subheading { + margin: 0; + font-weight: 400; + } + + .md-subhead { + opacity: .54; + font-size: 14px; + letter-spacing: .01em; + line-height: 20px; + } + + .md-title { + font-size: 24px; + letter-spacing: 0; + line-height: 32px; + } + + .md-card-content { + padding: 16px; + font-size: 14px; + line-height: 22px; + + &:last-child { + padding-bottom: 24px; + } + } + + .md-card-actions { + padding: 8px; + display: flex; + justify-content: flex-end; + + .md-button { + margin: 0; + + &:first-child { + margin-left: 0; + } + + &:last-child { + margin-right: 0; + } + + + .md-button { + margin-left: 4px; + } + } + } + + .md-card-area { + position: relative; + } + + > .md-card-area { + &:not(.md-inset) { + border-bottom: 1px solid; + } + + &.md-inset { + position: relative; + + &:after { + height: 1px; + position: absolute; + right: 16px; + bottom: 0; + left: 16px; + content: " "; + } + } + } + + .md-card-media-cover { + position: relative; + color: #fff; + + &.md-text-scrim { + .md-backdrop { + position: absolute; + top: 0; + right: 0; + bottom: 0; + left: 0; + z-index: 1; + } + } + + .md-card-area { + position: absolute; + right: 0; + bottom: 0; + left: 0; + z-index: 2; + } + + .md-card-header + .md-card-actions { + padding-top: 0; + } + + .md-subhead { + opacity: 1; + } + } +} diff --git a/src/components/mdCard/mdCard.theme b/src/components/mdCard/mdCard.theme new file mode 100644 index 0000000..bacbfcc --- /dev/null +++ b/src/components/mdCard/mdCard.theme @@ -0,0 +1,30 @@ +.THEME_NAME { + .md-card, + &.md-card { + > .md-card-area { + &:not(.md-inset) { + border-bottom-color: #{'BACKGROUND-CONTRAST-0.12'}; + } + + &.md-inset { + &:after { + background-color: #{'BACKGROUND-CONTRAST-0.12'}; + } + } + } + + .md-card-media-cover { + &.md-text-scrim { + .md-backdrop { + background: linear-gradient(to bottom, #{'BACKGROUND-CONTRAST-0.0'} 20%, #{'BACKGROUND-CONTRAST-0.275'} 66%, #{'BACKGROUND-CONTRAST-0.55'} 100%); + } + } + + &.md-solid { + .md-card-area { + background-color: #{'BACKGROUND-CONTRAST-0.4'}; + } + } + } + } +} diff --git a/src/components/mdCard/mdCard.vue b/src/components/mdCard/mdCard.vue new file mode 100644 index 0000000..145a50a --- /dev/null +++ b/src/components/mdCard/mdCard.vue @@ -0,0 +1,22 @@ + + + + + diff --git a/src/components/mdCard/mdCardActions.vue b/src/components/mdCard/mdCardActions.vue new file mode 100644 index 0000000..934e7b5 --- /dev/null +++ b/src/components/mdCard/mdCardActions.vue @@ -0,0 +1,5 @@ + diff --git a/src/components/mdCard/mdCardArea.vue b/src/components/mdCard/mdCardArea.vue new file mode 100644 index 0000000..e04fc2e --- /dev/null +++ b/src/components/mdCard/mdCardArea.vue @@ -0,0 +1,20 @@ + + + diff --git a/src/components/mdCard/mdCardContent.vue b/src/components/mdCard/mdCardContent.vue new file mode 100644 index 0000000..c67ba70 --- /dev/null +++ b/src/components/mdCard/mdCardContent.vue @@ -0,0 +1,5 @@ + diff --git a/src/components/mdCard/mdCardHeader.vue b/src/components/mdCard/mdCardHeader.vue new file mode 100644 index 0000000..ea44ecd --- /dev/null +++ b/src/components/mdCard/mdCardHeader.vue @@ -0,0 +1,5 @@ + diff --git a/src/components/mdCard/mdCardMedia.vue b/src/components/mdCard/mdCardMedia.vue new file mode 100644 index 0000000..e9d9622 --- /dev/null +++ b/src/components/mdCard/mdCardMedia.vue @@ -0,0 +1,5 @@ + diff --git a/src/components/mdCard/mdCardMediaCover.vue b/src/components/mdCard/mdCardMediaCover.vue new file mode 100644 index 0000000..70e80de --- /dev/null +++ b/src/components/mdCard/mdCardMediaCover.vue @@ -0,0 +1,98 @@ + + + diff --git a/src/core/stylesheets/variables.scss b/src/core/stylesheets/variables.scss index e69906d..8939e00 100644 --- a/src/core/stylesheets/variables.scss +++ b/src/core/stylesheets/variables.scss @@ -5,7 +5,7 @@ $font-roboto: Roboto, Lato, sans-serif; -/* Transitions +/* Transitions - Based on Angular Material ========================================================================== */ $swift-ease-out-duration: .4s !default; @@ -34,7 +34,7 @@ $material-leave: all $material-leave-duration $material-leave-timing-function; -/* Elevation +/* Elevation - Based on Angular Material ========================================================================== */ $shadow-key-umbra-opacity: .2 !default; diff --git a/src/index.js b/src/index.js index 8295b86..37251c6 100644 --- a/src/index.js +++ b/src/index.js @@ -4,6 +4,7 @@ import mdBottomBar from './components/mdBottomBar'; import mdButton from './components/mdButton'; import mdButtonToggle from './components/mdButtonToggle'; import mdCheckbox from './components/mdCheckbox'; +import mdCard from './components/mdCard'; import mdDivider from './components/mdDivider'; import mdIcon from './components/mdIcon'; import mdInputContainer from './components/mdInputContainer'; @@ -25,6 +26,7 @@ let options = { mdButton, mdButtonToggle, mdCheckbox, + mdCard, mdDivider, mdIcon, mdInputContainer,