diff --git a/.changeset/green-bulldogs-shop.md b/.changeset/green-bulldogs-shop.md new file mode 100644 index 0000000000..f2ffa4ff8b --- /dev/null +++ b/.changeset/green-bulldogs-shop.md @@ -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 diff --git a/docs/app/docs/built-ins/tabs/page.mdx b/docs/app/docs/built-ins/tabs/page.mdx index 42adb12a8a..80fdd0e080 100644 --- a/docs/app/docs/built-ins/tabs/page.mdx +++ b/docs/app/docs/built-ins/tabs/page.mdx @@ -10,10 +10,10 @@ icon: CardsIcon import { Tabs } from 'nextra/components' {/* prettier-ignore */} - - **pnpm**: Fast, disk space efficient package manager. - **npm** is a package manager for the JavaScript programming language. - **Yarn** is a software packaging system. + + **pnpm**: Fast, disk space efficient package manager. + **npm** is a package manager for the JavaScript programming language. + **Yarn** is a software packaging system. ## Usage @@ -24,10 +24,10 @@ import { Tabs } from 'nextra/components' ```mdx import { Tabs } from 'nextra/components' - - **pnpm**: Fast, disk space efficient package manager. - **npm** is a package manager for the JavaScript programming language. - **Yarn** is a software packaging system. + + **pnpm**: Fast, disk space efficient package manager. + **npm** is a package manager for the JavaScript programming language. + **Yarn** is a software packaging system. ``` @@ -38,16 +38,14 @@ You can use the `defaultIndex` prop to set the default tab index: ```mdx /defaultIndex="1"/ import { Tabs } from 'nextra/components' - - ... - +... ``` And you will have `npm` as the default tab: {/* prettier-ignore */} - - **pnpm**: Fast, disk space efficient package manager. - **npm** is a package manager for the JavaScript programming language. - **Yarn** is a software packaging system. + + **pnpm**: Fast, disk space efficient package manager. + **npm** is a package manager for the JavaScript programming language. + **Yarn** is a software packaging system. diff --git a/examples/blog/app/posts/(with-comments)/nextra-components/page.mdx b/examples/blog/app/posts/(with-comments)/nextra-components/page.mdx index 05a62200af..1f327b3fc8 100644 --- a/examples/blog/app/posts/(with-comments)/nextra-components/page.mdx +++ b/examples/blog/app/posts/(with-comments)/nextra-components/page.mdx @@ -74,10 +74,10 @@ Contents for step 2. ## `` {/* prettier-ignore */} - - **pnpm**: Fast, disk space efficient package manager. - **npm** is a package manager for the JavaScript programming language. - **Yarn** is a software packaging system. + + **pnpm**: Fast, disk space efficient package manager. + **npm** is a package manager for the JavaScript programming language. + **Yarn** is a software packaging system. ## `` diff --git a/examples/docs/src/content/themes/docs/tabs.mdx b/examples/docs/src/content/themes/docs/tabs.mdx index 1ee0d4c62c..940b55e1ac 100644 --- a/examples/docs/src/content/themes/docs/tabs.mdx +++ b/examples/docs/src/content/themes/docs/tabs.mdx @@ -10,23 +10,23 @@ A built-in component provided by `nextra-theme-docs`. import { Tabs } from 'nextra/components' - - + + ```js filename="hi.js" import { useState, useEffect } from 'react'; ``` - + ```cpp filename="hi.cpp" #include ``` - + ```c filename="hi.c" #include ``` - + ```python filename="hello.py" print('Hello, world!') ``` @@ -38,23 +38,23 @@ import { Tabs } from 'nextra/components' ### MDX component ````mdx filename="tabs.mdx" - - + + ```js filename="hi.js" import { useState, useEffect } from 'react'; ``` - + ```cpp filename="hi.cpp" #include ``` - + ```c filename="hi.c" #include ``` - + ```python filename="hello.py" print('Hello, world!') ``` diff --git a/examples/swr-site/content/en/docs/advanced/scrollbar-x.mdx b/examples/swr-site/content/en/docs/advanced/scrollbar-x.mdx index 4f81f1b62a..da4f334733 100644 --- a/examples/swr-site/content/en/docs/advanced/scrollbar-x.mdx +++ b/examples/swr-site/content/en/docs/advanced/scrollbar-x.mdx @@ -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 | johndoe@example.com | 555-555-5555 | 123 Main St, Anytown USA | 01/01/2000 | M | Junior | Full-time | 01/01/2022 | 05/01/2024 | 54321 | @@ -10,22 +8,3 @@ import { Tabs } from 'nextra/components' | 44444 | Ashley | Moore | Business | 3.5 | 2022 | ashleymoore@example.com | 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 | davidtaylor@example.com | 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 | jessicaanderson@example.com | 555-555-5555 | 111 Cedar St, Anytown USA | 08/08/1993 | F | Senior | Full-time | 01/01/2019 | 12/01/2022 | 56789 | - - - dada - dadasd - diff --git a/examples/swr-site/content/en/index.mdx b/examples/swr-site/content/en/index.mdx index f3b1aba3f9..bd128806a3 100644 --- a/examples/swr-site/content/en/index.mdx +++ b/examples/swr-site/content/en/index.mdx @@ -10,25 +10,25 @@ import { Callout, Tabs } from 'nextra/components' - - + + ```js filename="hi.js" import { useState, useEffect } from 'react'; ``` - + ```cpp filename="hi.cpp" #include ``` - + ```c filename="hi.c" #include ``` - - ```c filename="hi.c" - #include + + ```python filename="hello.py" + print('Hello, world!') ``` @@ -47,7 +47,7 @@ And the UI will be always **fast** and **reactive**. -
+
[Get Started](/docs/getting-started) · [Examples](/examples/basic) · [Blog](/blog) · [GitHub Repository](https://github.com/vercel/swr)
diff --git a/packages/nextra/src/client/components/tabs/index.client.tsx b/packages/nextra/src/client/components/tabs/index.client.tsx index 14cb4a40a3..cc73d061f9 100644 --- a/packages/nextra/src/client/components/tabs/index.client.tsx +++ b/packages/nextra/src/client/components/tabs/index.client.tsx @@ -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 @@ -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'] @@ -114,6 +132,24 @@ export const Tabs: FC< onChange?.(index) } + const tabPanels = + items ?? + Children.map( + children, + child => + isValidElement(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.' + ) + } + return ( - {items.map((item, index) => ( + {tabPanels.map((item, index) => ( = ({ +type TabPanelProps = { name?: string; disabled?: boolean } + +export const Tab: FC = ({ children, // For SEO display all the Panel in the DOM and set `display: none;` for those that are not selected unmount = false,