ToggleSwitch focus issues
invalidred opened this issue · comments
Description
<ToggleSwitch />
currently focuses on itself right after transitioning from on->loading->off
or off->loading->on
. This is expected behaviour in some cases. However in other cases where the focus needs to shift from <ToggleSwitch />
to some other element on the page, the current implementation does not allow to:
- Not focus on
<ToggleSwitch />
by default - Allow the parent of
<ToggleSwitch />
to programmatically control the focus on demand usingref
Reproduction Steps
Notice how the code tries to textRef.current.focus()
after 2 seconds and fails to get focus on itself as the <ToggleSwitch />
overrides the focus to itself.
const App = () => {
const [isChecked, setIsChecked] = React.useState(false)
const textRef = React.useRef()
const handleClick = event => {
/* this setTimeout imitates an async call to an API */
setTimeout(() => {
setIsChecked(!isChecked)
console.log(textRef)
setTimeout(() => { textRef.current.focus() }, 2000)
}, 2000)
}
return (
<FlexGrid gutter={false}>
<FlexGrid.Row>
<FlexGrid.Col xs={12} md={3}>
<span ref={textRef}>some text</span>
<ToggleSwitch
id="toggle-accessibility"
label="Enable data"
tooltipCopy="en"
tooltipText="Tool Tip Text"
spinnerLabel="Request is processing."
checked={isChecked}
autofocus={false}
onClick={handleClick}
/>
</FlexGrid.Col>
</FlexGrid.Row>
</FlexGrid>
)
}
Workaround details
None
Recommendation
- Introduce an
autofocus
boolean prop that is disabled by default (this point is debatable) - Forward ref back to parent so parent can focus on
<ToggleSwitch />
programmatically. We could useImperativeHandle hook to accomplish this.
This is the expected usage proposed
const Parent = ({ someProp }) => {
const toggleSwitchRef = useRef()
useEffect(() => {
if (someConditionMet) {
toggleSwitchRef.current.focus()
}
},[someProp])
return (
<ToggleSwitch
id="toggle-accessibility"
label="Enable data"
tooltipCopy="en"
tooltipText="Tool Tip Text"
spinnerLabel="Request is processing."
checked={isChecked}
autofocus={false} /* NEW PROP */
ref={toggleSwitchRef} /* NEW Support for REF */
onClick={handleClick}
/>
)
}
Proposal (ACs)
- add new prop
autofocus
set tofalse
by default (this is a breaking change) - make use of the
useImperativeHandle
React hook to allow forwarding refs to Toggle Switch - Document how to set focus programmatically on feedback copy (making use of
tabindex="-1"
)
Meta
- TDS version (npm or DSM): v2.0.0
- Willing to develop solution: Yes
- Has workaround: Maybe?
- High impact: Yes
Thanks for opening the issue @invalidred , please triage this on Friday developer weekly!
this issue has been reviewed by @theetrain and @invalidred and is in development
Now available in @tds/community-toggle-switch@3.0.0
.