Skip to content

feat(card): new helper sub-components #2375

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Dec 31, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
205 changes: 109 additions & 96 deletions src/components/card/README.md

Large diffs are not rendered by default.

41 changes: 13 additions & 28 deletions src/components/card/card-body.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { mergeData } from 'vue-functional-data-merge'
import prefixPropName from '../../utils/prefix-prop-name'
import copyProps from '../../utils/copyProps'
import pluckProps from '../../utils/pluck-props'
import { assign } from '../../utils/object'
import stripScripts from '../../utils/strip-scripts'
import cardMixin from '../../mixins/card-mixin'
import BCardTitle, { props as titleProps } from './card-title'
import BCardSubTitle, { props as subTitleProps } from './card-sub-title'

export const props = assign(
{},
Expand All @@ -13,23 +15,11 @@ export const props = assign(
bodyClass: {
type: [String, Object, Array],
default: null
},
title: {
type: String,
default: null
},
titleTag: {
type: String,
default: 'h4'
},
subTitle: {
type: String,
default: null
},
subTitleTag: {
type: String,
default: 'h6'
},
}
},
titleProps,
subTitleProps,
{
overlay: {
type: Boolean,
default: false
Expand All @@ -48,16 +38,13 @@ export default {
let cardContent = children || [ h(false) ]

if (props.title) {
cardTitle = h(props.titleTag, {
staticClass: 'card-title',
domProps: { innerHTML: stripScripts(props.title) }
})
cardTitle = h(BCardTitle, { props: pluckProps(titleProps, props) })
}

if (props.subTitle) {
cardSubTitle = h(props.subTitleTag, {
staticClass: 'card-subtitle mb-2 text-muted',
domProps: { innerHTML: stripScripts(props.subTitle) }
cardSubTitle = h(BCardSubTitle, {
props: pluckProps(subTitleProps, props),
class: [ 'mb-2' ]
})
}

Expand All @@ -69,9 +56,7 @@ export default {
{
'card-img-overlay': props.overlay,
[`bg-${props.bodyBgVariant}`]: Boolean(props.bodyBgVariant),
[`border-${props.bodyBorderVariant}`]: Boolean(
props.bodyBorderVariant
),
[`border-${props.bodyBorderVariant}`]: Boolean(props.bodyBorderVariant),
[`text-${props.bodyTextVariant}`]: Boolean(props.bodyTextVariant)
},
props.bodyClass || {}
Expand Down
38 changes: 38 additions & 0 deletions src/components/card/card-sub-title.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { mergeData } from 'vue-functional-data-merge'
import stripScripts from '../../utils/strip-scripts'

export const props = {
subTitle: {
type: String,
default: null
},
subTitleTag: {
type: String,
default: 'h6'
},
subTitleTextVariant: {
type: String,
default: 'muted'
}
}

// @vue/component
export default {
name: 'BCardSubTitle',
functional: true,
props,
render (h, { props, data, children }) {
const domProps = children ? {} : { innerHTML: stripScripts(props.subTitle) }
return h(
props.subTitleTag,
mergeData(data, {
staticClass: 'card-subtitle',
class: [
props.subTitleTextVariant ? `text-${props.subTitleTextVariant}` : null
],
domProps
}),
children
)
}
}
22 changes: 22 additions & 0 deletions src/components/card/card-text.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { mergeData } from 'vue-functional-data-merge'

export const props = {
textTag: {
type: String,
default: 'p'
}
}

// @vue/component
export default {
name: 'BCardText',
functional: true,
props,
render (h, { props, data, children }) {
return h(
props.textTag,
mergeData(data, { staticClass: 'card-text' }),
children
)
}
}
36 changes: 36 additions & 0 deletions src/components/card/card-text.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import CardText from './card-text'
import { mount } from '@vue/test-utils'

describe('card-text', async () => {
it('has root element "p"', async () => {
const wrapper = mount(CardText)
expect(wrapper.is('p')).toBe(true)
})

it('has class card-text', async () => {
const wrapper = mount(CardText)
expect(wrapper.classes()).toContain('card-text')
})

it('has custom root element "div" when prop text-tag=div', async () => {
const wrapper = mount(CardText, {
context: {
props: {
textTag: 'div'
}
}
})
expect(wrapper.is('div')).toBe(true)
expect(wrapper.classes()).toContain('card-text')
})

it('accepts custom classes', async () => {
const wrapper = mount(CardText, {
context: {
class: ['foobar']
}
})
expect(wrapper.classes()).toContain('card-text')
expect(wrapper.classes()).toContain('foobar')
})
})
31 changes: 31 additions & 0 deletions src/components/card/card-title.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { mergeData } from 'vue-functional-data-merge'
import stripScripts from '../../utils/strip-scripts'

export const props = {
title: {
type: String,
default: null
},
titleTag: {
type: String,
default: 'h4'
}
}

// @vue/component
export default {
name: 'BCardTitle',
functional: true,
props,
render (h, { props, data, children }) {
const domProps = children ? {} : { innerHTML: stripScripts(props.title) }
return h(
props.titleTag,
mergeData(data, {
staticClass: 'card-title',
domProps
}),
children
)
}
}
6 changes: 6 additions & 0 deletions src/components/card/index.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,23 @@
import BCard from './card'
import BCardHeader from './card-header'
import BCardBody from './card-body'
import BCardTitle from './card-title'
import BCardSubTitle from './card-sub-title'
import BCardFooter from './card-footer'
import BCardImg from './card-img'
import BCardText from './card-text'
import BCardGroup from './card-group'
import { registerComponents, vueUse } from '../../utils/plugins'

const components = {
BCard,
BCardHeader,
BCardBody,
BCardTitle,
BCardSubTitle,
BCardFooter,
BCardImg,
BCardText,
BCardGroup
}

Expand Down
49 changes: 26 additions & 23 deletions src/components/card/package.json
Original file line number Diff line number Diff line change
@@ -1,25 +1,28 @@
{
"name": "@bootstrap-vue/card",
"version": "1.0.0",
"meta": {
"title": "Card",
"component": "BCard",
"components": [
"BCardHeader",
"BCardFooter",
"BCardBody",
"BCardImg",
"BCardGroup"
],
"slots": [
{
"name": "header",
"description": "For custom rendering of header content"
},
{
"name": "footer",
"description": "For custom rendering of footer content"
}
]
}
"name": "@bootstrap-vue/card",
"version": "1.0.0",
"meta": {
"title": "Card",
"component": "BCard",
"components": [
"BCardHeader",
"BCardFooter",
"BCardBody",
"BCardTitle",
"BCardSubTitle",
"BCardImg",
"BCardText",
"BCardGroup"
],
"slots": [
{
"name": "header",
"description": "For custom rendering of header content"
},
{
"name": "footer",
"description": "For custom rendering of footer content"
}
]
}
}