telus / tds-community

TELUS Design System Community Components

Home Page:https://tds.telus.com/community/index.html

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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:

  1. Not focus on <ToggleSwitch /> by default
  2. Allow the parent of <ToggleSwitch /> to programmatically control the focus on demand using ref

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

  1. Introduce an autofocus boolean prop that is disabled by default (this point is debatable)
  2. 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 to false 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