@@ -121,7 +121,7 @@ const inputStyles = {
121121} ;
122122
123123export const StyledCheckbox = withStyles ( inputStyles ) ( ( props ) => {
124- const { correctness, classes, checked, onChange, disabled, value, id } = props ;
124+ const { correctness, classes, checked, onChange, disabled, value, id, onKeyDown , inputRef } = props ;
125125 const key = ( k ) => ( correctness ? `${ correctness } -${ k } ` : k ) ;
126126
127127 const resolved = {
@@ -135,7 +135,9 @@ export const StyledCheckbox = withStyles(inputStyles)((props) => {
135135 return (
136136 < Checkbox
137137 id = { id }
138+ inputRef = { inputRef }
138139 aria-checked = { checked }
140+ onKeyDown = { onKeyDown }
139141 focusVisibleClassName = { checked ? classes . focusVisibleChecked : classes . focusVisibleUnchecked }
140142 disableRipple
141143 { ...miniProps }
@@ -150,7 +152,7 @@ export const StyledCheckbox = withStyles(inputStyles)((props) => {
150152} ) ;
151153
152154export const StyledRadio = withStyles ( inputStyles ) ( ( props ) => {
153- const { correctness, classes, checked, onChange, disabled, value, id, tagName } = props ;
155+ const { correctness, classes, checked, onChange, disabled, value, id, tagName, inputRef } = props ;
154156 const key = ( k ) => ( correctness ? `${ correctness } -${ k } ` : k ) ;
155157
156158 const resolved = {
@@ -164,6 +166,7 @@ export const StyledRadio = withStyles(inputStyles)((props) => {
164166 return (
165167 < Radio
166168 id = { id }
169+ inputRef = { inputRef }
167170 aria-checked = { checked }
168171 focusVisibleClassName = { checked ? classes . focusVisibleChecked : classes . focusVisibleUnchecked }
169172 disableRipple
@@ -193,6 +196,7 @@ export class ChoiceInput extends React.Component {
193196 value : PropTypes . string . isRequired ,
194197 classes : PropTypes . object ,
195198 className : PropTypes . string ,
199+ tagName : PropTypes . string ,
196200 hideTick : PropTypes . bool ,
197201 isEvaluateMode : PropTypes . bool ,
198202 choicesLayout : PropTypes . oneOf ( [ 'vertical' , 'grid' , 'horizontal' ] ) ,
@@ -220,6 +224,37 @@ export class ChoiceInput extends React.Component {
220224 return 'choice-' + ( Math . random ( ) * 10000 ) . toFixed ( ) ;
221225 }
222226
227+ handleKeyDown = ( event ) => {
228+ const { choiceMode } = this . props ;
229+
230+ if ( choiceMode !== 'checkbox' ) return ;
231+
232+ const isArrowDown = event . key === 'ArrowDown' ;
233+ const isArrowUp = event . key === 'ArrowUp' ;
234+
235+ if ( ! isArrowDown && ! isArrowUp ) return ;
236+
237+ event . preventDefault ( ) ;
238+
239+ const currentEl = document . getElementById ( this . choiceId ) ;
240+ if ( ! currentEl ) return ;
241+
242+ const fieldset = currentEl . closest ( 'fieldset' ) ;
243+ if ( ! fieldset ) return ;
244+
245+ const groupCheckboxes = Array . from ( fieldset . querySelectorAll ( 'input[type="checkbox"]' ) ) ;
246+
247+ const currentIndex = groupCheckboxes . findIndex ( ( el ) => el === currentEl ) ;
248+ if ( currentIndex === - 1 ) return ;
249+
250+ const nextIndex = isArrowDown ? currentIndex + 1 : currentIndex - 1 ;
251+ const nextEl = groupCheckboxes [ nextIndex ] ;
252+
253+ if ( nextEl ) {
254+ nextEl . focus ( ) ;
255+ }
256+ } ;
257+
223258 render ( ) {
224259 const {
225260 choiceMode,
@@ -276,6 +311,7 @@ export class ChoiceInput extends React.Component {
276311 value,
277312 id : this . choiceId ,
278313 onChange : this . onToggleChoice ,
314+ onKeyDown : this . handleKeyDown ,
279315 'aria-describedby' : this . descId ,
280316 } ;
281317
@@ -298,7 +334,7 @@ export class ChoiceInput extends React.Component {
298334 ) : (
299335 < >
300336 { hasMathOrImage && screenReaderLabel }
301- < Tag { ...tagProps } />
337+ < Tag { ...tagProps } inputRef = { this . props . autoFocusRef } />
302338 </ >
303339 ) ;
304340
0 commit comments