A centralized system for displaying and stylizing focus indicators anywhere on a webpage.
npm install react-focus-ringsA centralized system for displaying and stylizing focus indicators anywhere on a webpage.
!a gif showing focus rings in action
When working on creating
a complete keyboard navigation experience for Discord,
we ran into a number of problems with rendering clean and consistent focus rings and were unable to
find any suitable native alternatives. After a lot of trial and error, we landed on this system as a
way to meet all of our needs. You can read more about the process we went through in
this blog post.
This package is published underreact-focus-rings and can be installed with any
npm-compatible package manager.
This library is composed of two components: FocusRing and FocusRingScope.
FocusRingScope is responsible for providing a frame of reference for calculating the position of
any FocusRing instances it contains. The containerRef prop takes aReact.Ref that references the DOM element that
should be used for these position calculations. You'll want to include a FocusRingScope instance
at the top level of your application. If a component creates a new scroll container, or is
absolutely positioned within the viewport, you should add a new FocusRingScope.
``tsx`
function ScopeExample() {
const containerRef = React.useRef
return (
);
}
Keep in mind that **the element provided to containerRef must be styled withposition: relative** or else the alignment calculations will be incorrect. If you find thatFocusRing isn't being rendered at all or its positioning is wrong, verify that you have aFocusRingScope in the correct places and that the containerRef element has theposition: relative style.
The FocusRing is the main show. You can wrap any focusable element with a FocusRing and it willfocus
add the required /blur listeners and magically render the focus ring when the elementButton
receives focus. We recommend integrating this at the design primitive level, in custom components
like or Link, so you get the focus ring behavior across your application with minimal
effort.
`tsx`
function Button(props: ButtonProps) {
return (
);
}
#### Props
FocusRing has a few props you can use to get the right behavior and alignment. If using TypeScriptFocusRingProps
the type is exported as
`tsx`
import { FocusRingProps } from "react-focus-rings";
- within - acts like:focus-within
and will renderenabled
the focus ring if _any_ descendant is focused
- - controls whether the FocusRing is being renderedfocused
- - controls the focused stateoffset
- - lets you adjust the alignment of the focus ring, relative to the focused element. Cannumber
be a orOffset
objectfocusTarget
- - lets you choose a different element to act as the focus target for the ring. MustringTarget
be used with .ringTarget
- - lets you choose a different element to render the ring around. Must be used withfocusTarget
.focusWithinClassName
- - lets you apply a CSS class to the focused element when a descendant is:focus-within
focused. Like .
The focus ring also relies on some default CSS styles in order to render properly. To make this work
in your project, be sure to import the styles separately somwhere within your app with
import "react-focus-rings/src/styles.css";.
A complete, minimal example might look like this:
`tsx
import * as React from "react";
import ReactDOM from "react-dom";
import { FocusRing, FocusRingScope } from "react-focus-rings";
import "react-focus-rings/src/styles.css";
function App() { Here's a paragraph with some text. Here's another paragraph with more text.
const containerRef = React.useRef
return (
);
}
ReactDOM.render(
`
You can find a more complete example in the
examples` directory of this
repository. You can find a
hosted version of the example application here.