Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

deprecate Tabs#items prop, suggest to use Tabs.Tab#name and Tabs.Tab#disabled props instead #4064

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/green-bulldogs-shop.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"nextra": patch
---

deprecate `Tabs#items` prop which will be removed in Nextra 5. Use `Tabs.Tab#name` and `Tabs.Tab#disabled` props instead
28 changes: 13 additions & 15 deletions docs/app/docs/built-ins/tabs/page.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ icon: CardsIcon
import { Tabs } from 'nextra/components'

{/* prettier-ignore */}
<Tabs items={['pnpm', 'npm', 'yarn']}>
<Tabs.Tab>**pnpm**: Fast, disk space efficient package manager.</Tabs.Tab>
<Tabs.Tab>**npm** is a package manager for the JavaScript programming language.</Tabs.Tab>
<Tabs.Tab>**Yarn** is a software packaging system.</Tabs.Tab>
<Tabs>
<Tabs.Tab name="pnpm">**pnpm**: Fast, disk space efficient package manager.</Tabs.Tab>
<Tabs.Tab name="npm">**npm** is a package manager for the JavaScript programming language.</Tabs.Tab>
<Tabs.Tab name="yarn">**Yarn** is a software packaging system.</Tabs.Tab>
</Tabs>

## Usage
Expand All @@ -24,10 +24,10 @@ import { Tabs } from 'nextra/components'
```mdx
import { Tabs } from 'nextra/components'

<Tabs items={['pnpm', 'npm', 'yarn']}>
<Tabs.Tab>**pnpm**: Fast, disk space efficient package manager.</Tabs.Tab>
<Tabs.Tab>**npm** is a package manager for the JavaScript programming language.</Tabs.Tab>
<Tabs.Tab>**Yarn** is a software packaging system.</Tabs.Tab>
<Tabs>
<Tabs.Tab name="pnpm">**pnpm**: Fast, disk space efficient package manager.</Tabs.Tab>
<Tabs.Tab name="npm">**npm** is a package manager for the JavaScript programming language.</Tabs.Tab>
<Tabs.Tab name="yarn">**Yarn** is a software packaging system.</Tabs.Tab>
</Tabs>
```

Expand All @@ -38,16 +38,14 @@ You can use the `defaultIndex` prop to set the default tab index:
```mdx /defaultIndex="1"/
import { Tabs } from 'nextra/components'

<Tabs items={['pnpm', 'npm', 'yarn']} defaultIndex="1">
...
</Tabs>
<Tabs defaultIndex="1">...</Tabs>
```

And you will have `npm` as the default tab:

{/* prettier-ignore */}
<Tabs items={['pnpm', 'npm', 'yarn']} defaultIndex="1">
<Tabs.Tab>**pnpm**: Fast, disk space efficient package manager.</Tabs.Tab>
<Tabs.Tab>**npm** is a package manager for the JavaScript programming language.</Tabs.Tab>
<Tabs.Tab>**Yarn** is a software packaging system.</Tabs.Tab>
<Tabs defaultIndex="1">
<Tabs.Tab name="pnpm">**pnpm**: Fast, disk space efficient package manager.</Tabs.Tab>
<Tabs.Tab name="npm">**npm** is a package manager for the JavaScript programming language.</Tabs.Tab>
<Tabs.Tab name="yarn">**Yarn** is a software packaging system.</Tabs.Tab>
</Tabs>
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,10 @@ Contents for step 2.
## `<Tabs>`

{/* prettier-ignore */}
<Tabs items={['pnpm', 'npm', 'yarn']}>
<Tabs.Tab>**pnpm**: Fast, disk space efficient package manager.</Tabs.Tab>
<Tabs.Tab>**npm** is a package manager for the JavaScript programming language.</Tabs.Tab>
<Tabs.Tab>**Yarn** is a software packaging system.</Tabs.Tab>
<Tabs>
<Tabs.Tab name="pnpm">**pnpm**: Fast, disk space efficient package manager.</Tabs.Tab>
<Tabs.Tab name="npm">**npm** is a package manager for the JavaScript programming language.</Tabs.Tab>
<Tabs.Tab name="yarn">**Yarn** is a software packaging system.</Tabs.Tab>
</Tabs>

## `<FileTree>`
Expand Down
20 changes: 10 additions & 10 deletions examples/docs/src/content/themes/docs/tabs.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,23 @@ A built-in component provided by `nextra-theme-docs`.

import { Tabs } from 'nextra/components'

<Tabs items={['JavaScript', 'C++', {label:'C', disabled: true}, 'Python']} defaultIndex={1}>
<Tabs.Tab>
<Tabs defaultIndex={1}>
<Tabs.Tab name="JavaScript">
```js filename="hi.js"
import { useState, useEffect } from 'react';
```
</Tabs.Tab>
<Tabs.Tab>
<Tabs.Tab name="C++">
```cpp filename="hi.cpp"
#include <iostream>
```
</Tabs.Tab>
<Tabs.Tab>
<Tabs.Tab name="C" disabled>
```c filename="hi.c"
#include <stdio.h>
```
</Tabs.Tab>
<Tabs.Tab>
<Tabs.Tab name="Python">
```python filename="hello.py"
print('Hello, world!')
```
Expand All @@ -38,23 +38,23 @@ import { Tabs } from 'nextra/components'
### MDX component

````mdx filename="tabs.mdx"
<Tabs items={['JavaScript', 'C++', {label:'C', disabled: true}, 'Python']} defaultIndex={1}>
<Tabs.Tab>
<Tabs defaultIndex={1}>
<Tabs.Tab name="JavaScript">
```js filename="hi.js"
import { useState, useEffect } from 'react';
```
</Tabs.Tab>
<Tabs.Tab>
<Tabs.Tab name="C++">
```cpp filename="hi.cpp"
#include <iostream>
```
</Tabs.Tab>
<Tabs.Tab>
<Tabs.Tab name="C" disabled>
```c filename="hi.c"
#include <stdio.h>
```
</Tabs.Tab>
<Tabs.Tab>
<Tabs.Tab name="Python">
```python filename="hello.py"
print('Hello, world!')
```
Expand Down
21 changes: 0 additions & 21 deletions examples/swr-site/content/en/docs/advanced/scrollbar-x.mdx
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { Tabs } from 'nextra/components'

| **Student ID** | **First Name** | **Last Name** | **Major** | **GPA** | **Graduation Year** | **Email** | **Phone Number** | **Address** | **Date of Birth** | **Gender** | **Class Standing** | **Enrollment Status** | **Enrollment Date** | **Graduation Date** | **Advisor ID** |
| :------------- | :------------- | :------------ | :---------------- | :------ | :------------------ | :--------------------------- | :--------------- | :------------------------ | :---------------- | :--------- | :----------------- | :-------------------- | :------------------ | :------------------ | :------------- |
| 12345 | John | Doe | Computer Science | 3.5 | 2024 | [email protected] | 555-555-5555 | 123 Main St, Anytown USA | 01/01/2000 | M | Junior | Full-time | 01/01/2022 | 05/01/2024 | 54321 |
Expand All @@ -10,22 +8,3 @@ import { Tabs } from 'nextra/components'
| 44444 | Ashley | Moore | Business | 3.5 | 2022 | [email protected] | 555-555-5555 | 753 Birch St, Anytown USA | 06/06/1995 | F | Senior | Part-time | 01/01/2021 | 05/01/2022 | 98765 |
| 55555 | David | Taylor | Engineering | 3.9 | 2024 | [email protected] | 555-555-5555 | 964 Maple St, Anytown USA | 07/07/1994 | M | Junior | Full-time | 01/01/2022 | 05/01/2024 | 54321 |
| 77777 | Jessica | Anderson | Communications | 3.6 | 2023 | [email protected] | 555-555-5555 | 111 Cedar St, Anytown USA | 08/08/1993 | F | Senior | Full-time | 01/01/2019 | 12/01/2022 | 56789 |

<Tabs
items={[
'name',
'version',
'private',
'dependencies',
'scripts',
'eslintConfig',
'browserslist',
'development',
'name',
'version',
'private'
]}
>
<Tabs.Tab className="bg-red-500">dada</Tabs.Tab>
<Tabs.Tab>dadasd</Tabs.Tab>
</Tabs>
16 changes: 8 additions & 8 deletions examples/swr-site/content/en/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -10,25 +10,25 @@ import { Callout, Tabs } from 'nextra/components'

<Features lang={props.params.lang} title={metadata.title} />

<Tabs items={['JavaScript', 'C++', {label:'C', disabled: true}, 'Python', 'TypeScript', 'GraphQL', 'Rust', 'C#', 'Go', 'HTML', 'CSS', 'plaintext', 'bash']} defaultIndex={1}>
<Tabs.Tab>
<Tabs defaultIndex={1}>
<Tabs.Tab name="JavaScript">
```js filename="hi.js"
import { useState, useEffect } from 'react';
```
</Tabs.Tab>
<Tabs.Tab>
<Tabs.Tab name="C++">
```cpp filename="hi.cpp"
#include <iostream>
```
</Tabs.Tab>
<Tabs.Tab>
<Tabs.Tab name="C" disabled>
```c filename="hi.c"
#include <stdio.h>
```
</Tabs.Tab>
<Tabs.Tab>
```c filename="hi.c"
#include <stdio.h>
<Tabs.Tab className="Python">
```python filename="hello.py"
print('Hello, world!')
```
</Tabs.Tab>
</Tabs>
Expand All @@ -47,7 +47,7 @@ And the UI will be always **fast** and **reactive**.

</Callout>

<div className="mt-16 mb-20 text-center">
<div className="mb-20 mt-16 text-center">
[Get Started](/docs/getting-started) · [Examples](/examples/basic) ·
[Blog](/blog) · [GitHub Repository](https://github.com/vercel/swr)
</div>
Expand Down
50 changes: 44 additions & 6 deletions packages/nextra/src/client/components/tabs/index.client.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,21 @@ import {
TabPanels
} from '@headlessui/react'
import type {
TabPanelProps as HeadlessTabPanelProps,
TabProps as HeadlessTabProps,
TabGroupProps,
TabListProps,
TabPanelProps
TabListProps
} from '@headlessui/react'
import cn from 'clsx'
import type { FC, ReactElement, ReactNode } from 'react'
import { Fragment, useEffect, useRef, useState } from 'react'
import {
Children,
Fragment,
isValidElement,
useEffect,
useRef,
useState
} from 'react'
import { useHash } from '../../hooks/use-hash.js'

type TabItem = string | ReactElement
Expand All @@ -29,9 +36,20 @@ function isTabObjectItem(item: unknown): item is TabObjectItem {
return !!item && typeof item === 'object' && 'label' in item
}

const warnOnce: ((message: string) => void) & {
wasWarned?: boolean
} = message => {
if (warnOnce.wasWarned) return
console.warn(message)
warnOnce.wasWarned = true
}

export const Tabs: FC<
{
items: (TabItem | TabObjectItem)[]
/*
* @deprecated Use `Tabs.Tab#name` and `Tabs.Tab#disabled` props instead
**/
items?: (TabItem | TabObjectItem)[]
children: ReactNode
storageKey?: string
className?: TabListProps['className']
Expand Down Expand Up @@ -114,6 +132,24 @@ export const Tabs: FC<
onChange?.(index)
}

const tabPanels =
items ??
Children.map(
children,
child =>
isValidElement<TabPanelProps>(child) &&
({
label: child.props.name!,
disabled: child.props.disabled!
} satisfies TabObjectItem)
)!

if (process.env.NODE_ENV !== 'production') {
warnOnce(
'You are using deprecated `Tabs#items` prop, and which will be removed in Nextra 5. Use `Tabs.Tab#name` and `Tabs.Tab#disabled` props instead.'
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
'You are using deprecated `Tabs#items` prop, and which will be removed in Nextra 5. Use `Tabs.Tab#name` and `Tabs.Tab#disabled` props instead.'
'You are using the deprecated `Tabs#items` prop, which will be removed in Nextra 5. Instead, use the `Tabs.Tab#name` and `Tabs.Tab#disabled` props.'

)
}

return (
<TabGroup
selectedIndex={selectedIndex}
Expand All @@ -131,7 +167,7 @@ export const Tabs: FC<
)
}
>
{items.map((item, index) => (
{tabPanels.map((item, index) => (
<HeadlessTab
key={index}
disabled={isTabObjectItem(item) && item.disabled}
Expand Down Expand Up @@ -169,7 +205,9 @@ export const Tabs: FC<
)
}

export const Tab: FC<TabPanelProps> = ({
type TabPanelProps = { name?: string; disabled?: boolean }

export const Tab: FC<HeadlessTabPanelProps & TabPanelProps> = ({
children,
// For SEO display all the Panel in the DOM and set `display: none;` for those that are not selected
unmount = false,
Expand Down
Loading