https://github.com/accessible-ui/tabs
🅰 An accessible and versatile tabs component for React with keyboard navigation and labeling features taught in w3.org's WAI-ARIA tabs example
https://github.com/accessible-ui/tabs
a11y a11y-tabs accessible-tabs accessiblity aria react tabs
Last synced: 4 months ago
JSON representation
🅰 An accessible and versatile tabs component for React with keyboard navigation and labeling features taught in w3.org's WAI-ARIA tabs example
- Host: GitHub
- URL: https://github.com/accessible-ui/tabs
- Owner: accessible-ui
- License: mit
- Created: 2019-12-27T02:27:01.000Z (over 5 years ago)
- Default Branch: master
- Last Pushed: 2023-01-06T02:23:08.000Z (over 2 years ago)
- Last Synced: 2024-04-24T16:36:59.414Z (about 1 year ago)
- Topics: a11y, a11y-tabs, accessible-tabs, accessiblity, aria, react, tabs
- Language: TypeScript
- Homepage: https://codesandbox.io/s/accessibletabs-example-0dw15
- Size: 2.85 MB
- Stars: 2
- Watchers: 2
- Forks: 1
- Open Issues: 15
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- Contributing: CONTRIBUTING.md
- License: LICENSE
- Code of conduct: CODE_OF_CONDUCT.md
Awesome Lists containing this project
README
# @accessible/tabs
> 🅰 An accessible and versatile tabs component for React with keyboard navigation and labeling features taught in w3.org's WAI-ARIA tabs example
```sh
npm i @accessible/tabs
```---
An accessible and versatile tabs component for React modeled after
the [WAI-ARIA example taught here](https://www.w3.org/TR/wai-aria-practices/examples/tabs/tabs-1/tabs.html).## Quick Start
[Check out the example on **CodeSandbox**](https://codesandbox.io/s/accessibletabs-example-0dw15)
```jsx harmony
import {Tabs, TabList, Tab, Panel} from '@accessible/tabs'const Component = () => (
Abstract
References
Abstract body
References body
)
```## API
### Components
| Component | Description |
| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| [``](#tabs) | This component creates the context for your tabs and contains some configuration options. You'll need to add [``](#tab) and [``](#panel) as children in order to actually create tabs. |
| [``](#tablist) | The component adds `role='tablist'` to its child component. |
| [``](#tab) | This component clones any React element and turns it into a tab that controls the visible state of a [``](#panel). It must be a child of [``](#tabs) and all tabs must be adjacent in the tree. Each tab has a corresponding [``](#panel) that shares the same index. |
| [``](#panel) | This component clones its child and turns it into a panel that corresponds to a [``](#tab) with the same index. All panels must be adjacent in the tree unless an `index` prop is defined. |### Hooks
| Hook | Description |
| --------------------------------- | --------------------------------------------------------------------------- |
| [`useTabs()`](#usetabs) | This hook returns the value of the [TabsContext object](#tabscontextvalue). |
| [`useTab()`](#usetabindex-number) | This hook returns the value of the [TabContext object](#tabcontextvalue). |### <Tabs>
This component creates the context for your tabs and contains some configuration options. You'll need to add
[``](#tab) and [``](#panel) as children in order to actually create tabs.#### Props
| Prop | Type | Default | Required? | Description |
| ---------------- | -------------------------- | ----------- | --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| defaultActive | `number` | `0` | No | The [``](#tab) index you want active by default. |
| active | `number` | `undefined` | No | Makes this a controlled component where the `activate` control has no effect. The tab index defined here is always the one that is active. |
| manualActivation | `boolean` | `false` | No | By default this component opens tabs automatically when using keyboard navigation to switch between tabs. By setting this to `true`, the user will have to use the `space` or `enter` key to activate the tab after the tab is focused. |
| preventScroll | `boolean` | `false` | No | When `true` this will prevent your browser from scrolling the document to bring the newly-focused tab into view. |
| onChange | `(active: number) => void` | `undefined` | No | Called each time the active tab changes. It provides the active tab `index` as its only argument. |
| children | `React.ReactNode[]` | `undefined` | Yes | You can define any children here with some caveats listed elsewhere. |### <TabList>
#### Props
| Prop | Type | Default | Required? | Description |
| -------- | -------------------- | ----------- | --------- | -------------------------------------------------------------------------------- |
| children | `React.ReactElement` | `undefined` | Yes | The child is cloned by this component and given a property for `role='tablist'`. |### <Tab>
This component clones any React element and turns it into a tab that controls the visible state of a [``](#panel). It must be a child of [``](#tabs) and all
tabs must be adjacent in the tree. Each tab has a corresponding [``](#panel) that shares the same index.```jsx harmony
// YES
const MyTabs = () => (
{/* index: 0 */}
{/* index: 1 */}
{/* index: 0 */}
{/* index: 1 */}
)// ABSOLUTELY NOT
const MyTabs = () => (
{/* The Tab components here are not adjacent in the tree. */}
)
```#### Props
| Prop | Type | Default | Required? | Description |
| ------------- | -------------------------------- | ----------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| activeClass | `string` | `undefined` | No | Adds this class to the child component when the tab is in an active state. |
| inactiveClass | `string` | `undefined` | No | Adds this class to the child component when the tab is in an inactive state. |
| activeStyle | `React.CSSProperties` | `undefined` | No | Adds these styles to the child component when the tab is in an active state. |
| inactiveStyle | `React.CSSProperties` | `undefined` | No | Adds these styles to the child component when the tab is in an inactive state. |
| id | `string` | `undefined` | No | Defining an ID here overrides the auto id generated for aria attributes. |
| disabled | `boolean` | `false` | No | Setting this to `true` will prevent the tab from activating if it isn't already active. |
| index | `number` | `undefined` | No | Setting an index here overrides the default index created when this component mounts. Indexes are used to match tabs to their corresponding [``](#panel). I would recommend not setting this property and letting the library handle it automatically. |
| onDelete | `(event: KeyboardEvent) => void` | `undefined` | No | This callback will fire if a user presses the `Delete` key on their keyboard when this tab (not the panel) is focused. |
| children | `React.ReactElement` | `undefined` | Yes | The child is cloned by this component and has aria attributes injected into its props as well as keyboard event handlers for navigating between tabs. |### <Panel>
This component clones its child and turns it into a panel that corresponds to a [``](#tab) with the same
index. All panels must be adjacent in the tree unless an `index` prop is defined. For example:```
[0]
[1]
[0]
[1]```
#### Props
| Prop | Type | Default | Required? | Description |
| ------------- | --------------------- | ----------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| activeClass | `string` | `undefined` | No | Adds this class to the child component when the panel's [``](#tab) is in an active state. |
| inactiveClass | `string` | `undefined` | No | Adds this class to the child component when the panel's [``](#tab) is in an inactive state. |
| activeStyle | `React.CSSProperties` | `undefined` | No | Adds these styles to the child component when the panel's [``](#tab) is in an active state. |
| inactiveStyle | `React.CSSProperties` | `undefined` | No | Adds these styles to the child component when the panel's [``](#tab) is in an inactive state. |
| index | `number` | `undefined` | No | Setting an index here overrides the default index created when this component mounts. Indexes are used to match panels to their corresponding [``](#tab). I would recommend not setting this property and letting the library handle it automatically. |
| children | `React.ReactElement` | `undefined` | Yes | The child is cloned by this component and has aria attributes injected into its props and will have its visible state controlled by the [``](#tab) component with the same index. |### useTab(index: number)
Returns [`TabContext object`](#tabcontextvalue) for the [``](#tab) corresponding to the provided `index`.
It must be used within a child of [``](#tabs).### TabContextValue
```typescript
interface TabContextValue {
// The ID used for aria attributes
id?: string
// A ref to the tab's underlying element
tabRef?: HTMLElement
// The index of the tab
index: number
// Activates this tab unless `disabled` is `true`
activate: () => void
// Is this tab active?
isActive: boolean
// Is this tab disabled?
disabled: boolean
}
```### useTabs()
This hook returns the value of the [TabsContext object](#tabscontextvalue). This hook must be within a child of [``](#tabs).
### TabsContextValue
```typescript
interface TabsContextValue {
// An array of tabs that have been registered
tabs: TabState[]
// Registers a new tab
registerTab: (
index: number,
element: HTMLElement,
id?: string,
disabled?: boolean
) => () => void
// The tab that is currently active
active: number | undefined
// Activates the tab at `index`
activate: (index: number | undefined) => void
// Is manual activation configured?
manualActivation: boolean
}type TabState =
| {
element?: HTMLElement
id?: string
disabled?: boolean
}
| undefined
```## LICENSE
MIT