Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
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
12 changes: 12 additions & 0 deletions tests/quantity-spin-button/data/assertions.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
assertionId,priority,assertionStatement,assertionPhrase,refIds
errorMessage,1,"Error message, 'Must be between 1 and 8', is conveyed","convey error message, 'Must be between 1 and 8'",aria-errormessage
interactionModeEnabled,2,Screen reader switched from reading mode to interaction mode|{screenReader} switched from {readingMode} to {interactionMode},switch from reading mode to interaction mode|switch from {readingMode} to {interactionMode},
isInvalid,1,"State, 'not valid', is conveyed","convey state, 'not valid'",aria-invalid
maximumValue8,2,"Maximum value, '8', is conveyed","convey maximum value, '8'",aria-valuemax
minimumValue1,2,"Minimum value, '1', is conveyed","convey minimum value, '1'",aria-valuemin
nameAdults,1,"Name of the spin button, 'Adults', is conveyed","convey name of spin button, 'Adults'",label
roleSpinbutton,1,Role 'spin button' is conveyed,"convey role, 'spin button'",spinbutton
value1,1,"Value, '1', is conveyed","convey value, '1'",aria-valuenow
value2,1,"Value, '2', is conveyed","convey value, '2'",aria-valuenow
value8,1,"Value, '8', is conveyed","convey value, '8'",aria-valuenow
value9,1,"Value, '9', is conveyed","convey value, '9'",aria-valuenow
25 changes: 25 additions & 0 deletions tests/quantity-spin-button/data/jaws-commands.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
testId,command,settings,assertionExceptions,presentationNumber
navForwardsToSpinbutton,down,virtualCursor,0:nameAdults 0:minimumValue1 0:maximumValue8 ,1
navForwardsToSpinbutton,f,virtualCursor,,1.1
navForwardsToSpinbutton,tab,virtualCursor,2:interactionModeEnabled,1.2
navForwardsToSpinbutton,tab,pcCursor,,1.3
navForwardsToSpinbutton,e,virtualCursor,,1.4
navBackToSpinbutton,up,virtualCursor,0:nameAdults,2
navBackToSpinbutton,shift+f,virtualCursor,,2.1
navBackToSpinbutton,shift+tab,virtualCursor,2:interactionModeEnabled,2.2
navBackToSpinbutton,shift+tab,pcCursor,,2.3
navBackToSpinbutton,shift+e,virtualCursor,,2.4
reqInfoAboutSpinbutton,ins+tab,virtualCursor,,7
reqInfoAboutSpinbutton,ins+up,virtualCursor,0:minimumValue1 0:maximumValue8,7.1
reqInfoAboutSpinbutton,ins+tab,pcCursor,,8
reqInfoAboutSpinbutton,ins+up,pcCursor,0:minimumValue1 0:maximumValue8,8.1
reqInfoAboutInvalidSpinbutton,ins+tab,virtualCursor,,9
reqInfoAboutInvalidSpinbutton,ins+up,virtualCursor,0:minimumValue1 0:maximumValue8 0:isInvalid 0:errorMessage,9.1
reqInfoAboutInvalidSpinbutton,ins+tab,pcCursor,,9.2
reqInfoAboutInvalidSpinbutton,ins+up,pcCursor,0:minimumValue1 0:maximumValue8 0:isInvalid 0:errorMessage,9.3
incrementSpinbuttonByOneStep,up,pcCursor,,11
decrementSpinbuttonByOneStep,down,pcCursor,,13
decrementSpinbuttonToMinimumValue,home,pcCursor,,19
incrementSpinbuttonToMaximumValue,end,pcCursor,,21
decrementSpinbuttonToMinimumValue,home,pcCursor,,19
incrementSpinbuttonToMaximumValue,end,pcCursor,,21
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// sets focus on a link after the spin button
testPageDocument.getElementById('afterlink').focus();
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// sets focus on a link before the chespin button
testPageDocument.getElementById('beforelink').focus();
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// sets focus on the 'Adults' spinbutton
testPageDocument.getElementById('adults').focus();
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// sets focus on the 'Adults' spinbutton and sets value to 2
testPageDocument.defaultView.spinButtonController.setValue('2', true);
testPageDocument.getElementById('adults').focus();
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// sets focus on the 'Adults' spinbutton and sets value to 9
testPageDocument.defaultView.spinButtonController.setValue('9', true);
testPageDocument.getElementById('adults').focus();
25 changes: 25 additions & 0 deletions tests/quantity-spin-button/data/nvda-commands.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
testId,command,settings,assertionExceptions,presentationNumber
navForwardsToSpinbutton,down,browseMode,0:nameAdults 0:minimumValue1 0:maximumValue8 ,1
navForwardsToSpinbutton,f,browseMode,,1.1
navForwardsToSpinbutton,tab,browseMode,2:interactionModeEnabled,1.2
navForwardsToSpinbutton,tab,focusMode,,1.3
navForwardsToSpinbutton,e,browseMode,,1.4
navBackToSpinbutton,up,browseMode,0:nameAdults 0:minimumValue1 0:maximumValue8 ,2
navBackToSpinbutton,shift+f,browseMode,,2.1
navBackToSpinbutton,shift+tab,browseMode,2:interactionModeEnabled,2.2
navBackToSpinbutton,shift+tab,focusMode,,2.3
navBackToSpinbutton,shift+e,browseMode,,2.4
reqInfoAboutSpinbutton,ins+tab,browseMode,,7
reqInfoAboutSpinbutton,ins+up,browseMode,0:minimumValue1 0:maximumValue8,7.1
reqInfoAboutSpinbutton,ins+tab,focusMode,,8
reqInfoAboutSpinbutton,ins+up,focusMode,0:minimumValue1 0:maximumValue8,8.1
reqInfoAboutInvalidSpinbutton,ins+tab,browseMode,,9
reqInfoAboutInvalidSpinbutton,ins+up,browseMode,0:minimumValue1 0:maximumValue8 0:isInvalid 0:errorMessage,9.1
reqInfoAboutInvalidSpinbutton,ins+tab,focusMode,,9.2
reqInfoAboutInvalidSpinbutton,ins+up,focusMode,0:minimumValue1 0:maximumValue8 0:isInvalid 0:errorMessage,9.3
incrementSpinbuttonByOneStep,up,focusMode,,11
decrementSpinbuttonByOneStep,down,focusMode,,13
decrementSpinbuttonToMinimumValue,home,focusMode,,19
incrementSpinbuttonToMaximumValue,end,focusMode,,21
decrementSpinbuttonToMinimumValue,home,focusMode,,19
incrementSpinbuttonToMaximumValue,end,focusMode,,21
14 changes: 14 additions & 0 deletions tests/quantity-spin-button/data/references.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
refId,type,value,linkText
author,metadata,Isabel Del Castillo,
title,metadata,Quantity Spin Button Example,
authorEmail,metadata,[email protected],
reference,metadata,reference/2025-10-23_121658/quantity-spinbutton.html,Test Case Page for Quantity Spin Button
designPattern,metadata,https://www.w3.org/WAI/ARIA/apg/patterns/spinbutton/,APG Pattern: Spinbutton
example,metadata,https://www.w3.org/WAI/ARIA/apg/patterns/spinbutton/examples/quantity-spinbutton/,APG Example: Quantity Spin Button
spinbutton,aria,spinbutton,spinbutton
aria-valuenow,aria,aria-valuenow,aria-valuenow
aria-valuemin,aria,aria-valuemin,aria-valuemin
aria-valuemax,aria,aria-valuemax,aria-valuemax
aria-invalid,aria,aria-invalid,aria-invalid
aria-errormessage,aria,aria-errormessage,aria-errormessage
label,htmlAam,label,HTML label
6 changes: 6 additions & 0 deletions tests/quantity-spin-button/data/scripts.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
setupScript,setupScriptDescription
setFocusAfterAdultsSpinbutton,sets focus on a link after the Adults spin button
setFocusBeforeAdultsSpinbutton,sets focus on a link before the Adults spin button
setFocusOnAdultsSpinbutton,sets focus on the 'Adults' spin button
setFocusOnAdultsSpinbuttonValue2,sets focus on the 'Adults' spin button and sets value to' 2'
setFocusOnAdultsSpinbuttonValue9,sets focus on the 'Adults' spin button and sets value to' 9'
9 changes: 9 additions & 0 deletions tests/quantity-spin-button/data/tests.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
testId,title,presentationNumber,setupScript,instructions,assertions
navForwardsToSpinbutton,Navigate forwards to a spin button,5,setFocusBeforeAdultsSpinbutton,"Starting at the 'Navigate forwards from here' link, navigate to the 'Adults' spinbutton.",roleSpinbutton nameAdults value1 minimumValue1 maximumValue8 0:interactionModeEnabled
navBackToSpinbutton,Navigate backwards to a spin button,6,setFocusAfterAdultsSpinbutton,"Starting at the 'Navigate backwards from here' link, navigate to the 'Adults' spinbutton.",roleSpinbutton nameAdults value1 minimumValue1 maximumValue8 0:interactionModeEnabled
reqInfoAboutSpinbutton,Request information about a spin button,9,setFocusOnAdultsSpinbutton,"Starting at the 'Adults' spinbutton, read information about the spinbutton.",roleSpinbutton nameAdults value1 minimumValue1 maximumValue8
reqInfoAboutInvalidSpinbutton,Request information about an invalid value in a spin button,10,setFocusOnAdultsSpinbuttonValue9,"Starting at the 'Adults' spinbutton, read information about the spinbutton.",roleSpinbutton nameAdults value9 isInvalid minimumValue1 maximumValue8 errorMessage
incrementSpinbuttonByOneStep,Increment a spin button by one step,12,setFocusOnAdultsSpinbutton,"Starting at the 'Adults' spin button, set its value to 2.",value2
decrementSpinbuttonByOneStep,Decrement a spin button by one step,14,setFocusOnAdultsSpinbuttonValue2,"Starting at the 'Adults' spin button, set its value to 1.",value1
decrementSpinbuttonToMinimumValue,Decrement a spin button to the minimum value,20,setFocusOnAdultsSpinbuttonValue2,"Starting at the 'Adults' spin button, set its value to 1.",value1
incrementSpinbuttonToMaximumValue,Increment a spin button to the maximum value,22,setFocusOnAdultsSpinbutton,"Starting at the 'Adults' spin button , set its value to 8.",value8
21 changes: 21 additions & 0 deletions tests/quantity-spin-button/data/voiceover_macos-commands.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
testId,command,settings,assertionExceptions,presentationNumber
navForwardsToSpinbutton,ctrl+opt+right,,0:nameAdults,5
navForwardsToSpinbutton,j,singleQuickKeyNavOn,,5.1
navForwardsToSpinbutton,tab,,,5.2
navBackToSpinbutton,ctrl+opt+left,,0:nameAdults,6
navBackToSpinbutton,shift+j,singleQuickKeyNavOn,,6.1
navBackToSpinbutton,shift+tab,,,6.2
reqInfoAboutSpinbutton,ctrl+opt+f3,,,9
reqInfoAboutSpinbutton,ctrl+opt+f4,,,9.1
reqInfoAboutInvalidSpinbutton,ctrl+opt+f3,,,10
reqInfoAboutInvalidSpinbutton,ctrl+opt+f4,,,10.1
incrementSpinbuttonByOneStep,up,quickNavOff,,12
incrementSpinbuttonByOneStep,ctrl+opt+shift+down ctrl+opt+up,,,12.1
incrementSpinbuttonByOneStep,ctrl+opt+shift+down ctrl+opt+right,,,12.2
decrementSpinbuttonByOneStep,down,quickNavOff,,14
decrementSpinbuttonByOneStep,ctrl+opt+shift+down ctrl+opt+down,,,14.1
decrementSpinbuttonByOneStep,ctrl+opt+shift+down ctrl+opt+left,,,14.2
decrementSpinbuttonToMinimumValue,home,,,20
incrementSpinbuttonToMaximumValue,end,,,22
decrementSpinbuttonToMinimumValue,home,,,20
incrementSpinbuttonToMaximumValue,end,,,22
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
.datepicker-spinbuttons {
margin-top: 1em;
}

.datepicker-spinbuttons .day {
width: 2em;
}

.datepicker-spinbuttons .month {
width: 6em;
}

.datepicker-spinbuttons .year {
width: 3em;
}

.datepicker-spinbuttons .spinbutton {
float: left;
text-align: center;
}

.datepicker-spinbuttons .spinbutton:first-child {
border-left: 4px;
}

.datepicker-spinbuttons .spinbutton:last-child {
border-right: 4px;
}

.datepicker-spinbuttons .spinbutton .previous,
.datepicker-spinbuttons .spinbutton .next {
color: #666;
}

.datepicker-spinbuttons .spinbutton.focus {
outline: 2px solid #005a9c;
}

.datepicker-spinbuttons .spinbutton.focus,
.datepicker-spinbuttons .spinbutton:hover {
color: #444;
background-color: #eee;
}

.datepicker-spinbuttons .spinbutton.focus [role="spinbutton"],
.datepicker-spinbuttons .spinbutton:hover [role="spinbutton"] {
background-color: #fff;
color: black;
}

.datepicker-spinbuttons .spinbutton .previous {
border-bottom: 1px solid black;
}

.datepicker-spinbuttons .spinbutton .next {
border-top: 1px solid black;
}

.datepicker-spinbuttons .spinbutton button {
padding: 0;
margin: 0;
border: none;
background-color: transparent;
}

.datepicker-spinbuttons .spinbutton .decrease svg polygon,
.datepicker-spinbuttons .spinbutton .increase svg polygon {
fill: #333;
stroke-width: 3px;
stroke: transparent;
}

.datepicker-spinbuttons .spinbutton .decrease {
position: relative;
top: 4px;
}

.datepicker-spinbuttons .spinbutton.focus svg polygon {
fill: #005a9c;
stroke: #005a9c;
}

.datepicker-spinbuttons .spinbutton .decrease:hover svg polygon,
.datepicker-spinbuttons .spinbutton .increase:hover svg polygon {
fill: #005a9c;
stroke: #005a9c;
}

div[role="separator"] {
clear: both;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
.spinners {
--length-s: 0.25rem;
--length-m: 0.5rem;
--color-field-background: white;
--color-button-background-idle: color-mix(in srgb, ghostwhite, darkblue 10%);
--color-button-background-hover: color-mix(in srgb, ghostwhite, darkblue 20%);
--color-interactive-focus: var(--wai-green, #005a6a);
--transition-duration-snappy: 0;
--transition-duration-leisurely: 0;

@media (prefers-reduced-motion: no-preference) and (forced-colors: none) {
--transition-duration-snappy: 0.15s;
--transition-duration-leisurely: 0.5s;
}

@media (forced-colors: active) {
--color-interactive-focus: Highlight;
}

display: inline-flex;
font-family: system-ui, sans-serif;
line-height: 1.4;
padding: 1rem;
background-color: color-mix(in srgb, ghostwhite, darkblue 1%);
border: 1px solid color-mix(in srgb, ghostwhite, darkblue 10%);
border-radius: 0.5rem;

*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}

.visually-hidden {
border: 0;
clip: rect(0 0 0 0);
height: auto;
margin: 0;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px;
white-space: nowrap;
}

fieldset {
padding: 0.5rem;
border: 1px solid transparent;
}

legend {
font-size: 1.2rem;
font-weight: bold;
margin-block-end: 1rem;
}

.spinner-fields {
display: flex;
flex-wrap: wrap;
gap: 2ch;
}

.spinner-field {
display: flex;
flex-direction: column;
align-items: start;
gap: 0.5rem;

label {
font-size: 1.2rem;
}

small {
font-size: 1rem;
}

[id^="error"] {
color: crimson;
}

[id^="error"],
&:has([aria-invalid="true"]) [id^="help"] {
display: none;
}

&:has([aria-invalid="true"]) [id^="error"] {
display: block;
}
}

.spinner {
display: flex;
flex-wrap: wrap;
gap: 0;
max-inline-size: calc(100vw - 6.4rem);
font-size: 1.4rem;
border: 1px solid color-mix(in srgb, ghostwhite, darkblue 60%);
border-radius: 0.25rem;
padding: 0.125em;
background-color: var(--color-field-background);
outline: 0 solid transparent;
outline-offset: 0;
transition:
outline-offset var(--transition-duration-snappy) ease,
outline-width var(--transition-duration-snappy) ease,
outline-color var(--transition-duration-snappy) ease,
border-color var(--transition-duration-snappy) ease;

&:focus-within {
outline: var(--length-s) solid var(--color-interactive-focus);
outline-offset: var(--length-s);
}

&:has([aria-invalid="true"]) {
border-color: crimson;
}

input,
button {
appearance: none;
font: inherit;
font-weight: bold;
color: inherit;
border: none;
background: transparent;
padding: 0.25em 0.5em;
margin: 0;
outline: none;
border-radius: 0;
}

[role="spinbutton"] {
text-align: center;
min-inline-size: 6ch;
font-variant-numeric: tabular-nums;

&,
&:hover,
&:focus {
border: none;
}
}

button {
min-inline-size: 3ch;
background-color: var(--color-button-background-idle);

&:hover {
background-color: var(--color-button-background-hover);
}

&[aria-disabled="true"] {
opacity: 0.25;
background-color: transparent;
cursor: not-allowed;
}
}
}
}
Loading