mirror of
https://github.com/nextui-org/nextui.git
synced 2025-12-08 19:26:11 +00:00
feat(docs): hero improved, tabs component initial structure
This commit is contained in:
parent
d5ec85063b
commit
b1bb36f898
@ -1,11 +1,16 @@
|
||||
import {useState} from "react";
|
||||
import {useState, FC} from "react";
|
||||
import {Card, CardHeader, Button, Avatar, CardBody, CardFooter} from "@nextui-org/react";
|
||||
import {clsx} from "@nextui-org/shared-utils";
|
||||
|
||||
export const UserTwitterCard = () => {
|
||||
interface UserTwitterCardProps {
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export const UserTwitterCard: FC<UserTwitterCardProps> = ({className}) => {
|
||||
const [isFollowed, setIsFollowed] = useState(false);
|
||||
|
||||
return (
|
||||
<Card className="max-w-[300px]">
|
||||
<Card className={clsx("max-w-[300px]", className)}>
|
||||
<CardHeader className="justify-between">
|
||||
<div className="flex gap-5">
|
||||
<Avatar isBordered radius="full" size="md" src="/avatars/avatar-1.png" />
|
||||
|
||||
@ -58,7 +58,7 @@ export const DocsNavbar = () => {
|
||||
<Navbar maxWidth="xl" position="sticky" onMenuOpenChange={setIsMenuOpen}>
|
||||
<NavbarContent className="basis-1/5 sm:basis-full" justify="start">
|
||||
<NavbarBrand className="gap-3">
|
||||
<NextUILogo />
|
||||
<NextUILogo auto />
|
||||
<Dropdown placement="bottom-start">
|
||||
<DropdownTrigger>
|
||||
<Button
|
||||
|
||||
@ -3,9 +3,9 @@ import {
|
||||
Button,
|
||||
Input,
|
||||
Tooltip,
|
||||
Card,
|
||||
Image,
|
||||
CardFooter,
|
||||
Card,
|
||||
CardBody,
|
||||
Switch,
|
||||
Spinner,
|
||||
@ -15,6 +15,7 @@ import {ArrowRightIcon, MoonFilledIcon, SunFilledIcon} from "@nextui-org/shared-
|
||||
import {useTheme} from "next-themes";
|
||||
import dynamic from "next/dynamic";
|
||||
|
||||
import {NextUILogo} from "@/components";
|
||||
import {GithubIcon} from "@/components/icons";
|
||||
import {UserTwitterCard} from "@/components/demos";
|
||||
|
||||
@ -38,19 +39,9 @@ const FloatingComponents: React.FC = () => {
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-4">
|
||||
<Input
|
||||
className="w-[200px]"
|
||||
color="secondary"
|
||||
defaultValue="NextUI"
|
||||
label="Input"
|
||||
labelPosition="outside"
|
||||
radius="xl"
|
||||
variant="bordered"
|
||||
onClear={() => {}}
|
||||
/>
|
||||
|
||||
<Switch
|
||||
classNames={{
|
||||
base: "relative top-[140px] left-[240px] animate-[levitate_13s_ease_infinite_1s_reverse]",
|
||||
startIcon: "text-white",
|
||||
}}
|
||||
endIcon={<MoonFilledIcon />}
|
||||
@ -60,56 +51,112 @@ const FloatingComponents: React.FC = () => {
|
||||
onChange={onChange}
|
||||
/>
|
||||
|
||||
<UserTwitterCard />
|
||||
<Card
|
||||
isFooterBlurred
|
||||
className="relative h-[120px] animate-[levitate_12s_ease_infinite_1s] left-[80px] top-[40px] z-0 max-w-fit"
|
||||
radius="2xl"
|
||||
>
|
||||
<Image
|
||||
className="object-cover -translate-y-6 h-[120%]"
|
||||
src="/images/card-example-6.jpeg"
|
||||
width={120}
|
||||
/>
|
||||
<CardFooter className="before:bg-black/10 before:border before:border-white/20 overflow-hidden justify-between py-2 absolute before:rounded-xl rounded-xl bottom-1 w-[calc(100%_-_8px)] shadow-lg ml-1 z-10">
|
||||
<p className="text-xs font-semibold text-white/80">Camera</p>
|
||||
<p className="text-xs font-semibold text-white/80">$525</p>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
|
||||
<Input
|
||||
className="relative animate-[levitate_10s_ease_infinite] -left-[144px] top-[0px] w-[200px]"
|
||||
color="secondary"
|
||||
defaultValue="NextUI"
|
||||
label="Input"
|
||||
labelPosition="outside"
|
||||
radius="xl"
|
||||
variant="bordered"
|
||||
onClear={() => {}}
|
||||
/>
|
||||
|
||||
<UserTwitterCard className="animate-[levitate_16s_ease_infinite] relative border-none -left-[240px] top-[20px]" />
|
||||
|
||||
<Card className="animate-[levitate_18s_ease_infinite] relative left-[90px] -top-[140px] right-8 shadow-lg z-10 max-w-fit border-none">
|
||||
<CardBody>
|
||||
<NextUILogo small size={60} />
|
||||
</CardBody>
|
||||
</Card>
|
||||
|
||||
<div className="relative z-10 -top-[230px] -right-[200px] animate-[levitate_14s_ease_infinite_1s]">
|
||||
<Pagination
|
||||
isCompact
|
||||
showControls
|
||||
showShadow
|
||||
classNames={{
|
||||
base: "shadow-lg rounded-xl",
|
||||
item: "bg-background dark:bg-content1",
|
||||
prev: "bg-background dark:bg-content1",
|
||||
next: "bg-background dark:bg-content1",
|
||||
}}
|
||||
initialPage={6}
|
||||
total={10}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<Tooltip
|
||||
isOpen
|
||||
showArrow
|
||||
className="text-sm"
|
||||
className="text-sm animate-[levitate_14s_ease_infinite]"
|
||||
color="secondary"
|
||||
content="Developers love Next.js"
|
||||
placement="top"
|
||||
>
|
||||
<Button className="max-w-fit" color="secondary" size="sm" variant="flat">
|
||||
<Button
|
||||
className="relative -left-[120px] -top-[80px] max-w-fit animate-[levitate_14s_ease_infinite_0.5s]"
|
||||
color="secondary"
|
||||
size="sm"
|
||||
variant="flat"
|
||||
>
|
||||
Tooltip
|
||||
</Button>
|
||||
</Tooltip>
|
||||
|
||||
<Card isFooterBlurred className="max-w-fit" radius="2xl">
|
||||
<Image className="object-cover" height={400} src="/images/hero-card.png" />
|
||||
<CardFooter className="bg-white/10 justify-between py-2 rounded-none absolute -bottom-0.5 z-10">
|
||||
<Card className="relative animate-[levitate_16s_ease_infinite] left-[220px] -top-[260px] right-8 shadow-lg z-10 max-w-fit border-none">
|
||||
<CardBody>
|
||||
<Spinner color="secondary" size="xl" />
|
||||
</CardBody>
|
||||
</Card>
|
||||
|
||||
<Card
|
||||
isFooterBlurred
|
||||
className="relative animate-[levitate_12s_ease_infinite_1s] left-10 -top-[300px] z-0 max-w-fit"
|
||||
radius="2xl"
|
||||
>
|
||||
<Image className="object-cover" height={200} src="/images/hero-card.jpeg" width={200} />
|
||||
<CardFooter className="before:bg-white/10 overflow-hidden justify-between py-2 absolute before:rounded-xl rounded-xl bottom-1 w-[calc(100%_-_8px)] shadow-lg ml-1 z-10">
|
||||
<p className="text-xs text-white/80">Available soon.</p>
|
||||
<Button color="secondary" radius="full" size="xs" variant="flat">
|
||||
Notify me
|
||||
</Button>
|
||||
</CardFooter>
|
||||
</Card>
|
||||
|
||||
<Card className="max-w-fit border-none">
|
||||
<CardBody>
|
||||
<Spinner color="secondary" size="xl" />
|
||||
</CardBody>
|
||||
</Card>
|
||||
|
||||
<Pagination isCompact showControls showShadow initialPage={6} total={10} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const Hero = () => {
|
||||
return (
|
||||
<section className="flex relative w-full flex-nowrap justify-between items-center h-[calc(84vh_-_64px)]">
|
||||
<div className="flex flex-col gap-6 w-2/3">
|
||||
<section className="flex relative w-full flex-nowrap justify-between items-center h-[calc(90vh_-_64px)] max-h-[800px]">
|
||||
<div className="flex flex-col gap-6 w-1/2">
|
||||
<div>
|
||||
<h1 className="text-6xl tracking-tight inline font-semibold">Make </h1>
|
||||
<h1 className="text-6xl tracking-tight inline font-semibold bg-clip-text text-transparent bg-gradient-to-b from-[#FF1CF7] to-[#b249f8]">
|
||||
<h1 className="text-5xl tracking-tight inline font-semibold">Make </h1>
|
||||
<h1 className="text-5xl tracking-tight inline font-semibold bg-clip-text text-transparent bg-gradient-to-b from-[#FF1CF7] to-[#b249f8]">
|
||||
beautiful
|
||||
</h1>
|
||||
<h1 className="text-6xl tracking-tight inline font-semibold">
|
||||
<h1 className="text-5xl tracking-tight inline font-semibold">
|
||||
websites regardless of your design experience.
|
||||
</h1>
|
||||
</div>
|
||||
<h4 className="font-normal text-xl text-neutral-500">
|
||||
<h4 className="text-xl font-light text-neutral-500">
|
||||
Beautiful, fast and modern React UI library.
|
||||
</h4>
|
||||
<div className="flex items-center gap-4">
|
||||
@ -131,10 +178,10 @@ export const Hero = () => {
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div className="relative h-full">
|
||||
<FloatingComponents />
|
||||
</div>
|
||||
<DynamicLopperBG className="absolute top-0 -z-50" />
|
||||
<DynamicLopperBG className="absolute -top-1/2 -z-50" />
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
@ -11,14 +11,7 @@ export interface LogoProps extends IconSvgProps {
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export const NextUILogo: React.FC<LogoProps> = ({
|
||||
auto = true,
|
||||
size,
|
||||
width,
|
||||
height,
|
||||
small,
|
||||
...props
|
||||
}) => {
|
||||
export const NextUILogo: React.FC<LogoProps> = ({auto, size, width, height, small, ...props}) => {
|
||||
const Small = () => (
|
||||
<svg
|
||||
className="data-[auto=true]:sm:hidden block text-foreground"
|
||||
|
||||
@ -13,6 +13,7 @@
|
||||
"@nextui-org/react": "workspace:*",
|
||||
"@nextui-org/theme": "workspace:*",
|
||||
"@nextui-org/shared-icons": "workspace:*",
|
||||
"@nextui-org/shared-utils": "workspace:*",
|
||||
"next": "13.3.0",
|
||||
"next-themes": "^0.2.1",
|
||||
"react": "^18.0.0",
|
||||
|
||||
BIN
apps/docs/public/images/hero-card.jpeg
Normal file
BIN
apps/docs/public/images/hero-card.jpeg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 497 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 18 KiB |
@ -28,10 +28,28 @@ module.exports = {
|
||||
'0%': { transform: 'scale(1)' },
|
||||
'50%': { transform: 'scale(1.2)' },
|
||||
'100%': { transform: 'scale(1)' },
|
||||
},
|
||||
levitate: {
|
||||
"0%": {
|
||||
transform: "translateY(0)",
|
||||
},
|
||||
"30%": {
|
||||
transform: "translateY(-10px)",
|
||||
},
|
||||
"50%": {
|
||||
transform: "translateY(4px)",
|
||||
},
|
||||
"70%": {
|
||||
transform: "translateY(-15px)",
|
||||
},
|
||||
"100%": {
|
||||
transform: "translateY(0)",
|
||||
},
|
||||
}
|
||||
},
|
||||
animation: {
|
||||
'heartbeat': 'heartbeat 1s ease-in-out infinite',
|
||||
'levitate': 'levitate 5s ease infinite',
|
||||
}
|
||||
},
|
||||
plugins: [nextui()],
|
||||
|
||||
24
packages/components/tabs/README.md
Normal file
24
packages/components/tabs/README.md
Normal file
@ -0,0 +1,24 @@
|
||||
# @nextui-org/tabs
|
||||
|
||||
A Quick description of the component
|
||||
|
||||
> This is an internal utility, not intended for public usage.
|
||||
|
||||
## Installation
|
||||
|
||||
```sh
|
||||
yarn add @nextui-org/tabs
|
||||
# or
|
||||
npm i @nextui-org/tabs
|
||||
```
|
||||
|
||||
## Contribution
|
||||
|
||||
Yes please! See the
|
||||
[contributing guidelines](https://github.com/nextui-org/nextui/blob/master/CONTRIBUTING.md)
|
||||
for details.
|
||||
|
||||
## Licence
|
||||
|
||||
This project is licensed under the terms of the
|
||||
[MIT license](https://github.com/nextui-org/nextui/blob/master/LICENSE).
|
||||
19
packages/components/tabs/__tests__/tabs.test.tsx
Normal file
19
packages/components/tabs/__tests__/tabs.test.tsx
Normal file
@ -0,0 +1,19 @@
|
||||
import * as React from "react";
|
||||
import {render} from "@testing-library/react";
|
||||
|
||||
import {Tabs} from "../src";
|
||||
|
||||
describe("Tabs", () => {
|
||||
it("should render correctly", () => {
|
||||
const wrapper = render(<Tabs />);
|
||||
|
||||
expect(() => wrapper.unmount()).not.toThrow();
|
||||
});
|
||||
|
||||
it("ref should be forwarded", () => {
|
||||
const ref = React.createRef<HTMLDivElement>();
|
||||
|
||||
render(<Tabs ref={ref} />);
|
||||
expect(ref.current).not.toBeNull();
|
||||
});
|
||||
});
|
||||
70
packages/components/tabs/package.json
Normal file
70
packages/components/tabs/package.json
Normal file
@ -0,0 +1,70 @@
|
||||
{
|
||||
"name": "@nextui-org/tabs",
|
||||
"version": "2.0.0-beta.1",
|
||||
"description": "Tabs organize content into multiple sections and allow users to navigate between them.",
|
||||
"keywords": [
|
||||
"tabs"
|
||||
],
|
||||
"author": "Junior Garcia <jrgarciadev@gmail.com>",
|
||||
"homepage": "https://nextui.org",
|
||||
"license": "MIT",
|
||||
"main": "src/index.ts",
|
||||
"sideEffects": false,
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/nextui-org/nextui.git",
|
||||
"directory": "packages/components/tabs"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/nextui-org/nextui/issues"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsup src --dts",
|
||||
"build:fast": "tsup src",
|
||||
"dev": "yarn build:fast -- --watch",
|
||||
"clean": "rimraf dist .turbo",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"prepack": "clean-package",
|
||||
"postpack": "clean-package restore"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=18",
|
||||
"framer-motion": ">=6.2.8"
|
||||
},
|
||||
"dependencies": {
|
||||
"@nextui-org/dom-utils": "workspace:*",
|
||||
"@nextui-org/shared-utils": "workspace:*",
|
||||
"@nextui-org/system": "workspace:*",
|
||||
"@nextui-org/theme": "workspace:*",
|
||||
"@nextui-org/aria-utils": "workspace:*",
|
||||
"@nextui-org/framer-transitions": "workspace:*",
|
||||
"@react-aria/focus": "^3.12.0",
|
||||
"@react-aria/interactions": "^3.15.0",
|
||||
"@react-aria/tabs": "^3.5.0",
|
||||
"@react-aria/utils": "^3.16.0",
|
||||
"@react-stately/tabs": "^3.4.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"framer-motion": "^10.11.2",
|
||||
"@react-types/shared": "^3.18.0",
|
||||
"react-lorem-component": "0.13.0",
|
||||
"@react-types/tabs": "^3.2.1",
|
||||
"clean-package": "2.2.0",
|
||||
"react": "^18.0.0"
|
||||
},
|
||||
"clean-package": "../../../clean-package.config.json",
|
||||
"tsup": {
|
||||
"clean": true,
|
||||
"target": "es2019",
|
||||
"format": [
|
||||
"cjs",
|
||||
"esm"
|
||||
]
|
||||
}
|
||||
}
|
||||
15
packages/components/tabs/src/base/tab-item-base.ts
Normal file
15
packages/components/tabs/src/base/tab-item-base.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import {BaseItem, ItemProps} from "@nextui-org/aria-utils";
|
||||
import {ReactNode} from "react";
|
||||
|
||||
interface Props<T extends object = {}> extends Omit<ItemProps<"div", T>, "children"> {
|
||||
/**
|
||||
* The content of the component.
|
||||
*/
|
||||
children?: ReactNode | null;
|
||||
}
|
||||
|
||||
export type TabItemProps<T extends object = {}> = Props<T>;
|
||||
|
||||
const TabItemBase = BaseItem as <T extends object>(props: TabItemProps<T>) => JSX.Element;
|
||||
|
||||
export default TabItemBase;
|
||||
12
packages/components/tabs/src/index.ts
Normal file
12
packages/components/tabs/src/index.ts
Normal file
@ -0,0 +1,12 @@
|
||||
import Tabs from "./tabs";
|
||||
|
||||
// export types
|
||||
export type {TabsProps} from "./tabs";
|
||||
export type {TabItemProps} from "./base/tab-item-base";
|
||||
|
||||
// export hooks
|
||||
export {useTabs} from "./use-tabs";
|
||||
|
||||
// export components
|
||||
export {Tabs};
|
||||
export {default as TabItem} from "./base/tab-item-base";
|
||||
91
packages/components/tabs/src/tab-item.tsx
Normal file
91
packages/components/tabs/src/tab-item.tsx
Normal file
@ -0,0 +1,91 @@
|
||||
import {forwardRef, HTMLNextUIProps} from "@nextui-org/system";
|
||||
import {useDOMRef} from "@nextui-org/dom-utils";
|
||||
import {clsx, dataAttr} from "@nextui-org/shared-utils";
|
||||
import {chain, filterDOMProps, mergeProps} from "@react-aria/utils";
|
||||
import {useFocusRing} from "@react-aria/focus";
|
||||
import {Node} from "@react-types/shared";
|
||||
import {useTab} from "@react-aria/tabs";
|
||||
import {useHover} from "@react-aria/interactions";
|
||||
import {motion} from "framer-motion";
|
||||
import {TRANSITION_EASINGS} from "@nextui-org/framer-transitions";
|
||||
|
||||
import {useTabsContext} from "./tabs-context";
|
||||
|
||||
export interface TabItemProps<T = object> extends HTMLNextUIProps<"div"> {
|
||||
/**
|
||||
* The tab item.
|
||||
*/
|
||||
item: Node<T>;
|
||||
}
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
const TabItem = forwardRef<TabItemProps, "div">((props, ref) => {
|
||||
const {as, className, item, style, onClick, ...otherProps} = props;
|
||||
|
||||
const {key} = item;
|
||||
|
||||
const Component = as || "div";
|
||||
const domRef = useDOMRef(ref);
|
||||
|
||||
const {slots, state, tabPanelId, classNames} = useTabsContext();
|
||||
|
||||
const {tabProps, isSelected, isDisabled, isPressed} = useTab({key}, state, domRef);
|
||||
const {focusProps, isFocused, isFocusVisible} = useFocusRing();
|
||||
const {hoverProps, isHovered} = useHover({
|
||||
isDisabled,
|
||||
});
|
||||
|
||||
const tabStyles = clsx(classNames?.tab, className, item.props?.className);
|
||||
|
||||
return (
|
||||
<Component
|
||||
ref={domRef}
|
||||
data-focus={dataAttr(isFocused)}
|
||||
data-focus-visible={dataAttr(isFocusVisible)}
|
||||
data-hover={dataAttr(isHovered)}
|
||||
data-hover-unselected={dataAttr(isHovered && !isSelected)}
|
||||
data-pressed={dataAttr(isPressed)}
|
||||
data-selected={dataAttr(isSelected)}
|
||||
{...mergeProps(
|
||||
tabProps,
|
||||
focusProps,
|
||||
hoverProps,
|
||||
filterDOMProps(item.props, {labelable: true}),
|
||||
otherProps,
|
||||
)}
|
||||
aria-controls={tabPanelId}
|
||||
className={slots.tab?.({class: tabStyles})}
|
||||
id={`${tabPanelId}-${key}`}
|
||||
style={{
|
||||
...style,
|
||||
WebkitTapHighlightColor: "transparent",
|
||||
}}
|
||||
onClick={chain(onClick, tabProps.onClick)}
|
||||
>
|
||||
{isSelected && (
|
||||
<motion.span
|
||||
className={slots.cursor({class: classNames?.cursor})}
|
||||
layoutDependency={false}
|
||||
layoutId="tab-item-cursor"
|
||||
transition={{
|
||||
ease: TRANSITION_EASINGS.softSpring,
|
||||
duration: 0.6,
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
<div
|
||||
className={slots.tabContent({
|
||||
class: classNames?.tabContent,
|
||||
})}
|
||||
>
|
||||
{item.rendered}
|
||||
</div>
|
||||
</Component>
|
||||
);
|
||||
});
|
||||
|
||||
TabItem.displayName = "NextUI.TabItem";
|
||||
|
||||
export default TabItem;
|
||||
58
packages/components/tabs/src/tab-panel.tsx
Normal file
58
packages/components/tabs/src/tab-panel.tsx
Normal file
@ -0,0 +1,58 @@
|
||||
import type {AriaTabPanelProps} from "@react-aria/tabs";
|
||||
|
||||
import {forwardRef, HTMLNextUIProps} from "@nextui-org/system";
|
||||
import {useDOMRef} from "@nextui-org/dom-utils";
|
||||
import {clsx} from "@nextui-org/shared-utils";
|
||||
import {filterDOMProps, mergeProps} from "@react-aria/utils";
|
||||
import {useTabPanel} from "@react-aria/tabs";
|
||||
import {useFocusRing} from "@react-aria/focus";
|
||||
|
||||
import {useTabsContext} from "./tabs-context";
|
||||
|
||||
interface Props extends HTMLNextUIProps<"div"> {}
|
||||
|
||||
export type TabPanelProps = Props & AriaTabPanelProps;
|
||||
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
const TabPanel = forwardRef<TabPanelProps, "div">((props, ref) => {
|
||||
const {as, className, ...otherProps} = props;
|
||||
|
||||
const Component = as || "div";
|
||||
const domRef = useDOMRef(ref);
|
||||
|
||||
const {slots, tabPanelId, state, classNames} = useTabsContext();
|
||||
|
||||
const {tabPanelProps} = useTabPanel(props, state, domRef);
|
||||
const {focusProps, isFocused, isFocusVisible} = useFocusRing();
|
||||
|
||||
const selectedItem = state.selectedItem;
|
||||
|
||||
const content = selectedItem?.props.children;
|
||||
|
||||
const tabPanelStyles = clsx(classNames?.panel, className, selectedItem.props?.className);
|
||||
|
||||
return (
|
||||
<Component
|
||||
ref={domRef}
|
||||
data-focus={isFocused}
|
||||
data-focus-visible={isFocusVisible}
|
||||
{...mergeProps(
|
||||
tabPanelProps,
|
||||
focusProps,
|
||||
filterDOMProps(selectedItem.props, {labelable: true}),
|
||||
otherProps,
|
||||
)}
|
||||
aria-labelledby={`${tabPanelId}-${state.selectedItem?.key}`}
|
||||
className={slots.panel?.({class: tabPanelStyles})}
|
||||
id={tabPanelId}
|
||||
>
|
||||
{content}
|
||||
</Component>
|
||||
);
|
||||
});
|
||||
|
||||
TabPanel.displayName = "NextUI.TabPanel";
|
||||
|
||||
export default TabPanel;
|
||||
10
packages/components/tabs/src/tabs-context.ts
Normal file
10
packages/components/tabs/src/tabs-context.ts
Normal file
@ -0,0 +1,10 @@
|
||||
import {createContext} from "@nextui-org/shared-utils";
|
||||
|
||||
import {ContextType} from "./use-tabs";
|
||||
|
||||
export const [TabsProvider, useTabsContext] = createContext<ContextType>({
|
||||
name: "TabsContext",
|
||||
strict: true,
|
||||
errorMessage:
|
||||
"useTabsContext: `context` is undefined. Seems you forgot to wrap component within <Tabs />",
|
||||
});
|
||||
32
packages/components/tabs/src/tabs.tsx
Normal file
32
packages/components/tabs/src/tabs.tsx
Normal file
@ -0,0 +1,32 @@
|
||||
import {forwardRef} from "@nextui-org/system";
|
||||
import {AriaTabProps} from "@react-aria/tabs";
|
||||
|
||||
import {TabsProvider} from "./tabs-context";
|
||||
import {UseTabsProps, useTabs} from "./use-tabs";
|
||||
import TabItem from "./tab-item";
|
||||
import TabPanel from "./tab-panel";
|
||||
|
||||
interface Props extends Omit<UseTabsProps, "ref"> {}
|
||||
|
||||
export type TabsProps = Props & AriaTabProps;
|
||||
|
||||
const Tabs = forwardRef<TabsProps, "div">((props, ref) => {
|
||||
const {Component, state, context, getBaseProps, getTabListProps} = useTabs({ref, ...props});
|
||||
|
||||
return (
|
||||
<TabsProvider value={context}>
|
||||
<div {...getBaseProps()}>
|
||||
<Component {...getTabListProps()}>
|
||||
{[...state.collection].map((item) => (
|
||||
<TabItem key={item.key} item={item} {...item.props} />
|
||||
))}
|
||||
</Component>
|
||||
</div>
|
||||
<TabPanel key={state.selectedItem?.key} />
|
||||
</TabsProvider>
|
||||
);
|
||||
});
|
||||
|
||||
Tabs.displayName = "NextUI.Tabs";
|
||||
|
||||
export default Tabs;
|
||||
100
packages/components/tabs/src/use-tabs.ts
Normal file
100
packages/components/tabs/src/use-tabs.ts
Normal file
@ -0,0 +1,100 @@
|
||||
import type {TabsVariantProps, SlotsToClasses, TabsSlots, TabsReturnType} from "@nextui-org/theme";
|
||||
|
||||
import {HTMLNextUIProps, mapPropsVariants, PropGetter} from "@nextui-org/system";
|
||||
import {tabs} from "@nextui-org/theme";
|
||||
import {useDOMRef} from "@nextui-org/dom-utils";
|
||||
import {clsx, ReactRef} from "@nextui-org/shared-utils";
|
||||
import {useMemo, ReactNode, useId} from "react";
|
||||
import {TabListState, TabListStateOptions, useTabListState} from "@react-stately/tabs";
|
||||
import {AriaTabListOptions, useTabList} from "@react-aria/tabs";
|
||||
import {filterDOMProps, mergeProps} from "@react-aria/utils";
|
||||
|
||||
export interface Props extends HTMLNextUIProps<"div"> {
|
||||
/**
|
||||
* Ref to the DOM node.
|
||||
*/
|
||||
ref?: ReactRef<HTMLElement | null>;
|
||||
/*
|
||||
* The list of `TabItem` elements.
|
||||
*/
|
||||
children?: ReactNode | ReactNode[];
|
||||
/**
|
||||
* Classname or List of classes to change the classNames of the element.
|
||||
* if `className` is passed, it will be added to the base slot.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* <Tabs classNames={{
|
||||
* base:"base-classes", // table wrapper
|
||||
* tab: "tab-classes", // tab item
|
||||
* panel: "panel-classes", // tab panel
|
||||
* }} />
|
||||
* ``
|
||||
*/
|
||||
classNames?: SlotsToClasses<TabsSlots>;
|
||||
}
|
||||
|
||||
export type UseTabsProps<T = object> = Props &
|
||||
TabsVariantProps &
|
||||
TabListStateOptions<T> &
|
||||
AriaTabListOptions<T>;
|
||||
|
||||
export type ContextType<T = object> = {
|
||||
state: TabListState<T>;
|
||||
slots: TabsReturnType;
|
||||
tabPanelId: string;
|
||||
classNames?: SlotsToClasses<TabsSlots>;
|
||||
};
|
||||
|
||||
export function useTabs<T extends object>(originalProps: UseTabsProps<T>) {
|
||||
const [props, variantProps] = mapPropsVariants(originalProps, tabs.variantKeys);
|
||||
|
||||
const {ref, as, className, classNames, ...otherProps} = props;
|
||||
|
||||
const Component = as || "div";
|
||||
|
||||
const domRef = useDOMRef(ref);
|
||||
|
||||
const state = useTabListState(otherProps);
|
||||
const {tabListProps} = useTabList(otherProps, state, domRef);
|
||||
|
||||
const tabListId = useId();
|
||||
const tabPanelId = useId();
|
||||
|
||||
const slots = useMemo(
|
||||
() =>
|
||||
tabs({
|
||||
...variantProps,
|
||||
className,
|
||||
}),
|
||||
[...Object.values(variantProps), className],
|
||||
);
|
||||
|
||||
const tabListStyles = clsx(className, classNames?.tabList);
|
||||
|
||||
const context = useMemo<ContextType<T>>(
|
||||
() => ({
|
||||
state,
|
||||
slots,
|
||||
tabPanelId,
|
||||
classNames,
|
||||
}),
|
||||
[state, slots, tabPanelId, classNames],
|
||||
);
|
||||
|
||||
const getBaseProps: PropGetter = (props) => ({
|
||||
className: slots.base({class: clsx(classNames?.base, props?.className)}),
|
||||
...mergeProps(filterDOMProps(otherProps, {labelable: true}), props),
|
||||
});
|
||||
|
||||
const getTabListProps: PropGetter = (props) => ({
|
||||
ref: domRef,
|
||||
className: slots.tabList({class: clsx(tabListStyles, props?.className)}),
|
||||
...mergeProps(tabListProps, props),
|
||||
id: tabListId,
|
||||
});
|
||||
|
||||
return {Component, state, context, getBaseProps, getTabListProps};
|
||||
}
|
||||
|
||||
export type UseTabsReturn = ReturnType<typeof useTabs>;
|
||||
65
packages/components/tabs/stories/tabs.stories.tsx
Normal file
65
packages/components/tabs/stories/tabs.stories.tsx
Normal file
@ -0,0 +1,65 @@
|
||||
import React from "react";
|
||||
import {ComponentStory, ComponentMeta} from "@storybook/react";
|
||||
import {tabs} from "@nextui-org/theme";
|
||||
import Lorem from "react-lorem-component";
|
||||
|
||||
import {Tabs, TabItem, TabsProps} from "../src";
|
||||
|
||||
export default {
|
||||
title: "Components/Tabs",
|
||||
component: Tabs,
|
||||
argTypes: {
|
||||
color: {
|
||||
control: {
|
||||
type: "select",
|
||||
options: ["neutral", "primary", "secondary", "success", "warning", "danger"],
|
||||
},
|
||||
},
|
||||
radius: {
|
||||
control: {
|
||||
type: "select",
|
||||
options: ["none", "base", "sm", "md", "lg", "xl", "full"],
|
||||
},
|
||||
},
|
||||
size: {
|
||||
control: {
|
||||
type: "select",
|
||||
options: ["xs", "sm", "md", "lg", "xl"],
|
||||
},
|
||||
},
|
||||
isDisabled: {
|
||||
control: {
|
||||
type: "boolean",
|
||||
},
|
||||
},
|
||||
},
|
||||
} as ComponentMeta<typeof Tabs>;
|
||||
|
||||
const defaultProps = {
|
||||
...tabs.defaultVariants,
|
||||
};
|
||||
|
||||
const Template: ComponentStory<typeof Tabs> = (args: TabsProps) => (
|
||||
<Tabs aria-label="Tabs example" {...args}>
|
||||
<TabItem key="world" title="World">
|
||||
<Lorem count={1} sentenceUpperBound={20} />
|
||||
</TabItem>
|
||||
<TabItem key="ny" title="N.Y">
|
||||
<Lorem count={1} sentenceUpperBound={30} />
|
||||
</TabItem>
|
||||
<TabItem key="business" title="Business">
|
||||
<Lorem count={1} sentenceUpperBound={10} />
|
||||
</TabItem>
|
||||
<TabItem key="arts" title="Arts">
|
||||
<Lorem count={1} sentenceUpperBound={50} />
|
||||
</TabItem>
|
||||
<TabItem key="science" title="Science">
|
||||
<Lorem count={1} sentenceUpperBound={24} />
|
||||
</TabItem>
|
||||
</Tabs>
|
||||
);
|
||||
|
||||
export const Default = Template.bind({});
|
||||
Default.args = {
|
||||
...defaultProps,
|
||||
};
|
||||
10
packages/components/tabs/tsconfig.json
Normal file
10
packages/components/tabs/tsconfig.json
Normal file
@ -0,0 +1,10 @@
|
||||
{
|
||||
"extends": "../../../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"tailwind-variants": ["../../../node_modules/tailwind-variants"]
|
||||
}
|
||||
},
|
||||
"include": ["src", "index.ts"]
|
||||
}
|
||||
@ -68,7 +68,8 @@
|
||||
"@nextui-org/table": "workspace:*",
|
||||
"@nextui-org/spacer": "workspace:*",
|
||||
"@nextui-org/divider": "workspace:*",
|
||||
"@nextui-org/kbd": "workspace:*"
|
||||
"@nextui-org/kbd": "workspace:*",
|
||||
"@nextui-org/tabs": "workspace:*"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"react": ">=18",
|
||||
|
||||
@ -28,3 +28,4 @@ export * from "@nextui-org/table";
|
||||
export * from "@nextui-org/spacer";
|
||||
export * from "@nextui-org/divider";
|
||||
export * from "@nextui-org/kbd";
|
||||
export * from "@nextui-org/tabs";
|
||||
|
||||
@ -89,7 +89,6 @@ const button = tv({
|
||||
isDisabled: {
|
||||
true: "opacity-50 pointer-events-none",
|
||||
},
|
||||
|
||||
isInGroup: {
|
||||
true: "[&:not(:first-child):not(:last-child)]:rounded-none",
|
||||
},
|
||||
|
||||
@ -163,7 +163,17 @@ const card = tv({
|
||||
},
|
||||
isFooterBlurred: {
|
||||
true: {
|
||||
footer: "bg-background/10 backdrop-blur backdrop-saturate-150",
|
||||
footer: [
|
||||
"before:content-['']",
|
||||
"before:block",
|
||||
"before:z-[-1]",
|
||||
"before:absolute",
|
||||
"before:-top-px",
|
||||
"before:inset-0",
|
||||
"before:bg-background/10",
|
||||
"before:backdrop-blur",
|
||||
"before:backdrop-saturate-150",
|
||||
],
|
||||
},
|
||||
},
|
||||
isDisabled: {
|
||||
|
||||
@ -34,3 +34,4 @@ export * from "./table";
|
||||
export * from "./spacer";
|
||||
export * from "./divider";
|
||||
export * from "./kbd";
|
||||
export * from "./tabs";
|
||||
|
||||
177
packages/core/theme/src/components/tabs.ts
Normal file
177
packages/core/theme/src/components/tabs.ts
Normal file
@ -0,0 +1,177 @@
|
||||
import type {VariantProps} from "tailwind-variants";
|
||||
|
||||
import {tv} from "tailwind-variants";
|
||||
|
||||
import {colorVariants} from "../utils";
|
||||
|
||||
/**
|
||||
* Tabs wrapper **Tailwind Variants** component
|
||||
*
|
||||
* @example
|
||||
* ```js
|
||||
* const {base, tabList, tab, panel} = tabs({...})
|
||||
*
|
||||
* <div className={base())}>
|
||||
* <div className={tabList())}>
|
||||
* <div className={tab())}>Tab 1</div>
|
||||
* <div className={tab())}>Tab 2</div>
|
||||
* <div className={tab())}>Tab 3</div>
|
||||
* </div>
|
||||
* <div className={panel())}>Selected panel</div>
|
||||
* </div>
|
||||
* ```
|
||||
*/
|
||||
const tabs = tv({
|
||||
slots: {
|
||||
base: "inline-block",
|
||||
tabList: ["flex", "items-center", "gap-2", "bg-neutral-100", "p-1"],
|
||||
tab: [
|
||||
"z-0",
|
||||
"w-full",
|
||||
"px-3",
|
||||
"py-1",
|
||||
"flex",
|
||||
"group",
|
||||
"relative",
|
||||
"justify-center",
|
||||
"items-center",
|
||||
"outline-none",
|
||||
"cursor-pointer",
|
||||
"transition-opacity",
|
||||
"text-neutral-600",
|
||||
"data-[selected=true]:text-foreground",
|
||||
"data-[hover-unselected=true]:opacity-70",
|
||||
// focus ring
|
||||
"data-[focus-visible=true]:outline-none",
|
||||
"data-[focus-visible=true]:ring-2",
|
||||
"data-[focus-visible=true]:ring-primary",
|
||||
"data-[focus-visible=true]:ring-offset-2",
|
||||
"data-[focus-visible=true]:ring-offset-background",
|
||||
"data-[focus-visible=true]:dark:ring-offset-background-dark",
|
||||
],
|
||||
tabContent: ["relative", "z-10"],
|
||||
cursor: ["absolute", "inset-0", "z-0", "bg-white", "shadow-md"],
|
||||
panel: ["mt-3"],
|
||||
},
|
||||
variants: {
|
||||
color: {
|
||||
neutral: {
|
||||
cursor: ["bg-background", "dark:bg-neutral"],
|
||||
tabContent: "group-data-[selected=true]:text-neutral-foreground",
|
||||
},
|
||||
primary: {
|
||||
cursor: colorVariants.solid.primary,
|
||||
tabContent: "group-data-[selected=true]:text-primary-foreground",
|
||||
},
|
||||
secondary: {
|
||||
cursor: colorVariants.solid.secondary,
|
||||
tabContent: "group-data-[selected=true]:text-secondary-foreground",
|
||||
},
|
||||
success: {
|
||||
cursor: colorVariants.solid.success,
|
||||
tabContent: "group-data-[selected=true]:text-success-foreground",
|
||||
},
|
||||
warning: {
|
||||
cursor: colorVariants.solid.warning,
|
||||
tabContent: "group-data-[selected=true]:text-warning-foreground",
|
||||
},
|
||||
danger: {
|
||||
cursor: colorVariants.solid.danger,
|
||||
tabContent: "group-data-[selected=true]:text-danger-foreground",
|
||||
},
|
||||
},
|
||||
size: {
|
||||
xs: {
|
||||
tabContent: "text-xs",
|
||||
tab: "h-7",
|
||||
},
|
||||
sm: {
|
||||
tabContent: "text-sm",
|
||||
tab: "h-8",
|
||||
},
|
||||
md: {
|
||||
tabContent: "text-sm",
|
||||
tab: "h-9",
|
||||
},
|
||||
lg: {
|
||||
tabContent: "text-base",
|
||||
tab: "h-10",
|
||||
},
|
||||
xl: {
|
||||
tabContent: "text-base",
|
||||
tab: "h-11",
|
||||
},
|
||||
},
|
||||
radius: {
|
||||
none: {
|
||||
tabList: "rounded-none",
|
||||
tab: "rounded-none",
|
||||
cursor: "rounded-none",
|
||||
},
|
||||
base: {
|
||||
tabList: "rounded",
|
||||
tab: "rounded",
|
||||
cursor: "rounded",
|
||||
},
|
||||
sm: {
|
||||
tabList: "rounded-sm",
|
||||
tab: "rounded-sm",
|
||||
cursor: "rounded-sm",
|
||||
},
|
||||
md: {
|
||||
tabList: "rounded-md",
|
||||
tab: "rounded-md",
|
||||
cursor: "rounded-md",
|
||||
},
|
||||
lg: {
|
||||
tabList: "rounded-lg",
|
||||
tab: "rounded-lg",
|
||||
cursor: "rounded-lg",
|
||||
},
|
||||
xl: {
|
||||
tabList: "rounded-xl",
|
||||
tab: "rounded-xl",
|
||||
cursor: "rounded-xl",
|
||||
},
|
||||
"2xl": {
|
||||
tabList: "rounded-2xl",
|
||||
tab: "rounded-2xl",
|
||||
cursor: "rounded-2xl",
|
||||
},
|
||||
"3xl": {
|
||||
tabList: "rounded-3xl",
|
||||
tab: "rounded-3xl",
|
||||
cursor: "rounded-3xl",
|
||||
},
|
||||
full: {
|
||||
tabList: "rounded-full",
|
||||
tab: "rounded-full",
|
||||
cursor: "rounded-full",
|
||||
},
|
||||
},
|
||||
fullWidth: {
|
||||
true: {
|
||||
base: "w-full",
|
||||
tabList: "w-full",
|
||||
},
|
||||
},
|
||||
isDisabled: {
|
||||
true: {
|
||||
tabList: "opacity-50 pointer-events-none",
|
||||
},
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
radius: "lg",
|
||||
color: "neutral",
|
||||
size: "md",
|
||||
fullWidth: false,
|
||||
isDisabled: false,
|
||||
},
|
||||
});
|
||||
|
||||
export type TabsVariantProps = VariantProps<typeof tabs>;
|
||||
export type TabsSlots = keyof ReturnType<typeof tabs>;
|
||||
export type TabsReturnType = ReturnType<typeof tabs>;
|
||||
|
||||
export {tabs};
|
||||
113
pnpm-lock.yaml
generated
113
pnpm-lock.yaml
generated
@ -275,6 +275,9 @@ importers:
|
||||
'@nextui-org/shared-icons':
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/utilities/shared-icons
|
||||
'@nextui-org/shared-utils':
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/utilities/shared-utils
|
||||
'@nextui-org/theme':
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/core/theme
|
||||
@ -1494,6 +1497,61 @@ importers:
|
||||
specifier: ^18.2.0
|
||||
version: 18.2.0
|
||||
|
||||
packages/components/tabs:
|
||||
dependencies:
|
||||
'@nextui-org/aria-utils':
|
||||
specifier: workspace:*
|
||||
version: link:../../utilities/aria-utils
|
||||
'@nextui-org/dom-utils':
|
||||
specifier: workspace:*
|
||||
version: link:../../utilities/dom-utils
|
||||
'@nextui-org/framer-transitions':
|
||||
specifier: workspace:*
|
||||
version: link:../../utilities/framer-transitions
|
||||
'@nextui-org/shared-utils':
|
||||
specifier: workspace:*
|
||||
version: link:../../utilities/shared-utils
|
||||
'@nextui-org/system':
|
||||
specifier: workspace:*
|
||||
version: link:../../core/system
|
||||
'@nextui-org/theme':
|
||||
specifier: workspace:*
|
||||
version: link:../../core/theme
|
||||
'@react-aria/focus':
|
||||
specifier: ^3.12.0
|
||||
version: 3.12.0(react@18.2.0)
|
||||
'@react-aria/interactions':
|
||||
specifier: ^3.15.0
|
||||
version: 3.15.0(react@18.2.0)
|
||||
'@react-aria/tabs':
|
||||
specifier: ^3.5.0
|
||||
version: 3.5.0(react@18.2.0)
|
||||
'@react-aria/utils':
|
||||
specifier: ^3.16.0
|
||||
version: 3.16.0(react@18.2.0)
|
||||
'@react-stately/tabs':
|
||||
specifier: ^3.4.0
|
||||
version: 3.4.0(react@18.2.0)
|
||||
devDependencies:
|
||||
'@react-types/shared':
|
||||
specifier: ^3.18.0
|
||||
version: 3.18.0(react@18.2.0)
|
||||
'@react-types/tabs':
|
||||
specifier: ^3.2.1
|
||||
version: 3.2.1(react@18.2.0)
|
||||
clean-package:
|
||||
specifier: 2.2.0
|
||||
version: 2.2.0
|
||||
framer-motion:
|
||||
specifier: ^10.11.2
|
||||
version: 10.11.2(react-dom@18.2.0)(react@18.2.0)
|
||||
react:
|
||||
specifier: ^18.2.0
|
||||
version: 18.2.0
|
||||
react-lorem-component:
|
||||
specifier: 0.13.0
|
||||
version: 0.13.0(react@18.2.0)
|
||||
|
||||
packages/components/tooltip:
|
||||
dependencies:
|
||||
'@nextui-org/aria-utils':
|
||||
@ -1666,6 +1724,9 @@ importers:
|
||||
'@nextui-org/table':
|
||||
specifier: workspace:*
|
||||
version: link:../../components/table
|
||||
'@nextui-org/tabs':
|
||||
specifier: workspace:*
|
||||
version: link:../../components/tabs
|
||||
'@nextui-org/theme':
|
||||
specifier: workspace:*
|
||||
version: link:../theme
|
||||
@ -6252,6 +6313,24 @@ packages:
|
||||
react-dom: 18.2.0(react@18.2.0)
|
||||
dev: false
|
||||
|
||||
/@react-aria/tabs@3.5.0(react@18.2.0):
|
||||
resolution: {integrity: sha512-QnCoNHDmeRoPWLHsr1Q81RN/KymwU79XS/zHguhZ3fx59je9bswUDG77NjylcPRXoOEOZ18gZ+Y7reBVRhNEog==}
|
||||
peerDependencies:
|
||||
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0
|
||||
dependencies:
|
||||
'@react-aria/focus': 3.12.0(react@18.2.0)
|
||||
'@react-aria/i18n': 3.7.1(react@18.2.0)
|
||||
'@react-aria/interactions': 3.15.0(react@18.2.0)
|
||||
'@react-aria/selection': 3.14.0(react@18.2.0)
|
||||
'@react-aria/utils': 3.16.0(react@18.2.0)
|
||||
'@react-stately/list': 3.8.0(react@18.2.0)
|
||||
'@react-stately/tabs': 3.4.0(react@18.2.0)
|
||||
'@react-types/shared': 3.18.0(react@18.2.0)
|
||||
'@react-types/tabs': 3.2.1(react@18.2.0)
|
||||
'@swc/helpers': 0.4.14
|
||||
react: 18.2.0
|
||||
dev: false
|
||||
|
||||
/@react-aria/toggle@3.6.0(react@18.2.0):
|
||||
resolution: {integrity: sha512-W6xncx5zzqCaPU2XsgjWnACHL3WBpxphYLvF5XlICRg0nZVjGPIWPDDUGyDoPsSUeGMW2vxtFY6erKXtcy4Kgw==}
|
||||
peerDependencies:
|
||||
@ -6383,6 +6462,19 @@ packages:
|
||||
react: 18.2.0
|
||||
dev: false
|
||||
|
||||
/@react-stately/list@3.8.0(react@18.2.0):
|
||||
resolution: {integrity: sha512-eJ1iUFnXPZi5MGW2h/RdNTrKtq4HLoAlFAQbC4eSPlET6VDeFsX9NkKhE/A111ia24DnWCqJB5zH20EvNbOxxA==}
|
||||
peerDependencies:
|
||||
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0
|
||||
dependencies:
|
||||
'@react-stately/collections': 3.7.0(react@18.2.0)
|
||||
'@react-stately/selection': 3.13.0(react@18.2.0)
|
||||
'@react-stately/utils': 3.6.0(react@18.2.0)
|
||||
'@react-types/shared': 3.18.0(react@18.2.0)
|
||||
'@swc/helpers': 0.4.14
|
||||
react: 18.2.0
|
||||
dev: false
|
||||
|
||||
/@react-stately/menu@3.5.1(react@18.2.0):
|
||||
resolution: {integrity: sha512-nnuZlDBFIc3gB34kofbKDStFg9r8rijY+7ez2VWQmss72I9D7+JTn7OXJxV0oQt2lBYmNfS5W6bC9uXk3Z4dLg==}
|
||||
peerDependencies:
|
||||
@ -6446,6 +6538,19 @@ packages:
|
||||
react: 18.2.0
|
||||
dev: false
|
||||
|
||||
/@react-stately/tabs@3.4.0(react@18.2.0):
|
||||
resolution: {integrity: sha512-GeU0cykAEsyTf2tWC7JZqqLrgxPT1WriCmu9QAswJ7Dev1PkPvwDy3CEhJ3QDklTlhiLXLZOooyHh37lZTjRdg==}
|
||||
peerDependencies:
|
||||
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0
|
||||
dependencies:
|
||||
'@react-stately/list': 3.8.0(react@18.2.0)
|
||||
'@react-stately/utils': 3.6.0(react@18.2.0)
|
||||
'@react-types/shared': 3.18.0(react@18.2.0)
|
||||
'@react-types/tabs': 3.2.1(react@18.2.0)
|
||||
'@swc/helpers': 0.4.14
|
||||
react: 18.2.0
|
||||
dev: false
|
||||
|
||||
/@react-stately/toggle@3.5.1(react@18.2.0):
|
||||
resolution: {integrity: sha512-PF4ZaATpXWu7DkneGSZ2/PA6LJ1MrhKNiaENTZlbojXMRr5kK33wPzaDW7I8O25IUm0+rvQicv7A6QkEOxgOPg==}
|
||||
peerDependencies:
|
||||
@ -6631,6 +6736,14 @@ packages:
|
||||
'@react-types/shared': 3.18.0(react@18.2.0)
|
||||
react: 18.2.0
|
||||
|
||||
/@react-types/tabs@3.2.1(react@18.2.0):
|
||||
resolution: {integrity: sha512-KgvhrYvISQUq540iuNc3bRvOCfLvaeqpB5VwDYR8amG1FVWHklCW8xx8Uz63SVkOvNtExYCrlw63M/OnjRUzOw==}
|
||||
peerDependencies:
|
||||
react: ^16.8.0 || ^17.0.0-rc.1 || ^18.0.0
|
||||
dependencies:
|
||||
'@react-types/shared': 3.18.0(react@18.2.0)
|
||||
react: 18.2.0
|
||||
|
||||
/@react-types/textfield@3.7.1(react@18.2.0):
|
||||
resolution: {integrity: sha512-6V5+6/VgDbmgN61pyVct1VrXb2hqq7Y43BFQ+/ZhFDlVaMpC5xKWKgW/gPbGLLc27gax8t2Brt7VHJj+d+yrUw==}
|
||||
peerDependencies:
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user