Skip to content

Commit 2722198

Browse files
feat: improve keyboard navigation and screen reader accessibility for… (aehrc#1767)
* feat: improve keyboard navigation and screen reader accessibility for choice dropdown fields - Remove multiline prop from Choice Select fields to render as proper single-line combobox - Add aria-labelledby to link field labels for proper VoiceOver announcement - Use aria-label fallback for tabled fields without visible labels This ensures VoiceOver announces the field name (e.g., 'Smoking status, combo box') and enables standard keyboard navigation (Tab to focus, Arrow keys to navigate options, Enter to select, Escape to close). Fixes aehrc#1762 * fix: Update Choice test to query for input instead of textarea After removing multiline prop from Select fields, the component now renders as <input> instead of <textarea>. Updated test to query for 'input' element to match the new rendering. * feat: Add openOnFocus to enable keyboard-only dropdown access Add openOnFocus prop to MUI Autocomplete components for Select choice fields. This enables the dropdown to open automatically when the field receives Tab focus, allowing full keyboard-only navigation without requiring mouse interaction. - Tab to field → dropdown opens automatically - Arrow keys → navigate options - Enter → select option - Escape → close dropdown * feat: Add explicit role='combobox' for proper VoiceOver recognition - Explicitly set role='combobox' on input element to ensure entire dropdown component (text input + arrow) is recognized as one unit - Removes 'openOnFocus' to prevent automatic dropdown opening that interferes with VoiceOver field name announcement - Maintains aria-labelledby for proper field name announcement This ensures VoiceOver announces 'Smoking status, combo box' and provides proper keyboard navigation instructions to users. Fixes aehrc#1762 * style: Fix prettier formatting in ChoiceSelectAnswerOptionFields --------- Co-authored-by: Maryam Mehdizadeh <maryam.mehdizadeh@csiro.au>
1 parent d491967 commit 2722198

3 files changed

Lines changed: 13 additions & 5 deletions

File tree

packages/smart-forms-renderer/src/components/FormComponents/ChoiceItems/ChoiceSelectAnswerOptionFields.tsx

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,6 @@ function ChoiceSelectAnswerOptionFields(props: ChoiceSelectAnswerOptionFieldsPro
7878
readOnly={readOnly && readOnlyVisualStyle === 'readonly'}
7979
renderInput={(params) => (
8080
<StandardTextField
81-
multiline
8281
textFieldWidth={textFieldWidth}
8382
isTabled={isTabled}
8483
placeholder={entryFormat || displayPrompt}
@@ -93,7 +92,14 @@ function ChoiceSelectAnswerOptionFields(props: ChoiceSelectAnswerOptionFieldsPro
9392
<ExpressionUpdateFadingIcon fadeIn={expressionUpdated} disabled={readOnly} />
9493
<DisplayUnitText readOnly={readOnly}>{displayUnit}</DisplayUnitText>
9594
</>
96-
)
95+
),
96+
inputProps: {
97+
...params.inputProps,
98+
...(isTabled
99+
? { 'aria-label': qItem.text ?? 'Unnamed choice dropdown' }
100+
: { 'aria-labelledby': `label-${qItem.linkId}` }),
101+
role: 'combobox'
102+
}
97103
}
98104
}}
99105
/>

packages/smart-forms-renderer/src/components/FormComponents/ChoiceItems/ChoiceSelectAnswerValueSetFields.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,6 @@ function ChoiceSelectAnswerValueSetFields(props: ChoiceSelectAnswerValueSetField
8585
readOnly={readOnly && readOnlyVisualStyle === 'readonly'}
8686
renderInput={(params) => (
8787
<StandardTextField
88-
multiline
8988
textFieldWidth={textFieldWidth}
9089
isTabled={isTabled}
9190
placeholder={entryFormat || displayPrompt}
@@ -103,7 +102,10 @@ function ChoiceSelectAnswerValueSetFields(props: ChoiceSelectAnswerValueSetField
103102
),
104103
inputProps: {
105104
...params.inputProps,
106-
'aria-label': qItem.text ?? 'Unnamed choice dropdown'
105+
...(isTabled
106+
? { 'aria-label': qItem.text ?? 'Unnamed choice dropdown' }
107+
: { 'aria-labelledby': `label-${qItem.linkId}` }),
108+
role: 'combobox'
107109
}
108110
}
109111
}}

packages/smart-forms-renderer/src/stories/itemTypes/Choice.stories.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ export const ChoiceAnswerOptionBasic: Story = createStory({
122122
expect(resultAfterClear).toHaveLength(0);
123123

124124
const elementAfterClear = await findByLinkIdOrLabel(canvasElement, aoTargetLinkId);
125-
const input = elementAfterClear.querySelector('textarea');
125+
const input = elementAfterClear.querySelector('input');
126126
expect(input?.value).toBe('');
127127
}
128128
}) as Story;

0 commit comments

Comments
 (0)