Reach-ui: Animated Dialog example doesn't retain focus state on dismissal

Created on 1 Oct 2020  路  2Comments  路  Source: reach/reach-ui

馃悰 Bug report

Current Behavior

In the Animated React Spring example, focus is not returned to the "Show Dialog" button when the dialog is dismissed.

Expected behavior

Focus is returned to the "Show Dialog" button when the dialog is dismissed.

Reproducible example

Animated React Spring

Suggested solution(s)

N/A

Additional context

I believe this is something to do with the react-spring library, since adding the library to my site using the same pattern as in the docs also resulted in the same behavior, whereas it works fine if I don't use react-spring.

Your environment

| Software | Name(s) | Version |
| ---------------- | ------- | ------- |
| Reach Package | | 0.11.2 |
| React | | 16.13.1|
| Browser | Chrome| 85.0.4183.121|
| Assistive tech | | |
| Node | | |
| npm/yarn | | |
| Operating System | Windows 10|19041.508|

Most helpful comment

@dstaley this is an issue with the docs example. If you update it to look like the following it should work as expected.

+ const AnimatedDialogOverlay = animated(DialogOverlay);
+ const AnimatedDialogContent = animated(DialogContent);
+
function Example(props) {
- const AnimatedDialogOverlay = animated(DialogOverlay);
- const AnimatedDialogContent = animated(DialogContent);
  const [showDialog, setShowDialog] = React.useState(false);
  const transitions = useTransition(showDialog, null, {
    from: { opacity: 0, y: -10 },
    enter: { opacity: 1, y: 0 },
    leave: { opacity: 0, y: 10 },
  });
  return (
    <div>
      <button onClick={() => setShowDialog(true)}>Show Dialog</button>
      {transitions.map(
        ({ item, key, props: styles }) =>
          item && (
-           <AnimatedDialogOverlay style={{ opacity: styles.opacity }}>
+           <AnimatedDialogOverlay style={{ opacity: styles.opacity }} key={key}>
              <AnimatedDialogContent
                style={{
                  transform: styles.y.interpolate(
                    value => `translate3d(0px, ${value}px, 0px)`
                  ),
                  border: "4px solid hsla(0, 0%, 0%, 0.5)",
                  borderRadius: 10,
                }}
              >
                <button onClick={() => setShowDialog(false)}>
                  Close Dialog
                </button>
                <p>React Spring makes it too easy!</p>
                <input type="text" />
                <br />
                <input type="text" />
                <button>Ayyyyyy</button>
              </AnimatedDialogContent>
            </AnimatedDialogOverlay>
          )
      )}
    </div>
  );
}

We move the AnimatedDialogOverlay and AnimatedDialogContent out of the render cycle, and we make sure to include our key prop on the transitions we map over.

Some of the example snippets are a bit outdated or contain small bugs like this. Thanks for finding this one! We would love your help updating them if you come across other issues. Would you be interested in creating a PR to update the animation docs to fix the snippet? 馃檪

All 2 comments

@dstaley this is an issue with the docs example. If you update it to look like the following it should work as expected.

+ const AnimatedDialogOverlay = animated(DialogOverlay);
+ const AnimatedDialogContent = animated(DialogContent);
+
function Example(props) {
- const AnimatedDialogOverlay = animated(DialogOverlay);
- const AnimatedDialogContent = animated(DialogContent);
  const [showDialog, setShowDialog] = React.useState(false);
  const transitions = useTransition(showDialog, null, {
    from: { opacity: 0, y: -10 },
    enter: { opacity: 1, y: 0 },
    leave: { opacity: 0, y: 10 },
  });
  return (
    <div>
      <button onClick={() => setShowDialog(true)}>Show Dialog</button>
      {transitions.map(
        ({ item, key, props: styles }) =>
          item && (
-           <AnimatedDialogOverlay style={{ opacity: styles.opacity }}>
+           <AnimatedDialogOverlay style={{ opacity: styles.opacity }} key={key}>
              <AnimatedDialogContent
                style={{
                  transform: styles.y.interpolate(
                    value => `translate3d(0px, ${value}px, 0px)`
                  ),
                  border: "4px solid hsla(0, 0%, 0%, 0.5)",
                  borderRadius: 10,
                }}
              >
                <button onClick={() => setShowDialog(false)}>
                  Close Dialog
                </button>
                <p>React Spring makes it too easy!</p>
                <input type="text" />
                <br />
                <input type="text" />
                <button>Ayyyyyy</button>
              </AnimatedDialogContent>
            </AnimatedDialogOverlay>
          )
      )}
    </div>
  );
}

We move the AnimatedDialogOverlay and AnimatedDialogContent out of the render cycle, and we make sure to include our key prop on the transitions we map over.

Some of the example snippets are a bit outdated or contain small bugs like this. Thanks for finding this one! We would love your help updating them if you come across other issues. Would you be interested in creating a PR to update the animation docs to fix the snippet? 馃檪

I can confirm that this change fixes the issue! Thanks @indiesquidge

Was this page helpful?
0 / 5 - 0 ratings