UNPKG

12.8 kBMarkdownView Raw
1# react-tabs [![npm version](https://img.shields.io/npm/v/react-tabs.svg)](https://www.npmjs.com/package/react-tabs) [![codecov](https://codecov.io/gh/reactjs/react-tabs/branch/main/graph/badge.svg?token=XnEVrthAub)](https://codecov.io/gh/reactjs/react-tabs)
2
3An accessible and easy tab component for ReactJS.
4
5https://reactcommunity.org/react-tabs/
6
7> Supports React 16.8.0 or newer
8
9<ins><blockquote class="rich-diff-level-zero"> <p class="rich-diff-level-one">react-tabs was tested on real mobile devices and browsers with<br>
10 <img src="./examples/src/images/Browserstack-logo.svg" height="50" alt="Browserstack">
11
12</p> </blockquote></ins>
13
14## Installing
15
16```bash
17yarn add react-tabs
18```
19or
20```bash
21npm install --save react-tabs
22```
23
24You can also use react-tabs directly as UMD build in an HTML document by adding
25
26```html
27<script src="https://unpkg.com/react-tabs/dist/react-tabs.development.js" />
28<!-- or -->
29<script src="https://unpkg.com/react-tabs/dist/react-tabs.production.min.js" />
30```
31
32For example usages of the UMD builds have a look at the [`old_examples/umd`](./old_examples/umd/) folder.
33The development UMD build also needs the package `prop-types` being loaded besides `react`.
34
35## Basic Example
36
37```js
38import { Tab, Tabs, TabList, TabPanel } from 'react-tabs';
39import 'react-tabs/style/react-tabs.css';
40
41export default () => (
42 <Tabs>
43 <TabList>
44 <Tab>Title 1</Tab>
45 <Tab>Title 2</Tab>
46 </TabList>
47
48 <TabPanel>
49 <h2>Any content 1</h2>
50 </TabPanel>
51 <TabPanel>
52 <h2>Any content 2</h2>
53 </TabPanel>
54 </Tabs>
55);
56```
57
58## API
59
60### resetIdCounter(): void
61
62Allows reseting the internal id counter which is used to generate unique id's for tabs and tab panels.
63
64You should never need to use this in the browser. Only if you are running an isomorphic react app that is rendered on the server you should call `resetIdCounter()` before every page render so that the ids that get generated on the server match the ids generated in the browser.
65
66```js
67import { resetIdCounter } from 'react-tabs';
68
69resetIdCounter();
70ReactDOMServer.renderToString(...);
71```
72
73## Components
74
75react-tabs consists of 4 components which all need to be used together.
76
77### &lt;Tabs /&gt;
78
79If you specify additional props on the `<Tabs />` component they will be forwarded to the rendered `<div />`.
80
81#### className: `string | Array<string> | { [string]: boolean }`
82
83> default: `"react-tabs"`
84
85Provide a custom class name for the outer `<div />` of the tabs.
86
87> You can also supply an array of class names or an object where the class names are the key and the value is a boolean indicating if the name should be added. See the docs of [classnames](https://github.com/JedWatson/classnames#usage) on how to supply different class names.
88
89#### defaultFocus: `boolean`
90
91> default: `false`
92
93If set to `true` the tabs will be focused on initial render. This allows immediate use of keyboard keys to switch tabs after the first render.
94
95#### defaultIndex: `number`
96
97> default: `0`
98
99This allows changing the tab that should be open on initial render. This is a zero-based index, so first tab is `0`, second tab is `1`, ...
100
101> This can only be used in uncontrolled mode when react-tabs handles the current selected tab internally and for this reason cannot be used together with `selectedIndex`. See [here](#controlled-vs-uncontrolled-mode) for more info on modes.
102
103#### direction: `string`
104
105> default: `"ltr"`
106
107Provide the direction of the component, can be either rtl or ltr.
108
109#### disabledTabClassName: `string`
110
111> default: `"react-tabs__tab--disabled"`
112
113Provide a custom class name for disabled tabs.
114
115> This option can also be set directly at the `<Tab />` component.
116
117#### disableUpDownKeys: `bool`
118
119> default: `false`
120
121Disable up & down arrow keys to change tabs.
122
123#### domRef: `(node: ?HTMLElement) => void`
124
125> default: `null`
126
127Register a callback that will receive the underlying DOM node for every mount. It will also receive null on unmount.
128
129#### environment: `Window`
130
131If you're rendering `react-tabs` within a different `window` context than the default one; for example, an iframe.
132
133#### forceRenderTabPanel: `boolean`
134
135> default: `false`
136
137By default only the current active tab will be rendered to DOM. If set to `true` all tabs will be rendered to the DOM always.
138
139> This can also be enabled for each individual `<TabPanel />` component with its prop `forceRender`.
140
141#### onSelect: `(index: number, lastIndex: number, event: Event) => ?boolean`
142
143> default: `undefined`
144
145This event handler is called every time a tab is about to change. It will be called with the `index` that it will be changed to, the `lastIndex` which was selected before and the underlying `event` which is usually either a `keydown` or `click` event. When `index` and `lastIndex` are equal it means the user clicked on the currently active tab.
146
147The callback can optionally return `false` to cancel the change to the new tab.
148
149> Returning `false` when the change to the new tab should be canceled is also important in controlled mode, as react-tabs still internally handles the focus of the tabs.
150
151> In controlled mode the `onSelect` handler is a required prop.
152
153#### selectedIndex: `number`
154
155> default: `null`
156
157Set the currently selected tab. This is a zero-based index, so first tab is `0`, second tab is `1`, ...
158
159This enables controlled mode, which also requires `onSelect` to be set. See [here](#controlled-vs-uncontrolled-mode) for more info on modes.
160
161#### selectedTabClassName: `string`
162
163> default: `"react-tabs__tab--selected"`
164
165Provide a custom class name for the active tab.
166
167> This option can also be set directly at the `<Tab />` component.
168
169#### selectedTabPanelClassName: `string`
170
171> default: `"react-tabs__tab-panel--selected"`
172
173Provide a custom class name for the active tab panel.
174
175> This option can also be set directly at the `<TabPanel />` component.
176
177### &lt;TabList /&gt;
178
179If you specify additional props on the `<TabList />` component they will be forwarded to the rendered `<ul />`.
180
181#### className: `string | Array<string> | { [string]: boolean }`
182
183> default: `"react-tabs__tab-list"`
184
185Provide a custom class name for the `<ul />`.
186
187> You can also supply an array of class names or an object where the class names are the key and the value is a boolean indicating if the name should be added. See the docs of [classnames](https://github.com/JedWatson/classnames#usage) on how to supply different class names.
188
189### &lt;Tab /&gt;
190
191If you specify additional props on the `<Tab />` component they will be forwarded to the rendered `<li />`.
192
193#### className: `string | Array<string> | { [string]: boolean }`
194
195> default: `"react-tabs__tab"`
196
197Provide a custom class name for the `<li />`.
198
199> You can also supply an array of class names or an object where the class names are the key and the value is a boolean indicating if the name should be added. See the docs of [classnames](https://github.com/JedWatson/classnames#usage) on how to supply different class names.
200
201#### disabled: `boolean`
202
203> default: `false`
204
205Disable this tab which will make it not do anything when clicked. Also a disabled class name will be added (see `disabledClassName`)
206
207#### disabledClassName: `string`
208
209> default: `"react-tabs__tab--disabled"`
210
211Provide a custom class name for disabled tabs.
212
213> This option can also be set for all `<Tab />` components with the prop `disabledTabClassName` on `<Tabs />`.
214
215#### selectedClassName: `string`
216
217> default: `"react-tabs__tab--selected"`
218
219Provide a custom class name for the active tab.
220
221> This option can also be set for all `<Tab />` components with the prop `selectedTabClassName` on `<Tabs />`.
222
223#### tabIndex: `string`
224
225> default: if selected `"0"` otherwise `null`
226
227Overrides the tabIndex to enabled tabbing between tabs.
228
229### &lt;TabPanel /&gt;
230
231If you specify additional props on the `<TabPanel />` component they will be forwarded to the rendered `<div />`.
232
233#### className: `string | Array<string> | { [string]: boolean }`
234
235> default: `"react-tabs__tab-panel"`
236
237Provide a custom class name for the `<div />` containing the tab content.
238
239> You can also supply an array of class names or an object where the class names are the key and the value is a boolean indicating if the name should be added. See the docs of [classnames](https://github.com/JedWatson/classnames#usage) on how to supply different class names.
240
241#### forceRender: `boolean`
242
243> default: `false`
244
245By default the tab content will only be rendered when the tab is active. If set to `true` the tab will also be rendered if inactive.
246
247> This can also be enabled for all `<TabPanel />` components with the prop `forceRenderTabPanel` on `<Tabs />`.
248
249#### selectedClassName: `string`
250
251> default: `"react-tabs__tab-panel--selected"`
252
253Provide a custom class name for the active tab panel.
254
255> This option can also be set for all `<TabPanel />` components with the prop `selectedTabPanelClassName` on `<Tabs />`.
256
257## Controlled vs Uncontrolled mode
258
259React tabs has two different modes it can operate in, which change the way how much you need to take care about the state yourself.
260
261### Uncontrolled mode
262
263This is the default mode of react-tabs and makes the react-tabs components handle its state internally. You can change the starting tab with `defaultIndex` and you can listen for changes with `onSelect`.
264
265In this mode you cannot force a tab change during runtime.
266
267```js
268<Tabs defaultIndex={1} onSelect={index => console.log(index)}>
269 <TabList>
270 <Tab>Title 1</Tab>
271 <Tab>Title 2</Tab>
272 </TabList>
273 <TabPanel></TabPanel>
274 <TabPanel></TabPanel>
275</Tabs>
276```
277
278### Controlled mode
279
280This mode has to be enabled by supplying `selectedIndex` to the `<Tabs />` component.
281
282In this mode react-tabs does not handle any tab selection state internally and leaves all the state management up to the outer application.
283
284This mode also enforces you to set a handler for `onSelect`. `defaultIndex` does not have any effect and will therefore throw an error.
285
286```js
287const App = () => {
288 const [tabIndex, setTabIndex] = useState(0);
289
290 return (
291 <Tabs selectedIndex={tabIndex} onSelect={index => setTabIndex(index)}>
292 <TabList>
293 <Tab>Title 1</Tab>
294 <Tab>Title 2</Tab>
295 </TabList>
296 <TabPanel></TabPanel>
297 <TabPanel></TabPanel>
298 </Tabs>
299 );
300};
301```
302
303## Styling
304
305react-tabs does not include any style loading by default. Default stylesheets are provided and can be included in your application if desired.
306
307### Webpack
308
309When using webpack and an appropriate loader (`css-loader`, `sass-loader`, `less-loader` or `style-loader`) you can simply import the default stylesheet.
310
311```js
312import 'react-tabs/style/react-tabs.css';
313// or
314import 'react-tabs/style/react-tabs.scss';
315// or
316import 'react-tabs/style/react-tabs.less';
317```
318
319### SASS
320
321When using SASS you can easily import the default styles
322
323```scss
324@import '../../path/to/node_modules/react-tabs/style/react-tabs.scss';
325```
326
327### LESS
328
329When using LESS you can easily import the default styles
330
331```scss
332@import '../../path/to/node_modules/react-tabs/style/react-tabs.less';
333```
334
335### UMD
336
337When using the UMD version of react-tabs you can easily use the default styles by adding
338
339```html
340<html>
341 <head>
342 ...
343 <link rel="stylesheet" href="https://unpkg.com/react-tabs/style/react-tabs.css">
344 </head>
345 ...
346</html>
347```
348
349
350### Custom Style
351
352You can also always just simply copy the default style to your own css/scss/less and modify it to your own needs. The changelog will always tell you when classes change and we also consider changes that break the styling as semver major.
353
354### Custom Components
355
356#### Set `tabsRole`
357In case you want to create your own component wrapping the ones that the library provides, you have to set its `tabsRole`. This value is used inside react-tabs to check the role of a component inside `<Tabs />`.
358
359Possible values for tabsRole are:
360 * Tab
361 * TabPanel
362 * TabList
363
364#### Pass through properties
365Note: Because of how react-tabs works internally (it uses cloning to opaquely control various parts of the tab state), you need to pass any incoming props to the component you're wrapping. The easiest way to do this is to use the rest and spread operators, e.g. see `{...otherProps}` below.
366
367
368
369``` javascript
370import { Tabs, TabList, Tab, TabPanel } from 'react-tabs';
371
372// All custom elements should pass through other props
373const CustomTab = ({ children, ...otherProps }) => (
374 <Tab {...otherProps}>
375 <h1>{children}</h1>
376 </Tab>
377);
378
379CustomTab.tabsRole = 'Tab'; // Required field to use your custom Tab
380
381const App = () => (
382 <Tabs>
383 <TabList>
384 <CustomTab>Custom Tab 1</CustomTab>
385 <CustomTab>Custom Tab 2</CustomTab>
386 </TabList>
387 <TabPanel>Panel 1</TabPanel>
388 <TabPanel>Panel 2</TabPanel>
389 </Tabs>
390);
391```
392
393## License
394
395MIT