UNPKG

12.6 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```
19
20or
21
22```bash
23npm install --save react-tabs
24```
25
26You can also use react-tabs directly as UMD build in an HTML document by adding
27
28```html
29<script src="https://unpkg.com/react-tabs/dist/react-tabs.development.js" />
30<!-- or -->
31<script src="https://unpkg.com/react-tabs/dist/react-tabs.production.min.js" />
32```
33
34For example usages of the UMD builds have a look at the [`old_examples/umd`](./old_examples/umd/) folder.
35The development UMD build also needs the package `prop-types` being loaded besides `react`.
36
37## Basic Example
38
39```js
40import { Tab, Tabs, TabList, TabPanel } from 'react-tabs';
41import 'react-tabs/style/react-tabs.css';
42
43export default () => (
44 <Tabs>
45 <TabList>
46 <Tab>Title 1</Tab>
47 <Tab>Title 2</Tab>
48 </TabList>
49
50 <TabPanel>
51 <h2>Any content 1</h2>
52 </TabPanel>
53 <TabPanel>
54 <h2>Any content 2</h2>
55 </TabPanel>
56 </Tabs>
57);
58```
59
60## API
61
62## Components
63
64react-tabs consists of 4 components which all need to be used together.
65
66### &lt;Tabs /&gt;
67
68If you specify additional props on the `<Tabs />` component they will be forwarded to the rendered `<div />`.
69
70#### className: `string | Array<string> | { [string]: boolean }`
71
72> default: `"react-tabs"`
73
74Provide a custom class name for the outer `<div />` of the tabs.
75
76> 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.
77
78#### defaultFocus: `boolean`
79
80> default: `false`
81
82If 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.
83
84#### defaultIndex: `number`
85
86> default: `0`
87
88This 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`, ...
89
90> 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.
91
92#### direction: `string`
93
94> default: `"ltr"`
95
96Provide the direction of the component, can be either rtl or ltr.
97
98#### disabledTabClassName: `string`
99
100> default: `"react-tabs__tab--disabled"`
101
102Provide a custom class name for disabled tabs.
103
104> This option can also be set directly at the `<Tab />` component.
105
106#### disableUpDownKeys: `bool`
107
108> default: `false`
109
110Disable up & down arrow keys to change tabs.
111
112#### domRef: `(node: ?HTMLElement) => void`
113
114> default: `null`
115
116Register a callback that will receive the underlying DOM node for every mount. It will also receive null on unmount.
117
118#### environment: `Window`
119
120If you're rendering `react-tabs` within a different `window` context than the default one; for example, an iframe.
121
122#### focusTabOnClick: `boolean`
123
124> default: `true`
125
126By default the tab that is clicked will also be focused in the DOM. If set to `false` the tab will not be focused anymore.
127
128> Be aware that keyboard navigation will not work after click if set to false. Though one can still focus the tabs by pressing `tab` and then keyboard navigation will work.
129
130#### forceRenderTabPanel: `boolean`
131
132> default: `false`
133
134By default only the current active tab will be rendered to DOM. If set to `true` all tabs will be rendered to the DOM always.
135
136> This can also be enabled for each individual `<TabPanel />` component with its prop `forceRender`.
137
138#### onSelect: `(index: number, lastIndex: number, event: Event) => ?boolean`
139
140> default: `undefined`
141
142This 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.
143
144The callback can optionally return `false` to cancel the change to the new tab.
145
146> 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.
147
148> In controlled mode the `onSelect` handler is a required prop.
149
150#### selectedIndex: `number`
151
152> default: `null`
153
154Set the currently selected tab. This is a zero-based index, so first tab is `0`, second tab is `1`, ...
155
156This enables controlled mode, which also requires `onSelect` to be set. See [here](#controlled-vs-uncontrolled-mode) for more info on modes.
157
158#### selectedTabClassName: `string`
159
160> default: `"react-tabs__tab--selected"`
161
162Provide a custom class name for the active tab.
163
164> This option can also be set directly at the `<Tab />` component.
165
166#### selectedTabPanelClassName: `string`
167
168> default: `"react-tabs__tab-panel--selected"`
169
170Provide a custom class name for the active tab panel.
171
172> This option can also be set directly at the `<TabPanel />` component.
173
174### &lt;TabList /&gt;
175
176If you specify additional props on the `<TabList />` component they will be forwarded to the rendered `<ul />`.
177
178#### className: `string | Array<string> | { [string]: boolean }`
179
180> default: `"react-tabs__tab-list"`
181
182Provide a custom class name for the `<ul />`.
183
184> 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.
185
186### &lt;Tab /&gt;
187
188If you specify additional props on the `<Tab />` component they will be forwarded to the rendered `<li />`.
189
190#### className: `string | Array<string> | { [string]: boolean }`
191
192> default: `"react-tabs__tab"`
193
194Provide a custom class name for the `<li />`.
195
196> 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.
197
198#### disabled: `boolean`
199
200> default: `false`
201
202Disable this tab which will make it not do anything when clicked. Also a disabled class name will be added (see `disabledClassName`)
203
204#### disabledClassName: `string`
205
206> default: `"react-tabs__tab--disabled"`
207
208Provide a custom class name for disabled tabs.
209
210> This option can also be set for all `<Tab />` components with the prop `disabledTabClassName` on `<Tabs />`.
211
212#### selectedClassName: `string`
213
214> default: `"react-tabs__tab--selected"`
215
216Provide a custom class name for the active tab.
217
218> This option can also be set for all `<Tab />` components with the prop `selectedTabClassName` on `<Tabs />`.
219
220#### tabIndex: `string`
221
222> default: if selected `"0"` otherwise `null`
223
224Overrides the tabIndex to enabled tabbing between tabs.
225
226### &lt;TabPanel /&gt;
227
228If you specify additional props on the `<TabPanel />` component they will be forwarded to the rendered `<div />`.
229
230#### className: `string | Array<string> | { [string]: boolean }`
231
232> default: `"react-tabs__tab-panel"`
233
234Provide a custom class name for the `<div />` containing the tab content.
235
236> 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.
237
238#### forceRender: `boolean`
239
240> default: `false`
241
242By 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.
243
244> This can also be enabled for all `<TabPanel />` components with the prop `forceRenderTabPanel` on `<Tabs />`.
245
246#### selectedClassName: `string`
247
248> default: `"react-tabs__tab-panel--selected"`
249
250Provide a custom class name for the active tab panel.
251
252> This option can also be set for all `<TabPanel />` components with the prop `selectedTabPanelClassName` on `<Tabs />`.
253
254## Controlled vs Uncontrolled mode
255
256React tabs has two different modes it can operate in, which change the way how much you need to take care about the state yourself.
257
258### Uncontrolled mode
259
260This 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`.
261
262In this mode you cannot force a tab change during runtime.
263
264```js
265<Tabs defaultIndex={1} onSelect={(index) => console.log(index)}>
266 <TabList>
267 <Tab>Title 1</Tab>
268 <Tab>Title 2</Tab>
269 </TabList>
270 <TabPanel></TabPanel>
271 <TabPanel></TabPanel>
272</Tabs>
273```
274
275### Controlled mode
276
277This mode has to be enabled by supplying `selectedIndex` to the `<Tabs />` component.
278
279In this mode react-tabs does not handle any tab selection state internally and leaves all the state management up to the outer application.
280
281This mode also enforces you to set a handler for `onSelect`. `defaultIndex` does not have any effect and will therefore throw an error.
282
283```js
284const App = () => {
285 const [tabIndex, setTabIndex] = useState(0);
286
287 return (
288 <Tabs selectedIndex={tabIndex} onSelect={(index) => setTabIndex(index)}>
289 <TabList>
290 <Tab>Title 1</Tab>
291 <Tab>Title 2</Tab>
292 </TabList>
293 <TabPanel></TabPanel>
294 <TabPanel></TabPanel>
295 </Tabs>
296 );
297};
298```
299
300## Styling
301
302react-tabs does not include any style loading by default. Default stylesheets are provided and can be included in your application if desired.
303
304### Webpack
305
306When using webpack and an appropriate loader (`css-loader`, `sass-loader`, `less-loader` or `style-loader`) you can simply import the default stylesheet.
307
308```js
309import 'react-tabs/style/react-tabs.css';
310// or
311import 'react-tabs/style/react-tabs.scss';
312// or
313import 'react-tabs/style/react-tabs.less';
314```
315
316### SASS
317
318When using SASS you can easily import the default styles
319
320```scss
321@import '../../path/to/node_modules/react-tabs/style/react-tabs.scss';
322```
323
324### LESS
325
326When using LESS you can easily import the default styles
327
328```scss
329@import '../../path/to/node_modules/react-tabs/style/react-tabs.less';
330```
331
332### UMD
333
334When using the UMD version of react-tabs you can easily use the default styles by adding
335
336```html
337<html>
338 <head>
339 ...
340 <link
341 rel="stylesheet"
342 href="https://unpkg.com/react-tabs/style/react-tabs.css"
343 />
344 </head>
345 ...
346</html>
347```
348
349### Custom Style
350
351You 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.
352
353### Custom Components
354
355#### Set `tabsRole`
356
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
361- Tab
362- TabPanel
363- TabList
364
365#### Pass through properties
366
367Note: 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.
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