From 08546e810582363fedecd9bdd3e478e77257150a Mon Sep 17 00:00:00 2001 From: Rijk van Zanten Date: Mon, 16 Mar 2020 15:21:59 -0400 Subject: [PATCH] [WIP] Card component (#115) * Start on card component * Add stories for card * Add card actions component * Right align actions * Update storybook * Update readme, tweak dialog card spacing * Fix tests * Move type styles into mixins --- src/components/v-card/index.ts | 4 + src/components/v-card/readme.md | 167 ++++++++++++++++++ src/components/v-card/v-card-actions.vue | 15 ++ src/components/v-card/v-card-subtitle.vue | 15 ++ src/components/v-card/v-card-text.vue | 14 ++ src/components/v-card/v-card-title.vue | 17 ++ src/components/v-card/v-card.story.ts | 93 ++++++++++ src/components/v-card/v-card.test.ts | 13 ++ src/components/v-card/v-card.vue | 61 +++++++ src/components/v-dialog/v-dialog.vue | 5 + src/styles/mixins/type-styles.scss | 23 +++ .../drawer-detail/drawer-detail.test.ts | 2 + 12 files changed, 429 insertions(+) create mode 100644 src/components/v-card/index.ts create mode 100644 src/components/v-card/readme.md create mode 100644 src/components/v-card/v-card-actions.vue create mode 100644 src/components/v-card/v-card-subtitle.vue create mode 100644 src/components/v-card/v-card-text.vue create mode 100644 src/components/v-card/v-card-title.vue create mode 100644 src/components/v-card/v-card.story.ts create mode 100644 src/components/v-card/v-card.test.ts create mode 100644 src/components/v-card/v-card.vue diff --git a/src/components/v-card/index.ts b/src/components/v-card/index.ts new file mode 100644 index 0000000000..ee384d2c5c --- /dev/null +++ b/src/components/v-card/index.ts @@ -0,0 +1,4 @@ +import VCard from './v-card.vue'; + +export { VCard }; +export default VCard; diff --git a/src/components/v-card/readme.md b/src/components/v-card/readme.md new file mode 100644 index 0000000000..bd7601a9c5 --- /dev/null +++ b/src/components/v-card/readme.md @@ -0,0 +1,167 @@ +# Card + +Renders a card. A card is nothing but a v-sheet with predefined building blocks to enforce consistency. + +## Usage + +```html + + Hello, world! + This is a card + Consectetur enim ullamco sint sit deserunt proident consectetur. + + Save + + +``` + +Cards can be used to consistently style dialogs: + +```html + + + + + Are you sure you want to delete 1 item? + + Cancel + Yes + + + +``` + +## Props +| Prop | Description | Default | +|------------|---------------------------------------------------|---------| +| `disabled` | Disable the card, prevents all cursor interaction | `false` | +| `tile` | Render without rounded corners | `false` | + +## Events +n/a + +## Slots +| Slot | Description | Data | +|-----------|-------------|------| +| _default_ | | | + +## CSS Variables +| Variable | Default | +|-----------------------------|--------------------| +| `--v-card-min-width` | `none` | +| `--v-card-max-width` | `400px` | +| `--v-card-min-height` | `none` | +| `--v-card-max-height` | `none` | +| `--v-card-padding` | `16px` | +| `--v-card-background-color` | `var(--highlight)` | + +--- + +# Card Title + +Functional component that enforces consistent styling. + +## Usage + +```html +Hello, world! +``` + +## Props +n/a + +## Events +n/a + +## Slots +| Slot | Description | Data | +|-----------|-------------|------| +| _default_ | | | + +## CSS Variables +n/a + +--- + +# Card Subtitle + +Functional component that enforces consistent styling. + +## Usage + +```html +Hello from the subtitle +``` + +## Props +n/a + +## Events +n/a + +## Slots +| Slot | Description | Data | +|-----------|-------------|------| +| _default_ | | | + +## CSS Variables +n/a + +--- + +# Card Text + +Functional component that enforces consistent styling. + +## Usage + +```html +Nisi anim deserunt Lorem reprehenderit laborum. +``` + +## Props +n/a + +## Events +n/a + +## Slots +| Slot | Description | Data | +|-----------|-------------|------| +| _default_ | | | + +## CSS Variables +n/a + +--- + +# Card Actions + +Functional component that enforces consistent styling. + +## Usage + +```html + + + + +``` + +## Props +n/a + +## Events +n/a + +## Slots +| Slot | Description | Data | +|-----------|-------------|------| +| _default_ | | | + +## CSS Variables +n/a + +--- diff --git a/src/components/v-card/v-card-actions.vue b/src/components/v-card/v-card-actions.vue new file mode 100644 index 0000000000..5dfb61bcc6 --- /dev/null +++ b/src/components/v-card/v-card-actions.vue @@ -0,0 +1,15 @@ + + + diff --git a/src/components/v-card/v-card-subtitle.vue b/src/components/v-card/v-card-subtitle.vue new file mode 100644 index 0000000000..659ded2d9f --- /dev/null +++ b/src/components/v-card/v-card-subtitle.vue @@ -0,0 +1,15 @@ + + + diff --git a/src/components/v-card/v-card-text.vue b/src/components/v-card/v-card-text.vue new file mode 100644 index 0000000000..152bca6643 --- /dev/null +++ b/src/components/v-card/v-card-text.vue @@ -0,0 +1,14 @@ + + + diff --git a/src/components/v-card/v-card-title.vue b/src/components/v-card/v-card-title.vue new file mode 100644 index 0000000000..87cff239bd --- /dev/null +++ b/src/components/v-card/v-card-title.vue @@ -0,0 +1,17 @@ + + + diff --git a/src/components/v-card/v-card.story.ts b/src/components/v-card/v-card.story.ts new file mode 100644 index 0000000000..c9a39a8e71 --- /dev/null +++ b/src/components/v-card/v-card.story.ts @@ -0,0 +1,93 @@ +import { withKnobs, boolean } from '@storybook/addon-knobs'; +import Vue from 'vue'; +import VCard from './v-card.vue'; +import VCardTitle from './v-card-title.vue'; +import VCardSubtitle from './v-card-subtitle.vue'; +import VCardText from './v-card-text.vue'; +import VCardActions from './v-card-actions.vue'; +import markdown from './readme.md'; +import withPadding from '../../../.storybook/decorators/with-padding'; +import { defineComponent, ref } from '@vue/composition-api'; + +Vue.component('v-card', VCard); +Vue.component('v-card-title', VCardTitle); +Vue.component('v-card-subtitle', VCardSubtitle); +Vue.component('v-card-text', VCardText); +Vue.component('v-card-actions', VCardActions); + +export default { + title: 'Components / Card', + decorators: [withKnobs, withPadding], + parameters: { + notes: markdown + } +}; + +export const basic = () => + defineComponent({ + props: { + disabled: { + default: boolean('Disabled', false) + }, + tile: { + default: boolean('Tile', false) + } + }, + template: ` + + Hello World! + This is the subtitle + Black ray-bans, you know she's with the band. Such a sight to see and it's all for me. Heaven is jealous of our love, angels are crying from up above. Turned the bedroom into a fair (a fair!) It’s in the palm of your hand now baby. + + ` + }); + +export const withImage = () => + defineComponent({ + template: ` + + + Hello World! + This is the subtitle + Black ray-bans, you know she's with the band. Such a sight to see and it's all for me. Heaven is jealous of our love, angels are crying from up above. Turned the bedroom into a fair (a fair!) It’s in the palm of your hand now baby. + + ` + }); + +export const withActions = () => + defineComponent({ + template: ` + + Hello World! + This is the subtitle + Black ray-bans, you know she's with the band. Such a sight to see and it's all for me. Heaven is jealous of our love, angels are crying from up above. Turned the bedroom into a fair (a fair!) It’s in the palm of your hand now baby. + + Click me + Click me + + + ` + }); + +export const asDialog = () => + defineComponent({ + setup() { + const active = ref(false); + return { active }; + }, + template: ` + + + + Are you sure you want to quit? + All unsaved changes will be lost. + + Cancel + Quit + + + + ` + }); diff --git a/src/components/v-card/v-card.test.ts b/src/components/v-card/v-card.test.ts new file mode 100644 index 0000000000..e2ad1604fd --- /dev/null +++ b/src/components/v-card/v-card.test.ts @@ -0,0 +1,13 @@ +import VCard from './v-card.vue'; +import VueCompositionAPI from '@vue/composition-api'; +import { shallowMount, createLocalVue } from '@vue/test-utils'; + +const localVue = createLocalVue(); +localVue.use(VueCompositionAPI); + +describe('Components / Card', () => { + it('Renders', () => { + const component = shallowMount(VCard, { localVue }); + expect(component.isVueInstance()).toBe(true); + }); +}); diff --git a/src/components/v-card/v-card.vue b/src/components/v-card/v-card.vue new file mode 100644 index 0000000000..2f202d58bb --- /dev/null +++ b/src/components/v-card/v-card.vue @@ -0,0 +1,61 @@ + + + + + diff --git a/src/components/v-dialog/v-dialog.vue b/src/components/v-dialog/v-dialog.vue index cf209a323d..56e911408d 100644 --- a/src/components/v-dialog/v-dialog.vue +++ b/src/components/v-dialog/v-dialog.vue @@ -68,6 +68,11 @@ export default defineComponent({ transition: opacity var(--medium) var(--transition); pointer-events: none; + .v-card { + --v-card-min-width: 400px; + --v-card-padding: 24px; + } + .v-sheet { --v-sheet-padding: 24px; } diff --git a/src/styles/mixins/type-styles.scss b/src/styles/mixins/type-styles.scss index 81768cb38e..524708e954 100644 --- a/src/styles/mixins/type-styles.scss +++ b/src/styles/mixins/type-styles.scss @@ -76,3 +76,26 @@ font-family: var(--family-sans-serif); line-height: 26px; } + +@mixin type-card-title { + color: var(--heading-text-color); + font-weight: 500; + font-size: 1.25rem; + line-height: 2rem; + letter-spacing: 0.0125em; +} + +@mixin type-card-subtitle { + color: var(--foreground-color-secondary); + font-weight: 400; + font-size: 0.875rem; + line-height: 1.375rem; + letter-spacing: 0.007em; +} + +@mixin type-card-text { + font-weight: 400; + font-size: 0.875rem; + line-height: 1.375rem; + letter-spacing: 0.007em; +} diff --git a/src/views/private-view/drawer-detail/drawer-detail.test.ts b/src/views/private-view/drawer-detail/drawer-detail.test.ts index e774d33c1e..6ffcc125eb 100644 --- a/src/views/private-view/drawer-detail/drawer-detail.test.ts +++ b/src/views/private-view/drawer-detail/drawer-detail.test.ts @@ -3,10 +3,12 @@ import VueCompositionAPI, { ref } from '@vue/composition-api'; import DrawerDetail from './drawer-detail.vue'; import * as GroupableComposition from '@/compositions/groupable/groupable'; import VIcon from '@/components/v-icon'; +import TransitionExpand from '@/components/transition/expand'; const localVue = createLocalVue(); localVue.use(VueCompositionAPI); localVue.component('v-icon', VIcon); +localVue.component('transition-expand', TransitionExpand); describe('Drawer Detail', () => { it('Uses the useGroupable composition', () => {