A reusable React implementation of accessible footnotes
react-a11y-footnotes
react-a11y-dialog is a thin React component to ease the use of accessible footnotes in React applications.
Install
npm install react-a11y-footnotes
Terminology
- Footnotes: the additional information present at the bottom of a content area using footnote references.
- Footnote reference: a text segment offering more information in the footnotes.
Usage
The library exports 3 parts, all necessary to make everything work correctly:
FootnotesProvider
: a component with no HTML footprint, that needs to wrap the content part of your application.FootnoteRef
: an inline component wrapping a footnote reference, rendering an anchor link (<a>
) to the correct footnote in the footer.Footnotes
: a component rendering the actual footnotes, usually placed at the end of the content area.
API
FootnotesProvider
The footnotesTitleId
prop can be passed to customise the id
attribute assigned to the title rendered by Footnotes
and referenced in every singled FootnoteRef
.
If you are going to customise the Title
prop from Footnotes
, make sure to render props.id
in the DOM, as this is how the value of footnotesTitleId
is mapped between the references and the footnotes.
FootnoteRef
The FootnoteRef
renders a link like this:
<a
id="css-counters-ref"
href="#css-counters-note"
aria-describedby="footnotes-label"
role="doc-noteref"
>CSS counters</a
>
- The
description
prop is mandatory and contains the content of the footnote. It can be a string or a React tree. - The
id
prop can be passed to handleid
manually, otherwise it is automatically generated from the reference content. - The
style
andclassName
props can be freely passed through in order to enable styling with CSS-in-JS libraries (see Styling section).
As you can see, the footnote reference itself does not contain a number (e.g. [1]
) on an asterisk (*
). This is done in CSS with pseudo-elements. If CSS does not render, the links still work and the footnotes still make sense, no big deal.
Footnotes
The Footnotes
component renders a HTML structure like this:
<footer role="doc-endnotes">
<h2 id="footnotes-label">Footnotes</h2>
<ol>
<li id="css-counters-note">
CSS counters are, in essence, variables maintained by CSS whose values may
be incremented by CSS rules to track how many times they’re used.
<a
href="#css-counters-ref"
aria-label="Back to content"
role="doc-backlink"
>↩</a
>
</li>
</ol>
</footer>
-
The
Wrapper
prop can be passed to customise the wrapper. It is'footer'
by default to render a<footer>
HTML element, and can accept any React component. This wrapper is technically not mandatory and could be replaced with aReact.Fragment
. -
The
Title
prop can be passed to customise the title. It isprops => <h2 {...props}>Footnotes</h2>
by default to render a title level 2 named “Footnotes”, and can accept any React component. This component can be visually hidden but it should still be present accessible! -
The
List
prop can be passed to customise the list. It is'ol'
by default to render a<ol>
HTML element, and can accept any React component. -
The
ListItem
prop can be passed to customise the list. It is'li'
by default to render a<li>
HTML element, and can accept any React component. -
The
BackLink
prop can be passed to customise the link back to the reference with each list item. It isprops => <a {...props}>↩</a>
by default to render a link containing↩
, and can accepted any component.
Styling
Styling is left at the description of the author. That being said, some very basic styling are packaged with the library and can be used if deemed necessary.
Using base styles
With a bundler
If you are using a module bundler like webpack or parcel, you can import them where you import the component.
// Import the components
import { FootnotesProvider, FootnoteRef, Footnotes } from 'react-a11y-footnotes'
// And the styles
import 'react-a11y-footnotes/dist/styles.css'
Without a bundler
If you’re not using a bundler you can find the styles at:
your-app/node_modules/react-a11y-foonotes/dist/styles.css
Include this file however you include the rest of your stylesheets. Alternatively, you can use a CDN like Unpkg, but this is not recommended for production apps.
<link
rel="stylesheet"
type="text/css"
href="https://unpkg.com/react-a11y-footnotes@<version>/dist/styles.css"
/>
Overriding and customisation
With CSS
The library provides namespaced data attributes as styling anchors:
data-a11y-footnotes-ref
: applied to every single footnote referencedata-a11y-footnotes-footer
: applied to the footnotes wrapperdata-a11y-footnotes-title
: applied to the footnotes titledata-a11y-footnotes-list
: applied to the footnotes listdata-a11y-footnotes-list-item
: applied to every individual footnotedata-a11y-footnotes-back-link
: applied to every individual back link
With CSS-in-JS
Given every component rendered by the Footnotes
component is customisable, and FootnoteRef
accept both style
and className
, integration with CSS-in-JS libraries should be relatively seamless.
For instance, the FootnoteRef
could be wrapped as such with Fela:
const refStyles = () => ({ color: 'deeppink' })
const Ref = createComponentWithProxy(refStyles, FootnoteRef)
And with styled-components:
const Ref = styled(FootnoteRef)`
color: deeppink;
`
ID generation
For a reference to link to its relevant footnote, and for the latter to provide a link back to the reference, there is an automatic system for resolving identifiers—regardless whether id
is passed to the reference or not.
Consider a reference which receives an id
prop named foobar
(<FootnoteRef id="foobar">
). The underlying anchor element will actually receive foobar-ref
as an id
(<a id="foobar-ref">
). Similarly, the relevant footnote will receive foobar-note
as an id
(<li id="foobar-note">
). This behaviour cannot be changed.
If no id
is passed to references (<FootnoteRef>
)—which is usually the case—the id
will be computed from the content of the reference. For instance if the text says “CSS counters”, the resolved identifiers will be css-counters-ref
and css-counters-note
.
Example
Find a complete demo on CodeSandbox.
import {
FootnotesProvider,
FootnoteRef as Ref,
Footnotes,
} from 'react-a11y-footnotes'
const YourComponent = props => {
return (
<FootnotesProvider>
<p>
Maintaining{' '}
<Ref description='Footnotes are notes placed at the bottom of a page. They cite references or comment on a designated part of the text above it.'>
footnotes
</Ref>{' '}
manually can be a pain. By using{' '}
<Ref description='Cascading Style Sheets'>CSS</Ref>{' '}
<Ref
id='with-a-custom-id'
description={
<>
<a
href='https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Lists_and_Counters/Using_CSS_counters'
target='_blank'
rel='noopener noreferrer'
>
CSS counters
</a>{' '}
are, in essence, variables maintained by CSS whose values may be
incremented by CSS rules to track how many times they’re used.
</>
}
>
counters
</Ref>{' '}
to add the numbered references in the text and an ordered list to
display the actual footnotes in the footer, it becomes extremely easy.
</p>
<Footnotes label='Footnotes' backLabel='Back to content' />
</FootnotesProvider>
)
}