From f1650d6e2409e1200fba598abb04fb7798207e92 Mon Sep 17 00:00:00 2001 From: Patrick Cate Date: Sat, 16 Dec 2023 23:59:03 -0500 Subject: [PATCH 01/16] fix(UsaRange): remove redundant ARIA attributes --- src/components/UsaRange/UsaRange.test.js | 20 +++++++------------- src/components/UsaRange/UsaRange.vue | 4 ---- 2 files changed, 7 insertions(+), 17 deletions(-) diff --git a/src/components/UsaRange/UsaRange.test.js b/src/components/UsaRange/UsaRange.test.js index 831669a0..83a3c2bf 100644 --- a/src/components/UsaRange/UsaRange.test.js +++ b/src/components/UsaRange/UsaRange.test.js @@ -19,19 +19,13 @@ describe('UsaRange', () => { cy.get('div.usa-form-group').should('not.have.attr', 'name') cy.get('label.usa-label').should('have.attr', 'for') - cy.get('input.usa-range').as('range').should('have.attr', 'id') - cy.get('@range') - .should('have.attr', 'name') - .and('contain', 'test-dropdown-name') - cy.get('@range').should('have.attr', 'type').and('contain', 'range') - cy.get('@range').should('have.attr', 'role').and('contain', 'slider') - cy.get('@range').should('have.attr', 'min').and('contain', 0) - cy.get('@range').should('have.attr', 'aria-valuemin').and('contain', 0) - cy.get('@range').should('have.attr', 'max').and('contain', 100) - cy.get('@range').should('have.attr', 'aria-valuemax').and('contain', 100) - cy.get('@range').should('have.attr', 'aria-valuenow').and('contain', '') - - cy.get('@range').should('have.attr', 'aria-describedby') + cy.get('input.usa-range').should('have.attr', 'id') + cy.get('input.usa-range') + .should('have.attr', 'name', 'test-dropdown-name') + .and('have.attr', 'type', 'range') + .and('have.attr', 'min', 0) + .and('have.attr', 'max', 100) + .and('have.attr', 'aria-describedby') }) it('displays `label`, `hint`, and `error-message` slot content', () => { diff --git a/src/components/UsaRange/UsaRange.vue b/src/components/UsaRange/UsaRange.vue index 9f709f59..e4e6807c 100644 --- a/src/components/UsaRange/UsaRange.vue +++ b/src/components/UsaRange/UsaRange.vue @@ -118,12 +118,8 @@ const ariaDescribedby = computed(() => { class="usa-range" :class="classes" type="range" - role="slider" :min="min" :max="max" - :aria-valuemin="min" - :aria-valuemax="max" - :aria-valuenow="rangeValue" :required="required" :aria-describedby="ariaDescribedby" /> From dc2bc9223172c3c87317deef3f28a7391cb9bc50 Mon Sep 17 00:00:00 2001 From: Patrick Cate Date: Sun, 17 Dec 2023 23:01:17 -0500 Subject: [PATCH 02/16] feat(UsaRange): add `unit` and `preposition` props --- src/components/UsaRange/UsaRange.stories.js | 22 ++++++++++++++++ src/components/UsaRange/UsaRange.test.js | 29 +++++++++++++++++++++ src/components/UsaRange/UsaRange.vue | 21 +++++++++++++++ 3 files changed, 72 insertions(+) diff --git a/src/components/UsaRange/UsaRange.stories.js b/src/components/UsaRange/UsaRange.stories.js index c9bcb8a9..74d78919 100644 --- a/src/components/UsaRange/UsaRange.stories.js +++ b/src/components/UsaRange/UsaRange.stories.js @@ -4,6 +4,8 @@ import UsaRange from './UsaRange.vue' const defaultProps = { min: UsaRange.props.min.default, max: UsaRange.props.max.default, + unit: UsaRange.props.unit.default, + preposition: UsaRange.props.preposition.default, modelValue: UsaRange.props.modelValue.default, label: UsaRange.props.label.default, required: UsaRange.props.required.default, @@ -22,6 +24,12 @@ export default { max: { control: { type: 'number' }, }, + unit: { + control: { type: 'text' }, + }, + preposition: { + control: { type: 'text' }, + }, modelValue: { control: { type: 'text' }, }, @@ -60,6 +68,8 @@ export default { args: { min: defaultProps.min, max: defaultProps.max, + unit: defaultProps.unit, + preposition: defaultProps.preposition, modelValue: defaultProps.modelValue, label: defaultProps.label, required: defaultProps.required, @@ -88,6 +98,8 @@ const DefaultTemplate = (args, { argTypes }) => ({ v-bind="$attrs" :min="min" :max="max" + :unit="unit" + :preposition="preposition" :label="label" :required="required" :error="error" @@ -120,6 +132,16 @@ DefaultValueRange.args = { } DefaultValueRange.storyName = 'Default Value' +export const CustomUnitAndPrepositionRange = DefaultTemplate.bind({}) +CustomUnitAndPrepositionRange.args = { + ...defaultProps, + label: 'Range label', + modelValue: '75', + unit: 'degrees', + preposition: 'out of a total', +} +CustomUnitAndPrepositionRange.storyName = 'Custom Unit and Preposition' + export const HintRange = DefaultTemplate.bind({}) HintRange.args = { ...defaultProps, diff --git a/src/components/UsaRange/UsaRange.test.js b/src/components/UsaRange/UsaRange.test.js index 83a3c2bf..a061aa4d 100644 --- a/src/components/UsaRange/UsaRange.test.js +++ b/src/components/UsaRange/UsaRange.test.js @@ -15,6 +15,8 @@ describe('UsaRange', () => { hint: () => 'Test hint', }, }) + .its('wrapper') + .as('wrapper') cy.get('div.usa-form-group').should('not.have.attr', 'name') cy.get('label.usa-label').should('have.attr', 'for') @@ -26,6 +28,14 @@ describe('UsaRange', () => { .and('have.attr', 'min', 0) .and('have.attr', 'max', 100) .and('have.attr', 'aria-describedby') + cy.get('input.usa-range').should('not.have.attr', 'aria-valuetext') + + // Check for correct default preposition prop value. + cy.get('@wrapper') + .vue() + .then(({ vm }) => { + expect(vm.props.preposition).to.equal('of') + }) }) it('displays `label`, `hint`, and `error-message` slot content', () => { @@ -79,6 +89,25 @@ describe('UsaRange', () => { .and('contain', 'custom-id-hint custom-id-error-message') }) + it('`aria-valuetext` attribute has correct text', () => { + cy.mount(UsaRange, { + props: { + modelValue: 10, + }, + }) + .its('wrapper') + .as('wrapper') + + cy.get('input').should('have.attr', 'aria-valuetext', '10 of 100') + + cy.get('@wrapper').invoke('setProps', { + unit: 'degrees', + preposition: 'at', + }) + + cy.get('input').should('have.attr', 'aria-valuetext', '10 degrees at 100') + }) + it('add required attribute if `required` prop is true', () => { cy.mount(UsaRange, { props: { diff --git a/src/components/UsaRange/UsaRange.vue b/src/components/UsaRange/UsaRange.vue index e4e6807c..819733d8 100644 --- a/src/components/UsaRange/UsaRange.vue +++ b/src/components/UsaRange/UsaRange.vue @@ -22,6 +22,14 @@ const props = defineProps({ type: Number, default: 100, }, + unit: { + type: String, + default: '', + }, + preposition: { + type: String, + default: 'of', + }, modelValue: { type: [String, Number], default: '', @@ -83,6 +91,18 @@ const ariaDescribedby = computed(() => { return ids.length ? ids.join(' ') : null }) + +const callout = computed(() => { + if (!rangeValue.value && rangeValue.value !== 0) { + return null + } + + if (props.unit) { + return `${rangeValue.value} ${props.unit} ${props.preposition} ${props.max}` + } + + return `${rangeValue.value} ${props.preposition} ${props.max}` +})