Feat/select component (#1313)

* chore(root): menu and select components in progress

* chore(root): merged with main

* feat(menu): stories created

* feat(dropdown): menu migrated to menu component

* feat(select): base implementation in progress

* feat(select): listbox implemented

* feat(select): scroll overflow and auto scroll added

* feat(select): colors & variants improved, inside placement complete, outside pending

* feat(scroll-shadow): new component in progress

* feat(select): scroll shadow integrated

* fix(select): popover implementation, more scroll shadow stories added

* feat(listbox): custom styles example added to stories

* chore(listbox): overflow hidden removed

* feat(select): variants and styles completed

* chore(select): description story added

* feat(select): more stories added

* fix(select): dynamic collections inference, styles improved, more stories added

* fix(select): auto scroll to selected item, scroll padding added

* chore(select): scroll behavior changed to nearest

* feat(select): custom item story added

* fix(select): autoscroll fixed

* feat(select): multi select support added

* feat(select): more examples added, clean-package modified to remove dev packages

* chore(modal): useImperativeHandle removed

* feat(select): render value story improved

* feat(docs): listbox & scroll shadow docs done

* feat(docs): select documentation in progress

* fix: select aria label (#1425)

* feat(docs): more examples added

* feat(docs): select multiple added, storybook favicon changed

* fix: added value to aria label of select (#1431)

* feat(select): more examples added, storybook favicon changed

* fix(popover): dialog role removed

* feat(select): api added, async loading exampled added

* fix: fixed list box on click not working with sr click (#1439)

* feat(select): async items loading support added and documented

* feat(root): input styles updated to be as the select ones

* chore(root): listbox and scroll shadow readme updated

* feat(select): ts examples added, banner updated

* fix(popover): voiceover closes when focusing an item fixed

* chore(select): focus scope removed

* fix(popover): free solo popover added to use without a trigger

* feat(select): blog post added

* chore(docs): search meta generated, multi controlled onchange example fixed

* chore(root): changeset added

---------

Co-authored-by: Jakob Guddas <github@jguddas.de>
This commit is contained in:
Junior Garcia 2023-08-21 09:28:01 -03:00 committed by GitHub
parent ea2868e58e
commit baec55029d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
215 changed files with 15770 additions and 1783 deletions

View File

@ -0,0 +1,26 @@
---
"@nextui-org/use-data-scroll-overflow": minor
"@nextui-org/use-aria-multiselect": minor
"@nextui-org/use-infinite-scroll": minor
"@nextui-org/scroll-shadow": minor
"@nextui-org/dropdown": minor
"@nextui-org/listbox": minor
"@nextui-org/popover": minor
"@nextui-org/select": minor
"@nextui-org/input": minor
"@nextui-org/react": minor
"@nextui-org/theme": minor
"@nextui-org/react-rsc-utils": patch
"@nextui-org/shared-icons": patch
"@nextui-org/accordion": patch
"@nextui-org/snippet": patch
"@nextui-org/modal": patch
"@nextui-org/menu": patch
"@nextui-org/tabs": patch
---
New components:
- Select
- Listbox
- ScrollShadow

View File

@ -0,0 +1,113 @@
/* eslint-disable no-console */
"use client";
import {Select, SelectItem} from "@nextui-org/react";
import {useEffect, useState} from "react";
import {useInfiniteScroll} from "@nextui-org/use-infinite-scroll";
type Pokemon = {
name: string;
url: string;
};
type UsePokemonListProps = {
/** Delay to wait before fetching more items */
fetchDelay?: number;
};
function usePokemonList({fetchDelay = 0}: UsePokemonListProps = {}) {
const [items, setItems] = useState<Pokemon[]>([]);
const [hasMore, setHasMore] = useState(true);
const [isLoading, setIsLoading] = useState(false);
const [offset, setOffset] = useState(0);
const limit = 10; // Number of items per page, adjust as necessary
const loadPokemon = async (currentOffset: number) => {
const controller = new AbortController();
const {signal} = controller;
try {
setIsLoading(true);
if (offset > 0) {
// Delay to simulate network latency
await new Promise((resolve) => setTimeout(resolve, fetchDelay));
}
let res = await fetch(
`https://pokeapi.co/api/v2/pokemon?offset=${currentOffset}&limit=${limit}`,
{signal},
);
if (!res.ok) {
throw new Error("Network response was not ok");
}
let json = await res.json();
setHasMore(json.next !== null);
// Append new results to existing ones
setItems((prevItems) => [...prevItems, ...json.results]);
} catch (error) {
// @ts-ignore
if (error.name === "AbortError") {
console.log("Fetch aborted");
} else {
console.error("There was an error with the fetch operation:", error);
}
} finally {
setIsLoading(false);
}
};
useEffect(() => {
loadPokemon(offset);
}, []);
const onLoadMore = () => {
const newOffset = offset + limit;
setOffset(newOffset);
loadPokemon(newOffset);
};
return {
items,
hasMore,
isLoading,
onLoadMore,
};
}
export default function Page() {
const [isOpen, setIsOpen] = useState(false);
const {items, hasMore, isLoading, onLoadMore} = usePokemonList({fetchDelay: 1500});
const [, scrollerRef] = useInfiniteScroll({
hasMore,
isEnabled: isOpen,
shouldUseLoader: false, // We don't want to show the loader at the bottom of the list
onLoadMore,
});
return (
<div className="p-6">
<Select
className="max-w-xs"
isLoading={isLoading}
items={items}
label="Pick a Pokemon"
placeholder="Select a Pokemon"
scrollRef={scrollerRef}
selectionMode="single"
onOpenChange={setIsOpen}
>
{(item) => (
<SelectItem key={item.name} className="capitalize">
{item.name}
</SelectItem>
)}
</Select>
</div>
);
}

View File

@ -105,7 +105,7 @@ const users = [
email: "kristen.cooper@example.com",
},
{
key: 6,
id: 6,
name: "Brian Kim",
role: "P. Manager",
team: "Management",

View File

@ -105,7 +105,7 @@ const users = [
email: "kristen.cooper@example.com",
},
{
key: 6,
id: 6,
name: "Brian Kim",
role: "P. Manager",
team: "Management",

View File

@ -15,7 +15,7 @@ const BlogPostCard = (post: BlogPost) => {
return (
<AnimatePresence>
{isMounted && (
<motion.div
<motion.article
animate={{opacity: 1, y: 0}}
exit={{opacity: 0, y: 5}}
initial={{opacity: 0, y: 5}}
@ -24,7 +24,7 @@ const BlogPostCard = (post: BlogPost) => {
<Card
isBlurred
as={NextLink}
className="p-2 border-transparent text-start bg-white/5 dark:bg-default-400/10 backdrop-blur-lg backdrop-saturate-[1.8]"
className="p-2 h-full border-transparent text-start bg-white/5 dark:bg-default-400/10 backdrop-blur-lg backdrop-saturate-[1.8]"
href={post.url}
isPressable={!!post.url}
>
@ -40,8 +40,8 @@ const BlogPostCard = (post: BlogPost) => {
</Link>
</CardHeader>
<CardBody className="pt-0 px-2 pb-1">
<Image className="mb-3" src={post.image} />
<p className="font-normal px-1 text-default-600">{post.description}</p>
<Image className="mb-4" src={post.image} />
<p className="font-normal w-full text-default-600">{post.description}</p>
</CardBody>
<CardFooter className="flex justify-between items-center">
<time className="block text-small text-default-500" dateTime={post.date}>
@ -50,7 +50,7 @@ const BlogPostCard = (post: BlogPost) => {
<Avatar size="sm" src={post.author?.avatar} />
</CardFooter>
</Card>
</motion.div>
</motion.article>
)}
</AnimatePresence>
);
@ -58,7 +58,7 @@ const BlogPostCard = (post: BlogPost) => {
export const BlogPostList = ({posts}: {posts: BlogPost[]}) => {
return (
<div className="mt-10 grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
<div className="mt-10 grid gap-4 grid-cols-[repeat(auto-fill,minmax(300px,1fr))]">
{posts.map((post, idx) => (
<BlogPostCard key={idx} {...post} />
))}

View File

@ -33,9 +33,11 @@ interface CodeDemoProps extends UseCodeDemoProps, WindowResizerProps {
enableResize?: boolean;
showTabs?: boolean;
showPreview?: boolean;
hideWindowActions?: boolean;
showOpenInCodeSandbox?: boolean;
isPreviewCentered?: boolean;
resizeEnabled?: boolean;
typescriptStrict?: boolean;
displayMode?: "always" | "visible";
isGradientBox?: boolean;
gradientColor?: GradientBoxProps["color"];
@ -52,8 +54,11 @@ export const CodeDemo: React.FC<CodeDemoProps> = ({
showPreview = true,
asIframe = false,
resizeEnabled = true,
hideWindowActions = false,
showSandpackPreview = false,
isPreviewCentered = false,
// when false .js files will be used
typescriptStrict = false,
showOpenInCodeSandbox,
isGradientBox = false,
defaultExpanded = false,
@ -96,6 +101,7 @@ export const CodeDemo: React.FC<CodeDemoProps> = ({
const content = asIframe ? (
<WindowResizer
hideWindowActions={hideWindowActions}
iframeHeight={previewHeight}
iframeInitialWidth={iframeInitialWidth}
iframeSrc={iframeSrc}
@ -121,6 +127,7 @@ export const CodeDemo: React.FC<CodeDemoProps> = ({
isGradientBox,
gradientColor,
previewHeight,
hideWindowActions,
asIframe,
showPreview,
isInView,
@ -138,6 +145,7 @@ export const CodeDemo: React.FC<CodeDemoProps> = ({
showEditor={showEditor}
showOpenInCodeSandbox={showOpenInCodeSandbox || showPreview}
showPreview={showSandpackPreview}
typescriptStrict={typescriptStrict}
/>
);

View File

@ -49,6 +49,7 @@ const resizer = tv({
export interface WindowResizerProps {
resizeEnabled?: boolean;
hideWindowActions?: boolean;
iframeHeight?: string | number;
iframeMinWidth?: number;
iframeSrc?: string;
@ -70,6 +71,7 @@ const WindowResizer: React.FC<WindowResizerProps> = (props) => {
iframeSrc,
iframeTitle,
resizeEnabled,
hideWindowActions = false,
iframeHeight: height = "420px",
iframeInitialWidth,
iframeMinWidth: minWidth = MIN_WIDTH,
@ -120,7 +122,7 @@ const WindowResizer: React.FC<WindowResizerProps> = (props) => {
width: isMobile ? "100%" : browserWidth,
}}
>
<WindowActions className="bg-default-100 dark:bg-default-50" />
{!hideWindowActions && <WindowActions className="bg-default-100 dark:bg-default-50" />}
<motion.iframe ref={iframeRef} className={iframe()} src={iframeSrc} title={iframeTitle} />
</motion.div>
{resizeEnabled && (

View File

@ -223,10 +223,13 @@ export const Navbar: FC<NavbarProps> = ({children, routes, mobileRoutes = [], sl
as={NextLink}
className="hover:bg-default-100 border-default-200/80 dark:border-default-100/80 transition-colors cursor-pointer"
color="secondary"
href="/blog/nextui-v2"
href="/blog/v2.1.0"
variant="dot"
>
Introducing NextUI v2.0
New components v2.1.0&nbsp;
<span aria-label="party emoji" role="img">
🎉
</span>
</Chip>
</NavbarItem>
</ul>

View File

@ -26,6 +26,7 @@ export const Sandpack: FC<SandpackProps> = ({
files: filesProp,
template,
highlightedLines,
typescriptStrict = false,
showPreview = false,
showEditor = true,
defaultExpanded = false,
@ -41,6 +42,7 @@ export const Sandpack: FC<SandpackProps> = ({
useSandpack({
files: filesProp,
template,
typescriptStrict,
highlightedLines,
});

View File

@ -10,6 +10,7 @@ import {useLocalStorage} from "@/hooks/use-local-storage";
export interface UseSandpackProps {
files?: SandpackFiles;
typescriptStrict?: boolean;
template?: SandpackPredefinedTemplate;
highlightedLines?: HighlightedLines;
}
@ -19,6 +20,7 @@ const importAllReact = 'import * as React from "react";';
export const useSandpack = ({
files = {},
typescriptStrict = false,
template = "vite-react",
highlightedLines,
}: UseSandpackProps) => {
@ -57,6 +59,9 @@ export const useSandpack = ({
if (key.includes("App") && !key.includes(mimeType)) {
return acc;
}
if (typescriptStrict && key.includes("js")) {
return acc;
}
// @ts-ignore
acc[key] = files[key];
@ -76,6 +81,11 @@ export const useSandpack = ({
const aName = getFileName(a);
const bName = getFileName(b);
// if bName includes "App" should be first
if (bName.includes("App")) {
return 1;
}
if (aFile?.includes(bName)) {
return -1;
}

View File

@ -164,8 +164,7 @@
"key": "chip",
"title": "Chip",
"keywords": "chip, tag, label, small actionable entity",
"path": "/docs/components/chip.mdx",
"newPost": true
"path": "/docs/components/chip.mdx"
},
{
"key": "circular-progress",
@ -183,8 +182,7 @@
"key": "divider",
"title": "Divider",
"keywords": "divider, boundary, separator, section divider",
"path": "/docs/components/divider.mdx",
"newPost": true
"path": "/docs/components/divider.mdx"
},
{
"key": "dropdown",
@ -208,8 +206,7 @@
"key": "kbd",
"title": "Kbd",
"keywords": "keyboard input, shortcut, keys, user input display",
"path": "/docs/components/kbd.mdx",
"newPost": true
"path": "/docs/components/kbd.mdx"
},
{
"key": "link",
@ -217,6 +214,13 @@
"keywords": "link, navigation, href, web page connection",
"path": "/docs/components/link.mdx"
},
{
"key": "listbox",
"title": "Listbox",
"keywords": "listbox, selection, option list, multiple choice",
"path": "/docs/components/listbox.mdx",
"newPost": true
},
{
"key": "modal",
"title": "Modal",
@ -253,18 +257,30 @@
"keywords": "radio group, selection set, option selection, exclusive choices",
"path": "/docs/components/radio-group.mdx"
},
{
"key": "select",
"title": "Select",
"keywords": "select, selection, option list, multiple choice",
"path": "/docs/components/select.mdx",
"newPost": true
},
{
"key": "skeleton",
"title": "Skeleton",
"keywords": "skeleton, loading state, placeholder, content preview",
"path": "/docs/components/skeleton.mdx",
"newPost": true
"path": "/docs/components/skeleton.mdx"
},
{
"key": "snippet",
"title": "Snippet",
"keywords": "snippet, code block, programming, code example",
"path": "/docs/components/snippet.mdx",
"path": "/docs/components/snippet.mdx"
},
{
"key": "scroll-shadow",
"title": "Scroll Shadow",
"keywords": "scroll shadow, scroll indicator, scroll bar, scroll position",
"path": "/docs/components/scroll-shadow.mdx",
"newPost": true
},
{
@ -295,8 +311,7 @@
"key": "tabs",
"title": "Tabs",
"keywords": "tabs, section navigation, categorized content, tabbed interface",
"path": "/docs/components/tabs.mdx",
"newPost": true
"path": "/docs/components/tabs.mdx"
},
{
"key": "textarea",

File diff suppressed because it is too large Load Diff

View File

@ -310,3 +310,16 @@ file helps streamline the process of transforming design ideas into functioning
To start using **NextUI v2.0**, head over to our [installation guide](/docs/guide/installation).
We can't wait to see the amazing things you'll build with **NextUI v2.0**!
---
## Community
We're excited to see the community adopt NextUI, raise issues, and provide feedback.
Whether it's a feature request, bug report, or a project to showcase, please get involved!
<Community />
## Contributing
PR's on NextUI are always welcome, please see our [contribution guidelines](https://github.com/nextui-org/nextui/blob/main/CONTRIBUTING.MD) to learn how you can contribute to this project.

View File

@ -0,0 +1,167 @@
---
title: "New components v2.1.0 🎉"
description: "NextUI v2.1.0 is here with new components, Select, Listbox and ScrollShadow."
date: "2023-08-22"
image: "/blog/v2.1.0.jpg"
tags: ["nextui", "select", "listbox", "scroll-shadow", "multi-select"]
author:
name: "Junior Garcia"
username: "@jrgarciadev"
link: "https://twitter.com/jrgarciadev"
avatar: "/avatars/junior-garcia.jpeg"
---
import {selectContent} from "@/content/components/select";
import {listboxContent} from "@/content/components/listbox";
import {scrollShadowContent} from "@/content/components/scroll-shadow";
<img
src="/blog/v2.1.0.jpg"
width={700}
height={350}
alt="NextUI v2"
className="w-full border border-transparent dark:border-default-200/50 object-fit rounded-xl shadow-lg"
/>
We are thrilled to announce the latest update to NextUI, version **2.1.0**! This release introduces some game-changing
additions that many of you have eagerly been waiting for.
First on the list is the highly-anticipated **Select** component. Fully customizable and beautifully designed, supports both single and
multi-select modes and is accessible out of the box.
But that's not all. We're also rolling out two more incredible components **Listbox** and **ScrollShadow**. The new
**Listbox** allows you to make list manipulations more efficient and visually appealing. Meanwhile, the
**ScrollShadow** component adds an elegant shadow effect to scrollable areas, enhancing the UI aesthetics while
also improving usability.
## Select
Creating a select component that is both accessible and customizable is a challenging task. We've spent a lot of time
researching and testing different approaches to come up with a solution that works for everyone. The result is a
component that is easy to use, fully accessible, and highly customizable.
The new **Select** component includes:
- Support for selecting a single option.
- Support for selecting multiple options.
- Support for disabled options.
- Support for sections.
- Labeling support for accessibility.
- Exposed to assistive technology as a button with a listbox popup using ARIA (combined with [Listbox](/docs/components/listbox)).
- Support for description and error message help text linked to the input via ARIA.
- Support for mouse, touch, and keyboard interactions.
- Tab stop focus management.
- Asyncronous options loading.
- Keyboard support for opening the listbox using the arrow keys, including automatically focusing the first or last item accordingly.
- Typeahead to allow selecting options by typing text, even without opening the listbox.
- Browser autofill integration via a hidden native `<select>` element.
- Support for mobile form navigation via software keyboard.
- Mobile screen reader listbox dismissal support.
- And much more...
### Single Select
The single select component is used to select a single option from a list of options. It is a combination of a button
and a listbox. The button displays the currently selected option and the listbox displays the available options.
<CodeDemo title="Usage" files={selectContent.usage} />
### Multiple Select
The multiple select component can be used to select multiple options from a list of options.
You only need to pass the `selectionMode="multiple"` prop to the `Select` component.
<CodeDemo title="Multiple Selection" files={selectContent.multiple} />
### Multiple Variants
The select component comes with multiple variants.
<CodeDemo title="Variants" files={selectContent.variants} />
### Chips Support
The select component is flexible and allows you to render any component as an option and as a selected option.
<CodeDemo title="Multiple Selection with Chips" files={selectContent.multipleWithChips} />
### Customizable
The select component is highly customizable, you can customize the selected option, the options, the listbox,
the popover and the scrollable area.
<CodeDemo title="Custom Styles" files={selectContent.customStyles} />
Go to the [Select](/docs/components/select) component page to learn more about sizes, colors, and more.
## Listbox
The listbox component allows you to make list manipulations more efficient and visually appealing.
The new **Listbox** component includes:
- Support for single, multiple, or no selection.
- Exposed to assistive technology as a `listbox` using ARIA.
- Support for disabled items.
- Support for sections.
- Labeling support for accessibility.
- Support for mouse, touch, and keyboard interactions.
- Tab stop focus management.
- Keyboard navigation support including arrow keys, home/end, page up/down, select all, and clear.
- Automatic scrolling support during keyboard navigation.
- Typeahead to allow focusing options by typing text.
### Usage
<CodeDemo title="Usage" files={listboxContent.usage} />
### Custom Styles
The Listbox components offers multiple customization options.
<CodeDemo title="Custom Styles" files={listboxContent.customStyles} />
> **Note**: In the above example, we've utilized the [Boxicons](https://boxicons.com/) icons collection.
Go to the [Listbox](/docs/components/listbox) component page to learn more about it.
## ScrollShadow
The ScrollShadow component gives a nice shadow effect to scrollable areas. These shadows are handled by using
the CSS `mask-image` property, which makes the shadows adapt to the background color.
### Usage
<CodeDemo title="Usage" files={scrollShadowContent.usage} />
You can hide the scrollbars, customize the shadows size, change the orientation, and more.
Go to the [ScrollShadow](/docs/components/scroll-shadow) component page to learn more about it.
<Spacer y={6}/>
We hope you enjoy these new components and the new features. We're excited to see what you build with them!
Thanks for reading and happy coding! 🚀
---
## Community
We're excited to see the community adopt NextUI, raise issues, and provide feedback.
Whether it's a feature request, bug report, or a project to showcase, please get involved!
<Community />
## Contributing
PR's on NextUI are always welcome, please see our [contribution guidelines](https://github.com/nextui-org/nextui/blob/main/CONTRIBUTING.MD) to learn how you can contribute to this project.

View File

@ -49,6 +49,7 @@ export default function App() {
"data-[hover=true]:text-foreground",
"data-[hover=true]:bg-default-100",
"dark:data-[hover=true]:bg-default-50",
"data-[selectable=true]:focus:bg-default-50",
"data-[pressed=true]:opacity-70",
"data-[focus-visible=true]:ring-default-500",
],

View File

@ -138,6 +138,7 @@ export default function App() {
<DropdownItem
key="edit"
shortcut="⌘⇧E"
showDivider
description="Allows you to edit the file"
startContent={<EditDocumentIcon className={iconClasses} />}
>
@ -145,7 +146,6 @@ export default function App() {
</DropdownItem>
<DropdownItem
key="delete"
showDivider
className="text-danger"
color="danger"
shortcut="⌘⇧D"

View File

@ -142,7 +142,6 @@ export default function App() {
</DropdownItem>
<DropdownItem
key="delete"
showDivider
className="text-danger"
color="danger"
shortcut="⌘⇧D"

View File

@ -19,7 +19,7 @@ export default function App() {
</Button>
</DropdownTrigger>
<DropdownMenu
aria-label="Single selection actions"
aria-label="Multiple selection example"
variant="flat"
closeOnSelect={false}
disallowEmptySelection

View File

@ -14,7 +14,7 @@ export default function App() {
<DropdownItem key="new" shortcut="⌘N">New file</DropdownItem>
<DropdownItem key="copy" shortcut="⌘C">Copy link</DropdownItem>
<DropdownItem key="edit" shortcut="⌘⇧E">Edit file</DropdownItem>
<DropdownItem key="delete" showDivider shortcut="⌘⇧D" className="text-danger" color="danger">
<DropdownItem key="delete" shortcut="⌘⇧D" className="text-danger" color="danger">
Delete file
</DropdownItem>
</DropdownMenu>

View File

@ -19,7 +19,7 @@ export default function App() {
</Button>
</DropdownTrigger>
<DropdownMenu
aria-label="Single selection actions"
aria-label="Single selection example"
variant="flat"
disallowEmptySelection
selectionMode="single"

View File

@ -6,7 +6,7 @@ import sizes from "./sizes";
import colors from "./colors";
import variants from "./variants";
import radius from "./radius";
import labelPositions from "./label-positions";
import labelPlacements from "./label-placements";
import description from "./description";
import password from "./password";
import clearButton from "./clear-button";
@ -26,7 +26,7 @@ export const inputContent = {
colors,
variants,
radius,
labelPositions,
labelPlacements,
description,
password,
clearButton,

View File

@ -1,7 +1,7 @@
const App = `import {Input} from "@nextui-org/react";
export default function App() {
const positions = [
const placements = [
"inside",
"outside",
"outside-left",
@ -12,13 +12,13 @@ export default function App() {
<div className="flex flex-col gap-2">
<h3 className="text-default-500 text-small">Without placeholder</h3>
<div className="flex w-full flex-wrap items-end md:flex-nowrap mb-6 md:mb-0 gap-4">
{positions.map((position) => (
{placements.map((placement) => (
<Input
key={position}
key={placement}
type="email"
label="Email"
labelPlacement={position}
description={position}
labelPlacement={placement}
description={placement}
/>
))}
</div>
@ -26,14 +26,14 @@ export default function App() {
<div className="flex flex-col gap-2">
<h3 className="text-default-500 text-small">With placeholder</h3>
<div className="flex w-full flex-wrap items-end md:flex-nowrap mb-6 md:mb-0 gap-4">
{positions.map((position) => (
{placements.map((placement) => (
<Input
key={position}
key={placement}
type="email"
label="Email"
labelPlacement={position}
labelPlacement={placement}
placeholder="Enter your email"
description={position}
description={placement}
/>
))}
</div>

View File

@ -1,7 +1,6 @@
const App = `import {Input} from "@nextui-org/react";
export default function App() {
const variants = ["flat", "bordered", "underlined", "faded"];
return (

View File

@ -0,0 +1,284 @@
const BugIcon = `export const BugIcon = (props) => (
<svg height="1em" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg" {...props}>
<path
d="M16.895,6.519l2.813-2.812l-1.414-1.414l-2.846,2.846c-0.233-0.166-0.473-0.321-0.723-0.454 c-1.723-0.91-3.726-0.911-5.45,0c-0.25,0.132-0.488,0.287-0.722,0.453L5.707,2.293L4.293,3.707l2.813,2.812 C6.53,7.242,6.08,8.079,5.756,9H2v2h2.307C4.242,11.495,4.2,11.997,4.2,12.5c0,0.507,0.042,1.013,0.107,1.511H2v2h2.753 c0.013,0.039,0.021,0.08,0.034,0.118c0.188,0.555,0.421,1.093,0.695,1.6c0.044,0.081,0.095,0.155,0.141,0.234l-2.33,2.33 l1.414,1.414l2.11-2.111c0.235,0.254,0.478,0.498,0.736,0.716c0.418,0.354,0.867,0.657,1.332,0.903 c0.479,0.253,0.982,0.449,1.496,0.58C10.911,21.931,11.455,22,12,22s1.089-0.069,1.618-0.204c0.514-0.131,1.017-0.327,1.496-0.58 c0.465-0.246,0.914-0.55,1.333-0.904c0.258-0.218,0.5-0.462,0.734-0.716l2.111,2.111l1.414-1.414l-2.33-2.33 c0.047-0.08,0.098-0.155,0.142-0.236c0.273-0.505,0.507-1.043,0.694-1.599c0.013-0.039,0.021-0.079,0.034-0.118H22v-2h-2.308 c0.065-0.499,0.107-1.004,0.107-1.511c0-0.503-0.042-1.005-0.106-1.5H22V9h-3.756C17.92,8.079,17.47,7.242,16.895,6.519z M8.681,7.748c0.445-0.558,0.96-0.993,1.528-1.294c1.141-0.603,2.442-0.602,3.581,0c0.569,0.301,1.084,0.736,1.53,1.295 c0.299,0.373,0.54,0.8,0.753,1.251H7.927C8.141,8.549,8.381,8.121,8.681,7.748z M17.8,12.5c0,0.522-0.042,1.044-0.126,1.553 c-0.079,0.49-0.199,0.973-0.355,1.436c-0.151,0.449-0.34,0.882-0.559,1.288c-0.217,0.399-0.463,0.772-0.733,1.11 c-0.267,0.333-0.56,0.636-0.869,0.898c-0.31,0.261-0.639,0.484-0.979,0.664s-0.695,0.317-1.057,0.41 c-0.04,0.01-0.082,0.014-0.122,0.023V14h-2v5.881c-0.04-0.009-0.082-0.013-0.122-0.023c-0.361-0.093-0.717-0.23-1.057-0.41 s-0.669-0.403-0.978-0.664c-0.311-0.263-0.604-0.565-0.871-0.899c-0.27-0.337-0.516-0.71-0.731-1.108 c-0.22-0.407-0.408-0.84-0.56-1.289c-0.156-0.463-0.276-0.946-0.356-1.438C6.242,13.544,6.2,13.022,6.2,12.5 c0-0.505,0.041-1.009,0.119-1.5h11.361C17.759,11.491,17.8,11.995,17.8,12.5z"
fill="currentColor"
/>
</svg>
);
`;
const PullRequestIcon = `export const PullRequestIcon = (props) => (
<svg height="1em" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg" {...props}>
<path
d="M19.01 15.163V7.997C19.005 6.391 17.933 4 15 4V2l-4 3 4 3V6c1.829 0 2.001 1.539 2.01 2v7.163c-1.44.434-2.5 1.757-2.5 3.337 0 1.93 1.57 3.5 3.5 3.5s3.5-1.57 3.5-3.5c0-1.58-1.06-2.903-2.5-3.337zm-1 4.837c-.827 0-1.5-.673-1.5-1.5s.673-1.5 1.5-1.5 1.5.673 1.5 1.5-.673 1.5-1.5 1.5zM9.5 5.5C9.5 3.57 7.93 2 6 2S2.5 3.57 2.5 5.5c0 1.58 1.06 2.903 2.5 3.337v6.326c-1.44.434-2.5 1.757-2.5 3.337C2.5 20.43 4.07 22 6 22s3.5-1.57 3.5-3.5c0-1.58-1.06-2.903-2.5-3.337V8.837C8.44 8.403 9.5 7.08 9.5 5.5zm-5 0C4.5 4.673 5.173 4 6 4s1.5.673 1.5 1.5S6.827 7 6 7s-1.5-.673-1.5-1.5zm3 13c0 .827-.673 1.5-1.5 1.5s-1.5-.673-1.5-1.5S5.173 17 6 17s1.5.673 1.5 1.5z"
fill="currentColor"
/>
</svg>
);`;
const ChatIcon = `export const ChatIcon = (props) => (
<svg height="1em" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg" {...props}>
<path
d="M5 18v3.766l1.515-.909L11.277 18H16c1.103 0 2-.897 2-2V8c0-1.103-.897-2-2-2H4c-1.103 0-2 .897-2 2v8c0 1.103.897 2 2 2h1zM4 8h12v8h-5.277L7 18.234V16H4V8z"
fill="currentColor"
/>
<path
d="M20 2H8c-1.103 0-2 .897-2 2h12c1.103 0 2 .897 2 2v8c1.103 0 2-.897 2-2V4c0-1.103-.897-2-2-2z"
fill="currentColor"
/>
</svg>
);`;
const PlayCircleIcon = `export const PlayCircleIcon = (props) => (
<svg height="1em" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg" {...props}>
<path
d="M12 2C6.486 2 2 6.486 2 12s4.486 10 10 10 10-4.486 10-10S17.514 2 12 2zm0 18c-4.411 0-8-3.589-8-8s3.589-8 8-8 8 3.589 8 8-3.589 8-8 8z"
fill="currentColor"
/>
<path d="m9 17 8-5-8-5z" fill="currentColor" />
</svg>
);`;
const LayoutIcon = `export const LayoutIcon = (props) => (
<svg height="1em" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg" {...props}>
<path
d="M19 3H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2V5c0-1.103-.897-2-2-2zm0 2 .001 4H5V5h14zM5 11h8v8H5v-8zm10 8v-8h4.001l.001 8H15z"
fill="currentColor"
/>
</svg>
);`;
const TagIcon = `export const TagIcon = (props) => (
<svg height="1em" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg" {...props}>
<path
d="M11.707 2.293A.997.997 0 0 0 11 2H6a.997.997 0 0 0-.707.293l-3 3A.996.996 0 0 0 2 6v5c0 .266.105.52.293.707l10 10a.997.997 0 0 0 1.414 0l8-8a.999.999 0 0 0 0-1.414l-10-10zM13 19.586l-9-9V6.414L6.414 4h4.172l9 9L13 19.586z"
fill="currentColor"
/>
<circle cx="8.353" cy="8.353" fill="currentColor" r="1.647" />
</svg>
);`;
const UsersIcon = `export const UsersIcon = (props) => (
<svg height="1em" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg" {...props}>
<path
d="M16.604 11.048a5.67 5.67 0 0 0 .751-3.44c-.179-1.784-1.175-3.361-2.803-4.44l-1.105 1.666c1.119.742 1.8 1.799 1.918 2.974a3.693 3.693 0 0 1-1.072 2.986l-1.192 1.192 1.618.475C18.951 13.701 19 17.957 19 18h2c0-1.789-.956-5.285-4.396-6.952z"
fill="currentColor"
/>
<path
d="M9.5 12c2.206 0 4-1.794 4-4s-1.794-4-4-4-4 1.794-4 4 1.794 4 4 4zm0-6c1.103 0 2 .897 2 2s-.897 2-2 2-2-.897-2-2 .897-2 2-2zm1.5 7H8c-3.309 0-6 2.691-6 6v1h2v-1c0-2.206 1.794-4 4-4h3c2.206 0 4 1.794 4 4v1h2v-1c0-3.309-2.691-6-6-6z"
fill="currentColor"
/>
</svg>
);`;
const WatchersIcon = `export const WatchersIcons = (props) => (
<svg height="1em" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg" {...props}>
<path
d="m21.977 13.783-2-9A1.002 1.002 0 0 0 19 4h-3v2h2.198l.961 4.326A4.467 4.467 0 0 0 17.5 10c-1.953 0-3.603 1.258-4.224 3h-2.553c-.621-1.742-2.271-3-4.224-3-.587 0-1.145.121-1.659.326L5.802 6H8V4H5a1 1 0 0 0-.976.783l-2 9 .047.011A4.552 4.552 0 0 0 2 14.5C2 16.981 4.019 19 6.5 19c2.31 0 4.197-1.756 4.449-4h2.102c.252 2.244 2.139 4 4.449 4 2.481 0 4.5-2.019 4.5-4.5 0-.242-.034-.475-.071-.706l.048-.011zM6.5 17C5.122 17 4 15.878 4 14.5S5.122 12 6.5 12 9 13.122 9 14.5 7.878 17 6.5 17zm11 0c-1.379 0-2.5-1.122-2.5-2.5s1.121-2.5 2.5-2.5 2.5 1.122 2.5 2.5-1.121 2.5-2.5 2.5z"
fill="currentColor"
/>
</svg>
);`;
const BookIcon = `export const BookIcon = (props) => (
<svg height="1em" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg" {...props}>
<path
d="M6 22h15v-2H6.012C5.55 19.988 5 19.805 5 19s.55-.988 1.012-1H21V4c0-1.103-.897-2-2-2H6c-1.206 0-3 .799-3 3v14c0 2.201 1.794 3 3 3zM5 8V5c0-.805.55-.988 1-1h13v12H5V8z"
fill="currentColor"
/>
<path d="M8 6h9v2H8z" fill="currentColor" />
</svg>
);`;
const ChevronRightIcon = `export const ChevronRightIcon = (props) => (
<svg
aria-hidden="true"
fill="none"
focusable="false"
height="1em"
role="presentation"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="1.5"
viewBox="0 0 24 24"
width="1em"
{...props}
>
<path d="m9 18 6-6-6-6" />
</svg>
);`;
const IconWrapper = `import {cn} from "@nextui-org/react";
const IconWrapper = ({children, className}) => (
<div className={cn(className, "flex items-center rounded-small justify-center w-7 h-7")}>
{children}
</div>
);`;
const ItemCounter = `const ItemCounter = ({number}) => (
<div className="flex items-center gap-1 text-default-400">
<span className="text-small">{number}</span>
<ChevronRightIcon className="text-xl" />
</div>
);`;
const App = `import {Listbox, ListboxItem} from "@nextui-org/react";
import {IconWrapper} from "./IconWrapper";
import {ItemCounter} from "./ItemCounter";
import {BugIcon} from "./BugIcon";
import {PullRequestIcon} from "./PullRequestIcon";
import {ChatIcon} from "./ChatIcon";
import {PlayCircleIcon} from "./PlayCircleIcon";
import {LayoutIcon} from "./LayoutIcon";
import {TagIcon} from "./TagIcon";
import {UsersIcon} from "./UsersIcon";
import {WatchersIcon} from "./WatchersIcon";
import {BookIcon} from "./BookIcon";
import {ChevronRightIcon} from "./ChevronRightIcon";
export default function App() {
return (
<Listbox
aria-label="User Menu"
onAction={(key) => alert(key)}
className="p-0 gap-0 divide-y divide-default-300/50 dark:divide-default-100/80 bg-content1 max-w-[300px] overflow-visible shadow-small rounded-medium"
itemClasses={{
base: "px-3 first:rounded-t-medium last:rounded-b-medium rounded-none gap-3 h-12 data-[hover=true]:bg-default-100/80",
}}
>
<ListboxItem
key="issues"
endContent={<ItemCounter number={13} />}
startContent={
<IconWrapper className="bg-success/10 text-success">
<BugIcon className="text-lg " />
</IconWrapper>
}
>
Issues
</ListboxItem>
<ListboxItem
key="pull_requests"
endContent={<ItemCounter number={6} />}
startContent={
<IconWrapper className="bg-primary/10 text-primary">
<PullRequestIcon className="text-lg " />
</IconWrapper>
}
>
Pull Requests
</ListboxItem>
<ListboxItem
key="discussions"
endContent={<ItemCounter number={293} />}
startContent={
<IconWrapper className="bg-secondary/10 text-secondary">
<ChatIcon className="text-lg " />
</IconWrapper>
}
>
Discussions
</ListboxItem>
<ListboxItem
key="actions"
endContent={<ItemCounter number={2} />}
startContent={
<IconWrapper className="bg-warning/10 text-warning">
<PlayCircleIcon className="text-lg " />
</IconWrapper>
}
>
Actions
</ListboxItem>
<ListboxItem
key="projects"
endContent={<ItemCounter number={4} />}
startContent={
<IconWrapper className="bg-default/50 text-foreground">
<LayoutIcon className="text-lg " />
</IconWrapper>
}
>
Projects
</ListboxItem>
<ListboxItem
key="releases"
className="group h-auto py-3"
endContent={<ItemCounter number={399} />}
startContent={
<IconWrapper className="bg-primary/10 text-primary">
<TagIcon className="text-lg" />
</IconWrapper>
}
textValue="Releases"
>
<div className="flex flex-col gap-1">
<span>Releases</span>
<div className="px-2 py-1 rounded-small bg-default-100 group-data-[hover=true]:bg-default-200">
<span className="text-tiny text-default-600">@nextui-org/react@2.0.10</span>
<div className="flex gap-2 text-tiny">
<span className="text-default-500">49 minutes ago</span>
<span className="text-success">Latest</span>
</div>
</div>
</div>
</ListboxItem>
<ListboxItem
key="contributors"
endContent={<ItemCounter number={79} />}
startContent={
<IconWrapper className="bg-warning/10 text-warning">
<UsersIcon />
</IconWrapper>
}
>
Contributors
</ListboxItem>
<ListboxItem
key="watchers"
endContent={<ItemCounter number={82} />}
startContent={
<IconWrapper className="bg-default/50 text-foreground">
<WatchersIcons />
</IconWrapper>
}
>
Watchers
</ListboxItem>
<ListboxItem
key="license"
endContent={<span className="text-small text-default-400">MIT</span>}
startContent={
<IconWrapper className="bg-danger/10 text-danger dark:text-danger-500">
<BookIcon />
</IconWrapper>
}
>
License
</ListboxItem>
</Listbox>
);
}`;
const react = {
"/App.jsx": App,
"/IconWrapper.jsx": IconWrapper,
"/ItemCounter.jsx": ItemCounter,
"/BugIcon.jsx": BugIcon,
"/PullRequestIcon.jsx": PullRequestIcon,
"/ChatIcon.jsx": ChatIcon,
"/PlayCircleIcon.jsx": PlayCircleIcon,
"/LayoutIcon.jsx": LayoutIcon,
"/TagIcon.jsx": TagIcon,
"/UsersIcon.jsx": UsersIcon,
"/WatchersIcons.jsx": WatchersIcon,
"/BookIcon.jsx": BookIcon,
"/ChevronRightIcon.jsx": ChevronRightIcon,
};
export default {
...react,
};

View File

@ -0,0 +1,169 @@
const AddNoteIcon = `export const AddNoteIcon = (props) => (
<svg
aria-hidden="true"
fill="none"
focusable="false"
height="1em"
role="presentation"
viewBox="0 0 24 24"
width="1em"
{...props}
>
<path
d="M7.37 22h9.25a4.87 4.87 0 0 0 4.87-4.87V8.37a4.87 4.87 0 0 0-4.87-4.87H7.37A4.87 4.87 0 0 0 2.5 8.37v8.75c0 2.7 2.18 4.88 4.87 4.88Z"
fill="currentColor"
opacity={0.4}
/>
<path
d="M8.29 6.29c-.42 0-.75-.34-.75-.75V2.75a.749.749 0 1 1 1.5 0v2.78c0 .42-.33.76-.75.76ZM15.71 6.29c-.42 0-.75-.34-.75-.75V2.75a.749.749 0 1 1 1.5 0v2.78c0 .42-.33.76-.75.76ZM12 14.75h-1.69V13c0-.41-.34-.75-.75-.75s-.75.34-.75.75v1.75H7c-.41 0-.75.34-.75.75s.34.75.75.75h1.81V18c0 .41.34.75.75.75s.75-.34.75-.75v-1.75H12c.41 0 .75-.34.75-.75s-.34-.75-.75-.75Z"
fill="currentColor"
/>
</svg>
);`;
const CopyDocumentIcon = `export const CopyDocumentIcon = (props) => (
<svg
aria-hidden="true"
fill="none"
focusable="false"
height="1em"
role="presentation"
viewBox="0 0 24 24"
width="1em"
{...props}
>
<path
d="M15.5 13.15h-2.17c-1.78 0-3.23-1.44-3.23-3.23V7.75c0-.41-.33-.75-.75-.75H6.18C3.87 7 2 8.5 2 11.18v6.64C2 20.5 3.87 22 6.18 22h5.89c2.31 0 4.18-1.5 4.18-4.18V13.9c0-.42-.34-.75-.75-.75Z"
fill="currentColor"
opacity={0.4}
/>
<path
d="M17.82 2H11.93C9.67 2 7.84 3.44 7.76 6.01c.06 0 .11-.01.17-.01h5.89C16.13 6 18 7.5 18 10.18V16.83c0 .06-.01.11-.01.16 2.23-.07 4.01-1.55 4.01-4.16V6.18C22 3.5 20.13 2 17.82 2Z"
fill="currentColor"
/>
<path
d="M11.98 7.15c-.31-.31-.84-.1-.84.33v2.62c0 1.1.93 2 2.07 2 .71.01 1.7.01 2.55.01.43 0 .65-.5.35-.8-1.09-1.09-3.03-3.04-4.13-4.16Z"
fill="currentColor"
/>
</svg>
);`;
const EditDocumentIcon = `export const EditDocumentIcon = (props) => (
<svg
aria-hidden="true"
fill="none"
focusable="false"
height="1em"
role="presentation"
viewBox="0 0 24 24"
width="1em"
{...props}
>
<path
d="M15.48 3H7.52C4.07 3 2 5.06 2 8.52v7.95C2 19.94 4.07 22 7.52 22h7.95c3.46 0 5.52-2.06 5.52-5.52V8.52C21 5.06 18.93 3 15.48 3Z"
fill="currentColor"
opacity={0.4}
/>
<path
d="M21.02 2.98c-1.79-1.8-3.54-1.84-5.38 0L14.51 4.1c-.1.1-.13.24-.09.37.7 2.45 2.66 4.41 5.11 5.11.03.01.08.01.11.01.1 0 .2-.04.27-.11l1.11-1.12c.91-.91 1.36-1.78 1.36-2.67 0-.9-.45-1.79-1.36-2.71ZM17.86 10.42c-.27-.13-.53-.26-.77-.41-.2-.12-.4-.25-.59-.39-.16-.1-.34-.25-.52-.4-.02-.01-.08-.06-.16-.14-.31-.25-.64-.59-.95-.96-.02-.02-.08-.08-.13-.17-.1-.11-.25-.3-.38-.51-.11-.14-.24-.34-.36-.55-.15-.25-.28-.5-.4-.76-.13-.28-.23-.54-.32-.79L7.9 10.72c-.35.35-.69 1.01-.76 1.5l-.43 2.98c-.09.63.08 1.22.47 1.61.33.33.78.5 1.28.5.11 0 .22-.01.33-.02l2.97-.42c.49-.07 1.15-.4 1.5-.76l5.38-5.38c-.25-.08-.5-.19-.78-.31Z"
fill="currentColor"
/>
</svg>
);`;
const DeleteDocumentIcon = `export const DeleteDocumentIcon = (props) => (
<svg
aria-hidden="true"
fill="none"
focusable="false"
height="1em"
role="presentation"
viewBox="0 0 24 24"
width="1em"
{...props}
>
<path
d="M21.07 5.23c-1.61-.16-3.22-.28-4.84-.37v-.01l-.22-1.3c-.15-.92-.37-2.3-2.71-2.3h-2.62c-2.33 0-2.55 1.32-2.71 2.29l-.21 1.28c-.93.06-1.86.12-2.79.21l-2.04.2c-.42.04-.72.41-.68.82.04.41.4.71.82.67l2.04-.2c5.24-.52 10.52-.32 15.82.21h.08c.38 0 .71-.29.75-.68a.766.766 0 0 0-.69-.82Z"
fill="currentColor"
/>
<path
d="M19.23 8.14c-.24-.25-.57-.39-.91-.39H5.68c-.34 0-.68.14-.91.39-.23.25-.36.59-.34.94l.62 10.26c.11 1.52.25 3.42 3.74 3.42h6.42c3.49 0 3.63-1.89 3.74-3.42l.62-10.25c.02-.36-.11-.7-.34-.95Z"
fill="currentColor"
opacity={0.399}
/>
<path
clipRule="evenodd"
d="M9.58 17a.75.75 0 0 1 .75-.75h3.33a.75.75 0 0 1 0 1.5h-3.33a.75.75 0 0 1-.75-.75ZM8.75 13a.75.75 0 0 1 .75-.75h5a.75.75 0 0 1 0 1.5h-5a.75.75 0 0 1-.75-.75Z"
fill="currentColor"
fillRule="evenodd"
/>
</svg>
);`;
const ListboxWrapper = `const ListboxWrapper = ({children}) => (
<div className="w-full max-w-[260px] border-small px-1 py-2 rounded-small border-default-200 dark:border-default-100">
{children}
</div>
);`;
const App = `import {Listbox, ListboxItem, cn} from "@nextui-org/react";
import {ListboxWrapper} from "./ListboxWrapper";
import {AddNoteIcon} from "./AddNoteIcon.jsx";
import {CopyDocumentIcon} from "./CopyDocumentIcon.jsx";
import {EditDocumentIcon} from "./EditDocumentIcon.jsx";
import {DeleteDocumentIcon} from "./DeleteDocumentIcon.jsx";
export default function App() {
const iconClasses = "text-xl text-default-500 pointer-events-none flex-shrink-0";
return (
<ListboxWrapper>
<Listbox variant="flat" aria-label="Listbox menu with descriptions">
<ListboxItem
key="new"
description="Create a new file"
startContent={<AddNoteIcon className={iconClasses} />}
>
New file
</ListboxItem>
<ListboxItem
key="copy"
description="Copy the file link"
startContent={<CopyDocumentIcon className={iconClasses} />}
>
Copy link
</ListboxItem>
<ListboxItem
key="edit"
showDivider
description="Allows you to edit the file"
startContent={<EditDocumentIcon className={iconClasses} />}
>
Edit file
</ListboxItem>
<ListboxItem
key="delete"
className="text-danger"
color="danger"
description="Permanently delete the file"
startContent={<DeleteDocumentIcon className={cn(iconClasses, "text-danger")} />}
>
Delete file
</ListboxItem>
</Listbox>
</ListboxWrapper>
);
}`;
const react = {
"/App.jsx": App,
"/ListboxWrapper.jsx": ListboxWrapper,
"/AddNoteIcon.jsx": AddNoteIcon,
"/CopyDocumentIcon.jsx": CopyDocumentIcon,
"/EditDocumentIcon.jsx": EditDocumentIcon,
"/DeleteDocumentIcon.jsx": DeleteDocumentIcon,
};
export default {
...react,
};

View File

@ -0,0 +1,36 @@
const ListboxWrapper = `const ListboxWrapper = ({children}) => (
<div className="w-full max-w-[260px] border-small px-1 py-2 rounded-small border-default-200 dark:border-default-100">
{children}
</div>
);`;
const App = `import {Listbox, ListboxItem} from "@nextui-org/react";
import {ListboxWrapper} from "./ListboxWrapper";
export default function App() {
return (
<ListboxWrapper>
<Listbox
aria-label="Example with disabled actions"
disabledKeys={["edit", "delete"]}
onAction={(key) => alert(key)}
>
<ListboxItem key="new">New file</ListboxItem>
<ListboxItem key="copy">Copy link</ListboxItem>
<ListboxItem key="edit">Edit file</ListboxItem>
<ListboxItem key="delete" className="text-danger" color="danger">
Delete file
</ListboxItem>
</Listbox>
</ListboxWrapper>
);
}`;
const react = {
"/App.jsx": App,
"/ListboxWrapper.jsx": ListboxWrapper,
};
export default {
...react,
};

View File

@ -0,0 +1,58 @@
const ListboxWrapper = `const ListboxWrapper = ({children}) => (
<div className="w-full max-w-[260px] border-small px-1 py-2 rounded-small border-default-200 dark:border-default-100">
{children}
</div>
);`;
const App = `import {Listbox, ListboxItem} from "@nextui-org/react";
import {ListboxWrapper} from "./ListboxWrapper";
export default function App() {
const items = [
{
key: "new",
label: "New file",
},
{
key: "copy",
label: "Copy link",
},
{
key: "edit",
label: "Edit file",
},
{
key: "delete",
label: "Delete file",
}
];
return (
<ListboxWrapper>
<Listbox
items={items}
aria-label="Dynamic Actions"
onAction={(key) => alert(key)}
>
{(item) => (
<ListboxItem
key={item.key}
color={item.key === "delete" ? "danger" : "default"}
className={item.key === "delete" ? "text-danger" : ""}
>
{item.label}
</ListboxItem>
)}
</Listbox>
</ListboxWrapper>
);
}`;
const react = {
"/App.jsx": App,
"/ListboxWrapper.jsx": ListboxWrapper,
};
export default {
...react,
};

View File

@ -0,0 +1,165 @@
const AddNoteIcon = `export const AddNoteIcon = (props) => (
<svg
aria-hidden="true"
fill="none"
focusable="false"
height="1em"
role="presentation"
viewBox="0 0 24 24"
width="1em"
{...props}
>
<path
d="M7.37 22h9.25a4.87 4.87 0 0 0 4.87-4.87V8.37a4.87 4.87 0 0 0-4.87-4.87H7.37A4.87 4.87 0 0 0 2.5 8.37v8.75c0 2.7 2.18 4.88 4.87 4.88Z"
fill="currentColor"
opacity={0.4}
/>
<path
d="M8.29 6.29c-.42 0-.75-.34-.75-.75V2.75a.749.749 0 1 1 1.5 0v2.78c0 .42-.33.76-.75.76ZM15.71 6.29c-.42 0-.75-.34-.75-.75V2.75a.749.749 0 1 1 1.5 0v2.78c0 .42-.33.76-.75.76ZM12 14.75h-1.69V13c0-.41-.34-.75-.75-.75s-.75.34-.75.75v1.75H7c-.41 0-.75.34-.75.75s.34.75.75.75h1.81V18c0 .41.34.75.75.75s.75-.34.75-.75v-1.75H12c.41 0 .75-.34.75-.75s-.34-.75-.75-.75Z"
fill="currentColor"
/>
</svg>
);`;
const CopyDocumentIcon = `export const CopyDocumentIcon = (props) => (
<svg
aria-hidden="true"
fill="none"
focusable="false"
height="1em"
role="presentation"
viewBox="0 0 24 24"
width="1em"
{...props}
>
<path
d="M15.5 13.15h-2.17c-1.78 0-3.23-1.44-3.23-3.23V7.75c0-.41-.33-.75-.75-.75H6.18C3.87 7 2 8.5 2 11.18v6.64C2 20.5 3.87 22 6.18 22h5.89c2.31 0 4.18-1.5 4.18-4.18V13.9c0-.42-.34-.75-.75-.75Z"
fill="currentColor"
opacity={0.4}
/>
<path
d="M17.82 2H11.93C9.67 2 7.84 3.44 7.76 6.01c.06 0 .11-.01.17-.01h5.89C16.13 6 18 7.5 18 10.18V16.83c0 .06-.01.11-.01.16 2.23-.07 4.01-1.55 4.01-4.16V6.18C22 3.5 20.13 2 17.82 2Z"
fill="currentColor"
/>
<path
d="M11.98 7.15c-.31-.31-.84-.1-.84.33v2.62c0 1.1.93 2 2.07 2 .71.01 1.7.01 2.55.01.43 0 .65-.5.35-.8-1.09-1.09-3.03-3.04-4.13-4.16Z"
fill="currentColor"
/>
</svg>
);`;
const EditDocumentIcon = `export const EditDocumentIcon = (props) => (
<svg
aria-hidden="true"
fill="none"
focusable="false"
height="1em"
role="presentation"
viewBox="0 0 24 24"
width="1em"
{...props}
>
<path
d="M15.48 3H7.52C4.07 3 2 5.06 2 8.52v7.95C2 19.94 4.07 22 7.52 22h7.95c3.46 0 5.52-2.06 5.52-5.52V8.52C21 5.06 18.93 3 15.48 3Z"
fill="currentColor"
opacity={0.4}
/>
<path
d="M21.02 2.98c-1.79-1.8-3.54-1.84-5.38 0L14.51 4.1c-.1.1-.13.24-.09.37.7 2.45 2.66 4.41 5.11 5.11.03.01.08.01.11.01.1 0 .2-.04.27-.11l1.11-1.12c.91-.91 1.36-1.78 1.36-2.67 0-.9-.45-1.79-1.36-2.71ZM17.86 10.42c-.27-.13-.53-.26-.77-.41-.2-.12-.4-.25-.59-.39-.16-.1-.34-.25-.52-.4-.02-.01-.08-.06-.16-.14-.31-.25-.64-.59-.95-.96-.02-.02-.08-.08-.13-.17-.1-.11-.25-.3-.38-.51-.11-.14-.24-.34-.36-.55-.15-.25-.28-.5-.4-.76-.13-.28-.23-.54-.32-.79L7.9 10.72c-.35.35-.69 1.01-.76 1.5l-.43 2.98c-.09.63.08 1.22.47 1.61.33.33.78.5 1.28.5.11 0 .22-.01.33-.02l2.97-.42c.49-.07 1.15-.4 1.5-.76l5.38-5.38c-.25-.08-.5-.19-.78-.31Z"
fill="currentColor"
/>
</svg>
);`;
const DeleteDocumentIcon = `export const DeleteDocumentIcon = (props) => (
<svg
aria-hidden="true"
fill="none"
focusable="false"
height="1em"
role="presentation"
viewBox="0 0 24 24"
width="1em"
{...props}
>
<path
d="M21.07 5.23c-1.61-.16-3.22-.28-4.84-.37v-.01l-.22-1.3c-.15-.92-.37-2.3-2.71-2.3h-2.62c-2.33 0-2.55 1.32-2.71 2.29l-.21 1.28c-.93.06-1.86.12-2.79.21l-2.04.2c-.42.04-.72.41-.68.82.04.41.4.71.82.67l2.04-.2c5.24-.52 10.52-.32 15.82.21h.08c.38 0 .71-.29.75-.68a.766.766 0 0 0-.69-.82Z"
fill="currentColor"
/>
<path
d="M19.23 8.14c-.24-.25-.57-.39-.91-.39H5.68c-.34 0-.68.14-.91.39-.23.25-.36.59-.34.94l.62 10.26c.11 1.52.25 3.42 3.74 3.42h6.42c3.49 0 3.63-1.89 3.74-3.42l.62-10.25c.02-.36-.11-.7-.34-.95Z"
fill="currentColor"
opacity={0.399}
/>
<path
clipRule="evenodd"
d="M9.58 17a.75.75 0 0 1 .75-.75h3.33a.75.75 0 0 1 0 1.5h-3.33a.75.75 0 0 1-.75-.75ZM8.75 13a.75.75 0 0 1 .75-.75h5a.75.75 0 0 1 0 1.5h-5a.75.75 0 0 1-.75-.75Z"
fill="currentColor"
fillRule="evenodd"
/>
</svg>
);`;
const ListboxWrapper = `const ListboxWrapper = ({children}) => (
<div className="w-full max-w-[260px] border-small px-1 py-2 rounded-small border-default-200 dark:border-default-100">
{children}
</div>
);`;
const App = `import {Listbox, ListboxItem, cn} from "@nextui-org/react";
import {ListboxWrapper} from "./ListboxWrapper";
import {AddNoteIcon} from "./AddNoteIcon.jsx";
import {CopyDocumentIcon} from "./CopyDocumentIcon.jsx";
import {EditDocumentIcon} from "./EditDocumentIcon.jsx";
import {DeleteDocumentIcon} from "./DeleteDocumentIcon.jsx";
export default function App() {
const iconClasses = "text-xl text-default-500 pointer-events-none flex-shrink-0";
return (
<ListboxWrapper>
<Listbox variant="faded" aria-label="Listbox menu with icons">
<ListboxItem
key="new"
startContent={<AddNoteIcon className={iconClasses} />}
>
New file
</ListboxItem>
<ListboxItem
key="copy"
startContent={<CopyDocumentIcon className={iconClasses} />}
>
Copy link
</ListboxItem>
<ListboxItem
key="edit"
showDivider
startContent={<EditDocumentIcon className={iconClasses} />}
>
Edit file
</ListboxItem>
<ListboxItem
key="delete"
className="text-danger"
color="danger"
startContent={<DeleteDocumentIcon className={cn(iconClasses, "text-danger")} />}
>
Delete file
</ListboxItem>
</Listbox>
</ListboxWrapper>
);
}`;
const react = {
"/App.jsx": App,
"/ListboxWrapper.jsx": ListboxWrapper,
"/AddNoteIcon.jsx": AddNoteIcon,
"/CopyDocumentIcon.jsx": CopyDocumentIcon,
"/EditDocumentIcon.jsx": EditDocumentIcon,
"/DeleteDocumentIcon.jsx": DeleteDocumentIcon,
};
export default {
...react,
};

View File

@ -0,0 +1,23 @@
import usage from "./usage";
import dynamic from "./dynamic";
import disabledKeys from "./disabled-keys";
import variants from "./variants";
import singleSelection from "./single-selection";
import multipleSelection from "./multiple-selection";
import icons from "./icons";
import description from "./description";
import sections from "./sections";
import customStyles from "./custom-styles";
export const listboxContent = {
usage,
dynamic,
disabledKeys,
variants,
singleSelection,
multipleSelection,
icons,
description,
sections,
customStyles,
};

View File

@ -0,0 +1,48 @@
const ListboxWrapper = `const ListboxWrapper = ({children}) => (
<div className="w-[260px] border-small px-1 py-2 rounded-small border-default-200 dark:border-default-100">
{children}
</div>
);`;
const App = `import {Listbox, ListboxItem} from "@nextui-org/react";
import {ListboxWrapper} from "./ListboxWrapper";
export default function App() {
const [selectedKeys, setSelectedKeys] = React.useState(new Set(["text"]));
const selectedValue = React.useMemo(
() => Array.from(selectedKeys).join(", "),
[selectedKeys]
);
return (
<div className="flex flex-col gap-2">
<ListboxWrapper>
<Listbox
aria-label="Multiple selection example"
variant="flat"
disallowEmptySelection
selectionMode="multiple"
selectedKeys={selectedKeys}
onSelectionChange={setSelectedKeys}
>
<ListboxItem key="text">Text</ListboxItem>
<ListboxItem key="number">Number</ListboxItem>
<ListboxItem key="date">Date</ListboxItem>
<ListboxItem key="single_date">Single Date</ListboxItem>
<ListboxItem key="iteration">Iteration</ListboxItem>
</Listbox>
</ListboxWrapper>
<p className="text-small text-default-500">Selected value: {selectedValue}</p>
</div>
);
}`;
const react = {
"/App.jsx": App,
"/ListboxWrapper.jsx": ListboxWrapper,
};
export default {
...react,
};

View File

@ -0,0 +1,172 @@
const AddNoteIcon = `export const AddNoteIcon = (props) => (
<svg
aria-hidden="true"
fill="none"
focusable="false"
height="1em"
role="presentation"
viewBox="0 0 24 24"
width="1em"
{...props}
>
<path
d="M7.37 22h9.25a4.87 4.87 0 0 0 4.87-4.87V8.37a4.87 4.87 0 0 0-4.87-4.87H7.37A4.87 4.87 0 0 0 2.5 8.37v8.75c0 2.7 2.18 4.88 4.87 4.88Z"
fill="currentColor"
opacity={0.4}
/>
<path
d="M8.29 6.29c-.42 0-.75-.34-.75-.75V2.75a.749.749 0 1 1 1.5 0v2.78c0 .42-.33.76-.75.76ZM15.71 6.29c-.42 0-.75-.34-.75-.75V2.75a.749.749 0 1 1 1.5 0v2.78c0 .42-.33.76-.75.76ZM12 14.75h-1.69V13c0-.41-.34-.75-.75-.75s-.75.34-.75.75v1.75H7c-.41 0-.75.34-.75.75s.34.75.75.75h1.81V18c0 .41.34.75.75.75s.75-.34.75-.75v-1.75H12c.41 0 .75-.34.75-.75s-.34-.75-.75-.75Z"
fill="currentColor"
/>
</svg>
);`;
const CopyDocumentIcon = `export const CopyDocumentIcon = (props) => (
<svg
aria-hidden="true"
fill="none"
focusable="false"
height="1em"
role="presentation"
viewBox="0 0 24 24"
width="1em"
{...props}
>
<path
d="M15.5 13.15h-2.17c-1.78 0-3.23-1.44-3.23-3.23V7.75c0-.41-.33-.75-.75-.75H6.18C3.87 7 2 8.5 2 11.18v6.64C2 20.5 3.87 22 6.18 22h5.89c2.31 0 4.18-1.5 4.18-4.18V13.9c0-.42-.34-.75-.75-.75Z"
fill="currentColor"
opacity={0.4}
/>
<path
d="M17.82 2H11.93C9.67 2 7.84 3.44 7.76 6.01c.06 0 .11-.01.17-.01h5.89C16.13 6 18 7.5 18 10.18V16.83c0 .06-.01.11-.01.16 2.23-.07 4.01-1.55 4.01-4.16V6.18C22 3.5 20.13 2 17.82 2Z"
fill="currentColor"
/>
<path
d="M11.98 7.15c-.31-.31-.84-.1-.84.33v2.62c0 1.1.93 2 2.07 2 .71.01 1.7.01 2.55.01.43 0 .65-.5.35-.8-1.09-1.09-3.03-3.04-4.13-4.16Z"
fill="currentColor"
/>
</svg>
);`;
const EditDocumentIcon = `export const EditDocumentIcon = (props) => (
<svg
aria-hidden="true"
fill="none"
focusable="false"
height="1em"
role="presentation"
viewBox="0 0 24 24"
width="1em"
{...props}
>
<path
d="M15.48 3H7.52C4.07 3 2 5.06 2 8.52v7.95C2 19.94 4.07 22 7.52 22h7.95c3.46 0 5.52-2.06 5.52-5.52V8.52C21 5.06 18.93 3 15.48 3Z"
fill="currentColor"
opacity={0.4}
/>
<path
d="M21.02 2.98c-1.79-1.8-3.54-1.84-5.38 0L14.51 4.1c-.1.1-.13.24-.09.37.7 2.45 2.66 4.41 5.11 5.11.03.01.08.01.11.01.1 0 .2-.04.27-.11l1.11-1.12c.91-.91 1.36-1.78 1.36-2.67 0-.9-.45-1.79-1.36-2.71ZM17.86 10.42c-.27-.13-.53-.26-.77-.41-.2-.12-.4-.25-.59-.39-.16-.1-.34-.25-.52-.4-.02-.01-.08-.06-.16-.14-.31-.25-.64-.59-.95-.96-.02-.02-.08-.08-.13-.17-.1-.11-.25-.3-.38-.51-.11-.14-.24-.34-.36-.55-.15-.25-.28-.5-.4-.76-.13-.28-.23-.54-.32-.79L7.9 10.72c-.35.35-.69 1.01-.76 1.5l-.43 2.98c-.09.63.08 1.22.47 1.61.33.33.78.5 1.28.5.11 0 .22-.01.33-.02l2.97-.42c.49-.07 1.15-.4 1.5-.76l5.38-5.38c-.25-.08-.5-.19-.78-.31Z"
fill="currentColor"
/>
</svg>
);`;
const DeleteDocumentIcon = `export const DeleteDocumentIcon = (props) => (
<svg
aria-hidden="true"
fill="none"
focusable="false"
height="1em"
role="presentation"
viewBox="0 0 24 24"
width="1em"
{...props}
>
<path
d="M21.07 5.23c-1.61-.16-3.22-.28-4.84-.37v-.01l-.22-1.3c-.15-.92-.37-2.3-2.71-2.3h-2.62c-2.33 0-2.55 1.32-2.71 2.29l-.21 1.28c-.93.06-1.86.12-2.79.21l-2.04.2c-.42.04-.72.41-.68.82.04.41.4.71.82.67l2.04-.2c5.24-.52 10.52-.32 15.82.21h.08c.38 0 .71-.29.75-.68a.766.766 0 0 0-.69-.82Z"
fill="currentColor"
/>
<path
d="M19.23 8.14c-.24-.25-.57-.39-.91-.39H5.68c-.34 0-.68.14-.91.39-.23.25-.36.59-.34.94l.62 10.26c.11 1.52.25 3.42 3.74 3.42h6.42c3.49 0 3.63-1.89 3.74-3.42l.62-10.25c.02-.36-.11-.7-.34-.95Z"
fill="currentColor"
opacity={0.399}
/>
<path
clipRule="evenodd"
d="M9.58 17a.75.75 0 0 1 .75-.75h3.33a.75.75 0 0 1 0 1.5h-3.33a.75.75 0 0 1-.75-.75ZM8.75 13a.75.75 0 0 1 .75-.75h5a.75.75 0 0 1 0 1.5h-5a.75.75 0 0 1-.75-.75Z"
fill="currentColor"
fillRule="evenodd"
/>
</svg>
);`;
const ListboxWrapper = `const ListboxWrapper = ({children}) => (
<div className="w-full max-w-[260px] border-small px-1 py-2 rounded-small border-default-200 dark:border-default-100">
{children}
</div>
);`;
const App = `import {Listbox, ListboxItem, ListboxSection, cn} from "@nextui-org/react";
import {ListboxWrapper} from "./ListboxWrapper";
import {AddNoteIcon} from "./AddNoteIcon.jsx";
import {CopyDocumentIcon} from "./CopyDocumentIcon.jsx";
import {EditDocumentIcon} from "./EditDocumentIcon.jsx";
import {DeleteDocumentIcon} from "./DeleteDocumentIcon.jsx";
export default function App() {
const iconClasses = "text-xl text-default-500 pointer-events-none flex-shrink-0";
return (
<ListboxWrapper>
<Listbox variant="flat" aria-label="Listbox menu with sections">
<ListboxSection title="Actions" showDivider>
<ListboxItem
key="new"
description="Create a new file"
startContent={<AddNoteIcon className={iconClasses} />}
>
New file
</ListboxItem>
<ListboxItem
key="copy"
description="Copy the file link"
startContent={<CopyDocumentIcon className={iconClasses} />}
>
Copy link
</ListboxItem>
<ListboxItem
key="edit"
description="Allows you to edit the file"
startContent={<EditDocumentIcon className={iconClasses} />}
>
Edit file
</ListboxItem>
</ListboxSection>
<ListboxSection title="Danger zone">
<ListboxItem
key="delete"
className="text-danger"
color="danger"
description="Permanently delete the file"
startContent={<DeleteDocumentIcon className={cn(iconClasses, "text-danger")} />}
>
Delete file
</ListboxItem>
</ListboxSection>
</Listbox>
</ListboxWrapper>
);
}`;
const react = {
"/App.jsx": App,
"/ListboxWrapper.jsx": ListboxWrapper,
"/AddNoteIcon.jsx": AddNoteIcon,
"/CopyDocumentIcon.jsx": CopyDocumentIcon,
"/EditDocumentIcon.jsx": EditDocumentIcon,
"/DeleteDocumentIcon.jsx": DeleteDocumentIcon,
};
export default {
...react,
};

View File

@ -0,0 +1,48 @@
const ListboxWrapper = `const ListboxWrapper = ({children}) => (
<div className="w-[260px] border-small px-1 py-2 rounded-small border-default-200 dark:border-default-100">
{children}
</div>
);`;
const App = `import {Listbox, ListboxItem} from "@nextui-org/react";
import {ListboxWrapper} from "./ListboxWrapper";
export default function App() {
const [selectedKeys, setSelectedKeys] = React.useState(new Set(["text"]));
const selectedValue = React.useMemo(
() => Array.from(selectedKeys).join(", "),
[selectedKeys]
);
return (
<div className="flex flex-col gap-2">
<ListboxWrapper>
<Listbox
aria-label="Single selection example"
variant="flat"
disallowEmptySelection
selectionMode="single"
selectedKeys={selectedKeys}
onSelectionChange={setSelectedKeys}
>
<ListboxItem key="text">Text</ListboxItem>
<ListboxItem key="number">Number</ListboxItem>
<ListboxItem key="date">Date</ListboxItem>
<ListboxItem key="single_date">Single Date</ListboxItem>
<ListboxItem key="iteration">Iteration</ListboxItem>
</Listbox>
</ListboxWrapper>
<p className="text-small text-default-500">Selected value: {selectedValue}</p>
</div>
);
}`;
const react = {
"/App.jsx": App,
"/ListboxWrapper.jsx": ListboxWrapper,
};
export default {
...react,
};

View File

@ -0,0 +1,35 @@
const ListboxWrapper = `const ListboxWrapper = ({children}) => (
<div className="w-full max-w-[260px] border-small px-1 py-2 rounded-small border-default-200 dark:border-default-100">
{children}
</div>
);`;
const App = `import {Listbox, ListboxItem} from "@nextui-org/react";
import {ListboxWrapper} from "./ListboxWrapper";
export default function App() {
return (
<ListboxWrapper>
<Listbox
aria-label="Actions"
onAction={(key) => alert(key)}
>
<ListboxItem key="new">New file</ListboxItem>
<ListboxItem key="copy">Copy link</ListboxItem>
<ListboxItem key="edit">Edit file</ListboxItem>
<ListboxItem key="delete" className="text-danger" color="danger">
Delete file
</ListboxItem>
</Listbox>
</ListboxWrapper>
);
}`;
const react = {
"/App.jsx": App,
"/ListboxWrapper.jsx": ListboxWrapper,
};
export default {
...react,
};

View File

@ -0,0 +1,72 @@
const ListboxWrapper = `const ListboxWrapper = ({children}) => (
<div className="w-full max-w-[260px] border-small px-1 py-2 rounded-small border-default-200 dark:border-default-100">
{children}
</div>
);`;
const App = `import {Listbox, ListboxItem, RadioGroup, Radio} from "@nextui-org/react";
import {ListboxWrapper} from "./ListboxWrapper";
export default function App() {
const [selectedVariant, setSelectedVariant] = React.useState("solid")
const [selectedColor, setSelectedColor] = React.useState("default")
const variants = ["solid", "bordered", "light", "flat", "faded", "shadow"];
const colors = ["default", "primary", "secondary", "success", "warning", "danger"];
return (
<div className="flex flex-col gap-4">
<ListboxWrapper>
<Listbox
aria-label="Listbox Variants"
color={selectedColor}
variant={selectedVariant}
>
<ListboxItem key="new">New file</ListboxItem>
<ListboxItem key="copy">Copy link</ListboxItem>
<ListboxItem key="edit">Edit file</ListboxItem>
<ListboxItem key="delete" className="text-danger" color="danger">
Delete file
</ListboxItem>
</Listbox>
</ListboxWrapper>
<div className="flex flex-col gap-2">
<RadioGroup
label="Select listbox item variant"
orientation="horizontal"
color={selectedVariant}
defaultValue="solid"
onValueChange={setSelectedVariant}
>
{variants.map((variant) => (
<Radio key={variant} value={variant} className="capitalize">
{variant}
</Radio>
))}
</RadioGroup>
<RadioGroup
label="Select listbox item color"
orientation="horizontal"
color={selectedColor}
defaultValue="default"
onValueChange={setSelectedColor}
>
{colors.map((color) => (
<Radio key={color} value={color} className="capitalize">
{color}
</Radio>
))}
</RadioGroup>
</div>
</div>
);
}`;
const react = {
"/App.jsx": App,
"/ListboxWrapper.jsx": ListboxWrapper,
};
export default {
...react,
};

View File

@ -5,7 +5,7 @@ export default function App() {
return (
<div className="flex flex-col gap-5">
<p className="text-default-500">Selected Page: {currentPage}</p>
<p className="text-small text-default-500">Selected Page: {currentPage}</p>
<Pagination
total={10}
color="secondary"

View File

@ -0,0 +1,54 @@
const Content = `export const Content = () => (
<div>
<p>
Sit nulla est ex deserunt exercitation anim occaecat. Nostrud ullamco deserunt aute id consequat veniam incididunt duis in sint irure nisi. Mollit officia cillum Lorem ullamco minim nostrud elit officia tempor esse quis.
</p>
<p>
Sunt ad dolore quis aute consequat. Magna exercitation reprehenderit magna aute tempor cupidatat consequat elit dolor adipisicing. Mollit dolor eiusmod sunt ex incididunt cillum quis. Velit duis sit officia eiusmod Lorem aliqua enim laboris do dolor eiusmod. Et mollit incididunt nisi consectetur esse laborum eiusmod pariatur proident Lorem eiusmod et. Culpa deserunt nostrud ad veniam.
</p>
<p>
Est velit labore esse esse cupidatat. Velit id elit consequat minim. Mollit enim excepteur ea laboris adipisicing aliqua proident occaecat do do adipisicing adipisicing ut fugiat. Consequat pariatur ullamco aute sunt esse. Irure excepteur eu non eiusmod. Commodo commodo et ad ipsum elit esse pariatur sit adipisicing sunt excepteur enim.
</p>
<p>
Incididunt duis commodo mollit esse veniam non exercitation dolore occaecat ea nostrud laboris. Adipisicing occaecat fugiat fugiat irure fugiat in magna non consectetur proident fugiat. Commodo magna et aliqua elit sint cupidatat. Sint aute ullamco enim cillum anim ex. Est eiusmod commodo occaecat consequat laboris est do duis. Enim incididunt non culpa velit quis aute in elit magna ullamco in consequat ex proident.
</p>
<p>
Dolore incididunt mollit fugiat pariatur cupidatat ipsum laborum cillum. Commodo consequat velit cupidatat duis ex nisi non aliquip ad ea pariatur do culpa. Eiusmod proident adipisicing tempor tempor qui pariatur voluptate dolor do ea commodo. Veniam voluptate cupidatat ex nisi do ullamco in quis elit.
</p>
<p>
Cillum proident veniam cupidatat pariatur laborum tempor cupidatat anim eiusmod id nostrud pariatur tempor reprehenderit. Do esse ullamco laboris sunt proident est ea exercitation cupidatat. Do Lorem eiusmod aliqua culpa ullamco consectetur veniam voluptate cillum. Dolor consequat cillum tempor laboris mollit laborum reprehenderit reprehenderit veniam aliqua deserunt cupidatat consequat id.
</p>
<p>
Est id tempor excepteur enim labore sint aliquip consequat duis minim tempor proident. Dolor incididunt aliquip minim elit ea. Exercitation non officia eu id.
</p>
<p>
Ipsum ipsum consequat incididunt do aliquip pariatur nostrud. Qui ut sint culpa labore Lorem. Magna deserunt aliquip aute duis consectetur magna amet anim. Magna fugiat est nostrud veniam. Officia duis ea sunt aliqua.
</p>
<p>
Ipsum minim officia aute anim minim aute aliquip aute non in non. Ipsum aliquip proident ut dolore eiusmod ad fugiat fugiat ut ex. Ea velit Lorem ut et commodo nulla voluptate veniam ea et aliqua esse id. Pariatur dolor et adipisicing ea mollit. Ipsum non irure proident ipsum dolore aliquip adipisicing laborum irure dolor nostrud occaecat exercitation.
</p>
<p>
Culpa qui reprehenderit nostrud aliqua reprehenderit et ullamco proident nisi commodo non ut. Ipsum quis irure nisi sint do qui velit nisi. Sunt voluptate eu reprehenderit tempor consequat eiusmod Lorem irure velit duis Lorem laboris ipsum cupidatat. Pariatur excepteur tempor veniam cillum et nulla ipsum veniam ad ipsum ad aute. Est officia duis pariatur ad eiusmod id voluptate.
</p>
</div>
);`;
const App = `import {ScrollShadow} from "@nextui-org/react";
import {Content} from "./Content";
export default function App() {
return (
<ScrollShadow size={100} className="w-[300px] h-[400px]">
<Content />
</ScrollShadow>
);
}`;
const react = {
"/App.jsx": App,
"/Content.jsx": Content,
};
export default {
...react,
};

View File

@ -0,0 +1,54 @@
const Content = `export const Content = () => (
<div>
<p>
Sit nulla est ex deserunt exercitation anim occaecat. Nostrud ullamco deserunt aute id consequat veniam incididunt duis in sint irure nisi. Mollit officia cillum Lorem ullamco minim nostrud elit officia tempor esse quis.
</p>
<p>
Sunt ad dolore quis aute consequat. Magna exercitation reprehenderit magna aute tempor cupidatat consequat elit dolor adipisicing. Mollit dolor eiusmod sunt ex incididunt cillum quis. Velit duis sit officia eiusmod Lorem aliqua enim laboris do dolor eiusmod. Et mollit incididunt nisi consectetur esse laborum eiusmod pariatur proident Lorem eiusmod et. Culpa deserunt nostrud ad veniam.
</p>
<p>
Est velit labore esse esse cupidatat. Velit id elit consequat minim. Mollit enim excepteur ea laboris adipisicing aliqua proident occaecat do do adipisicing adipisicing ut fugiat. Consequat pariatur ullamco aute sunt esse. Irure excepteur eu non eiusmod. Commodo commodo et ad ipsum elit esse pariatur sit adipisicing sunt excepteur enim.
</p>
<p>
Incididunt duis commodo mollit esse veniam non exercitation dolore occaecat ea nostrud laboris. Adipisicing occaecat fugiat fugiat irure fugiat in magna non consectetur proident fugiat. Commodo magna et aliqua elit sint cupidatat. Sint aute ullamco enim cillum anim ex. Est eiusmod commodo occaecat consequat laboris est do duis. Enim incididunt non culpa velit quis aute in elit magna ullamco in consequat ex proident.
</p>
<p>
Dolore incididunt mollit fugiat pariatur cupidatat ipsum laborum cillum. Commodo consequat velit cupidatat duis ex nisi non aliquip ad ea pariatur do culpa. Eiusmod proident adipisicing tempor tempor qui pariatur voluptate dolor do ea commodo. Veniam voluptate cupidatat ex nisi do ullamco in quis elit.
</p>
<p>
Cillum proident veniam cupidatat pariatur laborum tempor cupidatat anim eiusmod id nostrud pariatur tempor reprehenderit. Do esse ullamco laboris sunt proident est ea exercitation cupidatat. Do Lorem eiusmod aliqua culpa ullamco consectetur veniam voluptate cillum. Dolor consequat cillum tempor laboris mollit laborum reprehenderit reprehenderit veniam aliqua deserunt cupidatat consequat id.
</p>
<p>
Est id tempor excepteur enim labore sint aliquip consequat duis minim tempor proident. Dolor incididunt aliquip minim elit ea. Exercitation non officia eu id.
</p>
<p>
Ipsum ipsum consequat incididunt do aliquip pariatur nostrud. Qui ut sint culpa labore Lorem. Magna deserunt aliquip aute duis consectetur magna amet anim. Magna fugiat est nostrud veniam. Officia duis ea sunt aliqua.
</p>
<p>
Ipsum minim officia aute anim minim aute aliquip aute non in non. Ipsum aliquip proident ut dolore eiusmod ad fugiat fugiat ut ex. Ea velit Lorem ut et commodo nulla voluptate veniam ea et aliqua esse id. Pariatur dolor et adipisicing ea mollit. Ipsum non irure proident ipsum dolore aliquip adipisicing laborum irure dolor nostrud occaecat exercitation.
</p>
<p>
Culpa qui reprehenderit nostrud aliqua reprehenderit et ullamco proident nisi commodo non ut. Ipsum quis irure nisi sint do qui velit nisi. Sunt voluptate eu reprehenderit tempor consequat eiusmod Lorem irure velit duis Lorem laboris ipsum cupidatat. Pariatur excepteur tempor veniam cillum et nulla ipsum veniam ad ipsum ad aute. Est officia duis pariatur ad eiusmod id voluptate.
</p>
</div>
);`;
const App = `import {ScrollShadow} from "@nextui-org/react";
import {Content} from "./Content";
export default function App() {
return (
<ScrollShadow hideScrollBar className="w-[300px] h-[400px]">
<Content />
</ScrollShadow>
);
}`;
const react = {
"/App.jsx": App,
"/Content.jsx": Content,
};
export default {
...react,
};

View File

@ -0,0 +1,54 @@
const Content = `export const Content = ({className}) => (
<div className={className}>
<p>
Sit nulla est ex deserunt exercitation anim occaecat. Nostrud ullamco deserunt aute id consequat veniam incididunt duis in sint irure nisi. Mollit officia cillum Lorem ullamco minim nostrud elit officia tempor esse quis.
</p>
<p>
Sunt ad dolore quis aute consequat. Magna exercitation reprehenderit magna aute tempor cupidatat consequat elit dolor adipisicing. Mollit dolor eiusmod sunt ex incididunt cillum quis. Velit duis sit officia eiusmod Lorem aliqua enim laboris do dolor eiusmod. Et mollit incididunt nisi consectetur esse laborum eiusmod pariatur proident Lorem eiusmod et. Culpa deserunt nostrud ad veniam.
</p>
<p>
Est velit labore esse esse cupidatat. Velit id elit consequat minim. Mollit enim excepteur ea laboris adipisicing aliqua proident occaecat do do adipisicing adipisicing ut fugiat. Consequat pariatur ullamco aute sunt esse. Irure excepteur eu non eiusmod. Commodo commodo et ad ipsum elit esse pariatur sit adipisicing sunt excepteur enim.
</p>
<p>
Incididunt duis commodo mollit esse veniam non exercitation dolore occaecat ea nostrud laboris. Adipisicing occaecat fugiat fugiat irure fugiat in magna non consectetur proident fugiat. Commodo magna et aliqua elit sint cupidatat. Sint aute ullamco enim cillum anim ex. Est eiusmod commodo occaecat consequat laboris est do duis. Enim incididunt non culpa velit quis aute in elit magna ullamco in consequat ex proident.
</p>
<p>
Dolore incididunt mollit fugiat pariatur cupidatat ipsum laborum cillum. Commodo consequat velit cupidatat duis ex nisi non aliquip ad ea pariatur do culpa. Eiusmod proident adipisicing tempor tempor qui pariatur voluptate dolor do ea commodo. Veniam voluptate cupidatat ex nisi do ullamco in quis elit.
</p>
<p>
Cillum proident veniam cupidatat pariatur laborum tempor cupidatat anim eiusmod id nostrud pariatur tempor reprehenderit. Do esse ullamco laboris sunt proident est ea exercitation cupidatat. Do Lorem eiusmod aliqua culpa ullamco consectetur veniam voluptate cillum. Dolor consequat cillum tempor laboris mollit laborum reprehenderit reprehenderit veniam aliqua deserunt cupidatat consequat id.
</p>
<p>
Est id tempor excepteur enim labore sint aliquip consequat duis minim tempor proident. Dolor incididunt aliquip minim elit ea. Exercitation non officia eu id.
</p>
<p>
Ipsum ipsum consequat incididunt do aliquip pariatur nostrud. Qui ut sint culpa labore Lorem. Magna deserunt aliquip aute duis consectetur magna amet anim. Magna fugiat est nostrud veniam. Officia duis ea sunt aliqua.
</p>
<p>
Ipsum minim officia aute anim minim aute aliquip aute non in non. Ipsum aliquip proident ut dolore eiusmod ad fugiat fugiat ut ex. Ea velit Lorem ut et commodo nulla voluptate veniam ea et aliqua esse id. Pariatur dolor et adipisicing ea mollit. Ipsum non irure proident ipsum dolore aliquip adipisicing laborum irure dolor nostrud occaecat exercitation.
</p>
<p>
Culpa qui reprehenderit nostrud aliqua reprehenderit et ullamco proident nisi commodo non ut. Ipsum quis irure nisi sint do qui velit nisi. Sunt voluptate eu reprehenderit tempor consequat eiusmod Lorem irure velit duis Lorem laboris ipsum cupidatat. Pariatur excepteur tempor veniam cillum et nulla ipsum veniam ad ipsum ad aute. Est officia duis pariatur ad eiusmod id voluptate.
</p>
</div>
);`;
const App = `import {ScrollShadow} from "@nextui-org/react";
import {Content} from "./Content";
export default function App() {
return (
<ScrollShadow orientation="horizontal" className="max-w-[400px] max-h-[300px]">
<Content className="w-[800px]" />
</ScrollShadow>
);
}`;
const react = {
"/App.jsx": App,
"/Content.jsx": Content,
};
export default {
...react,
};

View File

@ -0,0 +1,13 @@
import usage from "./usage";
import hideScrollbar from "./hide-scrollbar";
import customSize from "./custom-size";
import horizontal from "./horizontal";
import offset from "./offset";
export const scrollShadowContent = {
usage,
hideScrollbar,
customSize,
horizontal,
offset,
};

View File

@ -0,0 +1,59 @@
const Content = `export const Content = ({className}) => (
<div className={className}>
<p>
Sit nulla est ex deserunt exercitation anim occaecat. Nostrud ullamco deserunt aute id consequat veniam incididunt duis in sint irure nisi. Mollit officia cillum Lorem ullamco minim nostrud elit officia tempor esse quis.
</p>
<p>
Sunt ad dolore quis aute consequat. Magna exercitation reprehenderit magna aute tempor cupidatat consequat elit dolor adipisicing. Mollit dolor eiusmod sunt ex incididunt cillum quis. Velit duis sit officia eiusmod Lorem aliqua enim laboris do dolor eiusmod. Et mollit incididunt nisi consectetur esse laborum eiusmod pariatur proident Lorem eiusmod et. Culpa deserunt nostrud ad veniam.
</p>
<p>
Est velit labore esse esse cupidatat. Velit id elit consequat minim. Mollit enim excepteur ea laboris adipisicing aliqua proident occaecat do do adipisicing adipisicing ut fugiat. Consequat pariatur ullamco aute sunt esse. Irure excepteur eu non eiusmod. Commodo commodo et ad ipsum elit esse pariatur sit adipisicing sunt excepteur enim.
</p>
<p>
Incididunt duis commodo mollit esse veniam non exercitation dolore occaecat ea nostrud laboris. Adipisicing occaecat fugiat fugiat irure fugiat in magna non consectetur proident fugiat. Commodo magna et aliqua elit sint cupidatat. Sint aute ullamco enim cillum anim ex. Est eiusmod commodo occaecat consequat laboris est do duis. Enim incididunt non culpa velit quis aute in elit magna ullamco in consequat ex proident.
</p>
<p>
Dolore incididunt mollit fugiat pariatur cupidatat ipsum laborum cillum. Commodo consequat velit cupidatat duis ex nisi non aliquip ad ea pariatur do culpa. Eiusmod proident adipisicing tempor tempor qui pariatur voluptate dolor do ea commodo. Veniam voluptate cupidatat ex nisi do ullamco in quis elit.
</p>
<p>
Cillum proident veniam cupidatat pariatur laborum tempor cupidatat anim eiusmod id nostrud pariatur tempor reprehenderit. Do esse ullamco laboris sunt proident est ea exercitation cupidatat. Do Lorem eiusmod aliqua culpa ullamco consectetur veniam voluptate cillum. Dolor consequat cillum tempor laboris mollit laborum reprehenderit reprehenderit veniam aliqua deserunt cupidatat consequat id.
</p>
<p>
Est id tempor excepteur enim labore sint aliquip consequat duis minim tempor proident. Dolor incididunt aliquip minim elit ea. Exercitation non officia eu id.
</p>
<p>
Ipsum ipsum consequat incididunt do aliquip pariatur nostrud. Qui ut sint culpa labore Lorem. Magna deserunt aliquip aute duis consectetur magna amet anim. Magna fugiat est nostrud veniam. Officia duis ea sunt aliqua.
</p>
<p>
Ipsum minim officia aute anim minim aute aliquip aute non in non. Ipsum aliquip proident ut dolore eiusmod ad fugiat fugiat ut ex. Ea velit Lorem ut et commodo nulla voluptate veniam ea et aliqua esse id. Pariatur dolor et adipisicing ea mollit. Ipsum non irure proident ipsum dolore aliquip adipisicing laborum irure dolor nostrud occaecat exercitation.
</p>
<p>
Culpa qui reprehenderit nostrud aliqua reprehenderit et ullamco proident nisi commodo non ut. Ipsum quis irure nisi sint do qui velit nisi. Sunt voluptate eu reprehenderit tempor consequat eiusmod Lorem irure velit duis Lorem laboris ipsum cupidatat. Pariatur excepteur tempor veniam cillum et nulla ipsum veniam ad ipsum ad aute. Est officia duis pariatur ad eiusmod id voluptate.
</p>
</div>
);`;
const App = `import {ScrollShadow} from "@nextui-org/react";
import {Content} from "./Content";
export default function App() {
return (
<ScrollShadow
hideScrollBar
offset={100}
orientation="horizontal"
className="max-w-[400px] max-h-[300px]"
>
<Content className="w-[800px]" />
</ScrollShadow>
);
}`;
const react = {
"/App.jsx": App,
"/Content.jsx": Content,
};
export default {
...react,
};

View File

@ -0,0 +1,54 @@
const Content = `export const Content = () => (
<div>
<p>
Sit nulla est ex deserunt exercitation anim occaecat. Nostrud ullamco deserunt aute id consequat veniam incididunt duis in sint irure nisi. Mollit officia cillum Lorem ullamco minim nostrud elit officia tempor esse quis.
</p>
<p>
Sunt ad dolore quis aute consequat. Magna exercitation reprehenderit magna aute tempor cupidatat consequat elit dolor adipisicing. Mollit dolor eiusmod sunt ex incididunt cillum quis. Velit duis sit officia eiusmod Lorem aliqua enim laboris do dolor eiusmod. Et mollit incididunt nisi consectetur esse laborum eiusmod pariatur proident Lorem eiusmod et. Culpa deserunt nostrud ad veniam.
</p>
<p>
Est velit labore esse esse cupidatat. Velit id elit consequat minim. Mollit enim excepteur ea laboris adipisicing aliqua proident occaecat do do adipisicing adipisicing ut fugiat. Consequat pariatur ullamco aute sunt esse. Irure excepteur eu non eiusmod. Commodo commodo et ad ipsum elit esse pariatur sit adipisicing sunt excepteur enim.
</p>
<p>
Incididunt duis commodo mollit esse veniam non exercitation dolore occaecat ea nostrud laboris. Adipisicing occaecat fugiat fugiat irure fugiat in magna non consectetur proident fugiat. Commodo magna et aliqua elit sint cupidatat. Sint aute ullamco enim cillum anim ex. Est eiusmod commodo occaecat consequat laboris est do duis. Enim incididunt non culpa velit quis aute in elit magna ullamco in consequat ex proident.
</p>
<p>
Dolore incididunt mollit fugiat pariatur cupidatat ipsum laborum cillum. Commodo consequat velit cupidatat duis ex nisi non aliquip ad ea pariatur do culpa. Eiusmod proident adipisicing tempor tempor qui pariatur voluptate dolor do ea commodo. Veniam voluptate cupidatat ex nisi do ullamco in quis elit.
</p>
<p>
Cillum proident veniam cupidatat pariatur laborum tempor cupidatat anim eiusmod id nostrud pariatur tempor reprehenderit. Do esse ullamco laboris sunt proident est ea exercitation cupidatat. Do Lorem eiusmod aliqua culpa ullamco consectetur veniam voluptate cillum. Dolor consequat cillum tempor laboris mollit laborum reprehenderit reprehenderit veniam aliqua deserunt cupidatat consequat id.
</p>
<p>
Est id tempor excepteur enim labore sint aliquip consequat duis minim tempor proident. Dolor incididunt aliquip minim elit ea. Exercitation non officia eu id.
</p>
<p>
Ipsum ipsum consequat incididunt do aliquip pariatur nostrud. Qui ut sint culpa labore Lorem. Magna deserunt aliquip aute duis consectetur magna amet anim. Magna fugiat est nostrud veniam. Officia duis ea sunt aliqua.
</p>
<p>
Ipsum minim officia aute anim minim aute aliquip aute non in non. Ipsum aliquip proident ut dolore eiusmod ad fugiat fugiat ut ex. Ea velit Lorem ut et commodo nulla voluptate veniam ea et aliqua esse id. Pariatur dolor et adipisicing ea mollit. Ipsum non irure proident ipsum dolore aliquip adipisicing laborum irure dolor nostrud occaecat exercitation.
</p>
<p>
Culpa qui reprehenderit nostrud aliqua reprehenderit et ullamco proident nisi commodo non ut. Ipsum quis irure nisi sint do qui velit nisi. Sunt voluptate eu reprehenderit tempor consequat eiusmod Lorem irure velit duis Lorem laboris ipsum cupidatat. Pariatur excepteur tempor veniam cillum et nulla ipsum veniam ad ipsum ad aute. Est officia duis pariatur ad eiusmod id voluptate.
</p>
</div>
);`;
const App = `import {ScrollShadow} from "@nextui-org/react";
import {Content} from "./Content";
export default function App() {
return (
<ScrollShadow className="w-[300px] h-[400px]">
<Content />
</ScrollShadow>
);
}`;
const react = {
"/App.jsx": App,
"/Content.jsx": Content,
};
export default {
...react,
};

View File

@ -0,0 +1,187 @@
const usePokemonListTs = `export type Pokemon = {
name: string;
url: string;
};
export type UsePokemonListProps = {
/** Delay to wait before fetching more items */
fetchDelay?: number;
};
export function usePokemonList({fetchDelay = 0}: UsePokemonListProps = {}) {
const [items, setItems] = React.useState<Pokemon[]>([]);
const [hasMore, setHasMore] = React.useState(true);
const [isLoading, setIsLoading] = React.useState(false);
const [offset, setOffset] = React.useState(0);
const limit = 10; // Number of items per page, adjust as necessary
const loadPokemon = async (currentOffset: number) => {
const controller = new AbortController();
const {signal} = controller;
try {
setIsLoading(true);
if (offset > 0) {
// Delay to simulate network latency
await new Promise((resolve) => setTimeout(resolve, fetchDelay));
}
let res = await fetch(
\`https://pokeapi.co/api/v2/pokemon?offset=\${currentOffset}&limit=\${limit}\`,
{signal},
);
if (!res.ok) {
throw new Error("Network response was not ok");
}
let json = await res.json();
setHasMore(json.next !== null);
// Append new results to existing ones
setItems((prevItems) => [...prevItems, ...json.results]);
} catch (error) {
if (error.name === "AbortError") {
console.log("Fetch aborted");
} else {
console.error("There was an error with the fetch operation:", error);
}
} finally {
setIsLoading(false);
}
};
React.useEffect(() => {
loadPokemon(offset);
}, []);
const onLoadMore = () => {
const newOffset = offset + limit;
setOffset(newOffset);
loadPokemon(newOffset);
};
return {
items,
hasMore,
isLoading,
onLoadMore,
};
}
`;
const usePokemonList = `export function usePokemonList({fetchDelay = 0} = {}) {
const [items, setItems] = React.useState([]);
const [hasMore, setHasMore] = React.useState(true);
const [isLoading, setIsLoading] = React.useState(false);
const [offset, setOffset] = React.useState(0);
const limit = 10; // Number of items per page, adjust as necessary
const loadPokemon = async (currentOffset) => {
const controller = new AbortController();
const {signal} = controller;
try {
setIsLoading(true);
if (offset > 0) {
// Delay to simulate network latency
await new Promise((resolve) => setTimeout(resolve, fetchDelay));
}
let res = await fetch(
\`https://pokeapi.co/api/v2/pokemon?offset=\${currentOffset}&limit=\${limit}\`,
{signal},
);
if (!res.ok) {
throw new Error("Network response was not ok");
}
let json = await res.json();
setHasMore(json.next !== null);
// Append new results to existing ones
setItems((prevItems) => [...prevItems, ...json.results]);
} catch (error) {
if (error.name === "AbortError") {
console.log("Fetch aborted");
} else {
console.error("There was an error with the fetch operation:", error);
}
} finally {
setIsLoading(false);
}
};
React.useEffect(() => {
loadPokemon(offset);
}, []);
const onLoadMore = () => {
const newOffset = offset + limit;
setOffset(newOffset);
loadPokemon(newOffset);
};
return {
items,
hasMore,
isLoading,
onLoadMore,
};
};`;
const App = `import {Select, SelectItem} from "@nextui-org/react";
import {useInfiniteScroll} from "@nextui-org/use-infinity-scroll";
import {usePokemonList} from "./usePokemonList";
export default function App() {
const [isOpen, setIsOpen] = React.useState(false);
const {items, hasMore, isLoading, onLoadMore} = usePokemonList({fetchDelay: 1500});
const [, scrollerRef] = useInfiniteScroll({
hasMore,
isEnabled: isOpen,
shouldUseLoader: false, // We don't want to show the loader at the bottom of the list
onLoadMore,
});
return (
<Select
className="max-w-xs"
isLoading={isLoading}
items={items}
label="Pick a Pokemon"
placeholder="Select a Pokemon"
scrollRef={scrollerRef}
selectionMode="single"
onOpenChange={setIsOpen}
>
{(item) => (
<SelectItem key={item.name} className="capitalize">
{item.name}
</SelectItem>
)}
</Select>
);
}`;
const react = {
"/App.jsx": App,
"/usePokemonList.js": usePokemonList,
};
const reactTs = {
"/App.tsx": App,
"/usePokemonList.ts": usePokemonListTs,
};
export default {
...react,
...reactTs,
};

View File

@ -0,0 +1,71 @@
const data = `export const animals = [
{label: "Cat", value: "cat", description: "The second most popular pet in the world"},
{label: "Dog", value: "dog", description: "The most popular pet in the world"},
{label: "Elephant", value: "elephant", description: "The largest land animal"},
{label: "Lion", value: "lion", description: "The king of the jungle"},
{label: "Tiger", value: "tiger", description: "The largest cat species"},
{label: "Giraffe", value: "giraffe", description: "The tallest land animal"},
{
label: "Dolphin",
value: "dolphin",
description: "A widely distributed and diverse group of aquatic mammals",
},
{label: "Penguin", value: "penguin", description: "A group of aquatic flightless birds"},
{label: "Zebra", value: "zebra", description: "A several species of African equids"},
{
label: "Shark",
value: "shark",
description: "A group of elasmobranch fish characterized by a cartilaginous skeleton",
},
{
label: "Whale",
value: "whale",
description: "Diverse group of fully aquatic placental marine mammals",
},
{label: "Otter", value: "otter", description: "A carnivorous mammal in the subfamily Lutrinae"},
{label: "Crocodile", value: "crocodile", description: "A large semiaquatic reptile"},
];`;
const App = `import {Select, SelectItem} from "@nextui-org/react";
import {animals} from "./data";
export default function App() {
const colors = [
"default",
"primary",
"secondary",
"success",
"warning",
"danger",
];
return (
<div className="w-full flex flex-row flex-wrap gap-4">
{colors.map((color) => (
<Select
key={color}
color={color}
label="Favorite Animal"
placeholder="Select an animal"
defaultSelectedKeys={["cat"]}
className="max-w-xs"
>
{animals.map((animal) => (
<SelectItem key={animal.value} value={animal.value}>
{animal.label}
</SelectItem>
))}
</Select>
))}
</div>
);
}`;
const react = {
"/App.jsx": App,
"/data.js": data,
};
export default {
...react,
};

View File

@ -0,0 +1,238 @@
const data = `export const users = [
{
id: 1,
name: "Tony Reichert",
role: "CEO",
team: "Management",
status: "active",
age: "29",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/male/1.png",
email: "tony.reichert@example.com",
},
{
id: 2,
name: "Zoey Lang",
role: "Tech Lead",
team: "Development",
status: "paused",
age: "25",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/female/1.png",
email: "zoey.lang@example.com",
},
{
id: 3,
name: "Jane Fisher",
role: "Sr. Dev",
team: "Development",
status: "active",
age: "22",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/female/2.png",
email: "jane.fisher@example.com",
},
{
id: 4,
name: "William Howard",
role: "C.M.",
team: "Marketing",
status: "vacation",
age: "28",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/male/2.png",
email: "william.howard@example.com",
},
{
id: 5,
name: "Kristen Copper",
role: "S. Manager",
team: "Sales",
status: "active",
age: "24",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/female/3.png",
email: "kristen.cooper@example.com",
},
{
id: 6,
name: "Brian Kim",
role: "P. Manager",
team: "Management",
age: "29",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/male/3.png",
email: "brian.kim@example.com",
status: "Active",
},
{
id: 7,
name: "Michael Hunt",
role: "Designer",
team: "Design",
status: "paused",
age: "27",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/male/4.png",
email: "michael.hunt@example.com",
},
{
id: 8,
name: "Samantha Brooks",
role: "HR Manager",
team: "HR",
status: "active",
age: "31",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/female/4.png",
email: "samantha.brooks@example.com",
},
{
id: 9,
name: "Frank Harrison",
role: "F. Manager",
team: "Finance",
status: "vacation",
age: "33",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/male/5.png",
email: "frank.harrison@example.com",
},
{
id: 10,
name: "Emma Adams",
role: "Ops Manager",
team: "Operations",
status: "active",
age: "35",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/female/5.png",
email: "emma.adams@example.com",
},
{
id: 11,
name: "Brandon Stevens",
role: "Jr. Dev",
team: "Development",
status: "active",
age: "22",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/male/7.png",
email: "brandon.stevens@example.com",
},
{
id: 12,
name: "Megan Richards",
role: "P. Manager",
team: "Product",
status: "paused",
age: "28",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/female/7.png",
email: "megan.richards@example.com",
},
{
id: 13,
name: "Oliver Scott",
role: "S. Manager",
team: "Security",
status: "active",
age: "37",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/male/8.png",
email: "oliver.scott@example.com",
},
{
id: 14,
name: "Grace Allen",
role: "M. Specialist",
team: "Marketing",
status: "active",
age: "30",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/female/8.png",
email: "grace.allen@example.com",
},
{
id: 15,
name: "Noah Carter",
role: "IT Specialist",
team: "I. Technology",
status: "paused",
age: "31",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/male/9.png",
email: "noah.carter@example.com",
},
{
id: 16,
name: "Ava Perez",
role: "Manager",
team: "Sales",
status: "active",
age: "29",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/female/9.png",
email: "ava.perez@example.com",
},
{
id: 17,
name: "Liam Johnson",
role: "Data Analyst",
team: "Analysis",
status: "active",
age: "28",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/male/11.png",
email: "liam.johnson@example.com",
},
{
id: 18,
name: "Sophia Taylor",
role: "QA Analyst",
team: "Testing",
status: "active",
age: "27",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/female/11.png",
email: "sophia.taylor@example.com",
},
{
id: 19,
name: "Lucas Harris",
role: "Administrator",
team: "Information Technology",
status: "paused",
age: "32",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/male/12.png",
email: "lucas.harris@example.com",
},
{
id: 20,
name: "Mia Robinson",
role: "Coordinator",
team: "Operations",
status: "active",
age: "26",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/female/12.png",
email: "mia.robinson@example.com",
},
];`;
const App = `import {Select, SelectItem, Avatar} from "@nextui-org/react";
import {users} from "./data";
export default function App() {
return (
<Select
items={users}
label="Assigned to"
placeholder="Select a user"
labelPlacement="outside"
className="max-w-xs"
>
{(user) => (
<SelectItem key={user.id} textValue={user.name}>
<div className="flex gap-2 items-center">
<Avatar alt={user.name} className="flex-shrink-0" size="sm" src={user.avatar} />
<div className="flex flex-col">
<span className="text-small">{user.name}</span>
<span className="text-tiny text-default-400">{user.email}</span>
</div>
</div>
</SelectItem>
)}
</Select>
);
}`;
const react = {
"/App.jsx": App,
"/data.js": data,
};
export default {
...react,
};

View File

@ -0,0 +1,320 @@
const data = `export const users = [
{
id: 1,
name: "Tony Reichert",
role: "CEO",
team: "Management",
status: "active",
age: "29",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/male/1.png",
email: "tony.reichert@example.com",
},
{
id: 2,
name: "Zoey Lang",
role: "Tech Lead",
team: "Development",
status: "paused",
age: "25",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/female/1.png",
email: "zoey.lang@example.com",
},
{
id: 3,
name: "Jane Fisher",
role: "Sr. Dev",
team: "Development",
status: "active",
age: "22",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/female/2.png",
email: "jane.fisher@example.com",
},
{
id: 4,
name: "William Howard",
role: "C.M.",
team: "Marketing",
status: "vacation",
age: "28",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/male/2.png",
email: "william.howard@example.com",
},
{
id: 5,
name: "Kristen Copper",
role: "S. Manager",
team: "Sales",
status: "active",
age: "24",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/female/3.png",
email: "kristen.cooper@example.com",
},
{
id: 6,
name: "Brian Kim",
role: "P. Manager",
team: "Management",
age: "29",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/male/3.png",
email: "brian.kim@example.com",
status: "Active",
},
{
id: 7,
name: "Michael Hunt",
role: "Designer",
team: "Design",
status: "paused",
age: "27",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/male/4.png",
email: "michael.hunt@example.com",
},
{
id: 8,
name: "Samantha Brooks",
role: "HR Manager",
team: "HR",
status: "active",
age: "31",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/female/4.png",
email: "samantha.brooks@example.com",
},
{
id: 9,
name: "Frank Harrison",
role: "F. Manager",
team: "Finance",
status: "vacation",
age: "33",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/male/5.png",
email: "frank.harrison@example.com",
},
{
id: 10,
name: "Emma Adams",
role: "Ops Manager",
team: "Operations",
status: "active",
age: "35",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/female/5.png",
email: "emma.adams@example.com",
},
{
id: 11,
name: "Brandon Stevens",
role: "Jr. Dev",
team: "Development",
status: "active",
age: "22",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/male/7.png",
email: "brandon.stevens@example.com",
},
{
id: 12,
name: "Megan Richards",
role: "P. Manager",
team: "Product",
status: "paused",
age: "28",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/female/7.png",
email: "megan.richards@example.com",
},
{
id: 13,
name: "Oliver Scott",
role: "S. Manager",
team: "Security",
status: "active",
age: "37",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/male/8.png",
email: "oliver.scott@example.com",
},
{
id: 14,
name: "Grace Allen",
role: "M. Specialist",
team: "Marketing",
status: "active",
age: "30",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/female/8.png",
email: "grace.allen@example.com",
},
{
id: 15,
name: "Noah Carter",
role: "IT Specialist",
team: "I. Technology",
status: "paused",
age: "31",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/male/9.png",
email: "noah.carter@example.com",
},
{
id: 16,
name: "Ava Perez",
role: "Manager",
team: "Sales",
status: "active",
age: "29",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/female/9.png",
email: "ava.perez@example.com",
},
{
id: 17,
name: "Liam Johnson",
role: "Data Analyst",
team: "Analysis",
status: "active",
age: "28",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/male/11.png",
email: "liam.johnson@example.com",
},
{
id: 18,
name: "Sophia Taylor",
role: "QA Analyst",
team: "Testing",
status: "active",
age: "27",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/female/11.png",
email: "sophia.taylor@example.com",
},
{
id: 19,
name: "Lucas Harris",
role: "Administrator",
team: "Information Technology",
status: "paused",
age: "32",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/male/12.png",
email: "lucas.harris@example.com",
},
{
id: 20,
name: "Mia Robinson",
role: "Coordinator",
team: "Operations",
status: "active",
age: "26",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/female/12.png",
email: "mia.robinson@example.com",
},
];`;
const App = `import {Select, SelectItem, Avatar} from "@nextui-org/react";
import {users} from "./data";
export default function App() {
return (
<Select
items={users}
label="Assigned to"
placeholder="Select a user"
labelPlacement="outside"
classNames={{
base: "max-w-xs",
trigger: "h-12",
}}
renderValue={(items) => {
return items.map((item) => (
<div key={item.key} className="flex items-center gap-2">
<Avatar
alt={item.data.name}
className="flex-shrink-0"
size="sm"
src={item.data.avatar}
/>
<div className="flex flex-col">
<span>{item.data.name}</span>
<span className="text-default-500 text-tiny">({item.data.email})</span>
</div>
</div>
));
}}
>
{(user) => (
<SelectItem key={user.id} textValue={user.name}>
<div className="flex gap-2 items-center">
<Avatar alt={user.name} className="flex-shrink-0" size="sm" src={user.avatar} />
<div className="flex flex-col">
<span className="text-small">{user.name}</span>
<span className="text-tiny text-default-400">{user.email}</span>
</div>
</div>
</SelectItem>
)}
</Select>
);
}`;
const AppTs = `import {Select, SelectItem, Avatar, SelectedItems} from "@nextui-org/react";
import {users} from "./data";
type User = {
id: number;
name: string;
role: string;
team: string;
status: string;
age: string;
avatar: string;
email: string;
};
export default function App() {
return (
<Select
items={users}
label="Assigned to"
placeholder="Select a user"
labelPlacement="outside"
classNames={{
base: "max-w-xs",
trigger: "h-12",
}}
renderValue={(items: SelectedItems<User>) => {
return items.map((item) => (
<div key={item.key} className="flex items-center gap-2">
<Avatar
alt={item.data.name}
className="flex-shrink-0"
size="sm"
src={item.data.avatar}
/>
<div className="flex flex-col">
<span>{item.data.name}</span>
<span className="text-default-500 text-tiny">({item.data.email})</span>
</div>
</div>
));
}}
>
{(user) => (
<SelectItem key={user.id} textValue={user.name}>
<div className="flex gap-2 items-center">
<Avatar alt={user.name} className="flex-shrink-0" size="sm" src={user.avatar} />
<div className="flex flex-col">
<span className="text-small">{user.name}</span>
<span className="text-tiny text-default-400">{user.email}</span>
</div>
</div>
</SelectItem>
)}
</Select>
);
}`;
const react = {
"/App.jsx": App,
"/data.js": data,
};
const reactTs = {
"/App.tsx": AppTs,
"/data.ts": data,
};
export default {
...react,
...reactTs,
};

View File

@ -0,0 +1,55 @@
const App = `import {Select, SelectItem, SelectSection} from "@nextui-org/react";
export default function App() {
const headingClasses = "flex w-full sticky top-1 z-20 py-1.5 px-2 bg-default-100 shadow-small rounded-small";
return (
<Select
label="Favorite Animal"
placeholder="Select an animal"
className="max-w-xs"
scrollShadowProps={{
isEnabled: false,
}}
>
<SelectSection
title="Mammals"
classNames={{
heading: headingClasses,
}}
>
<SelectItem key="Lion">Lion</SelectItem>
<SelectItem key="Tiger">Tiger</SelectItem>
<SelectItem key="Elephant">Elephant</SelectItem>
<SelectItem key="Kangaroo">Kangaroo</SelectItem>
<SelectItem key="Panda">Panda</SelectItem>
<SelectItem key="Giraffe">Giraffe</SelectItem>
<SelectItem key="Zebra">Zebra</SelectItem>
<SelectItem key="Cheetah">Cheetah</SelectItem>
</SelectSection>
<SelectSection
title="Birds"
classNames={{
heading: headingClasses,
}}
>
<SelectItem key="Eagle">Eagle</SelectItem>
<SelectItem key="Parrot">Parrot</SelectItem>
<SelectItem key="Penguin">Penguin</SelectItem>
<SelectItem key="Ostrich">Ostrich</SelectItem>
<SelectItem key="Peacock">Peacock</SelectItem>
<SelectItem key="Swan">Swan</SelectItem>
<SelectItem key="Falcon">Falcon</SelectItem>
<SelectItem key="Flamingo">Flamingo</SelectItem>
</SelectSection>
</Select>
);
}`;
const react = {
"/App.jsx": App,
};
export default {
...react,
};

View File

@ -0,0 +1,81 @@
const data = `export const animals = [
{label: "Cat", value: "cat", description: "The second most popular pet in the world"},
{label: "Dog", value: "dog", description: "The most popular pet in the world"},
{label: "Elephant", value: "elephant", description: "The largest land animal"},
{label: "Lion", value: "lion", description: "The king of the jungle"},
{label: "Tiger", value: "tiger", description: "The largest cat species"},
{label: "Giraffe", value: "giraffe", description: "The tallest land animal"},
{
label: "Dolphin",
value: "dolphin",
description: "A widely distributed and diverse group of aquatic mammals",
},
{label: "Penguin", value: "penguin", description: "A group of aquatic flightless birds"},
{label: "Zebra", value: "zebra", description: "A several species of African equids"},
{
label: "Shark",
value: "shark",
description: "A group of elasmobranch fish characterized by a cartilaginous skeleton",
},
{
label: "Whale",
value: "whale",
description: "Diverse group of fully aquatic placental marine mammals",
},
{label: "Otter", value: "otter", description: "A carnivorous mammal in the subfamily Lutrinae"},
{label: "Crocodile", value: "crocodile", description: "A large semiaquatic reptile"},
];`;
const SelectorIcon = `export const SelectorIcon = (props) => (
<svg
aria-hidden="true"
fill="none"
focusable="false"
height="1em"
role="presentation"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="1.5"
viewBox="0 0 24 24"
width="1em"
{...props}
>
<path d="M0 0h24v24H0z" fill="none" stroke="none" />
<path d="M8 9l4 -4l4 4" />
<path d="M16 15l-4 4l-4 -4" />
</svg>
);`;
const App = `import {Select, SelectItem} from "@nextui-org/react";
import {SelectorIcon} from "./SelectorIcon";
import {animals} from "./data";
export default function App() {
return (
<Select
label="Favorite Animal"
placeholder="Select an animal"
labelPlacement="outside"
className="max-w-xs"
disableSelectorIconRotation
selectorIcon={<SelectorIcon />}
>
{animals.map((animal) => (
<SelectItem key={animal.value} value={animal.value}>
{animal.label}
</SelectItem>
))}
</Select>
);
}`;
const react = {
"/App.jsx": App,
"/data.js": data,
"/SelectorIcon.jsx": SelectorIcon,
};
export default {
...react,
};

View File

@ -0,0 +1,279 @@
const data = `export const users = [
{
id: 1,
name: "Tony Reichert",
role: "CEO",
team: "Management",
status: "active",
age: "29",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/male/1.png",
email: "tony.reichert@example.com",
},
{
id: 2,
name: "Zoey Lang",
role: "Tech Lead",
team: "Development",
status: "paused",
age: "25",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/female/1.png",
email: "zoey.lang@example.com",
},
{
id: 3,
name: "Jane Fisher",
role: "Sr. Dev",
team: "Development",
status: "active",
age: "22",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/female/2.png",
email: "jane.fisher@example.com",
},
{
id: 4,
name: "William Howard",
role: "C.M.",
team: "Marketing",
status: "vacation",
age: "28",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/male/2.png",
email: "william.howard@example.com",
},
{
id: 5,
name: "Kristen Copper",
role: "S. Manager",
team: "Sales",
status: "active",
age: "24",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/female/3.png",
email: "kristen.cooper@example.com",
},
{
id: 6,
name: "Brian Kim",
role: "P. Manager",
team: "Management",
age: "29",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/male/3.png",
email: "brian.kim@example.com",
status: "Active",
},
{
id: 7,
name: "Michael Hunt",
role: "Designer",
team: "Design",
status: "paused",
age: "27",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/male/4.png",
email: "michael.hunt@example.com",
},
{
id: 8,
name: "Samantha Brooks",
role: "HR Manager",
team: "HR",
status: "active",
age: "31",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/female/4.png",
email: "samantha.brooks@example.com",
},
{
id: 9,
name: "Frank Harrison",
role: "F. Manager",
team: "Finance",
status: "vacation",
age: "33",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/male/5.png",
email: "frank.harrison@example.com",
},
{
id: 10,
name: "Emma Adams",
role: "Ops Manager",
team: "Operations",
status: "active",
age: "35",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/female/5.png",
email: "emma.adams@example.com",
},
{
id: 11,
name: "Brandon Stevens",
role: "Jr. Dev",
team: "Development",
status: "active",
age: "22",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/male/7.png",
email: "brandon.stevens@example.com",
},
{
id: 12,
name: "Megan Richards",
role: "P. Manager",
team: "Product",
status: "paused",
age: "28",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/female/7.png",
email: "megan.richards@example.com",
},
{
id: 13,
name: "Oliver Scott",
role: "S. Manager",
team: "Security",
status: "active",
age: "37",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/male/8.png",
email: "oliver.scott@example.com",
},
{
id: 14,
name: "Grace Allen",
role: "M. Specialist",
team: "Marketing",
status: "active",
age: "30",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/female/8.png",
email: "grace.allen@example.com",
},
{
id: 15,
name: "Noah Carter",
role: "IT Specialist",
team: "I. Technology",
status: "paused",
age: "31",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/male/9.png",
email: "noah.carter@example.com",
},
{
id: 16,
name: "Ava Perez",
role: "Manager",
team: "Sales",
status: "active",
age: "29",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/female/9.png",
email: "ava.perez@example.com",
},
{
id: 17,
name: "Liam Johnson",
role: "Data Analyst",
team: "Analysis",
status: "active",
age: "28",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/male/11.png",
email: "liam.johnson@example.com",
},
{
id: 18,
name: "Sophia Taylor",
role: "QA Analyst",
team: "Testing",
status: "active",
age: "27",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/female/11.png",
email: "sophia.taylor@example.com",
},
{
id: 19,
name: "Lucas Harris",
role: "Administrator",
team: "Information Technology",
status: "paused",
age: "32",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/male/12.png",
email: "lucas.harris@example.com",
},
{
id: 20,
name: "Mia Robinson",
role: "Coordinator",
team: "Operations",
status: "active",
age: "26",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/female/12.png",
email: "mia.robinson@example.com",
},
];`;
const App = `import {Select, SelectItem, Avatar} from "@nextui-org/react";
import {users} from "./data";
export default function App() {
return (
<Select
items={users}
label="Assigned to"
className="max-w-xs"
variant="bordered"
classNames={{
label: "group-data-[filled=true]:-translate-y-5",
trigger: "min-h-unit-16",
listboxWrapper: "max-h-[400px]",
}}
listboxProps={{
itemClasses: {
base: [
"rounded-md",
"text-default-500",
"transition-opacity",
"data-[hover=true]:text-foreground",
"data-[hover=true]:bg-default-100",
"dark:data-[hover=true]:bg-default-50",
"data-[selectable=true]:focus:bg-default-50",
"data-[pressed=true]:opacity-70",
"data-[focus-visible=true]:ring-default-500",
],
},
}}
popoverProps={{
classNames: {
base: "p-0 border-small border-divider bg-background",
arrow: "bg-default-200",
},
}}
renderValue={(items) => {
return items.map((item) => (
<div key={item.key} className="flex items-center gap-2">
<Avatar
alt={item.data.name}
className="flex-shrink-0"
size="sm"
src={item.data.avatar}
/>
<div className="flex flex-col">
<span>{item.data.name}</span>
<span className="text-default-500 text-tiny">({item.data.email})</span>
</div>
</div>
));
}}
>
{(user) => (
<SelectItem key={user.id} textValue={user.name}>
<div className="flex gap-2 items-center">
<Avatar alt={user.name} className="flex-shrink-0" size="sm" src={user.avatar} />
<div className="flex flex-col">
<span className="text-small">{user.name}</span>
<span className="text-tiny text-default-400">{user.email}</span>
</div>
</div>
</SelectItem>
)}
</Select>
);
}`;
const react = {
"/App.jsx": App,
"/data.js": data,
};
export default {
...react,
};

View File

@ -0,0 +1,57 @@
const data = `export const animals = [
{label: "Cat", value: "cat", description: "The second most popular pet in the world"},
{label: "Dog", value: "dog", description: "The most popular pet in the world"},
{label: "Elephant", value: "elephant", description: "The largest land animal"},
{label: "Lion", value: "lion", description: "The king of the jungle"},
{label: "Tiger", value: "tiger", description: "The largest cat species"},
{label: "Giraffe", value: "giraffe", description: "The tallest land animal"},
{
label: "Dolphin",
value: "dolphin",
description: "A widely distributed and diverse group of aquatic mammals",
},
{label: "Penguin", value: "penguin", description: "A group of aquatic flightless birds"},
{label: "Zebra", value: "zebra", description: "A several species of African equids"},
{
label: "Shark",
value: "shark",
description: "A group of elasmobranch fish characterized by a cartilaginous skeleton",
},
{
label: "Whale",
value: "whale",
description: "Diverse group of fully aquatic placental marine mammals",
},
{label: "Otter", value: "otter", description: "A carnivorous mammal in the subfamily Lutrinae"},
{label: "Crocodile", value: "crocodile", description: "A large semiaquatic reptile"},
];`;
const App = `import {Select, SelectItem} from "@nextui-org/react";
import {animals} from "./data";
export default function App() {
return (
<Select
label="Favorite Animal"
placeholder="Select an animal"
description="The second most popular pet in the world"
defaultSelectedKeys={["cat"]}
className="max-w-xs"
>
{animals.map((animal) => (
<SelectItem key={animal.value} value={animal.value}>
{animal.label}
</SelectItem>
))}
</Select>
);
}`;
const react = {
"/App.jsx": App,
"/data.js": data,
};
export default {
...react,
};

View File

@ -0,0 +1,56 @@
const data = `export const animals = [
{label: "Cat", value: "cat", description: "The second most popular pet in the world"},
{label: "Dog", value: "dog", description: "The most popular pet in the world"},
{label: "Elephant", value: "elephant", description: "The largest land animal"},
{label: "Lion", value: "lion", description: "The king of the jungle"},
{label: "Tiger", value: "tiger", description: "The largest cat species"},
{label: "Giraffe", value: "giraffe", description: "The tallest land animal"},
{
label: "Dolphin",
value: "dolphin",
description: "A widely distributed and diverse group of aquatic mammals",
},
{label: "Penguin", value: "penguin", description: "A group of aquatic flightless birds"},
{label: "Zebra", value: "zebra", description: "A several species of African equids"},
{
label: "Shark",
value: "shark",
description: "A group of elasmobranch fish characterized by a cartilaginous skeleton",
},
{
label: "Whale",
value: "whale",
description: "Diverse group of fully aquatic placental marine mammals",
},
{label: "Otter", value: "otter", description: "A carnivorous mammal in the subfamily Lutrinae"},
{label: "Crocodile", value: "crocodile", description: "A large semiaquatic reptile"},
];`;
const App = `import {Select, SelectItem} from "@nextui-org/react";
import {animals} from "./data";
export default function App() {
return (
<Select
label="Favorite Animal"
placeholder="Select an animal"
disabledKeys={["zebra", "tiger", "lion", "elephant", "crocodile", "whale"]}
className="max-w-xs"
>
{animals.map((animal) => (
<SelectItem key={animal.value} value={animal.value}>
{animal.label}
</SelectItem>
))}
</Select>
);
}`;
const react = {
"/App.jsx": App,
"/data.js": data,
};
export default {
...react,
};

View File

@ -0,0 +1,57 @@
const data = `export const animals = [
{label: "Cat", value: "cat", description: "The second most popular pet in the world"},
{label: "Dog", value: "dog", description: "The most popular pet in the world"},
{label: "Elephant", value: "elephant", description: "The largest land animal"},
{label: "Lion", value: "lion", description: "The king of the jungle"},
{label: "Tiger", value: "tiger", description: "The largest cat species"},
{label: "Giraffe", value: "giraffe", description: "The tallest land animal"},
{
label: "Dolphin",
value: "dolphin",
description: "A widely distributed and diverse group of aquatic mammals",
},
{label: "Penguin", value: "penguin", description: "A group of aquatic flightless birds"},
{label: "Zebra", value: "zebra", description: "A several species of African equids"},
{
label: "Shark",
value: "shark",
description: "A group of elasmobranch fish characterized by a cartilaginous skeleton",
},
{
label: "Whale",
value: "whale",
description: "Diverse group of fully aquatic placental marine mammals",
},
{label: "Otter", value: "otter", description: "A carnivorous mammal in the subfamily Lutrinae"},
{label: "Crocodile", value: "crocodile", description: "A large semiaquatic reptile"},
];`;
const App = `import {Select, SelectItem} from "@nextui-org/react";
import {animals} from "./data";
export default function App() {
return (
<Select
isDisabled
label="Favorite Animal"
placeholder="Select an animal"
defaultSelectedKeys={["cat"]}
className="max-w-xs"
>
{animals.map((animal) => (
<SelectItem key={animal.value} value={animal.value}>
{animal.label}
</SelectItem>
))}
</Select>
);
}`;
const react = {
"/App.jsx": App,
"/data.js": data,
};
export default {
...react,
};

View File

@ -0,0 +1,52 @@
const data = `export const animals = [
{label: "Cat", value: "cat", description: "The second most popular pet in the world"},
{label: "Dog", value: "dog", description: "The most popular pet in the world"},
{label: "Elephant", value: "elephant", description: "The largest land animal"},
{label: "Lion", value: "lion", description: "The king of the jungle"},
{label: "Tiger", value: "tiger", description: "The largest cat species"},
{label: "Giraffe", value: "giraffe", description: "The tallest land animal"},
{
label: "Dolphin",
value: "dolphin",
description: "A widely distributed and diverse group of aquatic mammals",
},
{label: "Penguin", value: "penguin", description: "A group of aquatic flightless birds"},
{label: "Zebra", value: "zebra", description: "A several species of African equids"},
{
label: "Shark",
value: "shark",
description: "A group of elasmobranch fish characterized by a cartilaginous skeleton",
},
{
label: "Whale",
value: "whale",
description: "Diverse group of fully aquatic placental marine mammals",
},
{label: "Otter", value: "otter", description: "A carnivorous mammal in the subfamily Lutrinae"},
{label: "Crocodile", value: "crocodile", description: "A large semiaquatic reptile"},
];`;
const App = `import {Select, SelectItem} from "@nextui-org/react";
import {animals} from "./data";
export default function App() {
return (
<Select
items={animals}
label="Favorite Animal"
placeholder="Select an animal"
className="max-w-xs"
>
{(animal) => <SelectItem key={animal.value}>{animal.label}</SelectItem>}
</Select>
);
}`;
const react = {
"/App.jsx": App,
"/data.js": data,
};
export default {
...react,
};

View File

@ -0,0 +1,67 @@
const data = `export const animals = [
{label: "Cat", value: "cat", description: "The second most popular pet in the world"},
{label: "Dog", value: "dog", description: "The most popular pet in the world"},
{label: "Elephant", value: "elephant", description: "The largest land animal"},
{label: "Lion", value: "lion", description: "The king of the jungle"},
{label: "Tiger", value: "tiger", description: "The largest cat species"},
{label: "Giraffe", value: "giraffe", description: "The tallest land animal"},
{
label: "Dolphin",
value: "dolphin",
description: "A widely distributed and diverse group of aquatic mammals",
},
{label: "Penguin", value: "penguin", description: "A group of aquatic flightless birds"},
{label: "Zebra", value: "zebra", description: "A several species of African equids"},
{
label: "Shark",
value: "shark",
description: "A group of elasmobranch fish characterized by a cartilaginous skeleton",
},
{
label: "Whale",
value: "whale",
description: "Diverse group of fully aquatic placental marine mammals",
},
{label: "Otter", value: "otter", description: "A carnivorous mammal in the subfamily Lutrinae"},
{label: "Crocodile", value: "crocodile", description: "A large semiaquatic reptile"},
];`;
const App = `import {Select, SelectItem} from "@nextui-org/react";
import {animals} from "./data";
export default function App() {
const [value, setValue] = React.useState(new Set([]));
const [touched, setTouched] = React.useState(false);
const isValid = value.has("cat");
return (
<Select
label="Favorite Animal"
variant="bordered"
placeholder="Select an animal"
description="The second most popular pet in the world"
errorMessage={isValid || !touched ? "" : "You must select a cat"}
validationState={isValid || !touched ? "valid" : "invalid"}
selectedKeys={value}
className="max-w-xs"
onSelectionChange={setValue}
onClose={() => setTouched(true)}
>
{animals.map((animal) => (
<SelectItem key={animal.value} value={animal.value}>
{animal.label}
</SelectItem>
))}
</Select>
);
}`;
const react = {
"/App.jsx": App,
"/data.js": data,
};
export default {
...react,
};

View File

@ -0,0 +1,61 @@
import usage from "./usage";
import dynamic from "./dynamic";
import disabled from "./disabled";
import disabledItems from "./disabled-items";
import required from "./required";
import sizes from "./sizes";
import colors from "./colors";
import variants from "./variants";
import radius from "./radius";
import labelPlacements from "./label-placements";
import startContent from "./start-content";
import itemStartContent from "./item-start-content";
import asyncLoadingItems from "./async-loading-items";
import withoutScrollShadow from "./without-scroll-shadow";
import description from "./description";
import errorMessage from "./error-message";
import singleControlled from "./single-controlled";
import singleControlledOnChange from "./single-controlled-onchange";
import openState from "./open-state";
import customItems from "./custom-items";
import customRenderValue from "./custom-render-value";
import sections from "./sections";
import customSectionsStyle from "./custom-sections-style";
import multiple from "./multiple";
import multipleControlled from "./multiple-controlled";
import multipleControlledOnChange from "./multiple-controlled-onchange";
import multipleWithChips from "./multiple-chips";
import customSelectorIcon from "./custom-selector-icon";
import customStyles from "./custom-styles";
export const selectContent = {
usage,
dynamic,
disabled,
disabledItems,
required,
sizes,
colors,
variants,
radius,
labelPlacements,
asyncLoadingItems,
description,
startContent,
itemStartContent,
withoutScrollShadow,
errorMessage,
singleControlled,
singleControlledOnChange,
openState,
customItems,
customRenderValue,
sections,
customSectionsStyle,
multiple,
multipleControlled,
multipleControlledOnChange,
multipleWithChips,
customSelectorIcon,
customStyles,
};

View File

@ -0,0 +1,75 @@
const App = `import {Select, SelectItem, Avatar} from "@nextui-org/react";
export default function App() {
return (
<Select
className="max-w-xs"
label="Select country"
>
<SelectItem
key="argentina"
startContent={<Avatar alt="Argentina" className="w-6 h-6" src="https://flagcdn.com/ar.svg" />}
>
Argentina
</SelectItem>
<SelectItem
key="venezuela"
startContent={<Avatar alt="Venezuela" className="w-6 h-6" src="https://flagcdn.com/ve.svg" />}
>
Venezuela
</SelectItem>
<SelectItem
key="brazil"
startContent={<Avatar alt="Brazil" className="w-6 h-6" src="https://flagcdn.com/br.svg" />}
>
Brazil
</SelectItem>
<SelectItem
key="switzerland"
startContent={
<Avatar alt="Switzerland" className="w-6 h-6" src="https://flagcdn.com/ch.svg" />
}
>
Switzerland
</SelectItem>
<SelectItem
key="germany"
startContent={<Avatar alt="Germany" className="w-6 h-6" src="https://flagcdn.com/de.svg" />}
>
Germany
</SelectItem>
<SelectItem
key="spain"
startContent={<Avatar alt="Spain" className="w-6 h-6" src="https://flagcdn.com/es.svg" />}
>
Spain
</SelectItem>
<SelectItem
key="france"
startContent={<Avatar alt="France" className="w-6 h-6" src="https://flagcdn.com/fr.svg" />}
>
France
</SelectItem>
<SelectItem
key="italy"
startContent={<Avatar alt="Italy" className="w-6 h-6" src="https://flagcdn.com/it.svg" />}
>
Italy
</SelectItem>
<SelectItem
key="mexico"
startContent={<Avatar alt="Mexico" className="w-6 h-6" src="https://flagcdn.com/mx.svg" />}
>
Mexico
</SelectItem>
</Select>
);
}`;
const react = {
"/App.jsx": App,
};
export default {
...react,
};

View File

@ -0,0 +1,89 @@
const data = `export const animals = [
{label: "Cat", value: "cat", description: "The second most popular pet in the world"},
{label: "Dog", value: "dog", description: "The most popular pet in the world"},
{label: "Elephant", value: "elephant", description: "The largest land animal"},
{label: "Lion", value: "lion", description: "The king of the jungle"},
{label: "Tiger", value: "tiger", description: "The largest cat species"},
{label: "Giraffe", value: "giraffe", description: "The tallest land animal"},
{
label: "Dolphin",
value: "dolphin",
description: "A widely distributed and diverse group of aquatic mammals",
},
{label: "Penguin", value: "penguin", description: "A group of aquatic flightless birds"},
{label: "Zebra", value: "zebra", description: "A several species of African equids"},
{
label: "Shark",
value: "shark",
description: "A group of elasmobranch fish characterized by a cartilaginous skeleton",
},
{
label: "Whale",
value: "whale",
description: "Diverse group of fully aquatic placental marine mammals",
},
{label: "Otter", value: "otter", description: "A carnivorous mammal in the subfamily Lutrinae"},
{label: "Crocodile", value: "crocodile", description: "A large semiaquatic reptile"},
];`;
const App = `import {Select, SelectItem} from "@nextui-org/react";
import {animals} from "./data";
export default function App() {
const placements = [
"inside",
"outside",
"outside-left",
];
return (
<div className="w-full flex flex-col gap-4">
<div className="flex flex-col gap-2">
<h3 className="text-default-500 text-small">Without placeholder</h3>
<div className="flex w-full flex-wrap items-end md:flex-nowrap mb-6 md:mb-0 gap-4">
{placements.map((placement) => (
<Select
labelPlacement={placement}
label="Favorite Animal"
className="max-w-xs"
>
{animals.map((animal) => (
<SelectItem key={animal.value} value={animal.value}>
{animal.label}
</SelectItem>
))}
</Select>
))}
</div>
</div>
<div className="flex flex-col gap-2">
<h3 className="text-default-500 text-small">With placeholder</h3>
<div className="flex w-full flex-wrap items-end md:flex-nowrap mb-6 md:mb-0 gap-4">
{placements.map((placement) => (
<Select
labelPlacement={placement}
label="Favorite Animal"
placeholder="Select an animal"
className="max-w-xs"
>
{animals.map((animal) => (
<SelectItem key={animal.value} value={animal.value}>
{animal.label}
</SelectItem>
))}
</Select>
))}
</div>
</div>
</div>
);
}`;
const react = {
"/App.jsx": App,
"/data.js": data,
};
export default {
...react,
};

View File

@ -0,0 +1,312 @@
const data = `export const users = [
{
id: 1,
name: "Tony Reichert",
role: "CEO",
team: "Management",
status: "active",
age: "29",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/male/1.png",
email: "tony.reichert@example.com",
},
{
id: 2,
name: "Zoey Lang",
role: "Tech Lead",
team: "Development",
status: "paused",
age: "25",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/female/1.png",
email: "zoey.lang@example.com",
},
{
id: 3,
name: "Jane Fisher",
role: "Sr. Dev",
team: "Development",
status: "active",
age: "22",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/female/2.png",
email: "jane.fisher@example.com",
},
{
id: 4,
name: "William Howard",
role: "C.M.",
team: "Marketing",
status: "vacation",
age: "28",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/male/2.png",
email: "william.howard@example.com",
},
{
id: 5,
name: "Kristen Copper",
role: "S. Manager",
team: "Sales",
status: "active",
age: "24",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/female/3.png",
email: "kristen.cooper@example.com",
},
{
id: 6,
name: "Brian Kim",
role: "P. Manager",
team: "Management",
age: "29",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/male/3.png",
email: "brian.kim@example.com",
status: "Active",
},
{
id: 7,
name: "Michael Hunt",
role: "Designer",
team: "Design",
status: "paused",
age: "27",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/male/4.png",
email: "michael.hunt@example.com",
},
{
id: 8,
name: "Samantha Brooks",
role: "HR Manager",
team: "HR",
status: "active",
age: "31",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/female/4.png",
email: "samantha.brooks@example.com",
},
{
id: 9,
name: "Frank Harrison",
role: "F. Manager",
team: "Finance",
status: "vacation",
age: "33",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/male/5.png",
email: "frank.harrison@example.com",
},
{
id: 10,
name: "Emma Adams",
role: "Ops Manager",
team: "Operations",
status: "active",
age: "35",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/female/5.png",
email: "emma.adams@example.com",
},
{
id: 11,
name: "Brandon Stevens",
role: "Jr. Dev",
team: "Development",
status: "active",
age: "22",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/male/7.png",
email: "brandon.stevens@example.com",
},
{
id: 12,
name: "Megan Richards",
role: "P. Manager",
team: "Product",
status: "paused",
age: "28",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/female/7.png",
email: "megan.richards@example.com",
},
{
id: 13,
name: "Oliver Scott",
role: "S. Manager",
team: "Security",
status: "active",
age: "37",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/male/8.png",
email: "oliver.scott@example.com",
},
{
id: 14,
name: "Grace Allen",
role: "M. Specialist",
team: "Marketing",
status: "active",
age: "30",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/female/8.png",
email: "grace.allen@example.com",
},
{
id: 15,
name: "Noah Carter",
role: "IT Specialist",
team: "I. Technology",
status: "paused",
age: "31",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/male/9.png",
email: "noah.carter@example.com",
},
{
id: 16,
name: "Ava Perez",
role: "Manager",
team: "Sales",
status: "active",
age: "29",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/female/9.png",
email: "ava.perez@example.com",
},
{
id: 17,
name: "Liam Johnson",
role: "Data Analyst",
team: "Analysis",
status: "active",
age: "28",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/male/11.png",
email: "liam.johnson@example.com",
},
{
id: 18,
name: "Sophia Taylor",
role: "QA Analyst",
team: "Testing",
status: "active",
age: "27",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/female/11.png",
email: "sophia.taylor@example.com",
},
{
id: 19,
name: "Lucas Harris",
role: "Administrator",
team: "Information Technology",
status: "paused",
age: "32",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/male/12.png",
email: "lucas.harris@example.com",
},
{
id: 20,
name: "Mia Robinson",
role: "Coordinator",
team: "Operations",
status: "active",
age: "26",
avatar: "https://d2u8k2ocievbld.cloudfront.net/memojis/female/12.png",
email: "mia.robinson@example.com",
},
];`;
const App = `import {Select, SelectItem, Avatar, Chip} from "@nextui-org/react";
import {users} from "./data";
export default function App() {
return (
<Select
items={users}
label="Assigned to"
variant="bordered"
isMultiline={true}
selectionMode="multiple"
placeholder="Select a user"
labelPlacement="outside"
classNames={{
base: "max-w-xs",
trigger: "min-h-unit-12 py-2",
}}
renderValue={(items) => {
return (
<div className="flex flex-wrap gap-2">
{items.map((item) => (
<Chip key={item.key}>{item.data.name}</Chip>
))}
</div>
);
}}
>
{(user) => (
<SelectItem key={user.id} textValue={user.name}>
<div className="flex gap-2 items-center">
<Avatar alt={user.name} className="flex-shrink-0" size="sm" src={user.avatar} />
<div className="flex flex-col">
<span className="text-small">{user.name}</span>
<span className="text-tiny text-default-400">{user.email}</span>
</div>
</div>
</SelectItem>
)}
</Select>
);
}`;
const AppTs = `import {Select, SelectItem, Avatar, Chip, SelectedItems} from "@nextui-org/react";
import {users} from "./data";
type User = {
id: number;
name: string;
role: string;
team: string;
status: string;
age: string;
avatar: string;
email: string;
};
export default function App() {
return (
<Select
items={users}
label="Assigned to"
variant="bordered"
isMultiline={true}
selectionMode="multiple"
placeholder="Select a user"
labelPlacement="outside"
classNames={{
base: "max-w-xs",
trigger: "min-h-unit-12 py-2",
}}
renderValue={(items: SelectedItems<User>) => {
return (
<div className="flex flex-wrap gap-2">
{items.map((item) => (
<Chip key={item.key}>{item.data.name}</Chip>
))}
</div>
);
}}
>
{(user) => (
<SelectItem key={user.id} textValue={user.name}>
<div className="flex gap-2 items-center">
<Avatar alt={user.name} className="flex-shrink-0" size="sm" src={user.avatar} />
<div className="flex flex-col">
<span className="text-small">{user.name}</span>
<span className="text-tiny text-default-400">{user.email}</span>
</div>
</div>
</SelectItem>
)}
</Select>
);
}`;
const react = {
"/App.jsx": App,
"/data.js": data,
};
const reactTs = {
"/App.tsx": AppTs,
"/data.js": data,
};
export default {
...react,
...reactTs,
};

View File

@ -0,0 +1,104 @@
const data = `export const animals = [
{label: "Cat", value: "cat", description: "The second most popular pet in the world"},
{label: "Dog", value: "dog", description: "The most popular pet in the world"},
{label: "Elephant", value: "elephant", description: "The largest land animal"},
{label: "Lion", value: "lion", description: "The king of the jungle"},
{label: "Tiger", value: "tiger", description: "The largest cat species"},
{label: "Giraffe", value: "giraffe", description: "The tallest land animal"},
{
label: "Dolphin",
value: "dolphin",
description: "A widely distributed and diverse group of aquatic mammals",
},
{label: "Penguin", value: "penguin", description: "A group of aquatic flightless birds"},
{label: "Zebra", value: "zebra", description: "A several species of African equids"},
{
label: "Shark",
value: "shark",
description: "A group of elasmobranch fish characterized by a cartilaginous skeleton",
},
{
label: "Whale",
value: "whale",
description: "Diverse group of fully aquatic placental marine mammals",
},
{label: "Otter", value: "otter", description: "A carnivorous mammal in the subfamily Lutrinae"},
{label: "Crocodile", value: "crocodile", description: "A large semiaquatic reptile"},
];`;
const App = `import {Select, SelectItem} from "@nextui-org/react";
import {animals} from "./data";
export default function App() {
const [values, setValues] = React.useState(new Set([]));
const handleSelectionChange = (e) => {
setValues(new Set(e.target.value.split(",")));
};
return (
<div className="flex w-full max-w-xs flex-col gap-2">
<Select
label="Favorite Animal"
selectionMode="multiple"
placeholder="Select an animal"
selectedKeys={values}
className="max-w-xs"
onChange={handleSelectionChange}
>
{animals.map((animal) => (
<SelectItem key={animal.value} value={animal.value}>
{animal.label}
</SelectItem>
))}
</Select>
<p className="text-small text-default-500">Selected: {Array.from(values).join(", ")}</p>
</div>
);
}`;
const AppTs = `import {Select, SelectItem, Selection} from "@nextui-org/react";
import {animals} from "./data";
export default function App() {
const [values, setValues] = React.useState<Selection>(new Set([]));
const handleSelectionChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
setValues(new Set(e.target.value.split(",")));
};
return (
<div className="flex w-full max-w-xs flex-col gap-2">
<Select
label="Favorite Animal"
selectionMode="multiple"
placeholder="Select an animal"
selectedKeys={values}
className="max-w-xs"
onChange={handleSelectionChange}
>
{animals.map((animal) => (
<SelectItem key={animal.value} value={animal.value}>
{animal.label}
</SelectItem>
))}
</Select>
<p className="text-small text-default-500">Selected: {Array.from(values).join(", ")}</p>
</div>
);
}`;
const react = {
"/App.jsx": App,
"/data.js": data,
};
const reactTs = {
"/App.tsx": AppTs,
"/data.ts": data,
};
export default {
...react,
...reactTs,
};

View File

@ -0,0 +1,96 @@
const data = `export const animals = [
{label: "Cat", value: "cat", description: "The second most popular pet in the world"},
{label: "Dog", value: "dog", description: "The most popular pet in the world"},
{label: "Elephant", value: "elephant", description: "The largest land animal"},
{label: "Lion", value: "lion", description: "The king of the jungle"},
{label: "Tiger", value: "tiger", description: "The largest cat species"},
{label: "Giraffe", value: "giraffe", description: "The tallest land animal"},
{
label: "Dolphin",
value: "dolphin",
description: "A widely distributed and diverse group of aquatic mammals",
},
{label: "Penguin", value: "penguin", description: "A group of aquatic flightless birds"},
{label: "Zebra", value: "zebra", description: "A several species of African equids"},
{
label: "Shark",
value: "shark",
description: "A group of elasmobranch fish characterized by a cartilaginous skeleton",
},
{
label: "Whale",
value: "whale",
description: "Diverse group of fully aquatic placental marine mammals",
},
{label: "Otter", value: "otter", description: "A carnivorous mammal in the subfamily Lutrinae"},
{label: "Crocodile", value: "crocodile", description: "A large semiaquatic reptile"},
];`;
const App = `import {Select, SelectItem} from "@nextui-org/react";
import {animals} from "./data";
export default function App() {
const [values, setValues] = React.useState(new Set(["cat", "dog"]));
return (
<div className="flex w-full max-w-xs flex-col gap-2">
<Select
label="Favorite Animal"
selectionMode="multiple"
placeholder="Select an animal"
selectedKeys={values}
className="max-w-xs"
onSelectionChange={setValues}
>
{animals.map((animal) => (
<SelectItem key={animal.value} value={animal.value}>
{animal.label}
</SelectItem>
))}
</Select>
<p className="text-small text-default-500">Selected: {Array.from(values).join(", ")}</p>
</div>
);
}`;
const AppTs = `import {Select, SelectItem, Selection} from "@nextui-org/react";
import {animals} from "./data";
export default function App() {
const [values, setValues] = React.useState<Selection>(new Set(["cat", "dog"]));
return (
<div className="flex w-full max-w-xs flex-col gap-2">
<Select
label="Favorite Animal"
selectionMode="multiple"
placeholder="Select an animal"
selectedKeys={values}
className="max-w-xs"
onSelectionChange={setValues}
>
{animals.map((animal) => (
<SelectItem key={animal.value} value={animal.value}>
{animal.label}
</SelectItem>
))}
</Select>
<p className="text-small text-default-500">Selected: {Array.from(values).join(", ")}</p>
</div>
);
}`;
const react = {
"/App.jsx": App,
"/data.js": data,
};
const reactTs = {
"/App.tsx": AppTs,
"/data.ts": data,
};
export default {
...react,
...reactTs,
};

View File

@ -0,0 +1,56 @@
const data = `export const animals = [
{label: "Cat", value: "cat", description: "The second most popular pet in the world"},
{label: "Dog", value: "dog", description: "The most popular pet in the world"},
{label: "Elephant", value: "elephant", description: "The largest land animal"},
{label: "Lion", value: "lion", description: "The king of the jungle"},
{label: "Tiger", value: "tiger", description: "The largest cat species"},
{label: "Giraffe", value: "giraffe", description: "The tallest land animal"},
{
label: "Dolphin",
value: "dolphin",
description: "A widely distributed and diverse group of aquatic mammals",
},
{label: "Penguin", value: "penguin", description: "A group of aquatic flightless birds"},
{label: "Zebra", value: "zebra", description: "A several species of African equids"},
{
label: "Shark",
value: "shark",
description: "A group of elasmobranch fish characterized by a cartilaginous skeleton",
},
{
label: "Whale",
value: "whale",
description: "Diverse group of fully aquatic placental marine mammals",
},
{label: "Otter", value: "otter", description: "A carnivorous mammal in the subfamily Lutrinae"},
{label: "Crocodile", value: "crocodile", description: "A large semiaquatic reptile"},
];`;
const App = `import {Select, SelectItem} from "@nextui-org/react";
import {animals} from "./data";
export default function App() {
return (
<Select
label="Favorite Animal"
placeholder="Select an animal"
selectionMode="multiple"
className="max-w-xs"
>
{animals.map((animal) => (
<SelectItem key={animal.value} value={animal.value}>
{animal.label}
</SelectItem>
))}
</Select>
);
}`;
const react = {
"/App.jsx": App,
"/data.js": data,
};
export default {
...react,
};

View File

@ -0,0 +1,64 @@
const data = `export const animals = [
{label: "Cat", value: "cat", description: "The second most popular pet in the world"},
{label: "Dog", value: "dog", description: "The most popular pet in the world"},
{label: "Elephant", value: "elephant", description: "The largest land animal"},
{label: "Lion", value: "lion", description: "The king of the jungle"},
{label: "Tiger", value: "tiger", description: "The largest cat species"},
{label: "Giraffe", value: "giraffe", description: "The tallest land animal"},
{
label: "Dolphin",
value: "dolphin",
description: "A widely distributed and diverse group of aquatic mammals",
},
{label: "Penguin", value: "penguin", description: "A group of aquatic flightless birds"},
{label: "Zebra", value: "zebra", description: "A several species of African equids"},
{
label: "Shark",
value: "shark",
description: "A group of elasmobranch fish characterized by a cartilaginous skeleton",
},
{
label: "Whale",
value: "whale",
description: "Diverse group of fully aquatic placental marine mammals",
},
{label: "Otter", value: "otter", description: "A carnivorous mammal in the subfamily Lutrinae"},
{label: "Crocodile", value: "crocodile", description: "A large semiaquatic reptile"},
];`;
const App = `import {Select, SelectItem, Button} from "@nextui-org/react";
import {animals} from "./data";
export default function App() {
const [isOpen, setIsOpen] = React.useState(false);
return (
<div className="flex w-full max-w-xs items-center gap-2">
<Select
isOpen={isOpen}
label="Favorite Animal"
placeholder="Select an animal"
defaultSelectedKeys={["cat"]}
className="max-w-xs"
>
{animals.map((animal) => (
<SelectItem key={animal.value} value={animal.value}>
{animal.label}
</SelectItem>
))}
</Select>
<Button onPress={() => setIsOpen(!isOpen)}>
{isOpen ? "Close" : "Open"}
</Button>
</div>
);
}`;
const react = {
"/App.jsx": App,
"/data.js": data,
};
export default {
...react,
};

View File

@ -0,0 +1,70 @@
const data = `export const animals = [
{label: "Cat", value: "cat", description: "The second most popular pet in the world"},
{label: "Dog", value: "dog", description: "The most popular pet in the world"},
{label: "Elephant", value: "elephant", description: "The largest land animal"},
{label: "Lion", value: "lion", description: "The king of the jungle"},
{label: "Tiger", value: "tiger", description: "The largest cat species"},
{label: "Giraffe", value: "giraffe", description: "The tallest land animal"},
{
label: "Dolphin",
value: "dolphin",
description: "A widely distributed and diverse group of aquatic mammals",
},
{label: "Penguin", value: "penguin", description: "A group of aquatic flightless birds"},
{label: "Zebra", value: "zebra", description: "A several species of African equids"},
{
label: "Shark",
value: "shark",
description: "A group of elasmobranch fish characterized by a cartilaginous skeleton",
},
{
label: "Whale",
value: "whale",
description: "Diverse group of fully aquatic placental marine mammals",
},
{label: "Otter", value: "otter", description: "A carnivorous mammal in the subfamily Lutrinae"},
{label: "Crocodile", value: "crocodile", description: "A large semiaquatic reptile"},
];`;
const App = `import {Select, SelectItem} from "@nextui-org/react";
import {animals} from "./data";
export default function App() {
const radius = [
"full",
"lg",
"md",
"sm",
"none",
];
return (
<div className="w-full flex flex-row flex-wrap gap-4">
{radius.map((r) => (
<Select
key={r}
radius={r}
label="Favorite Animal"
placeholder="Select an animal"
defaultSelectedKeys={["cat"]}
className="max-w-[45%]"
>
{animals.map((animal) => (
<SelectItem key={animal.value} value={animal.value}>
{animal.label}
</SelectItem>
))}
</Select>
))}
</div>
);
}`;
const react = {
"/App.jsx": App,
"/data.js": data,
};
export default {
...react,
};

View File

@ -0,0 +1,57 @@
const data = `export const animals = [
{label: "Cat", value: "cat", description: "The second most popular pet in the world"},
{label: "Dog", value: "dog", description: "The most popular pet in the world"},
{label: "Elephant", value: "elephant", description: "The largest land animal"},
{label: "Lion", value: "lion", description: "The king of the jungle"},
{label: "Tiger", value: "tiger", description: "The largest cat species"},
{label: "Giraffe", value: "giraffe", description: "The tallest land animal"},
{
label: "Dolphin",
value: "dolphin",
description: "A widely distributed and diverse group of aquatic mammals",
},
{label: "Penguin", value: "penguin", description: "A group of aquatic flightless birds"},
{label: "Zebra", value: "zebra", description: "A several species of African equids"},
{
label: "Shark",
value: "shark",
description: "A group of elasmobranch fish characterized by a cartilaginous skeleton",
},
{
label: "Whale",
value: "whale",
description: "Diverse group of fully aquatic placental marine mammals",
},
{label: "Otter", value: "otter", description: "A carnivorous mammal in the subfamily Lutrinae"},
{label: "Crocodile", value: "crocodile", description: "A large semiaquatic reptile"},
];`;
const App = `import {Select, SelectItem} from "@nextui-org/react";
import {animals} from "./data";
export default function App() {
return (
<Select
isRequired
label="Favorite Animal"
placeholder="Select an animal"
defaultSelectedKeys={["cat"]}
className="max-w-xs"
>
{animals.map((animal) => (
<SelectItem key={animal.value} value={animal.value}>
{animal.label}
</SelectItem>
))}
</Select>
);
}`;
const react = {
"/App.jsx": App,
"/data.js": data,
};
export default {
...react,
};

View File

@ -0,0 +1,40 @@
const App = `import {Select, SelectItem, SelectSection} from "@nextui-org/react";
export default function App() {
return (
<Select
label="Favorite Animal"
placeholder="Select an animal"
className="max-w-xs"
>
<SelectSection showDivider title="Mammals">
<SelectItem key="Lion">Lion</SelectItem>
<SelectItem key="Tiger">Tiger</SelectItem>
<SelectItem key="Elephant">Elephant</SelectItem>
<SelectItem key="Kangaroo">Kangaroo</SelectItem>
<SelectItem key="Panda">Panda</SelectItem>
<SelectItem key="Giraffe">Giraffe</SelectItem>
<SelectItem key="Zebra">Zebra</SelectItem>
<SelectItem key="Cheetah">Cheetah</SelectItem>
</SelectSection>
<SelectSection title="Birds">
<SelectItem key="Eagle">Eagle</SelectItem>
<SelectItem key="Parrot">Parrot</SelectItem>
<SelectItem key="Penguin">Penguin</SelectItem>
<SelectItem key="Ostrich">Ostrich</SelectItem>
<SelectItem key="Peacock">Peacock</SelectItem>
<SelectItem key="Swan">Swan</SelectItem>
<SelectItem key="Falcon">Falcon</SelectItem>
<SelectItem key="Flamingo">Flamingo</SelectItem>
</SelectSection>
</Select>
);
}`;
const react = {
"/App.jsx": App,
};
export default {
...react,
};

View File

@ -0,0 +1,104 @@
const data = `export const animals = [
{label: "Cat", value: "cat", description: "The second most popular pet in the world"},
{label: "Dog", value: "dog", description: "The most popular pet in the world"},
{label: "Elephant", value: "elephant", description: "The largest land animal"},
{label: "Lion", value: "lion", description: "The king of the jungle"},
{label: "Tiger", value: "tiger", description: "The largest cat species"},
{label: "Giraffe", value: "giraffe", description: "The tallest land animal"},
{
label: "Dolphin",
value: "dolphin",
description: "A widely distributed and diverse group of aquatic mammals",
},
{label: "Penguin", value: "penguin", description: "A group of aquatic flightless birds"},
{label: "Zebra", value: "zebra", description: "A several species of African equids"},
{
label: "Shark",
value: "shark",
description: "A group of elasmobranch fish characterized by a cartilaginous skeleton",
},
{
label: "Whale",
value: "whale",
description: "Diverse group of fully aquatic placental marine mammals",
},
{label: "Otter", value: "otter", description: "A carnivorous mammal in the subfamily Lutrinae"},
{label: "Crocodile", value: "crocodile", description: "A large semiaquatic reptile"},
];`;
const App = `import {Select, SelectItem} from "@nextui-org/react";
import {animals} from "./data";
export default function App() {
const [value, setValue] = React.useState(new Set([]));
const handleSelectionChange = (e) => {
setValue(new Set([e.target.value]));
};
return (
<div className="flex w-full max-w-xs flex-col gap-2">
<Select
label="Favorite Animal"
variant="bordered"
placeholder="Select an animal"
selectedKeys={value}
className="max-w-xs"
onChange={handleSelectionChange}
>
{animals.map((animal) => (
<SelectItem key={animal.value} value={animal.value}>
{animal.label}
</SelectItem>
))}
</Select>
<p className="text-small text-default-500">Selected: {value}</p>
</div>
);
}`;
const AppTs = `import {Select, SelectItem, Selection} from "@nextui-org/react";
import {animals} from "./data";
export default function App() {
const [value, setValue] = React.useState<Selection>(new Set([]));
const handleSelectionChange = (e: React.ChangeEvent<HTMLSelectElement>) => {
setValue(new Set([e.target.value]));
};
return (
<div className="flex w-full max-w-xs flex-col gap-2">
<Select
label="Favorite Animal"
variant="bordered"
placeholder="Select an animal"
selectedKeys={value}
className="max-w-xs"
onChange={handleSelectionChange}
>
{animals.map((animal) => (
<SelectItem key={animal.value} value={animal.value}>
{animal.label}
</SelectItem>
))}
</Select>
<p className="text-small text-default-500">Selected: {value}</p>
</div>
);
}`;
const react = {
"/App.jsx": App,
"/data.js": data,
};
const reactTs = {
"/App.tsx": AppTs,
"/data.js": data,
};
export default {
...react,
...reactTs,
};

View File

@ -0,0 +1,96 @@
const data = `export const animals = [
{label: "Cat", value: "cat", description: "The second most popular pet in the world"},
{label: "Dog", value: "dog", description: "The most popular pet in the world"},
{label: "Elephant", value: "elephant", description: "The largest land animal"},
{label: "Lion", value: "lion", description: "The king of the jungle"},
{label: "Tiger", value: "tiger", description: "The largest cat species"},
{label: "Giraffe", value: "giraffe", description: "The tallest land animal"},
{
label: "Dolphin",
value: "dolphin",
description: "A widely distributed and diverse group of aquatic mammals",
},
{label: "Penguin", value: "penguin", description: "A group of aquatic flightless birds"},
{label: "Zebra", value: "zebra", description: "A several species of African equids"},
{
label: "Shark",
value: "shark",
description: "A group of elasmobranch fish characterized by a cartilaginous skeleton",
},
{
label: "Whale",
value: "whale",
description: "Diverse group of fully aquatic placental marine mammals",
},
{label: "Otter", value: "otter", description: "A carnivorous mammal in the subfamily Lutrinae"},
{label: "Crocodile", value: "crocodile", description: "A large semiaquatic reptile"},
];`;
const AppTs = `import {Select, SelectItem, Selection} from "@nextui-org/react";
import {animals} from "./data";
export default function App() {
const [value, setValue] = React.useState<Selection>(new Set([]));
return (
<div className="flex w-full max-w-xs flex-col gap-2">
<Select
label="Favorite Animal"
variant="bordered"
placeholder="Select an animal"
selectedKeys={value}
className="max-w-xs"
onSelectionChange={setValue}
>
{animals.map((animal) => (
<SelectItem key={animal.value} value={animal.value}>
{animal.label}
</SelectItem>
))}
</Select>
<p className="text-default-500 text-small">Selected: {value}</p>
</div>
);
}`;
const App = `import {Select, SelectItem} from "@nextui-org/react";
import {animals} from "./data";
export default function App() {
const [value, setValue] = React.useState(new Set([]));
return (
<div className="flex w-full max-w-xs flex-col gap-2">
<Select
label="Favorite Animal"
variant="bordered"
placeholder="Select an animal"
selectedKeys={value}
className="max-w-xs"
onSelectionChange={setValue}
>
{animals.map((animal) => (
<SelectItem key={animal.value} value={animal.value}>
{animal.label}
</SelectItem>
))}
</Select>
<p className="text-small text-default-500">Selected: {value}</p>
</div>
);
}`;
const react = {
"/App.jsx": App,
"/data.js": data,
};
const reactTs = {
"/App.tsx": AppTs,
"/data.js": data,
};
export default {
...react,
...reactTs,
};

View File

@ -0,0 +1,75 @@
const data = `export const animals = [
{label: "Cat", value: "cat", description: "The second most popular pet in the world"},
{label: "Dog", value: "dog", description: "The most popular pet in the world"},
{label: "Elephant", value: "elephant", description: "The largest land animal"},
{label: "Lion", value: "lion", description: "The king of the jungle"},
{label: "Tiger", value: "tiger", description: "The largest cat species"},
{label: "Giraffe", value: "giraffe", description: "The tallest land animal"},
{
label: "Dolphin",
value: "dolphin",
description: "A widely distributed and diverse group of aquatic mammals",
},
{label: "Penguin", value: "penguin", description: "A group of aquatic flightless birds"},
{label: "Zebra", value: "zebra", description: "A several species of African equids"},
{
label: "Shark",
value: "shark",
description: "A group of elasmobranch fish characterized by a cartilaginous skeleton",
},
{
label: "Whale",
value: "whale",
description: "Diverse group of fully aquatic placental marine mammals",
},
{label: "Otter", value: "otter", description: "A carnivorous mammal in the subfamily Lutrinae"},
{label: "Crocodile", value: "crocodile", description: "A large semiaquatic reptile"},
];`;
const App = `import {Select, SelectItem} from "@nextui-org/react";
import {animals} from "./data";
export default function App() {
const sizes = ["sm", "md", "lg"];
return (
<div className="w-full flex flex-col gap-4">
{sizes.map((size) => (
<div key={size} className="flex w-full flex-wrap md:flex-nowrap mb-6 md:mb-0 gap-4">
<Select
size={size}
label="Select an animal"
className="max-w-xs"
>
{animals.map((animal) => (
<SelectItem key={animal.value} value={animal.value}>
{animal.label}
</SelectItem>
))}
</Select>
<Select
size={size}
label="Favorite Animal"
placeholder="Select an animal"
className="max-w-xs"
>
{animals.map((animal) => (
<SelectItem key={animal.value} value={animal.value}>
{animal.label}
</SelectItem>
))}
</Select>
</div>
))}
</div>
);
}`;
const react = {
"/App.jsx": App,
"/data.js": data,
};
export default {
...react,
};

View File

@ -0,0 +1,93 @@
const data = `export const animals = [
{label: "Cat", value: "cat", description: "The second most popular pet in the world"},
{label: "Dog", value: "dog", description: "The most popular pet in the world"},
{label: "Elephant", value: "elephant", description: "The largest land animal"},
{label: "Lion", value: "lion", description: "The king of the jungle"},
{label: "Tiger", value: "tiger", description: "The largest cat species"},
{label: "Giraffe", value: "giraffe", description: "The tallest land animal"},
{
label: "Dolphin",
value: "dolphin",
description: "A widely distributed and diverse group of aquatic mammals",
},
{label: "Penguin", value: "penguin", description: "A group of aquatic flightless birds"},
{label: "Zebra", value: "zebra", description: "A several species of African equids"},
{
label: "Shark",
value: "shark",
description: "A group of elasmobranch fish characterized by a cartilaginous skeleton",
},
{
label: "Whale",
value: "whale",
description: "Diverse group of fully aquatic placental marine mammals",
},
{label: "Otter", value: "otter", description: "A carnivorous mammal in the subfamily Lutrinae"},
{label: "Crocodile", value: "crocodile", description: "A large semiaquatic reptile"},
];`;
const PetIcon = `export const PetIcon = (props) => (
<svg
aria-hidden="true"
fill="none"
focusable="false"
height="1em"
role="presentation"
viewBox="0 0 24 24"
width="1em"
{...props}
>
<path
d="M19.0803 15.7203C18.4903 12.1903 15.1003 9.32031 11.5203 9.32031C7.63028 9.32031 4.21028 12.4703 3.88028 16.3503C3.75028 17.8503 4.23028 19.2703 5.22028 20.3403C6.20028 21.4103 7.58028 22.0003 9.08028 22.0003H13.7603C15.4503 22.0003 16.9303 21.3403 17.9403 20.1503C18.9503 18.9603 19.3503 17.3803 19.0803 15.7203Z"
fill="currentColor"
/>
<path
d="M10.2796 7.86C11.8978 7.86 13.2096 6.54819 13.2096 4.93C13.2096 3.31181 11.8978 2 10.2796 2C8.66141 2 7.34961 3.31181 7.34961 4.93C7.34961 6.54819 8.66141 7.86 10.2796 7.86Z"
fill="currentColor"
/>
<path
d="M16.94 9.02844C18.2876 9.02844 19.38 7.93601 19.38 6.58844C19.38 5.24086 18.2876 4.14844 16.94 4.14844C15.5924 4.14844 14.5 5.24086 14.5 6.58844C14.5 7.93601 15.5924 9.02844 16.94 9.02844Z"
fill="currentColor"
/>
<path
d="M20.5496 12.9313C21.6266 12.9313 22.4996 12.0582 22.4996 10.9812C22.4996 9.90429 21.6266 9.03125 20.5496 9.03125C19.4727 9.03125 18.5996 9.90429 18.5996 10.9812C18.5996 12.0582 19.4727 12.9313 20.5496 12.9313Z"
fill="currentColor"
/>
<path
d="M3.94 10.9816C5.28757 10.9816 6.38 9.88914 6.38 8.54156C6.38 7.19399 5.28757 6.10156 3.94 6.10156C2.59243 6.10156 1.5 7.19399 1.5 8.54156C1.5 9.88914 2.59243 10.9816 3.94 10.9816Z"
fill="currentColor"
/>
</svg>
);`;
const App = `import {Select, SelectItem} from "@nextui-org/react";
import {PetIcon} from "./PetIcon";
import {animals} from "./data";
export default function App() {
return (
<Select
label="Favorite Animal"
placeholder="Select an animal"
startContent={<PetIcon />}
defaultSelectedKeys={["cat"]}
className="max-w-xs"
>
{animals.map((animal) => (
<SelectItem key={animal.value} value={animal.value}>
{animal.label}
</SelectItem>
))}
</Select>
);
}`;
const react = {
"/App.jsx": App,
"/PetIcon.jsx": PetIcon,
"/data.js": data,
};
export default {
...react,
};

View File

@ -0,0 +1,67 @@
const data = `export const animals = [
{label: "Cat", value: "cat", description: "The second most popular pet in the world"},
{label: "Dog", value: "dog", description: "The most popular pet in the world"},
{label: "Elephant", value: "elephant", description: "The largest land animal"},
{label: "Lion", value: "lion", description: "The king of the jungle"},
{label: "Tiger", value: "tiger", description: "The largest cat species"},
{label: "Giraffe", value: "giraffe", description: "The tallest land animal"},
{
label: "Dolphin",
value: "dolphin",
description: "A widely distributed and diverse group of aquatic mammals",
},
{label: "Penguin", value: "penguin", description: "A group of aquatic flightless birds"},
{label: "Zebra", value: "zebra", description: "A several species of African equids"},
{
label: "Shark",
value: "shark",
description: "A group of elasmobranch fish characterized by a cartilaginous skeleton",
},
{
label: "Whale",
value: "whale",
description: "Diverse group of fully aquatic placental marine mammals",
},
{label: "Otter", value: "otter", description: "A carnivorous mammal in the subfamily Lutrinae"},
{label: "Crocodile", value: "crocodile", description: "A large semiaquatic reptile"},
];`;
const App = `import {Select, SelectItem} from "@nextui-org/react";
import {animals} from "./data";
export default function App() {
return (
<div className="flex w-full flex-wrap md:flex-nowrap gap-4">
<Select
label="Select an animal"
className="max-w-xs"
>
{animals.map((animal) => (
<SelectItem key={animal.value} value={animal.value}>
{animal.label}
</SelectItem>
))}
</Select>
<Select
label="Favorite Animal"
placeholder="Select an animal"
className="max-w-xs"
>
{animals.map((animal) => (
<SelectItem key={animal.value} value={animal.value}>
{animal.label}
</SelectItem>
))}
</Select>
</div>
);
}`;
const react = {
"/App.jsx": App,
"/data.js": data,
};
export default {
...react,
};

View File

@ -0,0 +1,75 @@
const data = `export const animals = [
{label: "Cat", value: "cat", description: "The second most popular pet in the world"},
{label: "Dog", value: "dog", description: "The most popular pet in the world"},
{label: "Elephant", value: "elephant", description: "The largest land animal"},
{label: "Lion", value: "lion", description: "The king of the jungle"},
{label: "Tiger", value: "tiger", description: "The largest cat species"},
{label: "Giraffe", value: "giraffe", description: "The tallest land animal"},
{
label: "Dolphin",
value: "dolphin",
description: "A widely distributed and diverse group of aquatic mammals",
},
{label: "Penguin", value: "penguin", description: "A group of aquatic flightless birds"},
{label: "Zebra", value: "zebra", description: "A several species of African equids"},
{
label: "Shark",
value: "shark",
description: "A group of elasmobranch fish characterized by a cartilaginous skeleton",
},
{
label: "Whale",
value: "whale",
description: "Diverse group of fully aquatic placental marine mammals",
},
{label: "Otter", value: "otter", description: "A carnivorous mammal in the subfamily Lutrinae"},
{label: "Crocodile", value: "crocodile", description: "A large semiaquatic reptile"},
];`;
const App = `import {Select, SelectItem} from "@nextui-org/react";
import {animals} from "./data";
export default function App() {
const variants = ["flat", "bordered", "underlined", "faded"];
return (
<div className="w-full flex flex-col gap-4">
{variants.map((variant) => (
<div key={variant} className="flex w-full flex-wrap md:flex-nowrap mb-6 md:mb-0 gap-4">
<Select
variant={variant}
label="Select an animal"
className="max-w-xs"
>
{animals.map((animal) => (
<SelectItem key={animal.value} value={animal.value}>
{animal.label}
</SelectItem>
))}
</Select>
<Select
variant={variant}
label="Favorite Animal"
placeholder="Select an animal"
className="max-w-xs"
>
{animals.map((animal) => (
<SelectItem key={animal.value} value={animal.value}>
{animal.label}
</SelectItem>
))}
</Select>
</div>
))}
</div>
);
}`;
const react = {
"/App.jsx": App,
"/data.js": data,
};
export default {
...react,
};

View File

@ -0,0 +1,59 @@
const data = `export const animals = [
{label: "Cat", value: "cat", description: "The second most popular pet in the world"},
{label: "Dog", value: "dog", description: "The most popular pet in the world"},
{label: "Elephant", value: "elephant", description: "The largest land animal"},
{label: "Lion", value: "lion", description: "The king of the jungle"},
{label: "Tiger", value: "tiger", description: "The largest cat species"},
{label: "Giraffe", value: "giraffe", description: "The tallest land animal"},
{
label: "Dolphin",
value: "dolphin",
description: "A widely distributed and diverse group of aquatic mammals",
},
{label: "Penguin", value: "penguin", description: "A group of aquatic flightless birds"},
{label: "Zebra", value: "zebra", description: "A several species of African equids"},
{
label: "Shark",
value: "shark",
description: "A group of elasmobranch fish characterized by a cartilaginous skeleton",
},
{
label: "Whale",
value: "whale",
description: "Diverse group of fully aquatic placental marine mammals",
},
{label: "Otter", value: "otter", description: "A carnivorous mammal in the subfamily Lutrinae"},
{label: "Crocodile", value: "crocodile", description: "A large semiaquatic reptile"},
];`;
const App = `import {Select, SelectItem} from "@nextui-org/react";
import {animals} from "./data";
export default function App() {
return (
<Select
label="Favorite Animal"
placeholder="Select an animal"
defaultSelectedKeys={["cat"]}
className="max-w-xs"
scrollShadowProps={{
isEnabled: false
}}
>
{animals.map((animal) => (
<SelectItem key={animal.value} value={animal.value}>
{animal.label}
</SelectItem>
))}
</Select>
);
}`;
const react = {
"/App.jsx": App,
"/data.js": data,
};
export default {
...react,
};

View File

@ -8,7 +8,7 @@ export default function App() {
<Switch isSelected={isSelected} onValueChange={setIsSelected}>
Airplane mode
</Switch>
<p className="text-default-500">Selected: {isSelected ? "true" : "false"}</p>
<p className="text-small text-default-500">Selected: {isSelected ? "true" : "false"}</p>
</div>
)
}`;

View File

@ -67,7 +67,7 @@ const users = [
email: "kristen.cooper@example.com",
},
{
key: 6,
id: 6,
name: "Brian Kim",
role: "P. Manager",
team: "Management",

View File

@ -67,7 +67,7 @@ const users = [
email: "kristen.cooper@example.com",
},
{
key: 6,
id: 6,
name: "Brian Kim",
role: "P. Manager",
team: "Management",

View File

@ -143,7 +143,7 @@ Here's an example of how to customize the accordion styles:
## Data Attributes
`AccordionItem` has the following attributes on the `root` element:
`AccordionItem` has the following attributes on the `base` element:
- **data-open**:
Whether the accordion item is open.
@ -164,7 +164,7 @@ Here's an example of how to customize the accordion styles:
## Accessibility
- Keyboard event support for <kbd>Space</kbd>, <kbd>Enter</kbd>, <kbd>Arrow Up</kbd>, <kbd>Arrow Down</kbd> and <kbd>Home</kbd> / <kbd>End</kbd> keys.
- Keyboard event support for <Kbd>Space</Kbd>, <Kbd>Enter</Kbd>, <Kbd>Arrow Up</Kbd>, <Kbd>Arrow Down</Kbd> and <Kbd>Home</Kbd> / <Kbd>End</Kbd> keys.
- Keyboard focus management and cross browser normalization.
- `aria-expanded` attribute for the accordion item.
- `aria-disabled` attribute for the accordion item.

View File

@ -140,7 +140,7 @@ You can customize any part of the avatar by using the `classNames` prop, each `s
## Data Attributes
`Avatar` has the following attributes on the `root` element:
`Avatar` has the following attributes on the `base` element:
- **data-hover**:
When the avatar is being hovered. Based on [useHover](https://react-spectrum.adobe.com/react-aria/useHover.html)

View File

@ -112,7 +112,7 @@ A common use case for the `ButtonGroup` component is to display a group of two b
## Data Attributes
`Button` has the following attributes on the `root` element:
`Button` has the following attributes on the `base` element:
- **data-hover**:
When the button is being hovered. Based on [useHover](https://react-spectrum.adobe.com/react-aria/useHover.html)
@ -132,7 +132,7 @@ A common use case for the `ButtonGroup` component is to display a group of two b
## Accessibility
- Button has role of `button`.
- Keyboard event support for <kbd>Space</kbd> and <kbd>Enter</kbd> keys.
- Keyboard event support for <Kbd>Space</Kbd> and <Kbd>Enter</Kbd> keys.
- Mouse and touch event handling, and press state management.
- Keyboard focus management and cross browser normalization.

View File

@ -81,7 +81,7 @@ You can use `Image` component as the cover of the card by taking it out of the `
## Data Attributes
`Card` has the following attributes on the `root` element:
`Card` has the following attributes on the `base` element:
- **data-hover**:
When the card is being hovered. Based on [useHover](https://react-spectrum.adobe.com/react-aria/useHover.html)

View File

@ -90,7 +90,7 @@ In case you need to customize the checkbox even further, you can use the `useChe
## Data Attributes
`Checkbox` has the following attributes on the `root` element:
`Checkbox` has the following attributes on the `base` element:
- **data-selected**:
When the checkbox is checked. Based on `isSelected` prop.
@ -120,7 +120,7 @@ In case you need to customize the checkbox even further, you can use the `useChe
- Built with a native HTML `<input>` element.
- Full support for browser features like form autofill.
- Keyboard focus management and cross browser normalization.
- Keyboard event support for <kbd>Tab</kbd> and <kbd>Space</kbd> keys.
- Keyboard event support for <Kbd>Tab</Kbd> and <Kbd>Space</Kbd> keys.
- Labeling support for assistive technology.
- Indeterminate state support.

View File

@ -82,7 +82,7 @@ You can customize the `CircularProgress` component by passing custom Tailwind CS
## Data Attributes
`CircularProgress` has the following attributes on the `root` element:
`CircularProgress` has the following attributes on the `base` element:
- **data-indeterminate**:
Indicates whether the progress is indeterminate.

View File

@ -32,7 +32,7 @@ Divider is a component that separates content in a page.
## Data Attributes
`Divider` has the following attributes on the `root` element:
`Divider` has the following attributes on the `base` element:
- **data-orientation**:
The orientation of the divider. Based on `orientation` prop.

View File

@ -97,6 +97,8 @@ You can set the `selectionMode` property as `multiple` to allow the user to sele
files={dropdownContent.multipleSelection}
/>
> **Note**: To allow empty selection, you can set the `disallowEmptySelection` property as `false`.
### With Shortcut
You can use the `shortcut` prop to add a shortcut to the dropdown item.
@ -189,18 +191,18 @@ you to customize each item individually.
| Key | Description |
| -------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------- |
| <kbd>Space</kbd> | When focus is on `DropdownTrigger`, opens the dropdown menu and focuses the first item. When focus is on an item, activates the focused item. |
| <kbd>Enter</kbd> | When focus is on `DropdownTrigger`, opens the dropdown menu and focuses the first item. When focus is on an item, activates the focused item. |
| <kbd>ArrowDown</kbd> | When focus is on `DropdownTrigger`, opens the dropdown menu. When focus is on an item, moves focus to the next item. |
| <kbd>ArrowUp</kbd> | When focus is on an item, moves focus to the previous item. |
| <kbd>Esc</kbd> | Closes the dropdown menu and moves focus to `DropdownTrigger`. |
| <kbd>A-Z</kbd> or <kbd>a-z</kbd> | When the menu is open, moves focus to the next menu item with a label that starts with the typed character if such an menu item exists. |
| <Kbd>Space</Kbd> | When focus is on `DropdownTrigger`, opens the dropdown menu and focuses the first item. When focus is on an item, activates the focused item. |
| <Kbd>Enter</Kbd> | When focus is on `DropdownTrigger`, opens the dropdown menu and focuses the first item. When focus is on an item, activates the focused item. |
| <Kbd>ArrowDown</Kbd> | When focus is on `DropdownTrigger`, opens the dropdown menu. When focus is on an item, moves focus to the next item. |
| <Kbd>ArrowUp</Kbd> | When focus is on an item, moves focus to the previous item. |
| <Kbd>Esc</Kbd> | Closes the dropdown menu and moves focus to `DropdownTrigger`. |
| <Kbd>A-Z</Kbd> or <Kbd>a-z</Kbd> | When the menu is open, moves focus to the next menu item with a label that starts with the typed character if such an menu item exists. |
<Spacer y={4} />
## Data Attributes
`DropdownItem` has the following attributes on the `root` element:
`DropdownItem` has the following attributes on the `base` element:
- **data-disabled**:
When the dropdown item is disabled. Based on dropdown `disabledKeys` prop.
@ -219,7 +221,7 @@ you to customize each item individually.
## Accessibility
- Exposed to assistive technology as a button with a menu using ARIA.
- Exposed to assistive technology as a `button` with a `menu` using ARIA.
- Support for single, multiple, or no selection.
- Support for disabled items.
- Support for sections.
@ -320,6 +322,7 @@ you to customize each item individually.
| startContent | `ReactNode` | The start content of the dropdown item. | - |
| endContent | `ReactNode` | The end content of the dropdown item. This is positioned after the shortcut and the selected icon. | - |
| selectedIcon | [SelectedIconProps](#dropdown-item-selected-icon-props) | Custom icon to render when the item is selected. | - |
| showDivider | `boolean` | Whether to show a divider below the item. | `false` |
| isDisabled | `boolean` | Whether the dropdown item should be disabled. (**Deprecated**) pass **disabledKeys** to `DropdownMenu` instead. | `false` |
| isSelected | `boolean` | Whether the dropdown item should be selected. (**Deprecated**) pass **selectedKeys** to `DropdownMenu` instead. | `false` |
| isReadOnly | `boolean` | Whether the dropdown item press events should be ignored. | `false` |

View File

@ -63,16 +63,10 @@ the end of the label and the input will be required.
You can change the position of the label by setting the `labelPlacement` property to `inside`, `outside` or `outside-left`.
<CodeDemo title="Label Positions" files={inputContent.labelPositions} />
<CodeDemo title="Label Placements" files={inputContent.labelPlacements} />
> **Note**: If the `label` is not passed, the `labelPlacement` property will be `outside` by default.
### With Description
You can add a description to the input by passing the `description` property.
<CodeDemo title="With Description" files={inputContent.description} />
### Password Input
You can use the `type` property to change the input type to `password`.
@ -92,6 +86,12 @@ You can use the `startContent` and `endContent` properties to add content to the
<CodeDemo title="Start and End Content" files={inputContent.startEndContent} />
### With Description
You can add a description to the input by passing the `description` property.
<CodeDemo title="With Description" files={inputContent.description} />
### With Error Message
You can combine the `validationState="invalid"` and `errorMessage` properties to show an invalid input.
@ -145,7 +145,7 @@ In case you need to customize the input even further, you can use the `useInput`
## Data Attributes
`Input` has the following attributes on the `root` element:
`Input` has the following attributes on the `base` element:
- **data-invalid**:
When the input is invalid. Based on `validationState` prop.
@ -157,6 +157,8 @@ In case you need to customize the input even further, you can use the `useInput`
When the input is being hovered. Based on [useHover](https://react-spectrum.adobe.com/react-aria/useHover.html)
- **data-focus**:
When the input is being focused. Based on [useFocusRing](https://react-spectrum.adobe.com/react-aria/useFocusRing.html).
- **data-focus-within**:
When the input is being focused or any of its children. Based on [useFocusWithin](https://react-spectrum.adobe.com/react-aria/useFocusWithin.html).
- **data-focus-visible**:
When the input is being focused with the keyboard. Based on [useFocusRing](https://react-spectrum.adobe.com/react-aria/useFocusRing.html).
- **data-disabled**:

View File

@ -85,7 +85,7 @@ In case you need to customize the link even further, you can use the `useLink` h
## Data Attributes
`Link` has the following attributes on the `root` element:
`Link` has the following attributes on the `base` element:
- **data-focus**:
When the link is being focused. Based on [useFocusRing](https://react-spectrum.adobe.com/react-aria/useFocusRing.html)
@ -101,7 +101,7 @@ In case you need to customize the link even further, you can use the `useLink` h
- Support for mouse, touch, and keyboard interactions.
- Support for navigation links via `<a>` elements or custom element types via ARIA.
- Support for disabled links.
- Keyboard users may activate links using the <kbd>Enter</kbd> key.
- Keyboard users may activate links using the <Kbd>Enter</Kbd> key.
<Spacer y={4} />{" "}

View File

@ -0,0 +1,292 @@
---
title: "Listbox"
description: "A listbox displays a list of options and allows a user to select one or more of them."
---
import {listboxContent} from "@/content/components/listbox";
# Listbox
A listbox displays a list of options and allows a user to select one or more of them.
<ComponentLinks component="listbox" reactAriaHook="useListBox" />
---
<CarbonAd />
## Import
NextUI exports 3 listbox-related components:
- **Listbox**: The main component, which is a wrapper for the other components.
- **ListboxSection**: The component that contains a group of listbox items.
- **ListboxItem**: The component that represents a listbox item.
<ImportTabs
commands={{
main: `import {
Listbox,
ListboxSection,
ListboxItem
} from "@nextui-org/react";`,
individual: `import {
Listbox,
ListboxSection,
ListboxItem
} from "@nextui-org/listbox";`,
}}
/>
## Usage
<CodeDemo title="Usage" files={listboxContent.usage} />
### Dynamic items
Listbox follows the [Collection Components API](https://react-spectrum.adobe.com/react-stately/collections.html), accepting both static and dynamic collections.
- **Static**: The usage example above shows the static implementation, which can be used when the full list of options is known ahead of time.
- **Dynamic**: The example below can be used when the options come from an external data source such as an API call, or update over time.
<CodeDemo title="Dynamic items" files={listboxContent.dynamic} />
### Disabled Keys
Listbox items can be disabled using the `disabledKeys` prop to the `Listbox` component.
<CodeDemo title="Disabled Keys" highlightedLines="10" files={listboxContent.disabledKeys} />
> **Note**: It's important to have a unique key for each item, otherwise the disabled keys will not work.
### Variants
You can use the `variant` in the `Listbox` component to change the `hover` style of the listbox items.
<CodeDemo title="Variants" highlightedLines="18" files={listboxContent.variants} />
### Single Selection
You can set the `selectionMode` property as `single` to allow the user to select only one item at a time.
<CodeDemo
title="Single Selection"
highlightedLines="20-22"
files={listboxContent.singleSelection}
/>
### Multiple Selection
You can set the `selectionMode` property as `multiple` to allow the user to select multiple items at a time.
<CodeDemo
title="Multiple Selection"
highlightedLines="20-22"
files={listboxContent.multipleSelection}
/>
> **Note**: To allow empty selection, you can set the `disallowEmptySelection` property as `false`.
### With Icons
It is possible to add icons to the listbox items using the `startContent` / `endContent` props.
<CodeDemo title="With Icons" highlightedLines="23,30,38" files={listboxContent.icons} />
> **Note**: Note: If you use `currentColor` as the icon color, the icon will have the same color as the item text.
### With Description
You can use the `description` prop to add a description to the listbox item.
<CodeDemo
title="With Description"
highlightedLines="17,24,32,41"
files={listboxContent.description}
/>
### With Sections
You can use the `ListboxSection` component to group listbox items.
<CodeDemo title="With Sections" highlightedLines="15,38" files={listboxContent.sections} />
> **Note**: Sections without a `title` must provide an `aria-label` for accessibility.
## Slots
Listbox has 2 components with slots the `ListboxItem` and `ListboxSection` components.
### ListboxItem
- **base**: The main slot for the listbox item. It wraps all the other slots.
- **wrapper**: The `title` and `description` wrapper.
- **title**: The title of the listbox item.
- **description**: The description of the listbox item.
- **selectedIcon**: The selected icon slot. This is only visible when the item is selected.
### ListboxSection
- **base**: The main slot for the listbox section. It wraps all the other slots.
- **heading**: The title that is render on top of the section group.
- **group**: The group of listbox items.
- **divider**: The divider that is render between the groups. This is only visible when `showDivider` is `true`.
### Customizing the listbox
You can customize the `Listbox` items style by using the `itemClasses` prop and passing custom Tailwind CSS classes.
<CodeDemo title="Custom Styles" files={listboxContent.customStyles} />
> **Note**: In the above example, we've utilized the [Boxicons](https://boxicons.com/) icons collection.
<Spacer y={4} />
### Keyboard Interactions
| Key | Description |
| ------------------------------------ | ---------------------------------------------------------------------------------------------------------------- |
| <Kbd>Home</Kbd> | Moves focus to the first item. |
| <Kbd>End</Kbd> | Moves focus to the last item. |
| <Kbd>ArrowDown</Kbd> | When focus is on an item, moves focus to the next item. |
| <Kbd>ArrowUp</Kbd> | When focus is on an item, moves focus to the previous item. |
| <Kbd>Enter</Kbd> or <Kbd>Space</Kbd> | When focus is on an item, selects the item. |
| <Kbd>A-Z</Kbd> or <Kbd>a-z</Kbd> | Moves focus to the next menu item with a label that starts with the typed character if such an menu item exists. |
## Data Attributes
`ListboxItem` has the following attributes on the `base` element:
- **data-disabled**:
When the listbox item is disabled. Based on listbox `disabledKeys` prop.
- **data-selected**:
When the listbox item is selected. Based on listbox `selectedKeys` prop.
- **data-selectable**:
When the listbox item is selectable. Based on listbox `selectionMode` prop.
- **data-hover**:
When the listbox item is being hovered. Based on [useHover](https://react-spectrum.adobe.com/react-aria/useHover.html)
- **data-pressed**:
When the listbox item is pressed. Based on [usePress](https://react-spectrum.adobe.com/react-aria/usePress.html)
- **data-focus**:
When the listbox item is being focused. Based on [useFocusRing](https://react-spectrum.adobe.com/react-aria/useFocusRing.html).
- **data-focus-visible**:
When the listbox item is being focused with the keyboard. Based on [useFocusRing](https://react-spectrum.adobe.com/react-aria/useFocusRing.html).
<Spacer y={4} />
## Accessibility
- Exposed to assistive technology as a `listbox` using ARIA.
- Support for single, multiple, or no selection.
- Support for disabled items.
- Support for sections.
- Labeling support for accessibility.
- Support for mouse, touch, and keyboard interactions.
- Tab stop focus management.
- Keyboard navigation support including arrow keys, home/end, page up/down, select all, and clear.
- Automatic scrolling support during keyboard navigation.
- Typeahead to allow focusing options by typing text.
<Spacer y={4} />
## API
### Listbox Props
| Attribute | Type | Description | Default |
| ---------------------- | ------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------- | --------- |
| children\* | `ReactNode[]` | The children to render. Usually a list of `ListboxItem` or `ListboxSection` | - |
| items | [`Iterable<T>`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols) | Item objects in the collection. (dynamic) | - |
| variant | `solid` \| `bordered` \| `light` \| `flat` \| `faded` \| `shadow` | The listbox items appearance style. | `solid` |
| color | `default` \| `primary` \| `secondary` \| `success` \| `warning` \| `danger` | The listbox items color theme. | `default` |
| selectionMode | `none` \| `single` \| `multiple` | The type of selection that is allowed in the collection. | - |
| selectedKeys | `React.Key[]` | The currently selected keys in the collection (controlled). | - |
| disabledKeys | `React.Key[]` | The item keys that are disabled. These items cannot be selected, focused, or otherwise interacted with. | - |
| defaultSelectedKeys | `all` \| `React.Key[]` | The initial selected keys in the collection (uncontrolled). | - |
| disallowEmptySelection | `boolean` | Whether the collection allows empty selection. | `false` |
| autoFocus | `boolean` \| `first` \| `last` | Where the focus should be set. | `false` |
| shouldFocusWrap | `boolean` | Whether keyboard navigation is circular. | `false` |
| disableAnimation | `boolean` | Whether to disable the animation of the listbox items. | `false` |
| itemClasses | `Record<"base" "wrapper" "title" "description" "selectedIcon", string>` | Allows to set custom class names for the listbox item slots. | - |
### Listbox Events
| Attribute | Type | Description |
| ----------------- | ----------------------------- | -------------------------------------------------- |
| onAction | `(key: React.Key) => void` | Handler that is called when an item is selected. |
| onSelectionChange | `(keys: React.Key[]) => void` | Handler that is called when the selection changes. |
---
### ListboxSection Props
| Attribute | Type | Description | Default |
| ------------ | ------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------- | ------- |
| children\* | `ReactNode` | The contents of the listbox section. Usually a list of `ListboxItem` components. (static) | - |
| title | `string` | The title of the listbox section. | - |
| items | [`Iterable<T>`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols) | Item objects in the collection. (dynamic) | - |
| showDivider | `boolean` | Whether to show the divider between the groups. | `false` |
| DividerProps | [DividerProps](/docs/components/divider) | The divider component props. | - |
| classNames | `Record<"base" "heading" "group" "divider", string>` | Allows to set custom class names for the listbox section slots. | - |
| itemClasses | `Record<"base" "wrapper" "title" "description" "shortcut" "selectedIcon", string>` | Allows to set custom class names for the listbox item slots. | - |
---
### ListboxItem Props
| Attribute | Type | Description | Default |
| ------------ | --------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------- | ------- |
| children\* | `ReactNode` | The contents of the listbox item. | - |
| key | `React.Key` | The unique key for the listbox item. | - |
| title | `string` \| `ReactNode` | The title of the listbox item. | - |
| textValue | `string` | A string representation of the item's contents, used for features like typeahead. | - |
| description | `string` \| `ReactNode` | The description of the listbox item. | - |
| shortcut | `string` \| `ReactNode` | The listbox item keyboard shortcut. | - |
| startContent | `ReactNode` | The start content of the listbox item. | - |
| endContent | `ReactNode` | The end content of the listbox item. This is positioned after the shortcut and the selected icon. | - |
| selectedIcon | [SelectedIconProps](#listbox-item-selected-icon-props) | Custom icon to render when the item is selected. | - |
| showDivider | `boolean` | Whether to show a divider below the item. | `false` |
| isDisabled | `boolean` | Whether the listbox item should be disabled. (**Deprecated**) pass **disabledKeys** to `Listbox` instead. | `false` |
| isSelected | `boolean` | Whether the listbox item should be selected. (**Deprecated**) pass **selectedKeys** to `Listbox` instead. | `false` |
| isReadOnly | `boolean` | Whether the listbox item press events should be ignored. | `false` |
| classNames | `Record<"base" "wrapper" "title" "description" "shortcut" "selectedIcon", string>` | Allows to set custom class names for the listbox item slots. | - |
### ListboxItem Events
| Attribute | Type | Description |
| ------------- | ------------------------------ | --------------------------------------------------------------------------------------------------------------- |
| onAction | `() => void` | Handler that is called when the listbox item is selected. (**Deprecated**) pass to `Listbox` instead. |
| onPress | `(e: PressEvent) => void` | Handler called when the press is released over the target. |
| onPressStart | `(e: PressEvent) => void` | Handler called when a press interaction starts. |
| onPressEnd | `(e: PressEvent) => void` | Handler called when a press interaction ends, either over the target or when the pointer leaves the target. |
| onPressChange | `(isPressed: boolean) => void` | Handler called when the press state changes. |
| onPressUp | `(e: PressEvent) => void` | Handler called when a press is released over the target, regardless of whether it started on the target or not. |
| onKeyDown | `(e: KeyboardEvent) => void` | Handler called when a key is pressed. |
| onKeyUp | `(e: KeyboardEvent) => void` | Handler called when a key is released. |
| onClick | `MouseEventHandler` | The native button click event handler (**Deprecated**) use **onPress** instead. |
---
### Types
#### Listbox Item Selected Icon Props
```ts
export type ListboxItemSelectedIconProps = {
/**
* The current icon, usually an checkmark icon.
*/
icon?: ReactNode;
/**
* The current selected status.
*/
isSelected?: boolean;
/**
* The current disabled status.
* @default false
*/
isDisabled?: boolean;
};
type selectedIcon?: ReactNode | ((props: ListboxItemSelectedIconProps) => ReactNode) | null;
```

View File

@ -141,7 +141,7 @@ You can customize the `Modal` component by passing custom Tailwind CSS classes t
## Data Attributes
`Modal` has the following attributes on the `root` element:
`Modal` has the following attributes on the `base` element:
- **data-open**:
When the modal is open. Based on modal state.
@ -153,7 +153,7 @@ You can customize the `Modal` component by passing custom Tailwind CSS classes t
## Accessibility
- Content outside the modal is hidden from assistive technologies while it is open.
- The modal optionally closes when interacting outside, or pressing the <kbd>Esc</kbd> key.
- The modal optionally closes when interacting outside, or pressing the <Kbd>Esc</Kbd> key.
- Focus is moved into the modal on mount, and restored to the trigger element on unmount.
- While open, focus is contained within the modal, preventing the user from tabbing outside.
- Scrolling the page behind the modal is prevented while it is open, including in mobile browsers.

View File

@ -210,7 +210,7 @@ When the `NavbarItem` is active, it will have a `data-active` attribute. You can
## Data Attributes
`Navbar` has the following attributes on the `root` element:
`Navbar` has the following attributes on the `base` element:
- **data-menu-open**:
Indicates if the navbar menu is open.
@ -222,12 +222,12 @@ When the `NavbarItem` is active, it will have a `data-active` attribute. You can
- **data-justify**:
The justify content of the navbar content. It takes into account the correct space distribution.
`NavbarItem` has the following attributes on the `root` element:
`NavbarItem` has the following attributes on the `base` element:
- **data-active**:
Indicates if the navbar item is active. It is used when the `isActive` prop is `true`.
`NavbarMenuToggle` has the following attributes on the `root` element:
`NavbarMenuToggle` has the following attributes on the `base` element:
- **data-open**:
Indicates if the navbar menu is open. It is used when the `isMenuOpen` prop is `true`.

View File

@ -135,7 +135,7 @@ your own implementation.
## Data Attributes
`Pagination` has the following attributes on the `root` element:
`Pagination` has the following attributes on the `base` element:
- **data-controls**:
Indicates whether the pagination has controls. Based on `showControls` prop.

View File

@ -124,7 +124,7 @@ You can customize the `Popover` component by passing custom Tailwind CSS classes
- The trigger and popover are automatically associated semantically via ARIA.
- Content outside the popover is hidden from assistive technologies while it is open.
- The popover closes when interacting outside, or pressing the <kbd>Escape</kbd> key.
- The popover closes when interacting outside, or pressing the <Kbd>Escape</Kbd> key.
- Focus is moved into the popover on mount, and restored to the trigger element on unmount.
- The popover is positioned relative to the trigger element, and automatically flips and adjusts to avoid overlapping with the edge of the browser window.
- Scrolling is prevented outside the popover to avoid unintentionally repositioning or closing it.

View File

@ -86,7 +86,7 @@ You can customize the `Progress` component by passing custom Tailwind CSS classe
## Data Attributes
`CircularProgress` has the following attributes on the `root` element:
`CircularProgress` has the following attributes on the `base` element:
- **data-indeterminate**:
Indicates whether the progress is indeterminate.

View File

@ -87,12 +87,12 @@ In case you need to customize the radio group even further, you can use the `use
## Data Attributes
- RadioGroup has the following attributes on the `root` element:
- RadioGroup has the following attributes on the `base` element:
- **data-orientation**:
The orientation of the radio group. Based on `orientation` prop.
- Radio has the following attributes on the `root` element:
- Radio has the following attributes on the `base` element:
- **data-selected**:
When the radio is checked. Based on `isSelected` prop.

View File

@ -0,0 +1,68 @@
---
title: "Scroll Shadow"
description: "Applies top and bottom shadows when content overflows on scroll."
---
import {scrollShadowContent} from "@/content/components/scroll-shadow";
# Scroll Shadow
Applies top and bottom shadows when content overflows on scroll.
<ComponentLinks component="scroll-shadow" />
---
<CarbonAd />
## Import
<ImportTabs
commands={{
main: 'import {ScrollShadow} from "@nextui-org/react";',
individual: 'import {ScrollShadow} from "@nextui-org/scroll-shadow";',
}}
/>
## Usage
<CodeDemo title="Usage" files={scrollShadowContent.usage} />
### Hide Scrollbar
You can use the `hideScrollBar` property to hide vertical and horizontal scrollbars.
<CodeDemo title="Hide Scrollbar" files={scrollShadowContent.hideScrollbar} />
### Custom Shadow Size
By default, the shadow size is `40` in pixels, but you can change it using the `size` property.
<CodeDemo title="Custom Shadow Size" files={scrollShadowContent.customSize} />
### Horizontal Orientation
In case you need to apply the shadow on the horizontal scroll, you can set the `orientation` property to `horizontal`.
<CodeDemo title="Horizontal Orientation" files={scrollShadowContent.horizontal} />
### Shadow Offset
By default the shadow offset is `0` in pixels, but you can change it using the `offset` property. This allows you to apply the shadow on
a specific position.
<CodeDemo title="Shadow Offset" files={scrollShadowContent.offset} />
<Spacer y={4} />{" "}
## API
### ShadowScroll Props
| Attribute | Type | Description | Default |
| ------------- | -------------------------- | ----------------------------------------------- | ---------- |
| size | `number` | The shadow size in pixels. | `40` |
| offset | `number` | The scroll offset to show the shadow in pixels. | `0` |
| hideScrollBar | `boolean` | Whether to hide the scrollbar or not. | `false` |
| orientation | `horizontal` \| `vertical` | The scroll orientation. | `vertical` |
| isEnabled | `boolean` | Whether the shadow is enabled or not. | `true` |

View File

@ -0,0 +1,427 @@
---
title: "Select"
description: "A select displays a collapsible list of options and allows a user to select one or more of them."
---
import {selectContent} from "@/content/components/select";
# Select
A select displays a collapsible list of options and allows a user to select one or more of them.
<ComponentLinks component="select" reactAriaHook="useSelect" />
---
<CarbonAd />
## Import
NextUI exports 3 select-related components:
- **Select**: The main component, which is a wrapper for the other components.
- **SelectSection**: The component that contains a group of select items.
- **SelectItem**: The component that represents a select item.
<ImportTabs
commands={{
main: 'import {Select, SelectSection, SelectItem} from "@nextui-org/react";',
individual: 'import {Select, SelectSection, SelectItem} from "@nextui-org/select";',
}}
/>
## Usage
<CodeDemo title="Usage" files={selectContent.usage} />
### Dynamic items
Select follows the [Collection Components API](https://react-spectrum.adobe.com/react-stately/collections.html), accepting both static and dynamic collections.
- **Static**: The usage example above shows the static implementation, which can be used when the full list of options is known ahead of time.
- **Dynamic**: The example below can be used when the options come from an external data source such as an API call, or update over time.
<CodeDemo title="Dynamic items" highlightedLines="8" files={selectContent.dynamic} />
### Disabled
<CodeDemo title="Disabled" highlightedLines="8" files={selectContent.disabled} />
### Disabled Items
You can disable specific items by using the `disabledKeys` property.
<CodeDemo title="Disabled Items" highlightedLines="8" files={selectContent.disabledItems} />
### Required
If you pass the `isRequired` property to the select, it will have a `danger` asterisk at
the end of the label and the select will be required.
<CodeDemo title="Required" highlightedLines="8" files={selectContent.required} />
### Sizes
<CodeDemo title="Sizes" highlightedLines="13,26" files={selectContent.sizes} />
### Colors
<CodeDemo title="Colors" files={selectContent.colors} />
### Variants
<CodeDemo title="Variants" files={selectContent.variants} />
### Radius
<CodeDemo title="Radius" files={selectContent.radius} />
### Label Placements
You can change the position of the label by setting the `labelPlacement` property to `inside`, `outside` or `outside-left`.
<CodeDemo title="Label Placements" highlightedLines="20,37" files={selectContent.labelPlacements} />
> **Note**: If the `label` is not passed, the `labelPlacement` property will be `outside` by default.
### Start Content
You can use the `startContent` and `endContent` properties to add content to the start and end of
the select.
<CodeDemo title="Start Content" highlightedLines="9" files={selectContent.startContent} />
### Item Start Content
Since the `Select` component uses the [Listbox](/docs/components/listbox) component under the hood, you can
use the `startContent` and `endContent` properties of the `SelectItem` component to add content to the start
and end of the select item.
<CodeDemo title="Item Start Content" files={selectContent.itemStartContent} />
### Custom Selector Icon
By default the select uses a `crevron-down` icon as the selector icon which rotates when the select is open. You can
customize this icon by passing a custom one to the `selectorIcon` property.
<CodeDemo title="Custom Selector Icon" files={selectContent.customSelectorIcon} />
> **Note**: Use the `disableSelectionIconRotation` property to disable the rotation of the icon.
### Without Scroll Shadow
Select component uses the [ScrollShadow](/docs/components/scroll-shadow) under the hood to show a shadow when the select content is scrollable.
You can disable this shadow by passing using the `scrollShadowProps` property.
<CodeDemo title="Without Scroll Shadow" files={selectContent.withoutScrollShadow} />
> **Note**: You can also use the `showScrollIndicators` property to disable the scroll indicators.
### With Description
You can add a description to the select by passing the `description` property.
<CodeDemo title="With Description" files={selectContent.description} />
### With Error Message
You can combine the `validationState="invalid"` and `errorMessage` properties to show an invalid select.
<CodeDemo title="With Error Message" files={selectContent.errorMessage} />
### Controlled
You can use the `selectedKeys` and `onSelectionChange` / `onChange` properties to control the select value.
Using `onSelectionChange`:
<CodeDemo title="Controlled with onSelectionChange" files={selectContent.singleControlled} />
Using `onChange`:
<CodeDemo title="Controlled with onChange" files={selectContent.singleControlledOnChange} />
### Controlling the open state
You can control the open state of the select by using the `isOpen` and `onOpenChange` / `onClose` properties.
<CodeDemo title="Controlling the open state" files={selectContent.openState} />
### Custom Items
You can customize the select items by modifying the `SelectItem` children.
<CodeDemo title="Custom Items" files={selectContent.customItems} />
### Custom Render Value
By default the select will render the selected item's text value, but you can customize this by passing a `renderValue` function.
<CodeDemo title="Custom Render Value" files={selectContent.customRenderValue} />
The `renderValue` function receives the selected items as a parameter and must return a
`ReactNode`. Check the [Render Value Function](#render-value-function) section for more details.
### With Sections
You can use the `SelectSection` component to group select items.
<CodeDemo title="With Sections" files={selectContent.sections} />
### Custom Sections Style
You can customize the sections style by using the `classNames` property of the `SelectSection` component.
<CodeDemo title="Custom Sections Style" files={selectContent.customSectionsStyle} />
### Asyncronous Loading
Select supports asyncronous loading, in the example below we are using a custom hook to fetch the [Pokemon API](https://pokeapi.co/api/v2/pokemon) data in combination with the `useInfinityScroll` hook to load more data when the user reaches the end of the list.
The `isLoading` prop is used to show a loading indicator intead of the selector icon when the data is being fetched.
<PackageManagers
commands={{
npm: "npm install @nextui-org/use-infinity-scroll",
yarn: "yarn add @nextui-org/use-infinity-scroll",
pnpm: "pnpm add @nextui-org/use-infinity-scroll",
}}
/>
```jsx
import {useInfinityScroll} from "@nextui-org/use-infinity-scroll";
```
<Spacer y={2} />
<CodeDemo
asIframe
typescriptStrict={true}
title="Asyncronous Loading"
hideWindowActions={true}
resizeEnabled={false}
displayMode="always"
files={selectContent.asyncLoadingItems}
previewHeight="400px"
iframeSrc="/examples/select/async-items-loading"
/>
### Multiple Select
You can use the `selectionMode="multiple"` property to allow multiple selection.
<CodeDemo title="Multiple Selection" files={selectContent.multiple} />
### Multiple Select Controlled
You can use the same properties as the single select to control the multiple select, `selectedKeys` and `onSelectionChange` / `onChange`.
Using `onSelectionChange`:
<CodeDemo
title="Multiple Selection Controlled with onSelectionChange"
files={selectContent.multipleControlled}
/>
Using `onChange`:
<CodeDemo
title="Multiple Selection Controlled with onChange"
files={selectContent.multipleControlledOnChange}
/>
### Mutliple With Chips
You can render any component as the select value by using the `renderValue` property. In this example we are
using the [Chip](/docs/components/chip) component to render the selected items.
<CodeDemo title="Multiple Selection with Chips" files={selectContent.multipleWithChips} />
> **Note**: Make sure to pass the `isMultiline` property to the `Select` component to allow the chips to wrap.
The `renderValue` function receives the selected items as a parameter and must return a
`ReactNode`. Check the [Render Value Function](#render-value-function) section for more details.
### Customizing the select
You can customize any slot of the select by using the `classNames` property. Select
component also provides the [popoverProps](/docs/components/popover#api) and [listboxProps](/docs/components/listbox#api) properties to customize
the popover and listbox components.
<CodeDemo title="Custom Styles" files={selectContent.customStyles} />
## Slots
- **base**: The main wrapper of the select. This wraps the rest of the slots.
- **label**: The label of the select.
- **trigger**: The trigger of the select. This wraps the label the inner wrapper and the selector icon.
- **innerWrapper**: The wrapper of the select content. This wraps the start/end content and the select value.
- **selectorIcon**: The selector icon of the select. This is the icon that rotates when the select is open (`data-open`).
- **value**: The select value. This is also the slot that wraps the `renderValue` function result.
- **listboxWrapper**: The wrapper of the listbox. This wraps the listbox component, this slot is used on top of the scroll shadow component.
- **listbox**: The listbox component. This is the component that wraps the select items.
- **popover**: The popover component. This is the component that wraps the listbox component.
- **helperWrapper**: The wrapper of the helper text. This wraps the helper text and the error message.
- **description**: The description of the select.
- **errorMessage**: The error message of the select.
## Data Attributes
`Select` has the following attributes on the `base` element:
- **data-filled**:
Indicates if the select has a value, is focused, has start/end content or is open.
`Select` has the following attributes on the `trigger` element:
- **data-open**:
Indicates if the select is open.
- **data-disabled**:
When the select trigger is disabled. Based on select `isDisabled` prop.
- **data-focus**:
When the select trigger is being focused. Based on [useFocusRing](https://react-spectrum.adobe.com/react-aria/useFocusRing.html).
- **data-focus-visible**:
When the select trigger is being focused with the keyboard. Based on [useFocusRing](https://react-spectrum.adobe.com/react-aria/useFocusRing.html).
- **data-pressed**:
When the select trigger is pressed. Based on [usePress](https://react-spectrum.adobe.com/react-aria/usePress.html)
- **data-hover**:
When the select trigger is being hovered. Based on [useHover](https://react-spectrum.adobe.com/react-aria/useHover.html)
`Select` has the following attributes on the `selectorIcon` element:
- **data-open**:
Indicates if the select is open.
`SelectItem` has the following attributes on the `base` element:
- **data-disabled**:
When the select item is disabled. Based on select `disabledKeys` prop.
- **data-selected**:
When the select item is selected. Based on select `selectedKeys` prop.
- **data-hover**:
When the select item is being hovered. Based on [useHover](https://react-spectrum.adobe.com/react-aria/useHover.html)
- **data-pressed**:
When the select item is pressed. Based on [usePress](https://react-spectrum.adobe.com/react-aria/usePress.html)
- **data-focus**:
When the select item is being focused. Based on [useFocusRing](https://react-spectrum.adobe.com/react-aria/useFocusRing.html).
- **data-focus-visible**:
When the select item is being focused with the keyboard. Based on [useFocusRing](https://react-spectrum.adobe.com/react-aria/useFocusRing.html).
<Spacer y={4} />
## Accessibility
- Exposed to assistive technology as a button with a listbox popup using ARIA (combined with [Listbox](/docs/components/listbox)).
- Support for selecting a single option.
- Support for selecting multiple options.
- Support for disabled options.
- Support for sections.
- Labeling support for accessibility.
- Support for description and error message help text linked to the input via ARIA.
- Support for mouse, touch, and keyboard interactions.
- Tab stop focus management.
- Keyboard support for opening the listbox using the arrow keys, including automatically focusing the first or last item accordingly.
- Typeahead to allow selecting options by typing text, even without opening the listbox.
- Browser autofill integration via a hidden native `<select>` element.
- Support for mobile form navigation via software keyboard.
- Mobile screen reader listbox dismissal support.
<Spacer y={4} />
## API
### Select Props
| Attribute | Type | Description | Default |
| ---------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- | ------------------ |
| children\* | `ReactNode[]` | The children to render. Usually a list of `SelectItem` and `SelectSection` elements. | - |
| items | [`Iterable<T>`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols) | Item objects in the select. (dynamic) | - |
| selectionMode | `single` \| `multiple` | The type of selection that is allowed in the collection. | - |
| selectedKeys | `all` \| `React.Key[]` | The currently selected keys in the collection (controlled). | - |
| disabledKeys | `all` \| `React.Key[]` | The item keys that are disabled. These items cannot be selected, focused, or otherwise interacted with. | - |
| defaultSelectedKeys | `all` \| `React.Key[]` | The initial selected keys in the collection (uncontrolled). | - |
| variant | `flat` \| `bordered` \| `faded` \| `underlined` | The variant of the select. | `flat` |
| color | `default` \| `primary` \| `secondary` \| `success` \| `warning` \| `danger` | The color of the select. | `default` |
| size | `sm` \| `md` \| `lg` | The size of the select. | `md` |
| radius | `none` \| `sm` \| `md` \| `lg` \| `full` | The radius of the select. | - |
| placeholder | `string` | The placeholder of the select. | `Select an option` |
| labelPlacement | `inside` \| `outside` \| `outside-left` | The position of the label. | `inside` |
| validationState | `valid` \| `invalid` | Whether the select should display its "valid" or "invalid" visual styling. | - |
| label | `ReactNode` | The content to display as the label. | - |
| description | `ReactNode` | A description for the select. Provides a hint such as specific requirements for what to choose. | - |
| errorMessage | `ReactNode` | An error message for the select. | - |
| startContent | `ReactNode` | Element to be rendered in the left side of the select. | - |
| endContent | `ReactNode` | Element to be rendered in the right side of the select. | - |
| selectorIcon | `ReactNode` | Element to be rendered as the selector icon. | - |
| scrollRef | `React.RefObject<HTMLElement>` | A ref to the scrollable element. | - |
| spinnerRef | `React.RefObject<HTMLElement>` | A ref to the spinner element. | - |
| fullWidth | `boolean` | Whether the select should take up the width of its parent. | `true` |
| isOpen | `boolean` | Whether the select is open by default (controlled). | - |
| defaultOpen | `boolean` | Whether the select is open by default (uncontrolled). | - |
| isRequired | `boolean` | Whether user select is required on the select before form submission. | `false` |
| isDisabled | `boolean` | Whether the select is disabled. | `false` |
| isMultiline | `boolean` | Whether the select should allow multiple lines of text. | `false` |
| showScrollIndicators | `boolean` | Whether the select should show scroll indicators when the listbox is scrollable. | `true` |
| autoFocus | `boolean` | Whether the select should be focused on the first mount. | `false` |
| disallowEmptySelection | `boolean` | Whether the collection allows empty selection. | `false` |
| disableAnimation | `boolean` | Whether the select should be animated. | `true` |
| disableSelectionIconRotation | `boolean` | Whether the select should disable the rotation of the selector icon. | `false` |
| popoverProps | [PopoverProps](/docs/components/popover#api) | Props to be passed to the popover component. | - |
| listboxProps | [ListboxProps](/docs/components/listbox#api) | Props to be passed to the listbox component. | - |
| scrollShadowProps | [ScrollShadowProps](/docs/components/scroll-shadow#api) | Props to be passed to the scroll shadow component. | - |
| classNames | `Record<"base" "label" "trigger" "innerWrapper" "selectorIcon" "value" "listboxWrapper" "listbox" "popover" "helperWrapper" "description" "errorMessage", string>` | Allows to set custom class names for the dropdown item slots. | - |
### Select Events
| Attribute | Type | Description |
| ----------------- | --------------------------------------------- | ------------------------------------------------------------------------------------ |
| onClose | `() => void` | Callback fired when the select popover is closed. |
| onOpenChange | `(isOpen: boolean) => void` | Callback fired when the select popover is opened or closed. |
| onSelectionChange | `(keys: React.Key[]) => void` | Callback fired when the selected keys change. |
| onChange | `React.ChangeEvent<HTMLSelectElement>` | Native select change event, fired when the selected value changes. |
| renderValue | [RenderValueFunction](#render-value-function) | Function to render the value of the select. It renders the selected item by default. |
---
### SelectItem Props
Check the [ListboxItem](/docs/components/listbox#listboxitem-props) props.
### SelectItem Events
Check the [ListboxItem](/docs/components/listbox#listboxitem-events) events.
### SelectSection Props
Check the [ListboxSection](/docs/components/listbox#listboxsection-props) props.
---
### Types
#### Render Value Function
The `T` type is the type of the data passed to the select `items`.
```tsx
export type SelectedItemProps<T> = {
/** A unique key for the item. */
key?: Key;
/** The props passed to the item. */
props?: Record<string, any>;
/** The item data. */
data?: T | null;
/** An accessibility label for this item. */
"aria-label"?: string;
/** The rendered contents of this item (e.g. JSX). */
rendered?: ReactNode;
/** A string value for this item, used for features like typeahead. */
textValue?: string;
/** The type of item this item represents. */
type?: string;
};
type SelectedItems<T> = Array<SelectedItemProps<T>>;
renderValue: (items: SelectedItems<T>) => ReactNode;
```

View File

@ -50,7 +50,7 @@ You can use the `isLoaded` prop to stop the skeleton animation and show the chil
## Data Attributes
`Skeleton` has the following attributes on the `root` element:
`Skeleton` has the following attributes on the `base` element:
- **data-loaded**:
Indicates the loaded state of the skeleton. Based on the `isLoaded` prop.

View File

@ -87,7 +87,7 @@ In case you need to customize the switch even further, you can use the `useSwitc
## Data Attributes
`Switch` has the following attributes on the `root` element:
`Switch` has the following attributes on the `base` element:
- **data-selected**:
When the switch is checked. Based on `isSelected` prop.
@ -111,7 +111,7 @@ In case you need to customize the switch even further, you can use the `useSwitc
- Built with a native HTML `<input>` element.
- Full support for browser features like form autofill.
- Keyboard focus management and cross browser normalization.
- Keyboard event support for <kbd>Tab</kbd> and <kbd>Space</kbd> keys.
- Keyboard event support for <Kbd>Tab</Kbd> and <Kbd>Space</Kbd> keys.
- Labeling support for assistive technology.
- Exposed as a switch to assistive technology via ARIA

View File

@ -96,7 +96,7 @@ You can customize the `Tabs` component by passing custom Tailwind CSS classes to
## Data Attributes
`Tab` has the following attributes on the `root` element:
`Tab` has the following attributes on the `base` element:
- **data-selected**:
When the tab is selected.

View File

@ -86,7 +86,7 @@ You can use the `value` and `onValueChange` properties to control the input valu
## Data Attributes
`Textarea` has the following attributes on the `root` element:
`Textarea` has the following attributes on the `base` element:
- **data-invalid**:
When the textarea is invalid. Based on `validationState` prop.

View File

@ -86,7 +86,7 @@ You can customize the `Tooltip` component by passing custom Tailwind CSS classes
## Data Attributes
`Tooltip` has the following attributes on the `root` element:
`Tooltip` has the following attributes on the `base` element:
- **data-open**:
When the tooltip is open. Based on tooltip state.

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

View File

@ -1,4 +1,5 @@
{
"remove": ["devDependencies"],
"replace": {
"main": "dist/index.js",
"module": "dist/index.mjs",

Some files were not shown because too many files have changed in this diff Show More