Skip to content

Commit

Permalink
feat: implement UsaSummaryBox component
Browse files Browse the repository at this point in the history
ISSUES CLOSED: #72
  • Loading branch information
patrickcate committed Nov 7, 2021
1 parent ffa2408 commit 83e9d6a
Show file tree
Hide file tree
Showing 4 changed files with 203 additions and 0 deletions.
58 changes: 58 additions & 0 deletions src/components/UsaSummaryBox/UsaSummaryBox.stories.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import UsaSummaryBox from './UsaSummaryBox.vue'

const defaultProps = {
heading: 'Key information',
headingTag: 'h2',
customClasses: {
body: [],
heading: [],
text: [],
},
}

export default {
component: UsaSummaryBox,
title: 'Components/UsaSummaryBox',
argTypes: {
id: {
control: { type: 'text' },
},
heading: {
control: { type: 'text' },
},
headingTag: {
options: ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'],
control: { type: 'select' },
},
defaultSlot: {
control: { type: 'text' },
},
},
args: {
heading: defaultProps.heading,
headingTag: defaultProps.headingTag,
defaultSlot: `<ul class="usa-list">
<li>If you are under a winter storm warning, <a class="usa-summary-box__link" href="#">find shelter</a> right away.</li>
<li>Sign up for <a class="usa-summary-box__link" href="#">your community's warning system</a>.</li>
<li>Learn the signs of, and basic treatments for, <a class="usa-summary-box__link" href="#">frostbite</a> and <a class="usa-summary-box__link" href="#">hypothermia</a>.</li>
<li>Gather emergency supplies for your <a class="usa-summary-box__link" href="#">home</a> and your <a class="usa-summary-box__link" href="#">car</a>.</li>
</ul>`,
},
}

const DefaultTemplate = (args, { argTypes }) => ({
components: { UsaSummaryBox },
props: Object.keys(argTypes),
setup() {
return {
...args,
}
},
template: `<UsaSummaryBox :id="id" :heading="heading" :heading-tag="headingTag">${args.defaultSlot}</UsaSummaryBox>`,
})

export const DefaultSummaryBox = DefaultTemplate.bind({})
DefaultSummaryBox.args = {
...defaultProps,
}
DefaultSummaryBox.storyName = 'Default'
86 changes: 86 additions & 0 deletions src/components/UsaSummaryBox/UsaSummaryBox.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import '@module/uswds/dist/css/uswds.min.css'
import { mount } from '@cypress/vue'
import UsaSummaryBox from './UsaSummaryBox.vue'

describe('UsaSummaryBox', () => {
const defaultSlotContent = `Test slot content.`

it('renders the component', () => {
mount(UsaSummaryBox, {
slots: {
default: () => defaultSlotContent,
},
})

cy.get('.usa-summary-box')
.should('have.attr', 'role')
.and('contain', 'region')
cy.get('.usa-summary-box__body').should('exist')
cy.get('.usa-summary-box__heading').should('contain', 'Key information')
cy.get('.usa-summary-box__text').should('contain', defaultSlotContent)
})

it('renders custom heading text', () => {
mount(UsaSummaryBox, {
props: {
heading: 'Custom heading text',
},
slots: {
default: () => defaultSlotContent,
},
})

cy.get('.usa-summary-box__heading').should('contain', 'Custom heading text')
})

it('aria-labelledby attribute matches id', () => {
mount(UsaSummaryBox, {
slots: {
default: () => defaultSlotContent,
},
})

cy.get('.usa-summary-box')
.invoke('attr', 'aria-labelledby')
.then(ariaLabeledBy => {
expect(ariaLabeledBy).to.not.be.empty
cy.get('.usa-summary-box__heading').should('have.id', ariaLabeledBy)
})
})

it('uses custom id prop', () => {
mount(UsaSummaryBox, {
props: {
id: 'custom-id',
},
slots: {
default: () => defaultSlotContent,
},
})

cy.get('.usa-summary-box')
.should('have.attr', 'aria-labelledby')
.and('contain', 'custom-id')

cy.get('.usa-summary-box__heading').should('have.id', 'custom-id')
})

it('adds custom CSS classes', () => {
mount(UsaSummaryBox, {
props: {
customClasses: {
body: ['test-body-class'],
heading: ['test-heading-class'],
text: ['test-text-class'],
},
},
slots: {
default: () => defaultSlotContent,
},
})

cy.get('.test-body-class').should('exist')
cy.get('.test-heading-class').should('exist')
cy.get('.test-text-class').should('exist')
})
})
55 changes: 55 additions & 0 deletions src/components/UsaSummaryBox/UsaSummaryBox.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
<script setup>
import { inject, computed } from 'vue'
import { nextId as nextUniqueId } from '@/utils/unique-id.js'
import BaseHeading from '@/components/BaseHeading'
const nextId = inject('nextId', nextUniqueId)
const props = defineProps({
id: {
type: String,
default: null,
},
heading: {
type: String,
default: 'Key information',
validator: heading => {
return heading !== ''
},
},
headingTag: {
type: String,
default: 'h2',
},
customClasses: {
type: Object,
default: () => {
return {
body: [],
heading: [],
text: [],
}
},
},
})
const computedId = computed(() => {
return !props.id ? nextId() : props.id
})
</script>
<template>
<div class="usa-summary-box" role="region" :aria-labelledby="computedId">
<div class="usa-summary-box__body" :class="[customClasses?.body]">
<BaseHeading
:id="computedId"
class="usa-summary-box__heading"
:class="[customClasses?.heading]"
:tag="headingTag"
>{{ heading }}</BaseHeading
>
<div class="usa-summary-box__text" :class="[customClasses?.text]">
<slot></slot>
</div>
</div>
</div>
</template>
4 changes: 4 additions & 0 deletions src/components/UsaSummaryBox/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import UsaSummaryBox from './UsaSummaryBox.vue'

export { UsaSummaryBox }
export default UsaSummaryBox

0 comments on commit 83e9d6a

Please sign in to comment.