mirror of
https://github.com/supabase/supabase.git
synced 2026-10-08 19:05:06 +03:00
* docs updates * docs expansion * minor docs fix * improvements * fix dependencies * docs expansion * more table examples * map over data * improve copy * Update apps/design-system/registry/default/example/table-row-link-actions.tsx Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * Update apps/design-system/registry/default/example/table-row-link-actions.tsx Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> * fixes * fix --------- Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
114 lines
4.7 KiB
Plaintext
114 lines
4.7 KiB
Plaintext
---
|
||
title: Accessibility
|
||
description: Make Supabase work for everyone.
|
||
---
|
||
|
||
Accessibility is about making an interface work for as many people as possible across as many circumstances as possible. All of us lean on affordances that accessible experiences provide:
|
||
|
||
- Keyboard navigation
|
||
- Legible and resizable elements
|
||
- Large tap targets
|
||
- Clear and simple language
|
||
|
||
## Checklist
|
||
|
||
About to push some code? At a minimum, check your work against this list:
|
||
|
||
- Are interactive page elements [keyboard-focusable](#focus-management)?
|
||
- Are all elements announcable by a [screen reader](#screen-reader-support)?
|
||
- Are textual elements legible and scalable?
|
||
- Can I use this on a smaller and/or older device?
|
||
|
||
## Focus management
|
||
|
||
All interactive page elements should be reachable by keyboard. Given the below inconsistency between devices and browsers, add `tabIndex={0}` to all buttons, links, and non-text inputs, ideally at the component level. Consider tying the state of `tabIndex` to the `disabled` state of a component, if applicable.
|
||
|
||
Chromium-based browsers and Firefox handle this automatically via the Tab key. Safari, by default, requires the Option key to also be held down. Enabling _Keyboard navigation_ on macOS Settings [removes this requirement](https://mayank.co/blog/safari-focus/#keyboard-navigation) but makes links non-tabbable as a result.
|
||
|
||
Interactive page elements should also provide visual feedback upon selection via a `focus-visible` state. We use consistent focus styles such as `inset-focus` so users recognize this state instantly.
|
||
|
||
[Button](components/button) has all of the above built-in. Bespoke interactive elements however, such as the below interactive [Table Row](components/table#examples), require these props to be added manually:
|
||
|
||
```tsx showLineNumbers {4-14}
|
||
<TableRow
|
||
key={id}
|
||
className="relative cursor-pointer h-16 inset-focus"
|
||
onClick={(event) => {
|
||
if (event.currentTarget !== event.target) return
|
||
handleBucketNavigation(bucket.id, event)
|
||
}}
|
||
onKeyDown={(event) => {
|
||
if (event.currentTarget !== event.target) return
|
||
if (event.key === 'Enter' || event.key === ' ') {
|
||
event.preventDefault()
|
||
handleBucketNavigation(bucket.id, event)
|
||
}
|
||
}}
|
||
tabIndex={0}
|
||
>
|
||
<TableCell>{name}</TableCell>
|
||
</TableRow>
|
||
```
|
||
|
||
Consider also affordances like `ctrl` and `meta` key support for opening in a new tab. Anything that you can do with a mouse input should be replicable by keyboard.
|
||
|
||
See the examples within [Table](components/table#examples) for more.
|
||
|
||
### Radio groups
|
||
|
||
Single-select option groups such as `<input type="radio">` should behave as a single control. Only the first item of radio groups should become focused with the Tab key. The next Tab should move focus from the group to the next focusable control.
|
||
|
||
Individual options inside of a group can be reached by arrow keys (↑ ↓ ← →). Space is the canonical key to activate radio options, with Enter being a secondary affordance.
|
||
|
||
### Jumping ahead
|
||
|
||
Some keyboard-navigable content may be contain hundreds or thousands of items. Help users jump to specific content with the following mitigation strategies:
|
||
|
||
- Search and filtering
|
||
- Pagination or virtualization
|
||
- “Jump to” shortcuts to skip ahead
|
||
|
||
## Screen readers
|
||
|
||
Textual elements are supported out-of-the-box by screen readers.
|
||
|
||
### Imagery
|
||
|
||
Images should have their contents described with an `alt` attribute. Write an objective description of the content rather than its context. For example:
|
||
|
||
```tsx showLineNumbers {2}
|
||
// Correct: painting a picture with words
|
||
<img src="beagle.png" alt="A tricolor beagle galloping through a grassy field, ears in the air" />
|
||
|
||
// Incorrect: Unhelpful context
|
||
<img src="beagle.png" alt="Our logo" />
|
||
```
|
||
|
||
Icons and other visual elements that aren’t strictly images should use the `aria-label` attribute. For example:
|
||
|
||
```tsx showLineNumbers {2}
|
||
<BucketTableCell>
|
||
<BucketIcon aria-label="bucket icon" size={16} />
|
||
</BucketTableCell>
|
||
```
|
||
|
||
Visual elements that are _purely_ visual aids may be removed from the accessibility tree via the `aria-hidden` attribute. For example:
|
||
|
||
```tsx showLineNumbers {2}
|
||
<BucketTableCell>
|
||
<ChevronRight aria-hidden={true} size={14} />
|
||
</BucketTableCell>
|
||
```
|
||
|
||
Never use `aria-hidden={true}` on focusable elements, since these are critical pieces of functionality.
|
||
|
||
### Scaffolding
|
||
|
||
Some scaffolding elements only make sense visually, in the context of surrounding visual content. For example: a table column for actions may not have a visual _Actions_ label because its purpose is obvious (by nearby contents) to a sighted person. For everyone else’s sake, this column should be titled with `sr-only` text:
|
||
|
||
```tsx showLineNumbers {2}
|
||
<TableHead>
|
||
<span className="sr-only">Actions</span>
|
||
</TableHead>
|
||
```
|