{"id":24911438,"url":"https://github.com/accessible-ui/tabs","last_synced_at":"2025-10-16T22:30:31.195Z","repository":{"id":38291097,"uuid":"230358589","full_name":"accessible-ui/tabs","owner":"accessible-ui","description":"🅰 An accessible and versatile tabs component for React with keyboard navigation and labeling features taught in w3.org's WAI-ARIA tabs example","archived":false,"fork":false,"pushed_at":"2023-01-06T02:23:08.000Z","size":2993,"stargazers_count":2,"open_issues_count":15,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-04-24T16:36:59.414Z","etag":null,"topics":["a11y","a11y-tabs","accessible-tabs","accessiblity","aria","react","tabs"],"latest_commit_sha":null,"homepage":"https://codesandbox.io/s/accessibletabs-example-0dw15","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/accessible-ui.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-12-27T02:27:01.000Z","updated_at":"2020-09-10T14:30:21.000Z","dependencies_parsed_at":"2023-02-05T03:01:20.444Z","dependency_job_id":null,"html_url":"https://github.com/accessible-ui/tabs","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/accessible-ui%2Ftabs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/accessible-ui%2Ftabs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/accessible-ui%2Ftabs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/accessible-ui%2Ftabs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/accessible-ui","download_url":"https://codeload.github.com/accessible-ui/tabs/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":236750118,"owners_count":19198816,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["a11y","a11y-tabs","accessible-tabs","accessiblity","aria","react","tabs"],"created_at":"2025-02-02T04:20:08.733Z","updated_at":"2025-10-16T22:30:25.899Z","avatar_url":"https://github.com/accessible-ui.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003chr/\u003e\n\n# @accessible/tabs\n\n\u003e 🅰 An accessible and versatile tabs component for React with keyboard navigation and labeling features taught in w3.org's WAI-ARIA tabs example\n\n```sh\nnpm i @accessible/tabs\n```\n\n\u003cp\u003e\n  \u003ca href=\"https://bundlephobia.com/result?p=@accessible/tabs\"\u003e\n    \u003cimg alt=\"Bundlephobia\" src=\"https://img.shields.io/bundlephobia/minzip/@accessible/tabs?style=for-the-badge\u0026labelColor=24292e\"\u003e\n  \u003c/a\u003e\n  \u003ca aria-label=\"Types\" href=\"https://www.npmjs.com/package/@accessible/tabs\"\u003e\n    \u003cimg alt=\"Types\" src=\"https://img.shields.io/npm/types/@accessible/tabs?style=for-the-badge\u0026labelColor=24292e\"\u003e\n  \u003c/a\u003e\n  \u003ca aria-label=\"Code coverage report\" href=\"https://codecov.io/gh/accessible-ui/tabs\"\u003e\n    \u003cimg alt=\"Code coverage\" src=\"https://img.shields.io/codecov/c/gh/accessible-ui/tabs?style=for-the-badge\u0026labelColor=24292e\"\u003e\n  \u003c/a\u003e\n  \u003ca aria-label=\"Build status\" href=\"https://travis-ci.com/accessible-ui/tabs\"\u003e\n    \u003cimg alt=\"Build status\" src=\"https://img.shields.io/travis/com/accessible-ui/tabs?style=for-the-badge\u0026labelColor=24292e\"\u003e\n  \u003c/a\u003e\n  \u003ca aria-label=\"NPM version\" href=\"https://www.npmjs.com/package/@accessible/tabs\"\u003e\n    \u003cimg alt=\"NPM Version\" src=\"https://img.shields.io/npm/v/@accessible/tabs?style=for-the-badge\u0026labelColor=24292e\"\u003e\n  \u003c/a\u003e\n  \u003ca aria-label=\"License\" href=\"https://jaredlunde.mit-license.org/\"\u003e\n    \u003cimg alt=\"MIT License\" src=\"https://img.shields.io/npm/l/@accessible/tabs?style=for-the-badge\u0026labelColor=24292e\"\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\n---\n\nAn accessible and versatile tabs component for React modeled after\nthe [WAI-ARIA example taught here](https://www.w3.org/TR/wai-aria-practices/examples/tabs/tabs-1/tabs.html).\n\n## Quick Start\n\n[Check out the example on **CodeSandbox**](https://codesandbox.io/s/accessibletabs-example-0dw15)\n\n```jsx harmony\nimport {Tabs, TabList, Tab, Panel} from '@accessible/tabs'\n\nconst Component = () =\u003e (\n  \u003cTabs defaultActive={0} manualActivation\u003e\n    \u003cTabList\u003e\n      \u003cdiv aria-label='Some research thing'\u003e\n        \u003cTab\u003e\n          \u003cbutton\u003eAbstract\u003c/button\u003e\n        \u003c/Tab\u003e\n        \u003cTab\u003e\n          \u003cbutton\u003eReferences\u003c/button\u003e\n        \u003c/Tab\u003e\n      \u003c/div\u003e\n    \u003c/TabList\u003e\n\n    \u003cPanel\u003e\n      \u003cdiv\u003eAbstract body\u003c/div\u003e\n    \u003c/Panel\u003e\n    \u003cPanel\u003e\n      \u003cdiv\u003eReferences body\u003c/div\u003e\n    \u003c/Panel\u003e\n  \u003c/Tabs\u003e\n)\n```\n\n## API\n\n### Components\n\n| Component               | Description                                                                                                                                                                                                                                                                               |\n| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| [`\u003cTabs\u003e`](#tabs)       | This component creates the context for your tabs and contains some configuration options. You'll need to add [`\u003cTab\u003e`](#tab) and [`\u003cPanel\u003e`](#panel) as children in order to actually create tabs.                                                                                        |\n| [`\u003cTabList\u003e`](#tablist) | The component adds `role='tablist'` to its child component.                                                                                                                                                                                                                               |\n| [`\u003cTab\u003e`](#tab)         | This component clones any React element and turns it into a tab that controls the visible state of a [`\u003cPanel\u003e`](#panel). It must be a child of [`\u003cTabs\u003e`](#tabs) and all tabs must be adjacent in the tree. Each tab has a corresponding [`\u003cPanel\u003e`](#panel) that shares the same index. |\n| [`\u003cPanel\u003e`](#panel)     | This component clones its child and turns it into a panel that corresponds to a [`\u003cTab\u003e`](#tab) with the same index. All panels must be adjacent in the tree unless an `index` prop is defined.                                                                                           |\n\n### Hooks\n\n| Hook                              | Description                                                                 |\n| --------------------------------- | --------------------------------------------------------------------------- |\n| [`useTabs()`](#usetabs)           | This hook returns the value of the [TabsContext object](#tabscontextvalue). |\n| [`useTab()`](#usetabindex-number) | This hook returns the value of the [TabContext object](#tabcontextvalue).   |\n\n### \u0026lt;Tabs\u0026gt;\n\nThis component creates the context for your tabs and contains some configuration options. You'll need to add\n[`\u003cTab\u003e`](#tab) and [`\u003cPanel\u003e`](#panel) as children in order to actually create tabs.\n\n#### Props\n\n| Prop             | Type                       | Default     | Required? | Description                                                                                                                                                                                                                             |\n| ---------------- | -------------------------- | ----------- | --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| defaultActive    | `number`                   | `0`         | No        | The [`\u003cTab\u003e`](#tab) index you want active by default.                                                                                                                                                                                   |\n| 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.                                                                                              |\n| 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. |\n| preventScroll    | `boolean`                  | `false`     | No        | When `true` this will prevent your browser from scrolling the document to bring the newly-focused tab into view.                                                                                                                        |\n| onChange         | `(active: number) =\u003e void` | `undefined` | No        | Called each time the active tab changes. It provides the active tab `index` as its only argument.                                                                                                                                       |\n| children         | `React.ReactNode[]`        | `undefined` | Yes       | You can define any children here with some caveats listed elsewhere.                                                                                                                                                                    |\n\n### \u0026lt;TabList\u0026gt;\n\n#### Props\n\n| Prop     | Type                 | Default     | Required? | Description                                                                      |\n| -------- | -------------------- | ----------- | --------- | -------------------------------------------------------------------------------- |\n| children | `React.ReactElement` | `undefined` | Yes       | The child is cloned by this component and given a property for `role='tablist'`. |\n\n### \u0026lt;Tab\u0026gt;\n\nThis component clones any React element and turns it into a tab that controls the visible state of a [`\u003cPanel\u003e`](#panel). It must be a child of [`\u003cTabs\u003e`](#tabs) and all\ntabs must be adjacent in the tree. Each tab has a corresponding [`\u003cPanel\u003e`](#panel) that shares the same index.\n\n```jsx harmony\n// YES\nconst MyTabs = () =\u003e (\n  \u003cTabs\u003e\n    \u003cTabList\u003e\n      {/* index: 0 */}\n      \u003cTab\u003e\n        \u003cdiv /\u003e\n      \u003c/Tab\u003e\n      {/* index: 1 */}\n      \u003cTab\u003e\n        \u003cdiv /\u003e\n      \u003c/Tab\u003e\n    \u003c/TabList\u003e\n    {/* index: 0 */}\n    \u003cPanel\u003e\n      \u003cdiv /\u003e\n    \u003c/Panel\u003e\n    {/* index: 1 */}\n    \u003cPanel\u003e\n      \u003cdiv /\u003e\n    \u003c/Panel\u003e\n  \u003c/Tabs\u003e\n)\n\n// ABSOLUTELY NOT\nconst MyTabs = () =\u003e (\n  \u003cTabs\u003e\n    \u003cTabList\u003e\n      {/* The Tab components here are not adjacent in the tree. */}\n      \u003cdiv\u003e\n        \u003cTab\u003e\n          \u003cdiv /\u003e\n        \u003c/Tab\u003e\n      \u003c/div\u003e\n      \u003cdiv\u003e\n        \u003cTab\u003e\n          \u003cdiv /\u003e\n        \u003c/Tab\u003e\n      \u003c/div\u003e\n    \u003c/TabList\u003e\n    \u003cPanel\u003e\n      \u003cdiv /\u003e\n    \u003c/Panel\u003e\n    \u003cPanel\u003e\n      \u003cdiv /\u003e\n    \u003c/Panel\u003e\n  \u003c/Tabs\u003e\n)\n```\n\n#### Props\n\n| Prop          | Type                             | Default     | Required? | Description                                                                                                                                                                                                                                                   |\n| ------------- | -------------------------------- | ----------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| activeClass   | `string`                         | `undefined` | No        | Adds this class to the child component when the tab is in an active state.                                                                                                                                                                                    |\n| inactiveClass | `string`                         | `undefined` | No        | Adds this class to the child component when the tab is in an inactive state.                                                                                                                                                                                  |\n| activeStyle   | `React.CSSProperties`            | `undefined` | No        | Adds these styles to the child component when the tab is in an active state.                                                                                                                                                                                  |\n| inactiveStyle | `React.CSSProperties`            | `undefined` | No        | Adds these styles to the child component when the tab is in an inactive state.                                                                                                                                                                                |\n| id            | `string`                         | `undefined` | No        | Defining an ID here overrides the auto id generated for aria attributes.                                                                                                                                                                                      |\n| disabled      | `boolean`                        | `false`     | No        | Setting this to `true` will prevent the tab from activating if it isn't already active.                                                                                                                                                                       |\n| 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 [`\u003cPanel\u003e`](#panel). I would recommend not setting this property and letting the library handle it automatically. |\n| onDelete      | `(event: KeyboardEvent) =\u003e 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.                                                                                                                                        |\n| 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.                                                                                                         |\n\n### \u0026lt;Panel\u0026gt;\n\nThis component clones its child and turns it into a panel that corresponds to a [`\u003cTab\u003e`](#tab) with the same\nindex. All panels must be adjacent in the tree unless an `index` prop is defined. For example:\n\n```\n\u003cTabs\u003e\n  \u003cTabList\u003e\n    [0] \u003cTab\u003e\n    [1] \u003cTab\u003e\n  \u003c/TabList\u003e\n\n  [0] \u003cPanel\u003e\n  [1] \u003cPanel\u003e\n\u003c/Tabs\u003e\n```\n\n#### Props\n\n| Prop          | Type                  | Default     | Required? | Description                                                                                                                                                                                                                                                 |\n| ------------- | --------------------- | ----------- | --------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| activeClass   | `string`              | `undefined` | No        | Adds this class to the child component when the panel's [`\u003cTab\u003e`](#tab) is in an active state.                                                                                                                                                              |\n| inactiveClass | `string`              | `undefined` | No        | Adds this class to the child component when the panel's [`\u003cTab\u003e`](#tab) is in an inactive state.                                                                                                                                                            |\n| activeStyle   | `React.CSSProperties` | `undefined` | No        | Adds these styles to the child component when the panel's [`\u003cTab\u003e`](#tab) is in an active state.                                                                                                                                                            |\n| inactiveStyle | `React.CSSProperties` | `undefined` | No        | Adds these styles to the child component when the panel's [`\u003cTab\u003e`](#tab) is in an inactive state.                                                                                                                                                          |\n| 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 [`\u003cTab\u003e`](#tab). I would recommend not setting this property and letting the library handle it automatically. |\n| 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 [`\u003cTab\u003e`](#tab) component with the same index.                                                                      |\n\n### useTab(index: number)\n\nReturns [`TabContext object`](#tabcontextvalue) for the [`\u003cTab\u003e`](#tab) corresponding to the provided `index`.\nIt must be used within a child of [`\u003cTabs\u003e`](#tabs).\n\n### TabContextValue\n\n```typescript\ninterface TabContextValue {\n  // The ID used for aria attributes\n  id?: string\n  // A ref to the tab's underlying element\n  tabRef?: HTMLElement\n  // The index of the tab\n  index: number\n  // Activates this tab unless `disabled` is `true`\n  activate: () =\u003e void\n  // Is this tab active?\n  isActive: boolean\n  // Is this tab disabled?\n  disabled: boolean\n}\n```\n\n### useTabs()\n\nThis hook returns the value of the [TabsContext object](#tabscontextvalue). This hook must be within a child of [`\u003cTabs\u003e`](#tabs).\n\n### TabsContextValue\n\n```typescript\ninterface TabsContextValue {\n  // An array of tabs that have been registered\n  tabs: TabState[]\n  // Registers a new tab\n  registerTab: (\n    index: number,\n    element: HTMLElement,\n    id?: string,\n    disabled?: boolean\n  ) =\u003e () =\u003e void\n  // The tab that is currently active\n  active: number | undefined\n  // Activates the tab at `index`\n  activate: (index: number | undefined) =\u003e void\n  // Is manual activation configured?\n  manualActivation: boolean\n}\n\ntype TabState =\n  | {\n      element?: HTMLElement\n      id?: string\n      disabled?: boolean\n    }\n  | undefined\n```\n\n## LICENSE\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faccessible-ui%2Ftabs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faccessible-ui%2Ftabs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faccessible-ui%2Ftabs/lists"}