Skip to content

Commit

Permalink
feat(UsaIconList): implement UsaIconList component
Browse files Browse the repository at this point in the history
ISSUES CLOSED: #175
  • Loading branch information
patrickcate committed May 18, 2022
1 parent 7377534 commit cafeb54
Show file tree
Hide file tree
Showing 5 changed files with 225 additions and 0 deletions.
68 changes: 68 additions & 0 deletions src/components/UsaIconList/UsaIconList.stories.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import UsaIconList from './UsaIconList.vue'
import UsaIconListItem from '@/components/UsaIconListItem'

const defaultProps = {
color: UsaIconList.props.color.default,
size: UsaIconList.props.size.default,
}

export default {
component: UsaIconList,
title: 'Components/UsaIconList',
argTypes: {
color: {
control: { type: 'text' },
},
defaultSlot: {
control: { type: 'text' },
},
},
args: {
color: defaultProps.color,
size: defaultProps.size,
defaultSlot: `<UsaIconListItem icon="check_circle">Icon list item</UsaIconListItem><UsaIconListItem icon="check_circle">Icon list item</UsaIconListItem><UsaIconListItem icon="check_circle">Icon list item</UsaIconListItem>`,
},
}

const DefaultTemplate = (args, { argTypes }) => ({
components: { UsaIconList, UsaIconListItem },
props: Object.keys(argTypes),
setup() {
return { ...args }
},
template: `<UsaIconList
:color="color"
:size="size"
>${args.defaultSlot}</UsaIconList>`,
})

export const DefaultIconList = DefaultTemplate.bind({})
DefaultIconList.args = {
...defaultProps,
}
DefaultIconList.storyName = 'Default'

export const ColorIconList = DefaultTemplate.bind({})
ColorIconList.args = {
...defaultProps,
color: 'success',
}
ColorIconList.storyName = 'Color'

export const SingleSizeIconList = DefaultTemplate.bind({})
SingleSizeIconList.args = {
...defaultProps,
size: 'lg',
}
SingleSizeIconList.storyName = 'Single Size'

export const ResponsiveSizesIconList = DefaultTemplate.bind({})
ResponsiveSizesIconList.args = {
...defaultProps,
size: {
mobile: 'lg',
tablet: 'xl',
desktop: '2xl',
},
}
ResponsiveSizesIconList.storyName = 'Responsive Sizes'
86 changes: 86 additions & 0 deletions src/components/UsaIconList/UsaIconList.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 { h } from 'vue'
import UsaIconList from './UsaIconList.vue'

describe('UsaIconList', () => {
it('renders the component', () => {
mount(UsaIconList, {
slots: {
default: () => h('li', {}, 'Test icon list item'),
},
})

cy.get('ul.usa-icon-list')
.should('have.attr', 'class')
.and('not.match', /usa-icon-list--/)
cy.get('.usa-icon-list > li').should('contain', 'Test icon list item')
})

it('applied color and size CSS classes from prop values', () => {
mount(UsaIconList, {
props: {
color: 'primary',
size: 'xl',
},
})

cy.get('.usa-icon-list')
.should('have.class', 'usa-icon-list--primary')
.and('have.class', 'usa-icon-list--size-xl')
})

it('formats RWD CSS size classes', () => {
mount(UsaIconList, {
props: {
size: {
mobile: 'sm',
tablet: 'lg',
desktop: '2xl',
},
},
})

cy.get('.usa-icon-list')
.should('have.class', 'mobile:usa-icon-list--size-sm')
.and('have.class', 'tablet:usa-icon-list--size-lg')
.and('have.class', 'desktop:usa-icon-list--size-2xl')
})

it('uses custom responsive prefix separator', () => {
mount(UsaIconList, {
props: {
size: {
mobile: 'sm',
tablet: 'lg',
desktop: '2xl',
},
},
global: {
provide: {
'vueUswds.prefixSeparator': '-',
},
},
})

cy.get('.usa-icon-list')
.should('have.class', 'mobile-usa-icon-list--size-sm')
.and('have.class', 'tablet-usa-icon-list--size-lg')
.and('have.class', 'desktop-usa-icon-list--size-2xl')
})

it('warns in console about invalid `size` prop', () => {
cy.stub(window.console, 'warn').as('consoleWarn')

mount(UsaIconList, {
props: {
size: 'invalidsize',
},
})

cy.get('@consoleWarn').should(
'be.calledWith',
`'invalidsize' is not a valid icon list size`
)
})
})
66 changes: 66 additions & 0 deletions src/components/UsaIconList/UsaIconList.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<script setup>
import { computed, inject } from 'vue'
import { PREFIX_SEPARATOR } from '@/utils/constants.js'
const prefixSeparator = inject('vueUswds.prefixSeparator', PREFIX_SEPARATOR)
const props = defineProps({
color: {
type: String,
default: '',
},
size: {
type: [String, Object],
default: '',
validator(size) {
let isValidSize = false
const validSizes = ['', '2xs', 'xs', 'sm', 'md', 'lg', 'xl', '2xl']
if (typeof size === 'string') {
isValidSize = validSizes.includes(size)
}
if (typeof size === 'object') {
isValidSize = Object.values(size).some(breakpointSize =>
validSizes.includes(breakpointSize)
)
}
if (!isValidSize) {
console.warn(`'${size}' is not a valid icon list size`)
}
return isValidSize
},
},
})
const sizeClasses = computed(() => {
if (!!props.size && typeof props.size === 'string') {
return [`usa-icon-list--size-${props.size}`]
}
if (typeof props.size === 'object' && Object.keys(props.size).length) {
return Object.keys(props.size).reduce((acc, breakpoint) => {
acc.push(
`${breakpoint}${prefixSeparator}usa-icon-list--size-${props.size[breakpoint]}`
)
return acc
}, [])
}
return []
})
const classes = computed(() => [
{ [`usa-icon-list--${props.color}`]: props.color },
...sizeClasses.value,
])
</script>

<template>
<ul class="usa-icon-list" :class="classes"
><slot></slot
></ul>
</template>
4 changes: 4 additions & 0 deletions src/components/UsaIconList/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import UsaIconList from './UsaIconList.vue'

export { UsaIconList }
export default UsaIconList
1 change: 1 addition & 0 deletions src/components/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,3 +81,4 @@ export { default as UsaTextInput } from './UsaTextInput'
export { default as UsaValidation } from './UsaValidation'
export { default as UsaIcon } from './UsaIcon'
export { default as UsaIconListItem } from './UsaIconListItem'
export { default as UsaIconList } from './UsaIconList'

0 comments on commit cafeb54

Please sign in to comment.