@neo4j-ndl/react
Version:
React implementation of Neo4j Design System
434 lines (368 loc) • 15 kB
Markdown
# Tabs
Import: `import { Tabs } from '@neo4j-ndl/react'`
## Props
### Tabs
| Prop | Type | Required | Default | Description |
|------|------|----------|---------|-------------|
| `as` | `ElementType<any, keyof IntrinsicElements>` | | | An override of the default HTML tag of the root of the component. Can also be another React component. |
| `children` | `ReactNode` | ✅ | | The content dislayed in the tabs |
| `fill` | `'filled' \| 'underline'` | | `underline` | The fill type of the tabs |
| `onBackground` | `'default' \| 'weak'` | | `weak` | What background the Tabs is placed on. This affects the gradient background of the scroll navigation buttons. |
| `onChange` | `(e: U) => void` | ✅ | | Callback function triggered when a new tab is selected |
| `ref` | `any` | | | A ref to apply to the root element. |
| `size` | `'large' \| 'small'` | | `large` | The size of the tabs |
| `value` | `string` | ✅ | | The currently active tabId |
### Tabs.Badge
| Prop | Type | Required | Default | Description |
|------|------|----------|---------|-------------|
| `children` | `ReactNode` | ✅ | | The content of the badge |
| `ref` | `Ref<HTMLSpanElement>` | | | A ref to apply to the root element. |
### Tabs.Tab
| Prop | Type | Required | Default | Description |
|------|------|----------|---------|-------------|
| `as` | `ElementType<any, keyof IntrinsicElements>` | | | An override of the default HTML tag of the root of the component. Can also be another React component. |
| `children` | `ReactNode` | ✅ | | The content of the tab |
| `description` | `string` | | | A string that will be shown as a tooltip when hovering over the button it also acts as an aria-label- {@link https://developer.mozilla.org/en-US/docs/Web/Accessibility/ARIA/Attributes/aria-label} |
| `id` | `string` | ✅ | | The id of the tab |
| `isDisabled` | `boolean` | | `false` | Whether the tab is disabled |
| `ref` | `any` | | | A ref to apply to the root element. |
| `tooltipProps` | `TooltipObjectProps` | | | Props for the tooltip component. |
When the `description` prop is set, hovering over the tab will show a tooltip with the text provided in the `description` prop. `tooltipProps` can be used to customize the tooltip appearance. The `TooltipObjectProps` type is defined as: `{ root?: Partial<React.ComponentProps<typeof Tooltip>>; trigger?: Partial<React.ComponentProps<typeof Tooltip.Trigger>>; content?: Partial<React.ComponentProps<typeof Tooltip.Content>>; }`, see the Tooltip component for more details.
### Tabs.TabPanel
| Prop | Type | Required | Default | Description |
|------|------|----------|---------|-------------|
| `as` | `ElementType<any, keyof IntrinsicElements>` | | | An override of the default HTML tag of the root of the component. Can also be another React component. |
| `children` | `ReactNode` | ✅ | | The content displayed in the tab panel |
| `ref` | `any` | | | A ref to apply to the root element. |
| `tabId` | `string` | ✅ | | The id of the tab panel |
| `value` | `string` | ✅ | | The currently selected tabId. The tab is visible if the value is equal to the tabId |
## Accessibility
## Implementation guidelines
The tabs is using the `role='tablist'` to convey related selection options and keyboard navigation is supported using the `role='tab'` and `role='tabpanel'`. It's important to give each tab an id and each tab panel an id.
## Examples
### Default
```tsx
import '@neo4j-ndl/base/lib/neo4j-ds-styles.css';
import { Tabs, Typography } from '@neo4j-ndl/react';
import { useState } from 'react';
type TabValues = '0' | '1' | '2';
const Component = () => {
const [value, setValue] = useState<TabValues>('0');
return (
<div>
<Tabs value={value} onChange={setValue} className="n-mb-token-8">
<Tabs.Tab id="0">Tab 1</Tabs.Tab>
<Tabs.Tab id="1">Tab 2</Tabs.Tab>
<Tabs.Tab id="2">Tab 3</Tabs.Tab>
</Tabs>
<Tabs.TabPanel value={value} tabId="0">
<Typography variant="body-medium">Tab 1 content</Typography>
</Tabs.TabPanel>
<Tabs.TabPanel value={value} tabId="1">
<Typography variant="body-medium">Tab 2 content</Typography>
</Tabs.TabPanel>
<Tabs.TabPanel value={value} tabId="2">
<Typography variant="body-medium">Tab 3 content</Typography>
</Tabs.TabPanel>
</div>
);
};
export default Component;
```
### Badge
```tsx
import '@neo4j-ndl/base/lib/neo4j-ds-styles.css';
import { Tabs, Typography } from '@neo4j-ndl/react';
import { useState } from 'react';
type TabValues = '0' | '1' | '2';
const Component = () => {
const [value, setValue] = useState<TabValues>('0');
return (
<div>
<Tabs value={value} onChange={setValue} className="n-mb-token-8">
<Tabs.Tab id="0">Tab 1</Tabs.Tab>
<Tabs.Tab id="1">
Tab 2 <Tabs.Badge>5</Tabs.Badge>
</Tabs.Tab>
<Tabs.Tab id="2">Tab 3</Tabs.Tab>
</Tabs>
<Tabs.TabPanel value={value} tabId="0">
<Typography variant="body-medium">Tab 1 content</Typography>
</Tabs.TabPanel>
<Tabs.TabPanel value={value} tabId="1">
<Typography variant="body-medium">Tab 2 content</Typography>
</Tabs.TabPanel>
<Tabs.TabPanel value={value} tabId="2">
<Typography variant="body-medium">Tab 3 content</Typography>
</Tabs.TabPanel>
</div>
);
};
export default Component;
```
### Disabled
```tsx
import '@neo4j-ndl/base/lib/neo4j-ds-styles.css';
import { Tabs, Typography } from '@neo4j-ndl/react';
import { useState } from 'react';
type TabValues = '0' | '1' | '2';
const Component = () => {
const [value, setValue] = useState<TabValues>('0');
return (
<div>
<Tabs value={value} onChange={setValue} className="n-mb-token-8">
<Tabs.Tab id="0">Tab 1</Tabs.Tab>
<Tabs.Tab id="1">Tab 2</Tabs.Tab>
<Tabs.Tab id="2" isDisabled={true}>
Tab 3
</Tabs.Tab>
</Tabs>
<Tabs.TabPanel value={value} tabId="0">
<Typography variant="body-medium">Tab 1 content</Typography>
</Tabs.TabPanel>
<Tabs.TabPanel value={value} tabId="1">
<Typography variant="body-medium">Tab 2 content</Typography>
</Tabs.TabPanel>
<Tabs.TabPanel value={value} tabId="2">
<Typography variant="body-medium">Tab 3 content</Typography>
</Tabs.TabPanel>
</div>
);
};
export default Component;
```
### Fill Variants
```tsx
import '@neo4j-ndl/base/lib/neo4j-ds-styles.css';
import { Tabs, Typography } from '@neo4j-ndl/react';
import { useState } from 'react';
type TabValues = '0' | '1' | '2';
const Component = () => {
const [underlineValue, setUnderlineValue] = useState<TabValues>('0');
const [filledValue, setFilledValue] = useState<TabValues>('0');
return (
<div className="n-flex n-gap-token-8">
<div className="n-flex n-flex-col n-gap-token-32">
<Typography variant="label">Underline (Default)</Typography>
<div>
<Tabs
value={underlineValue}
onChange={setUnderlineValue}
className="n-mb-token-8"
>
<Tabs.Tab id="0">Tab 1</Tabs.Tab>
<Tabs.Tab id="1">Tab 2</Tabs.Tab>
<Tabs.Tab id="2">Tab 3</Tabs.Tab>
</Tabs>
<Tabs.TabPanel value={underlineValue} tabId="0">
<Typography variant="body-medium">Tab 1 content</Typography>
</Tabs.TabPanel>
<Tabs.TabPanel value={underlineValue} tabId="1">
<Typography variant="body-medium">Tab 2 content</Typography>
</Tabs.TabPanel>
<Tabs.TabPanel value={underlineValue} tabId="2">
<Typography variant="body-medium">Tab 3 content</Typography>
</Tabs.TabPanel>
</div>
</div>
<div className="n-flex n-flex-col n-gap-token-8">
<Typography variant="label">Filled</Typography>
<div>
<Tabs
value={filledValue}
onChange={setFilledValue}
fill="filled"
className="n-mb-token-8"
>
<Tabs.Tab id="0">Tab 1</Tabs.Tab>
<Tabs.Tab id="1">Tab 2</Tabs.Tab>
<Tabs.Tab id="2">Tab 3</Tabs.Tab>
</Tabs>
<Tabs.TabPanel value={filledValue} tabId="0">
<Typography variant="body-medium">Tab 1 content</Typography>
</Tabs.TabPanel>
<Tabs.TabPanel value={filledValue} tabId="1">
<Typography variant="body-medium">Tab 2 content</Typography>
</Tabs.TabPanel>
<Tabs.TabPanel value={filledValue} tabId="2">
<Typography variant="body-medium">Tab 3 content</Typography>
</Tabs.TabPanel>
</div>
</div>
</div>
);
};
export default Component;
```
### Overflow
```tsx
import '@neo4j-ndl/base/lib/neo4j-ds-styles.css';
import { Tabs, Typography } from '@neo4j-ndl/react';
import { useState } from 'react';
const Component = () => {
const [value, setValue] = useState<string>('0');
return (
<div className="n-w-80">
<Tabs value={value} onChange={setValue} className="n-mb-token-8">
<Tabs.Tab id="0">Tab 1</Tabs.Tab>
<Tabs.Tab id="1">Tab 2</Tabs.Tab>
<Tabs.Tab id="2">Tab 3</Tabs.Tab>
<Tabs.Tab id="3">Tab 4</Tabs.Tab>
<Tabs.Tab id="4">Tab 5</Tabs.Tab>
<Tabs.Tab id="5">Tab 6</Tabs.Tab>
<Tabs.Tab id="6">Tab 7</Tabs.Tab>
<Tabs.Tab id="7">Tab 8</Tabs.Tab>
<Tabs.Tab id="8">Tab 9</Tabs.Tab>
<Tabs.Tab id="9">
Tab 10 is waay too long and will be cut off on smaller screens
</Tabs.Tab>
</Tabs>
<Tabs.TabPanel value={value} tabId="0">
<Typography variant="body-medium">Tab 1 content</Typography>
</Tabs.TabPanel>
<Tabs.TabPanel value={value} tabId="1">
<Typography variant="body-medium">Tab 2 content</Typography>
</Tabs.TabPanel>
<Tabs.TabPanel value={value} tabId="2">
<Typography variant="body-medium">Tab 3 content</Typography>
</Tabs.TabPanel>
<Tabs.TabPanel value={value} tabId="3">
<Typography variant="body-medium">Tab 4 content</Typography>
</Tabs.TabPanel>
<Tabs.TabPanel value={value} tabId="4">
<Typography variant="body-medium">Tab 5 content</Typography>
</Tabs.TabPanel>
<Tabs.TabPanel value={value} tabId="5">
<Typography variant="body-medium">Tab 6 content</Typography>
</Tabs.TabPanel>
<Tabs.TabPanel value={value} tabId="6">
<Typography variant="body-medium">Tab 7 content</Typography>
</Tabs.TabPanel>
<Tabs.TabPanel value={value} tabId="7">
<Typography variant="body-medium">Tab 8 content</Typography>
</Tabs.TabPanel>
<Tabs.TabPanel value={value} tabId="8">
<Typography variant="body-medium">Tab 9 content</Typography>
</Tabs.TabPanel>
<Tabs.TabPanel value={value} tabId="9">
<Typography variant="body-medium">Tab 10 content</Typography>
</Tabs.TabPanel>
</div>
);
};
export default Component;
```
### Sizes
```tsx
import '@neo4j-ndl/base/lib/neo4j-ds-styles.css';
import { Tabs, Typography } from '@neo4j-ndl/react';
import { useState } from 'react';
type TabValues = '0' | '1' | '2';
const Component = () => {
const [smallValue, setSmallValue] = useState<TabValues>('0');
const [largeValue, setLargeValue] = useState<TabValues>('0');
return (
<div className="n-flex n-gap-token-8">
<div className="n-flex n-flex-col n-gap-token-8">
<Typography variant="label">Small Size</Typography>
<div className="n-w-fit">
<Tabs
value={smallValue}
onChange={setSmallValue}
size="small"
className="n-mb-token-8"
>
<Tabs.Tab id="0">Tab 1</Tabs.Tab>
<Tabs.Tab id="1">Tab 2</Tabs.Tab>
<Tabs.Tab id="2">Tab 3</Tabs.Tab>
</Tabs>
<Tabs.TabPanel value={smallValue} tabId="0">
<Typography variant="body-small">
Content for small tab 1
</Typography>
</Tabs.TabPanel>
<Tabs.TabPanel value={smallValue} tabId="1">
<Typography variant="body-small">
Content for small tab 2
</Typography>
</Tabs.TabPanel>
<Tabs.TabPanel value={smallValue} tabId="2">
<Typography variant="body-small">
Content for small tab 3
</Typography>
</Tabs.TabPanel>
</div>
</div>
<div className="n-flex n-flex-col n-gap-token-8">
<Typography variant="label">Large Size (Default)</Typography>
<Tabs
value={largeValue}
onChange={setLargeValue}
size="large"
className="n-mb-token-8"
>
<Tabs.Tab id="0">Tab 1</Tabs.Tab>
<Tabs.Tab id="1">Tab 2</Tabs.Tab>
<Tabs.Tab id="2">Tab 3</Tabs.Tab>
</Tabs>
<Tabs.TabPanel value={largeValue} tabId="0">
<Typography variant="body-medium">Content for large tab 1</Typography>
</Tabs.TabPanel>
<Tabs.TabPanel value={largeValue} tabId="1">
<Typography variant="body-medium">Content for large tab 2</Typography>
</Tabs.TabPanel>
<Tabs.TabPanel value={largeValue} tabId="2">
<Typography variant="body-medium">Content for large tab 3</Typography>
</Tabs.TabPanel>
</div>
</div>
);
};
export default Component;
```
### With Icons
```tsx
import '@neo4j-ndl/base/lib/neo4j-ds-styles.css';
import { Tabs, Typography } from '@neo4j-ndl/react';
import {
CircleStackIconOutline,
DatabasePlusIcon,
InboxArrowDownIconOutline,
} from '@neo4j-ndl/react/icons';
import { useState } from 'react';
type TabValues = 'database' | 'add' | 'inbox';
const Component = () => {
const [value, setValue] = useState<TabValues>('database');
return (
<div className="n-mt-5">
<Tabs value={value} onChange={setValue} className="n-mb-token-8">
<Tabs.Tab id="database" description="Database">
<CircleStackIconOutline />
</Tabs.Tab>
<Tabs.Tab id="add" description="Add database">
<DatabasePlusIcon />
</Tabs.Tab>
<Tabs.Tab id="inbox" description="Inbox">
<InboxArrowDownIconOutline />
</Tabs.Tab>
</Tabs>
<Tabs.TabPanel value={value} tabId="database">
<Typography variant="body-medium">
Database management and operations.
</Typography>
</Tabs.TabPanel>
<Tabs.TabPanel value={value} tabId="add">
<Typography variant="body-medium">
Add new database or connection.
</Typography>
</Tabs.TabPanel>
<Tabs.TabPanel value={value} tabId="inbox">
<Typography variant="body-medium">
Inbox notifications and messages.
</Typography>
</Tabs.TabPanel>
</div>
);
};
export default Component;
```