From 0acf44f101dfd115a1faab3aa26ff78a5ad70939 Mon Sep 17 00:00:00 2001 From: mbucknel <mbucknell@usgs.gov> Date: Wed, 1 Jun 2022 16:24:41 -0500 Subject: [PATCH] Added a USWDS checkbox component --- .../vue-components/graph-controls.vue | 69 ++++++--------- .../scripts/uswds-components/checkbox.test.js | 86 +++++++++++++++++++ .../src/scripts/uswds-components/checkbox.vue | 71 +++++++++++++++ 3 files changed, 185 insertions(+), 41 deletions(-) create mode 100644 assets/src/scripts/uswds-components/checkbox.test.js create mode 100644 assets/src/scripts/uswds-components/checkbox.vue diff --git a/assets/src/scripts/monitoring-location/components/hydrograph/vue-components/graph-controls.vue b/assets/src/scripts/monitoring-location/components/hydrograph/vue-components/graph-controls.vue index 5c4c3dbd7..76cc102ed 100644 --- a/assets/src/scripts/monitoring-location/components/hydrograph/vue-components/graph-controls.vue +++ b/assets/src/scripts/monitoring-location/components/hydrograph/vue-components/graph-controls.vue @@ -1,40 +1,22 @@ <template> <div> - <div class="usa-checkbox"> - <input - id="iv-compare-timeseries-checkbox" - class="usa-checkbox__input" - type="checkbox" - name="graphControls" - value="compare" - :checked="compareChecked" - :disabled="!compareEnabled" - @change="selectCompare" - > - <label - class="usa-checkbox__label" - for="iv-compare-timeseries-checkbox" - > - Compare to last year - </label> - </div> - <div class="usa-checkbox"> - <input - id="iv-median-timeseries-checkbox" - class="usa-checkbox__input" - type="checkbox" - name="graphControls" - value="median" - :checked="medianChecked" - @change="selectMedian" - > - <label - class="usa-checkbox__label" - for="iv-median-timeseries-checkbox" - > - Display median - </label> - </div> + <USWDSCheckbox + label="Compare to last year" + name="graphControls" + value="compare" + id="iv-compare-timeseries-checkbox" + :is-checked="compareChecked" + :is-checkbox-disabled="!compareEnabled" + @toggleCheckbox="selectCompare" + /> + <USWDSCheckbox + label="Display median" + name="graphControls" + value="median" + id="iv-median-timeseries-checkbox" + :is-checked="medianChecked" + @toggleCheckbox="selectMedian" + /> </div> </template> @@ -44,6 +26,7 @@ import {createSelector} from 'reselect'; import {inject} from 'vue'; import config from 'ui/config'; +import USWDSCheckbox from 'ui/uswds-components/checkbox.vue'; import {getSelectedParameterCode, getSelectedTimeSpan} from 'ml/selectors/hydrograph-state-selector'; import {getTimeRange} from 'ml/selectors/hydrograph-data-selector'; @@ -55,6 +38,10 @@ import {showDataIndicators} from '../data-indicator'; export default { name: 'GraphControls', + components: { + USWDSCheckbox + }, + setup() { const hasIVData = function(parameterCode) { return config.ivPeriodOfRecord && parameterCode in config.ivPeriodOfRecord; @@ -86,11 +73,11 @@ export default { const reduxStore = inject('store'); const siteno = inject('siteno'); - function selectCompare(ev) { + function selectCompare(checked) { const reduxState = reduxStore.getState(); const currentTimeRange = getTimeRange('current')(reduxState); - actions.setCompareDataVisibility(ev.target.checked); - if (ev.target.checked) { + actions.setCompareDataVisibility(checked); + if (checked) { showDataIndicators(true, reduxStore); actions.retrievePriorYearIVData(siteno, { parameterCode: getSelectedParameterCode(reduxState), @@ -104,10 +91,10 @@ export default { } } - function selectMedian(ev) { + function selectMedian(checked) { const reduxState = reduxStore.getState(); - actions.setMedianDataVisibility(ev.target.checked); - if (ev.target.checked) { + actions.setMedianDataVisibility(checked); + if (checked) { showDataIndicators(true, reduxStore); actions.retrieveMedianStatistics(siteno, getSelectedParameterCode(reduxState)) .then(() => { diff --git a/assets/src/scripts/uswds-components/checkbox.test.js b/assets/src/scripts/uswds-components/checkbox.test.js new file mode 100644 index 000000000..d04cddad2 --- /dev/null +++ b/assets/src/scripts/uswds-components/checkbox.test.js @@ -0,0 +1,86 @@ +import {mount} from '@vue/test-utils'; + +import USWDSCheckbox from './checkbox.vue'; + +describe('components/uswds/checkbox', () => { + it('Expects a properly rendered unchecked USWDS checkbox', () => { + const wrapper = mount(USWDSCheckbox, { + props: { + label: 'This checkbox', + name: 'checkbox-name', + value: 'yes', + id: 'my-unique-id' + } + }); + + const checkbox = wrapper.find('.usa-checkbox__input'); + const checkboxLabel = wrapper.find('.usa-checkbox__label'); + expect(checkbox.attributes('id')).toBe('my-unique-id'); + expect(checkbox.attributes('name')).toBe('checkbox-name'); + expect(checkbox.attributes('value')).toBe('yes'); + expect(checkbox.element.checked).toBe(false); + expect(checkboxLabel.attributes('for')).toBe('my-unique-id'); + expect(checkboxLabel.text()).toBe('This checkbox'); + }); + + it('Expects a checkbox that is initial checked', () => { + const wrapper = mount(USWDSCheckbox, { + props: { + label: 'This checkbox', + name: 'checkbox-name', + value: 'yes', + id: 'my-unique-id', + isChecked: true + } + }); + + const checkbox = wrapper.find('.usa-checkbox__input'); + expect(checkbox.element.checked).toBe(true); + }); + + it('Expect to emit a toggleCheckbox event if the checkbox is clicked', async() => { + const wrapper = mount(USWDSCheckbox, { + props: { + label: 'This checkbox', + name: 'checkbox-name', + value: 'yes', + id: 'my-unique-id' + } + }); + const checkbox = wrapper.find('.usa-checkbox__input'); + checkbox.setChecked(true); + + expect(wrapper.emitted('toggleCheckbox')[0][0]).toBe(true); + + checkbox.setChecked(false); + + expect(wrapper.emitted('toggleCheckbox')[1][0]).toBe(false); + }); + + it('Expect checkbox to be disabled when prop true', () => { + const wrapper = mount(USWDSCheckbox, { + props: { + label: 'This checkbox', + name: 'checkbox-name', + value: 'yes', + id: 'my-unique-id', + isCheckboxDisabled: true + } + }); + const checkboxInput = wrapper.find('input'); + expect(checkboxInput.attributes('disabled')).toBeDefined(); + }); + + it('Expect checkbox to be enabled by default', () => { + const wrapper = mount(USWDSCheckbox, { + props: { + label: 'This checkbox', + name: 'checkbox-name', + value: 'yes', + id: 'my-unique-id' + } + }); + const checkboxInput = wrapper.find('input'); + expect(checkboxInput.attributes('disabled')).not.toBeDefined(); + }); +}); diff --git a/assets/src/scripts/uswds-components/checkbox.vue b/assets/src/scripts/uswds-components/checkbox.vue new file mode 100644 index 000000000..1dbf39c41 --- /dev/null +++ b/assets/src/scripts/uswds-components/checkbox.vue @@ -0,0 +1,71 @@ +<template> + <div class="usa-checkbox"> + <input + :id="id" + class="usa-checkbox__input" + type="checkbox" + :name="name" + :value="value" + :checked="isChecked" + :disabled="isCheckboxDisabled" + @change="toggleCheckbox" + > + <label + class="usa-checkbox__label" + :for="id" + > + {{ label }} + </label> + </div> +</template> + +<script> +/* + * @vue-prop {String} label + * @vue-prop {String} name + * @vue-prop {String} value + * @vue-prop {String} id - should be unique with the DOM + * @vue-prop {Boolean} isChecked - defaults to false + * @vue-prop {Boolean} isCheckboxDisabled - checkbox disabled when set to true, default is false + * @vue-event {DOM Event} toggleCheckbox + */ +export default { + name: 'USWDSCheckbox', + props: { + label: { + type: String, + required: true + }, + name: { + type: String, + required: true + }, + value: { + type: String, + required: true + }, + id: { + type: String, + required: true + }, + isChecked: { + type: Boolean, + default: false + }, + isCheckboxDisabled: { + type: Boolean, + default: false + } + }, + emits: ['toggleCheckbox'], + setup(props, {emit}) { + function toggleCheckbox(ev) { + emit('toggleCheckbox', ev.currentTarget.checked); + } + + return { + toggleCheckbox + }; + } +}; +</script> -- GitLab