Let's say I have a button that opens a Dialog
component. The button has custom theming/styling to specify various states, one of them being the :focus
state:
const useStyles = makeStyles({
root: {
"&:focus": {
backgroundColor: "#3A7DA9"
}
}
});
export default function App() {
const [open, setOpen] = useState(false);
const classes = useStyles();
return (
<div className="App">
<Button
id="button-that-opens-modal"
className={classes.root}
onClick={() => setOpen(true)}
>
Open the modal
</Button>
<Dialog open={open}>
<h3>This is the modal</h3>
<Button onClick={() => setOpen(false)}>
Close
</Button>
</Dialog>
</div>
);
}
What I've noticed is that every time I have this pattern, (where a button opens a dialog modal), when the modal is closed, the #button-that-opens-modal
is left with a :focus
state, which looks bad in terms of styling. Here's a quick gif:
Is this a known issue? I don't see why the :focus
should be automatically applied to the button when the modal closes. How can I stop this?
I can add a ref to the button, and make sure to manually unfocus the button in various places. Adding it in the onExited
method of the Dialog works, but flashes the focus state for a second:
export default function App() {
const [open, setOpen] = useState(false);
const buttonRef = useRef();
const classes = useStyles();
return (
<div className="App">
<Button
ref={buttonRef}
className={classes.root}
onClick={() => setOpen(true)}
>
Open the modal
</Button>
<Dialog
open={open}
TransitionProps={{
onExited: () => {
buttonRef.current?.blur(); // helps but creates a flash
}
}}
>
<h3>This is the modal</h3>
<Button onClick={() => {setOpen(false)}}>
Close
</Button>
</Dialog>
</div>
);
}
And even if I found exactly the right event handler to blur the button such the styling looks correct, this is not something I want to do for every Dialog
in an app that has many Button
- Dialog
pairs. Is there a Material-UI prop I can use to disable this 'auto-focus' back on the button, rather than having to create a ref and manually .blur
it for every Dialog
?
This is for accessibilty purpose. You can disable it by adding prop disableRestoreFocus
on your Dialog :)