Compare commits

...

82 Commits

Author SHA1 Message Date
github-actions[bot] a53e274d5b ci(changesets): version packages (#1615)
Co-authored-by: Junior Garcia <jrgarciadev@gmail.com>
2023-09-16 21:25:10 +00:00
Junior Garcia 425a034bca fix(packages): validation state deprecated, isInvalid prop adjusted (#1631) 2023-09-16 21:16:32 +00:00
lijianan a5a1ea5ade fix(docs): button custom implement (#1643) 2023-09-16 21:12:14 +00:00
Junior Garcia f6531c5f60 fix(core): extend variants function, destructuring order changed (#1642)
* fix(core): extend variants function, destructuring order changed

* chore(core): changeset added
2023-09-16 21:06:16 +00:00
Junior Garcia 37d5f12162 fix(docs): button custom implementation (#1641) 2023-09-16 20:28:52 +00:00
lijianan dd97fc3c4f fix: fix eslint warning (#1640) 2023-09-16 20:23:26 +00:00
lijianan ceddd0d1d9 refactor: optimize the time of ripple destroy (#1635)
* refactor: optimize the time of ripple destroy

* Update packages/components/button/src/use-button.ts

Co-authored-by: Jakob Guddas <github@jguddas.de>

* fix: fix

* Update packages/components/button/src/button.tsx

Co-authored-by: Jakob Guddas <github@jguddas.de>

* Update packages/components/card/src/card.tsx

Co-authored-by: Jakob Guddas <github@jguddas.de>

* Update packages/components/button/src/button.tsx

Co-authored-by: Jakob Guddas <github@jguddas.de>

* Update packages/components/card/src/card.tsx

Co-authored-by: Jakob Guddas <github@jguddas.de>

* Update packages/components/card/src/use-card.ts

Co-authored-by: Jakob Guddas <github@jguddas.de>

* Update packages/components/card/src/use-card.ts

Co-authored-by: Jakob Guddas <github@jguddas.de>

* fix: fix

* chore: revert

* Create fresh-cameras-provide.md

* Update packages/components/button/src/button.tsx

Co-authored-by: Junior Garcia <jrgarciadev@gmail.com>

* Update packages/components/button/src/button.tsx

Co-authored-by: Junior Garcia <jrgarciadev@gmail.com>

* Update packages/components/button/src/use-button.ts

Co-authored-by: Junior Garcia <jrgarciadev@gmail.com>

* Update packages/components/card/src/card.tsx

Co-authored-by: Junior Garcia <jrgarciadev@gmail.com>

* Update packages/components/card/src/card.tsx

Co-authored-by: Junior Garcia <jrgarciadev@gmail.com>

* fix: fix

* feat: add getUniqueID

---------

Co-authored-by: Jakob Guddas <github@jguddas.de>
Co-authored-by: Junior Garcia <jrgarciadev@gmail.com>
2023-09-16 20:11:04 +00:00
Junior Garcia bb8ed58749 fix(accordion): selectedKeys added to the values memo function (#1639) 2023-09-16 20:01:39 +00:00
markyong bbbdcbdfdf chore(root): update contributing.md note (#1638) 2023-09-16 19:17:59 +00:00
Junior Garcia bc424948c7 fix(accordion): accordion is no longer preventing spacebar (#1630) 2023-09-15 20:42:02 +00:00
Junior Garcia cdc30db14c fix(utils): filterDomProps fixed (#1629) 2023-09-14 22:49:58 -03:00
Junior Garcia 3aa86423aa Fix/1625 (#1628)
* fix(listbox): item classNames prop, listbox wrapper export

* chore(listbox): changesets
2023-09-15 00:53:26 +00:00
Junior Garcia 59ed34b3de fix(docs): table use case example fixed, sandpack tabs padding added (#1627) 2023-09-15 00:30:17 +00:00
Chong Ruei He f58fc9bb69 fix(docs): add scrollbehavior ts support (#1618) 2023-09-14 20:13:07 +00:00
Junior Garcia 9a478b6c1f chore(docs): hero events 2023-09-13 09:16:48 -03:00
Junior Garcia 7fd0327657 chore(docs): va events added 2023-09-13 08:39:58 -03:00
Bobby Chan 05c966e8a4 fix(card): corrected footerStyles in card footer (#1611) 2023-09-12 13:20:09 -03:00
Nahuel Alejandro Cabrera 5b014b76ff Update explanation in layout.mdx (#1601) 2023-09-12 13:19:10 -03:00
Koen Verheyen cf32b5ae8b Update standalone.ts (#1614) 2023-09-12 13:18:47 -03:00
github-actions[bot] 4452ed66c0 ci(changesets): version packages (#1599)
Co-authored-by: Junior Garcia <jrgarciadev@gmail.com>
2023-09-10 20:32:13 +00:00
Junior Garcia b1b30b7976 chore(root): fix changesets deploy (#1600) 2023-09-10 20:20:19 +00:00
github-actions[bot] 97ef2d7250 ci(changesets): version packages (#1565)
Co-authored-by: Junior Garcia <jrgarciadev@gmail.com>
2023-09-10 19:58:22 +00:00
Junior Garcia 8b39989090 chore(root): changesets 2023-09-10 16:46:31 -03:00
Chongyi Zheng 8363a3ecfc fix: avoid src in import path (#1596)
* fix: avoid `src` in import path

* fix: export `RippleType`
2023-09-10 19:42:55 +00:00
Jakob Guddas 5c30e04811 fix: set nowrap in chip (#1590)
* fix: set nowrap in chip

* Create early-garlics-deliver.md
2023-09-10 19:16:06 +00:00
Adrian 8606fbe0b9 fix(links): corrected typo in accordion link (#1594) 2023-09-10 01:10:46 +00:00
Junior Garcia 1612532eee chore: react-aria packages upgraded (#1589) 2023-09-09 13:50:21 +00:00
Junior Garcia a3be419cb3 Fix/1561 (#1563)
* fix(select): bottom space

* chore(select): changeset
2023-09-03 13:19:17 +00:00
github-actions[bot] 72a7f71377 ci(changesets): version packages (#1559)
Co-authored-by: Junior Garcia <jrgarciadev@gmail.com>
2023-09-02 21:38:53 +00:00
Junior Garcia 7c8341035d fix(pagination): changeset (#1558) 2023-09-02 21:28:41 +00:00
github-actions[bot] 6ca0ce309a ci(changesets): version packages (#1557)
Co-authored-by: Junior Garcia <jrgarciadev@gmail.com>
2023-09-02 21:20:10 +00:00
Junior Garcia acc2ff3913 Merge branch 'main' of github.com:nextui-org/nextui 2023-09-02 18:07:05 -03:00
Junior Garcia 4db10a47e9 chore: changeset pagination revert 2023-09-02 18:06:51 -03:00
Junior Garcia a9c4fab011 chore: pagination changes changeset removed (#1556) 2023-09-02 20:53:55 +00:00
Junior Garcia d61428d9e6 Revert "ci(changesets): version packages (#1550)" (#1555)
This reverts commit 43906f639e.
2023-09-02 20:52:36 +00:00
Junior Garcia 455b788924 fix(docs): missing pagination docs added 2023-09-02 17:48:31 -03:00
Junior Garcia 79cfdbd8ff Revert "fix: resolved cursor issues in pagination (#1222)" (#1554)
This reverts commit 28477447d3.
2023-09-02 20:46:01 +00:00
Junior Garcia 7d294e3a04 Revert "fix: fixed pagination scale animation (#1552)" (#1553)
This reverts commit 8fcc8b3767.
2023-09-02 20:45:49 +00:00
github-actions[bot] 43906f639e ci(changesets): version packages (#1550)
Co-authored-by: Junior Garcia <jrgarciadev@gmail.com>
2023-09-02 20:40:07 +00:00
Jakob Guddas 8fcc8b3767 fix: fixed pagination scale animation (#1552) 2023-09-02 15:45:27 -03:00
Jakob Guddas 28477447d3 fix: resolved cursor issues in pagination (#1222)
* fix: resolved cursor issues in pagination

* chore: added comment

* kick: trigger ci

* Create eighty-knives-heal.md
2023-09-02 18:01:38 +00:00
Junior Garcia fc3c6b9431 chore(root): tailwind variants upgraded (#1551)
* chore(root): tailwind variants upgraded

* fix(theme): prettier
2023-09-02 17:46:36 +00:00
Junior Garcia 59fda3772f fix(navbar-menu): dismiss buttons removed to fix the scroll (#1549) 2023-09-02 15:41:38 +00:00
Troye d8d2b87cb8 fix(docs): table async pagination (#1491)
* fix(docs): change to swr

* chore(table): change to swr

* fix(table): keep the pagination when switching pages

* chore(repo): pnpm lockfile updated
2023-09-02 12:56:39 +00:00
github-actions[bot] 64571e468c ci(changesets): version packages (#1514)
Co-authored-by: Junior Garcia <jrgarciadev@gmail.com>
2023-09-01 21:09:05 +00:00
Junior Garcia faf26acd23 fix(snippet): invalid props (#1546) 2023-09-01 20:52:16 +00:00
Junior Garcia cac56faf29 chore(docs): hero tooltip arrow removed (#1547) 2023-09-01 20:45:41 +00:00
Junior Garcia 09fe1d3141 Fix/1531 (#1545)
* fix(tabs): title prop was being passed to html element

* chore(tabs): changeset
2023-09-01 20:44:46 +00:00
Junior Garcia a9e324b351 fix(listbox): dynamic items types (#1544) 2023-09-01 20:42:20 +00:00
Junior Garcia 043b8420cf Fix/1492 (#1543)
* fix(select): select & input styles fixed

* chore(input): extra data attr added to input wrapper
2023-09-01 20:42:15 +00:00
Junior Garcia 57909accde Fix/1298 (#1542)
* fix(modal): focus trap added

* chore(navbar): changeset added
2023-09-01 20:42:08 +00:00
Vansh Shah 7a17256268 Solved error in Listbox Component (#1530) 2023-08-31 14:06:13 -03:00
MisterHims bf2bc265ee feat: adding some adjustements on listbox and dropdown doc pages (#1520)
* fix: some typo and renamed use infinite scroll call on async section of select docpage

* fix(listbox-docpage): note doublon from the with icons section

* fix(switch-docpage): add a missing whitespace

* fix(dropdown-docpage): remove note doublon

* fix(dropdown-docpage): adding DropdownSection dependencu into the with-section code

* fix(dropdown-docpage): do not need Button component on custom-trigger section code

* fix(dropdown-docpage): fixed typo missing letter on dropdown-item list

* fix(dropdown-section): add missing comma
2023-08-29 18:05:55 +00:00
MisterHims cf6bf749a1 feat: adding some ajustements on listbox and dropdown doc pages (#1518) 2023-08-29 13:20:51 -03:00
Tianen Pang 641bf0885b feat(system): extend props for nextui provider (#1513) 2023-08-28 13:00:24 -03:00
MisterHims 40b42001f9 fix: some typo and renamed use infinite scroll call on async section of select docpage (#1509) 2023-08-27 19:30:49 -03:00
github-actions[bot] 789a7209a2 ci(changesets): version packages (#1500)
Co-authored-by: Junior Garcia <jrgarciadev@gmail.com>
2023-08-26 14:57:11 +00:00
Junior Garcia 021aa16d96 chore(docs): inter font applied to tailwind config 2023-08-26 11:30:06 -03:00
Junior Garcia eb8a1fcc01 chore(docs): font family chnaged to inter 2023-08-26 11:24:28 -03:00
Junior Garcia 9b42a2fca1 fix(docs): select typo 2023-08-26 11:15:15 -03:00
Junior Garcia 5702287e56 fix(popover): arrow color (#1501) 2023-08-26 14:13:04 +00:00
Jakob Guddas 290cce15be fix: show focus ring when table row is focused in read mode (#1303)
* fix: show focus ring when table row is focused in read mode

* Create witty-trees-buy.md
2023-08-26 13:41:35 +00:00
github-actions[bot] 27bde30839 ci(changesets): version packages (#1499)
Co-authored-by: Junior Garcia <jrgarciadev@gmail.com>
2023-08-26 13:39:00 +00:00
Junior Garcia 6be3bc3516 fix(docs): textarea readonly typo 2023-08-26 10:30:13 -03:00
T/once e4113b05ce fix(navbar): unable to Close NavbarMenu (#1496)
* add mode wait to AnimatePresence

* add changeset
2023-08-26 13:29:27 +00:00
Junior Garcia a3a95e7196 Merge branch 'main' of github.com:nextui-org/nextui 2023-08-26 10:27:22 -03:00
Junior Garcia 8731159702 fix(docs): font family 2023-08-26 10:27:08 -03:00
Hyuuh b6adb2ae8c docs(components): 📝 change to the new rsc link (#1493)
The new docs for Next.js RSC has been moved to a new section.
2023-08-25 17:29:00 +00:00
github-actions[bot] cd2d9b70a9 ci(changesets): version packages (#1477)
Co-authored-by: Junior Garcia <jrgarciadev@gmail.com>
2023-08-23 03:26:47 +00:00
Junior Garcia a371e1a5fa Fix/tooltip arrow position (#1474)
* feat(blog): rss auto-discovery added

* fix(blog): feed.xml author name

* fix(tooltip): arrow position

* chore(tooltip): changeset
2023-08-23 03:11:15 +00:00
github-actions[bot] 5cdc4d1d87 ci(changesets): version packages (#1475)
Co-authored-by: Junior Garcia <jrgarciadev@gmail.com>
2023-08-23 03:11:05 +00:00
Junior Garcia 22c6e070dd Fix/1469 (#1476)
* feat(blog): rss auto-discovery added

* fix(blog): feed.xml author name

* fix(docs): sandpack files filter
2023-08-23 03:10:41 +00:00
Junior Garcia 0714192838 Merge branch 'main' of github.com:nextui-org/nextui 2023-08-23 00:02:41 -03:00
Junior Garcia ae9f300d45 Fix/1468 (#1472)
* feat(blog): rss auto-discovery added

* fix(blog): feed.xml author name

* fix(select): size prop

* chore(root): changeset
2023-08-23 02:59:03 +00:00
Junior Garcia a16dac04c8 Merge branch 'main' of github.com:nextui-org/nextui 2023-08-22 23:49:47 -03:00
Junior Garcia 94db001961 Chore/docs improvemements (#1473)
* feat(blog): rss auto-discovery added

* fix(blog): feed.xml author name

* chore(docs): pnpm script modified
2023-08-23 02:46:37 +00:00
Junior Garcia d77cf7658b Feat/add rss auto discovery (#1471)
* feat(blog): rss auto-discovery added

* fix(blog): feed.xml author name
2023-08-23 02:43:58 +00:00
Junior Garcia 46c47f7e6e fix(blog): feed.xml author name 2023-08-22 12:37:26 -03:00
Junior Garcia 35b9741663 feat(blog): rss auto-discovery added 2023-08-22 12:34:35 -03:00
github-actions[bot] 2b82ba86eb ci(changesets): version packages (#1465)
Co-authored-by: Junior Garcia <jrgarciadev@gmail.com>
2023-08-21 22:15:21 +00:00
Junior Garcia 904f538779 Chore/update react aria packages (#1463)
* fix(dropdown): popover and dropdown fixes

* fix(popover): arrow animation, shouldCloseOnInteractOutside function usage fixed

* chore(root): changeset

* chore(root): react-aria utils pkg updated

* fix(root): changesets

* fix(root): changeset
2023-08-21 22:06:36 +00:00
nirmalkumar 609e9f4c11 fix -( Image-Tag issue in Cover-image.ts ) (#1462) 2023-08-21 21:16:33 +00:00
288 changed files with 10946 additions and 6624 deletions
+1 -1
View File
@@ -182,7 +182,7 @@ pnpm test:update src/button # or npm run test:update src/button
pnpm build # or npm run build
```
> Note: ensure your version of Node is 14 or higher to run scripts
> Note: ensure your version of Node is 16 or higher to run scripts
6. Send your pull request:
@@ -11,8 +11,8 @@ import {
Spinner,
Pagination,
} from "@nextui-org/react";
import {useAsyncList} from "@react-stately/data";
import {useCallback, useMemo, useState} from "react";
import {useMemo, useState} from "react";
import useSWR from "swr";
type SWCharacter = {
name: string;
@@ -21,50 +21,23 @@ type SWCharacter = {
birth_year: string;
};
const fetcher = (...args: Parameters<typeof fetch>) => fetch(...args).then((res) => res.json());
export default function Page() {
const [page, setPage] = useState(1);
const [total, setTotal] = useState(0);
const [isLoading, setIsLoading] = useState(true);
const {data, isLoading} = useSWR<{
count: number;
results: SWCharacter[];
}>(`https://swapi.py4e.com/api/people?page=${page}`, fetcher, {
keepPreviousData: true,
});
const rowsPerPage = 10;
let list = useAsyncList<SWCharacter>({
async load({signal, cursor}) {
// If no cursor is available, then we're loading the first page.
// Otherwise, the cursor is the next URL to load, as returned from the previous page.
const res = await fetch(cursor || "https://swapi.py4e.com/api/people/?search=", {signal});
let json = await res.json();
setTotal(json.count);
setIsLoading(false);
return {
items: json.results,
cursor: json.next,
};
},
});
const pages = Math.ceil(total / rowsPerPage);
const items = useMemo(() => {
const start = (page - 1) * rowsPerPage;
const end = start + rowsPerPage;
return list.items.slice(start, end);
}, [page, list.items?.length]);
const onPaginationChange = useCallback(
(page: number) => {
setIsLoading(true);
if (page >= list.items.length / rowsPerPage) {
list.loadMore();
}
setPage(page);
},
[list.items.length],
);
const pages = useMemo(() => {
return data?.count ? Math.ceil(data.count / rowsPerPage) : 0;
}, [data?.count, rowsPerPage]);
return (
<div className="p-6">
@@ -80,7 +53,7 @@ export default function Page() {
color="primary"
page={page}
total={pages}
onChange={onPaginationChange}
onChange={(page) => setPage(page)}
/>
</div>
) : null
@@ -96,8 +69,8 @@ export default function Page() {
<TableColumn key="birth_year">Birth year</TableColumn>
</TableHeader>
<TableBody
isLoading={isLoading && !items.length}
items={items}
isLoading={isLoading || data?.results.length === 0}
items={data?.results ?? []}
loadingContent={<Spinner />}
>
{(item) => (
@@ -256,7 +256,7 @@ const users = [
},
];
type User = typeof users[0];
type User = (typeof users)[number];
export default function Page() {
const [filterValue, setFilterValue] = useState("");
@@ -256,7 +256,7 @@ const users = [
},
];
type User = typeof users[0];
type User = (typeof users)[number];
export default function Page() {
const [filterValue, setFilterValue] = useState("");
+2 -1
View File
@@ -24,7 +24,8 @@ export async function GET() {
url: `${siteConfig.siteUrl}/blog/${post.slug}`,
guid: `${siteConfig.siteUrl}/blog/${post.slug}`,
date: post.date,
author: `${author} <${siteConfig.email}>`,
// @ts-ignore - name does exist
author: `${author.name} <${siteConfig.email}>`,
categories: post.tags ?? [],
});
});
+3 -11
View File
@@ -1,6 +1,7 @@
import {Button, Image, Link} from "@nextui-org/react";
import {Image} from "@nextui-org/react";
import {Blockquote} from "@/components/docs/components/blockquote";
import {FigmaButton} from "@/components/figma-button";
export default function FigmaPage() {
return (
@@ -23,16 +24,7 @@ export default function FigmaPage() {
width="800"
/>
<div className="text-center max-w-2xl m-auto">
<Button className="max-w-fit" color="default" variant="bordered">
<Link
isExternal
showAnchorIcon
className="text-current"
href="https://www.figma.com/community/file/1267584376234254760"
>
Open in Figma
</Link>
</Button>
<FigmaButton />
<Blockquote color="warning">
This file is still in development and will be continuously updated.
</Blockquote>
+6
View File
@@ -53,6 +53,12 @@ export const metadata: Metadata = {
},
],
creator: "jrgarciadev",
alternates: {
canonical: "https://nextui.org",
types: {
"application/rss+xml": [{url: "https://nextui.org/feed.xml", title: "NextUI RSS Feed"}],
},
},
viewport:
"viewport-fit=cover, width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0",
};
+12
View File
@@ -8,10 +8,20 @@ import NextLink from "next/link";
import {AnimatePresence, motion} from "framer-motion";
import {useIsMounted} from "@/hooks/use-is-mounted";
import {trackEvent} from "@/utils/va";
const BlogPostCard = (post: BlogPost) => {
const isMounted = useIsMounted();
const handlePress = () => {
trackEvent("BlogPostCard - Selection", {
name: post.title,
action: "click",
category: "blog",
data: post.url ?? "",
});
};
return (
<AnimatePresence>
{isMounted && (
@@ -27,6 +37,7 @@ const BlogPostCard = (post: BlogPost) => {
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}
onPress={handlePress}
>
<CardHeader>
<Link
@@ -35,6 +46,7 @@ const BlogPostCard = (post: BlogPost) => {
href={post.url}
size="lg"
underline="hover"
onPress={handlePress}
>
<Balancer>{post.title}</Balancer>
</Link>
+26
View File
@@ -25,6 +25,7 @@ import {
import searchData from "@/config/search-meta.json";
import {useUpdateEffect} from "@/hooks/use-update-effect";
import {trackEvent} from "@/utils/va";
const hideOnPaths = ["examples"];
@@ -175,6 +176,13 @@ export const Cmdk: FC<{}> = () => {
const matches = intersectionBy(...matchesForEachWord, "objectID").slice(0, MAX_RESULTS);
trackEvent("Cmdk - Search", {
name: "cmdk - search",
action: "search",
category: "cmdk",
data: {query, words, matches: matches?.map((match) => match.url).join(", ")},
});
return matches;
},
[query],
@@ -190,10 +198,21 @@ export const Cmdk: FC<{}> = () => {
if (e?.key?.toLowerCase() === "k" && e[hotkey]) {
e.preventDefault();
isOpen ? onClose() : onOpen();
trackEvent("Cmdk - Open/Close", {
name: "cmdk - open/close",
action: "keydown",
category: "cmdk",
data: isOpen ? "close" : "open",
});
}
};
document.addEventListener("keydown", onKeyDown);
return () => {
document.removeEventListener("keydown", onKeyDown);
};
}, [isOpen]);
const onItemSelect = useCallback(
@@ -201,6 +220,13 @@ export const Cmdk: FC<{}> = () => {
onClose();
router.push(item.url);
addToRecentSearches(item);
trackEvent("Cmdk - ItemSelect", {
name: item.content,
action: "click",
category: "cmdk",
data: item.url,
});
},
[router, recentSearches],
);
@@ -108,9 +108,9 @@ function CodeTypewriter({value, className, css, ...props}: any) {
return (
<Pre className={className} css={css} {...props}>
<code
dangerouslySetInnerHTML={{__html: value}}
ref={wrapperRef}
className={className}
dangerouslySetInnerHTML={{__html: value}}
style={{opacity: 0}}
/>
</Pre>
@@ -155,7 +155,7 @@ const CodeBlock = React.forwardRef<HTMLPreElement, CodeBlockProps>((_props, forw
{...props}
>
{showWindowIcons && <WindowActions title={title} />}
<code className={clsx(classes, codeClasses)} dangerouslySetInnerHTML={{__html: result}} />
<code dangerouslySetInnerHTML={{__html: result}} className={clsx(classes, codeClasses)} />
</Pre>
);
});
@@ -3,6 +3,8 @@
import {useRef} from "react";
import {Button} from "@nextui-org/react";
import {trackEvent} from "@/utils/va";
export const CustomButton = () => {
const buttonRef = useRef<HTMLButtonElement | null>(null);
@@ -26,6 +28,11 @@ export const CustomButton = () => {
x: targetCenterX / clientWidth,
},
});
trackEvent("LandingPage - Confetti Button", {
action: "press",
category: "landing-page",
});
};
return (
@@ -9,6 +9,7 @@ import {useCodeDemo, UseCodeDemoProps} from "./use-code-demo";
import WindowResizer, {WindowResizerProps} from "./window-resizer";
import {GradientBoxProps} from "@/components/gradient-box";
import {trackEvent} from "@/utils/va";
const DynamicReactLiveDemo = dynamic(
() => import("./react-live-demo").then((m) => m.ReactLiveDemo),
@@ -180,6 +181,14 @@ export const CodeDemo: React.FC<CodeDemoProps> = ({
panel: "pt-0",
}}
variant="underlined"
onSelectionChange={(tabKey) => {
trackEvent("CodeDemo - Selection", {
name: tabKey as string,
action: "tabChange",
category: "docs",
data: tabKey ?? "",
});
}}
>
<Tab key="preview" title="Preview">
{previewContent}
@@ -1,8 +1,10 @@
import React, {forwardRef} from "react";
import React, {forwardRef, useEffect} from "react";
import {clsx, getUniqueID} from "@nextui-org/shared-utils";
import BaseHighlight, {Language, PrismTheme, defaultProps} from "prism-react-renderer";
import {debounce} from "lodash";
import defaultTheme from "@/libs/prism-theme";
import {trackEvent} from "@/utils/va";
interface CodeblockProps {
language: Language;
@@ -60,6 +62,45 @@ const Codeblock = forwardRef<HTMLPreElement, CodeblockProps>(
const shouldHighlightLine = calculateLinesToHighlight(metastring);
const isMultiLine = codeString.split("\n").length > 2;
const lastSelectionText = React.useRef<string | null>(null);
useEffect(() => {
const handleSelectionChange = () => {
if (!window.getSelection) return;
const el = window.getSelection()?.anchorNode?.parentNode;
if (!el) return;
const selectionText = window.getSelection()?.toString();
if (!selectionText) return;
if (
!selectionText ||
selectionText === lastSelectionText.current ||
!codeString.includes(selectionText)
)
return;
lastSelectionText.current = selectionText;
trackEvent("Codeblock - Selection", {
action: "selectText",
category: "docs",
data: selectionText,
});
};
const debouncedHandleSelectionChange = debounce(handleSelectionChange, 1000);
document.addEventListener("selectionchange", debouncedHandleSelectionChange);
return () => {
document.removeEventListener("selectionchange", debouncedHandleSelectionChange);
};
}, []);
return (
<BaseHighlight
{...defaultProps}
@@ -4,6 +4,7 @@ import Balancer from "react-wrap-balancer";
import {GithubIcon, NpmIcon, AdobeIcon, StorybookIcon, NextJsIcon} from "@/components/icons";
import {COMPONENT_PATH, COMPONENT_THEME_PATH} from "@/libs/github/constants";
import {trackEvent} from "@/utils/va";
export interface ComponentLinksProps {
component: string;
@@ -23,6 +24,16 @@ const ButtonLink = ({
href: string;
tooltip?: string | ReactNode;
}) => {
const handlePress = () => {
if (!href) return;
trackEvent("ComponentLinks - Click", {
category: "docs",
action: "click",
data: href || "",
});
};
const button = (
<Button
isExternal
@@ -31,6 +42,7 @@ const ButtonLink = ({
href={href}
size="sm"
startContent={startContent}
onPress={handlePress}
{...props}
>
{children}
@@ -81,7 +93,7 @@ export const ComponentLinks = ({
)}
{rscCompatible && (
<ButtonLink
href="https://nextjs.org/docs/getting-started/react-essentials#server-components"
href="https://nextjs.org/docs/app/building-your-application/rendering/server-components"
startContent={<NextJsIcon size={18} />}
tooltip={
<p>
@@ -2,6 +2,8 @@ import {Tabs, Tab, Snippet} from "@nextui-org/react";
import Codeblock from "./codeblock";
import {trackEvent} from "@/utils/va";
type PackageManager = {
key: string;
name: string;
@@ -32,6 +34,14 @@ export const ImportTabs = ({commands}: ImportTabsProps) => {
tabList: "relative h-10",
}}
variant="underlined"
onSelectionChange={(tabKey) => {
trackEvent("ImportTabs - Selection", {
name: tabKey as string,
action: "tabChange",
category: "docs",
data: commands[tabKey] ?? "",
});
}}
>
{importTabs.map(({key, name}) => {
if (!commands[key]) return null;
@@ -47,6 +57,14 @@ export const ImportTabs = ({commands}: ImportTabsProps) => {
pre: "font-light text-base",
copyButton: "text-lg text-default-400",
}}
onCopy={() => {
trackEvent("ImportTabs - Copy", {
name,
action: "copyInstallScript",
category: "docs",
data: commands[name] ?? "",
});
}}
>
<Codeblock
hideScrollBar
@@ -3,6 +3,7 @@ import {Tabs, Tab, Snippet} from "@nextui-org/react";
import Codeblock from "./codeblock";
import {YarnIcon, NpmSmallIcon, PnpmIcon} from "@/components/icons";
import {trackEvent} from "@/utils/va";
type PackageManagerName = "npm" | "yarn" | "pnpm";
@@ -27,7 +28,7 @@ const packageManagers: PackageManager[] = [
];
export interface PackageManagersProps {
commands: Partial<Record<PackageManagerName, string>>;
commands: Partial<Record<PackageManagerName, React.Key>>;
}
export const PackageManagers = ({commands}: PackageManagersProps) => {
@@ -39,6 +40,14 @@ export const PackageManagers = ({commands}: PackageManagersProps) => {
tabList: "h-10",
}}
variant="underlined"
onSelectionChange={(tabKey) => {
trackEvent("PackageManagers - Selection", {
name: tabKey as string,
action: "tabChange",
category: "docs",
data: commands[tabKey as unknown as PackageManagerName] ?? "",
});
}}
>
{packageManagers.map(({name, icon}) => {
if (!commands[name]) return null;
@@ -62,6 +71,14 @@ export const PackageManagers = ({commands}: PackageManagersProps) => {
pre: "font-light text-base",
copyButton: "text-lg text-zinc-500 mr-2",
}}
onCopy={() => {
trackEvent("PackageManagers - Copy", {
name,
action: "copyScript",
category: "docs",
data: commands[name] ?? "",
});
}}
>
<Codeblock removeIndent codeString={commands[name] as string} language="bash" />
</Snippet>
+18 -7
View File
@@ -1,31 +1,43 @@
"use client";
import * as React from "react";
import NextLink from "next/link";
import {Link} from "@nextui-org/react";
import {useRouter} from "next/navigation";
import {ChevronIcon} from "@nextui-org/shared-icons";
import manifest from "@/config/routes.json";
import {removeFromLast} from "@/utils";
import {Route} from "@/libs/docs/page";
import {useDocsRoute} from "@/hooks/use-docs-route";
import {trackEvent} from "@/utils/va";
export interface FooterNavProps {
currentRoute?: Route;
}
export const DocsPager: React.FC<FooterNavProps> = ({currentRoute}) => {
const router = useRouter();
const {prevRoute, nextRoute} = useDocsRoute(manifest.routes, currentRoute);
const handlePress = (path: string) => {
trackEvent("DocsPager - Click", {
category: "docs",
action: "click",
data: path || "",
});
router.push(removeFromLast(path || "", "."));
};
return (
<div className="flex w-full justify-between py-20">
{prevRoute ? (
<Link
isBlock
as={NextLink}
className="flex gap-2"
className="cursor-pointer flex gap-2"
color="foreground"
href={removeFromLast(prevRoute.path || "", ".")}
onPress={() => handlePress(prevRoute.path || "")}
>
<ChevronIcon className="text-primary" height={20} width={20} />
{prevRoute.title}
@@ -36,10 +48,9 @@ export const DocsPager: React.FC<FooterNavProps> = ({currentRoute}) => {
{nextRoute && (
<Link
isBlock
as={NextLink}
className="flex gap-1 items-center"
className="cursor-pointer flex gap-1 items-center"
color="foreground"
href={removeFromLast(nextRoute.path || "", ".")}
onPress={() => handlePress(nextRoute.path || "")}
>
{nextRoute.title}
<ChevronIcon className="rotate-180 text-primary" height={20} width={20} />
+7
View File
@@ -26,6 +26,7 @@ import {getRoutePaths} from "./utils";
import {Route} from "@/libs/docs/page";
import {TreeKeyboardDelegate} from "@/utils/tree-keyboard-delegate";
import {useScrollPosition} from "@/hooks/use-scroll-position";
import {trackEvent} from "@/utils/va";
export interface Props<T> extends Omit<ItemProps<T>, "title">, Route {
slug?: string;
@@ -88,6 +89,12 @@ function TreeItem<T>(props: TreeItemProps<T>) {
state.toggleKey(item.key);
} else {
router.push(paths.pathname);
trackEvent("SidebarDocs", {
category: "docs",
action: "click",
data: paths.pathname || "",
});
}
},
});
+25
View File
@@ -0,0 +1,25 @@
"use client";
import {Button, Link} from "@nextui-org/react";
import {trackEvent} from "@/utils/va";
export const FigmaButton = () => (
<Button
isExternal
showAnchorIcon
as={Link}
className="max-w-fit text-current"
color="default"
href="https://www.figma.com/community/file/1267584376234254760"
variant="bordered"
onPress={() => {
trackEvent("FigmaPage - Open Figma Link", {
action: "click",
category: "figma",
});
}}
>
Open in Figma
</Button>
);
@@ -14,6 +14,7 @@ import {PaletteIcon, MagicIcon, GamingConsoleIcon, StarIcon} from "@/components/
import {NextUILogo, CodeWindow} from "@/components";
import landingContent from "@/content/landing";
import {useIsMobile} from "@/hooks/use-media-query";
import {trackEvent} from "@/utils/va";
const themesTabs = (isMobile: boolean) => [
{
@@ -87,6 +88,12 @@ const CustomThemesExample = ({
const onSelectionChange = (value: React.Key) => {
onChangeTheme(value as Theme);
trackEvent("CustomThemes - Selection", {
action: "change_theme",
category: "landing-page",
data: value,
});
};
return (
@@ -6,6 +6,8 @@ import {Card, CardHeader, CardBody, LinkProps, SlotsToClasses} from "@nextui-org
import {useRouter} from "next/navigation";
import {LinkIcon} from "@nextui-org/shared-icons";
import {trackEvent} from "@/utils/va";
const styles = tv({
slots: {
base: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-4",
@@ -38,6 +40,13 @@ export const FeaturesGrid: React.FC<FeaturesGridProps> = ({features, classNames,
const slots = styles();
const handleClick = (feat: Feature) => {
trackEvent("FeaturesGrid - Click", {
name: feat.title,
action: "click",
category: "docs",
data: feat.href ?? "",
});
if (!feat.href) {
return;
}
@@ -105,7 +105,6 @@ export const FloatingComponents: React.FC<{}> = () => {
{isMounted && (
<Tooltip
showArrow
className="text-sm animate-[levitate_14s_ease_infinite]"
color="secondary"
content="Developers love Next.js"
@@ -9,6 +9,7 @@ import {FloatingComponents} from "./floating-components";
import {title, subtitle} from "@/components/primitives";
import {GithubIcon} from "@/components/icons";
import {trackEvent} from "@/utils/va";
const BgLooper = dynamic(() => import("./bg-looper").then((mod) => mod.BgLooper), {
ssr: false,
@@ -42,6 +43,14 @@ export const Hero = () => {
href="/docs/guide/introduction"
radius="full"
size="lg"
onPress={() => {
trackEvent("Hero - Get Started", {
name: "Get Started",
action: "click",
category: "landing-page",
data: "/docs/guide/introduction",
});
}}
>
Get Started
</Button>
@@ -56,6 +65,14 @@ export const Hero = () => {
size="lg"
startContent={<GithubIcon />}
variant="bordered"
onPress={() => {
trackEvent("Hero - Github", {
name: "Github",
action: "click",
category: "landing-page",
data: "https://github.com/nextui-org/nextui",
});
}}
>
Github
</Button>
@@ -11,6 +11,7 @@ import {FeaturesGrid} from "./features-grid";
import {sectionWrapper, subtitle, title} from "@/components/primitives";
import {GithubIcon, NoteLinearIcon, NextJsIcon} from "@/components/icons";
import {useIsMounted} from "@/hooks/use-is-mounted";
import {trackEvent} from "@/utils/va";
const bannerSuggestions = [
{
@@ -69,6 +70,13 @@ export const InstallBanner = () => {
href="/docs/guide/installation"
radius="full"
size="md"
onClick={() => {
trackEvent("InstallBanner - Get Started", {
action: "press",
category: "landing-page",
data: "/docs/guide/installation",
});
}}
>
Get Started
</Button>
@@ -81,6 +89,13 @@ export const InstallBanner = () => {
size="md"
startContent={<GithubIcon />}
variant="bordered"
onClick={() => {
trackEvent("InstallBanner - Github", {
action: "press",
category: "landing-page",
data: "https://github.com/nextui-org/nextui",
});
}}
>
Github
</Button>
+10 -1
View File
@@ -12,6 +12,7 @@ import {OpenCollectiveIcon, PatreonIcon, HeartBoldIcon, PlusLinearIcon} from "@/
import {Sponsor, SPONSOR_TIERS, SPONSOR_COLORS, getTier} from "@/libs/docs/sponsors";
import {SonarPulse} from "@/components/sonar-pulse";
import {useIsMobile} from "@/hooks/use-media-query";
import {trackEvent} from "@/utils/va";
export interface SupportProps {
sponsors: Sponsor[];
@@ -100,6 +101,14 @@ export const Support: FC<SupportProps> = ({sponsors = []}) => {
window.open(href, "_blank");
};
const handleBecomeSponsor = () => {
trackEvent("Support - Become a sponsor", {
action: "click",
category: "landing-page",
});
handleExternalLinkClick(supportAccounts[0].href);
};
const renderSponsors = useMemo(() => {
if (!sponsors.length) return null;
@@ -181,7 +190,7 @@ export const Support: FC<SupportProps> = ({sponsors = []}) => {
aria-label="Become a sponsor"
className="z-50 w-auto h-auto bg-gradient-to-b from-[#FF1CF7] to-[#7928CA]"
radius="full"
onPress={() => handleExternalLinkClick(supportAccounts[0].href)}
onPress={handleBecomeSponsor}
>
<PlusLinearIcon
className="flex items-center justify-center rounded-full text-white"
+22 -1
View File
@@ -12,6 +12,7 @@ import * as DocsComponents from "@/components/docs/components";
import * as BlogComponents from "@/components/blog/components";
import {Codeblock} from "@/components/docs/components";
import {VirtualAnchor, virtualAnchorEncode} from "@/components";
import {trackEvent} from "@/utils/va";
const Table: React.FC<{children?: React.ReactNode}> = ({children}) => {
return (
@@ -144,6 +145,13 @@ const Code = ({
copyButton: "text-lg text-zinc-500 mr-2",
}}
codeString={codeString}
onCopy={() => {
trackEvent("MDXComponents - Copy", {
category: "docs",
action: "copyCode",
data: codeString,
});
}}
>
<Codeblock codeString={codeString} language={language} metastring={meta} />
</Components.Snippet>
@@ -153,8 +161,21 @@ const Code = ({
const Link = ({href, children}: {href?: string; children?: React.ReactNode}) => {
const isExternal = href?.startsWith("http");
const handlePress = () => {
trackEvent("MDXComponents - Click", {
category: "docs",
action: "click",
data: href || "",
});
};
return (
<Components.Link href={href} isExternal={isExternal} showAnchorIcon={isExternal}>
<Components.Link
href={href}
isExternal={isExternal}
showAnchorIcon={isExternal}
onPress={handlePress}
>
{children}
</Components.Link>
);
+50 -5
View File
@@ -44,6 +44,7 @@ import {
import {useIsMounted} from "@/hooks/use-is-mounted";
import {DocsSidebar} from "@/components/docs/sidebar";
import {useCmdkStore} from "@/components/cmdk";
import {trackEvent} from "@/utils/va";
export interface NavbarProps {
routes: Route[];
@@ -74,8 +75,17 @@ export const Navbar: FC<NavbarProps> = ({children, routes, mobileRoutes = [], sl
setCommandKey(isAppleDevice() ? "command" : "ctrl");
}, []);
const handleOpenCmdk = () => {
cmdkStore.onOpen();
trackEvent("Navbar - Search", {
name: "navbar - search",
action: "press",
category: "cmdk",
});
};
const {pressProps} = usePress({
onPress: () => cmdkStore.onOpen(),
onPress: handleOpenCmdk,
});
const {focusProps, isFocusVisible} = useFocusRing();
@@ -101,7 +111,7 @@ export const Navbar: FC<NavbarProps> = ({children, routes, mobileRoutes = [], sl
strokeWidth={2}
/>
}
onPress={() => cmdkStore.onOpen()}
onPress={handleOpenCmdk}
>
Quick Search...
</Button>
@@ -121,6 +131,15 @@ export const Navbar: FC<NavbarProps> = ({children, routes, mobileRoutes = [], sl
}
};
const handlePressNavbarItem = (name: string, url: string) => {
trackEvent("NavbarItem", {
name,
action: "press",
category: "navbar",
data: url,
});
};
return (
<NextUINavbar
ref={ref}
@@ -138,6 +157,7 @@ export const Navbar: FC<NavbarProps> = ({children, routes, mobileRoutes = [], sl
aria-label="Home"
className="flex justify-start items-center gap-2 tap-highlight-transparent transition-opacity active:opacity-50"
href="/"
onClick={() => handlePressNavbarItem("Home", "/")}
>
<SmallLogo className="w-6 h-6 md:hidden" />
<LargeLogo className="h-5 md:h-6" />
@@ -184,6 +204,7 @@ export const Navbar: FC<NavbarProps> = ({children, routes, mobileRoutes = [], sl
color="foreground"
data-active={includes(docsPaths, pathname)}
href="/docs/guide/introduction"
onClick={() => handlePressNavbarItem("Docs", "/docs/guide/introduction")}
>
Docs
</NextLink>
@@ -194,6 +215,7 @@ export const Navbar: FC<NavbarProps> = ({children, routes, mobileRoutes = [], sl
color="foreground"
data-active={includes(pathname, "components")}
href="/docs/components/avatar"
onClick={() => handlePressNavbarItem("Components", "/docs/components/avatar")}
>
Components
</NextLink>
@@ -204,6 +226,7 @@ export const Navbar: FC<NavbarProps> = ({children, routes, mobileRoutes = [], sl
color="foreground"
data-active={includes(pathname, "blog")}
href="/blog"
onClick={() => handlePressNavbarItem("Blog", "/blog")}
>
Blog
</NextLink>
@@ -214,6 +237,7 @@ export const Navbar: FC<NavbarProps> = ({children, routes, mobileRoutes = [], sl
color="foreground"
data-active={includes(pathname, "figma")}
href="/figma"
onClick={() => handlePressNavbarItem("Figma", "/figma")}
>
Figma
</NextLink>
@@ -225,6 +249,7 @@ export const Navbar: FC<NavbarProps> = ({children, routes, mobileRoutes = [], sl
color="secondary"
href="/blog/v2.1.0"
variant="dot"
onClick={() => handlePressNavbarItem("New components v2.1.0", "/blog/v2.1.0")}
>
New components v2.1.0&nbsp;
<span aria-label="party emoji" role="img">
@@ -242,6 +267,7 @@ export const Navbar: FC<NavbarProps> = ({children, routes, mobileRoutes = [], sl
aria-label="Github"
className="p-1"
href="https://github.com/nextui-org/nextui"
onClick={() => handlePressNavbarItem("Github", "https://github.com/nextui-org/nextui")}
>
<GithubIcon className="text-default-600 dark:text-default-500" />
</Link>
@@ -273,13 +299,31 @@ export const Navbar: FC<NavbarProps> = ({children, routes, mobileRoutes = [], sl
<NavbarContent className="hidden sm:flex basis-1/5 sm:basis-full" justify="end">
<NavbarItem className="hidden sm:flex">
<Link isExternal aria-label="Twitter" className="p-1" href={siteConfig.links.twitter}>
<Link
isExternal
aria-label="Twitter"
className="p-1"
href={siteConfig.links.twitter}
onPress={() => handlePressNavbarItem("Twitter", siteConfig.links.twitter)}
>
<TwitterIcon className="text-default-600 dark:text-default-500" />
</Link>
<Link isExternal aria-label="Discord" className="p-1" href={siteConfig.links.discord}>
<Link
isExternal
aria-label="Discord"
className="p-1"
href={siteConfig.links.discord}
onPress={() => handlePressNavbarItem("Discord", siteConfig.links.discord)}
>
<DiscordIcon className="text-default-600 dark:text-default-500" />
</Link>
<Link isExternal aria-label="Github" className="p-1" href={siteConfig.links.github}>
<Link
isExternal
aria-label="Github"
className="p-1"
href={siteConfig.links.github}
onPress={() => handlePressNavbarItem("Github", siteConfig.links.github)}
>
<GithubIcon className="text-default-600 dark:text-default-500" />
</Link>
<ThemeSwitch />
@@ -295,6 +339,7 @@ export const Navbar: FC<NavbarProps> = ({children, routes, mobileRoutes = [], sl
<HeartFilledIcon className="text-danger group-data-[hover=true]:animate-heartbeat" />
}
variant="flat"
onPress={() => handlePressNavbarItem("Sponsor", siteConfig.links.sponsor)}
>
Sponsor
</Button>
@@ -1,16 +1,28 @@
import React from "react";
import {usePathname} from "next/navigation";
import {Tooltip, Link, Button} from "@nextui-org/react";
import {Tooltip, Button} from "@nextui-org/react";
import {capitalize, last} from "lodash";
import {BugIcon} from "@/components/icons";
import {ISSUE_REPORT_URL} from "@/libs/github/constants";
import {trackEvent} from "@/utils/va";
export const BugReportButton = () => {
const pathname = usePathname();
const componentTitle = capitalize(last(pathname?.split("/")));
const handlePress = () => {
trackEvent("BugReportButton - Sandpack", {
name: "sandpack - bug report",
action: "press",
category: "docs",
data: `${ISSUE_REPORT_URL}${componentTitle}`,
});
window.open(`${ISSUE_REPORT_URL}${componentTitle}`, "_blank");
};
return (
<Tooltip
className="text-xs px-2"
@@ -19,15 +31,7 @@ export const BugReportButton = () => {
placement="top"
radius="md"
>
<Button
isExternal
isIconOnly
as={Link}
href={`${ISSUE_REPORT_URL}${componentTitle}`}
size="sm"
title="Report a bug"
variant="light"
>
<Button isIconOnly size="sm" title="Report a bug" variant="light" onPress={handlePress}>
<BugIcon className="text-white dark:text-zinc-500" height={16} width={16} />
</Button>
</Tooltip>
@@ -1,10 +1,14 @@
import React from "react";
import {UnstyledOpenInCodeSandboxButton} from "@codesandbox/sandpack-react";
import {Tooltip, Button} from "@nextui-org/react";
import {useSandpack} from "@codesandbox/sandpack-react";
import {CodeSandboxIcon} from "@/components/icons";
import {trackEvent} from "@/utils/va";
export const CodeSandboxButton = () => {
const {sandpack} = useSandpack();
return (
<Tooltip
className="text-xs px-2"
@@ -13,7 +17,20 @@ export const CodeSandboxButton = () => {
placement="top"
radius="md"
>
<Button isIconOnly as="span" size="sm" title="Open in CodeSandbox" variant="light">
<Button
isIconOnly
as="span"
size="sm"
title="Open in CodeSandbox"
variant="light"
onPress={() => {
trackEvent("CodeSandboxButton - Sandpack", {
action: "press",
category: "docs",
data: sandpack.files[sandpack.activeFile],
});
}}
>
<UnstyledOpenInCodeSandboxButton
style={{
width: "100%",
@@ -3,6 +3,7 @@ import {useSandpack} from "@codesandbox/sandpack-react";
import {Tooltip, Button} from "@nextui-org/react";
import {useClipboard} from "@nextui-org/use-clipboard";
import {trackEvent} from "@/utils/va";
import {CopyLinearIcon} from "@/components/icons";
export const CopyButton = () => {
@@ -14,6 +15,13 @@ export const CopyButton = () => {
const code = sandpack.files[sandpack.activeFile].code;
copy(code);
trackEvent("CopyButton - Sandpack", {
name: "sandpack - copy code",
action: "press",
category: "docs",
data: sandpack.activeFile,
});
};
return (
@@ -3,6 +3,7 @@ import {Tabs, Tab} from "@nextui-org/react";
import {SandpackPredefinedTemplate} from "@codesandbox/sandpack-react";
import {TypescriptIcon, JavascriptIcon} from "@/components/icons";
import {trackEvent} from "@/utils/va";
interface Props {
template: SandpackPredefinedTemplate;
@@ -20,6 +21,12 @@ export const LanguageSelector: React.FC<LanguageSelectorProps> = ({template, onC
setSelectedTemplate(newTemplate);
setTimeout(() => {
trackEvent("LanguageSelector - Selection", {
name: "template",
action: "tabChange",
category: "docs",
data: newTemplate ?? "",
});
onChange?.(newTemplate);
}, 250);
}, [template, onChange]);
@@ -59,7 +59,10 @@ export const useSandpack = ({
if (key.includes("App") && !key.includes(mimeType)) {
return acc;
}
if (typescriptStrict && key.includes("js")) {
if (typescriptStrict && currentTemplate === "vite-react-ts" && key.includes(".js")) {
return acc;
}
if (currentTemplate === "vite-react" && key.includes(".ts")) {
return acc;
}
// @ts-ignore
@@ -100,7 +103,7 @@ export const useSandpack = ({
// Check if the file content includes 'React' import statements, if not, add it
if (!fileContent.includes(importReact) && !fileContent.includes(importAllReact)) {
fileContent = `${importReact}\n${fileContent}\n`;
fileContent = `${importReact}\n\n${fileContent}\n`;
}
// Check if file content includes any other dependencies, if yes, add it to dependencies
+7
View File
@@ -8,6 +8,7 @@ import {clsx} from "@nextui-org/shared-utils";
import {useIsSSR} from "@react-aria/ssr";
import {SunFilledIcon, MoonFilledIcon} from "@/components/icons";
import {trackEvent} from "@/utils/va";
export interface ThemeSwitchProps {
className?: string;
@@ -20,6 +21,12 @@ export const ThemeSwitch: FC<ThemeSwitchProps> = ({className, classNames}) => {
const onChange = () => {
theme === "light" ? setTheme("dark") : setTheme("light");
trackEvent("ThemeChange", {
action: "click",
category: "theme",
data: theme === "light" ? "dark" : "light",
});
};
const {Component, slots, isSelected, getBaseProps, getInputProps, getWrapperProps} = useSwitch({
+10
View File
@@ -1,7 +1,10 @@
"use client";
import React from "react";
import {Link} from "@nextui-org/react";
import {VercelIcon} from "@/components/icons";
import {trackEvent} from "@/utils/va";
export const VercelCallout: React.FC<unknown> = () => {
return (
@@ -9,6 +12,13 @@ export const VercelCallout: React.FC<unknown> = () => {
isExternal
className="flex justify-end items-center gap-2 text-foreground"
href="https://www.vercel.com?utm_source=nextui&utm_marketing=oss"
onClick={() => {
trackEvent("VercelCallout", {
name: "vercel callout",
action: "click",
category: "footer",
});
}}
>
<p className="font-normal">Deployed on</p>
<VercelIcon className="text-black dark:text-white" height={18} />
+2 -2
View File
@@ -1,6 +1,6 @@
import {DM_Sans} from "next/font/google";
import {Inter} from "next/font/google";
export const fontSans = DM_Sans({
export const fontSans = Inter({
variable: "--font-sans",
adjustFontFallback: true,
display: "optional",
@@ -1,13 +1,11 @@
const App = `import {forwardRef} from "react";
import {useButton, Ripple, Spinner} from "@nextui-org/react";
import {useButton, Drip, Spinner} from "@nextui-org/react";
const MyButton = forwardRef((props, ref) => {
const {
domRef,
children,
classNames,
drips,
spinnerSize,
spinner = <Spinner color="current" size={spinnerSize} />,
spinnerPlacement,
@@ -16,19 +14,22 @@ const MyButton = forwardRef((props, ref) => {
isLoading,
disableRipple,
getButtonProps,
getRippleProps,
} = useButton({
ref,
...props,
});
const {ripples} = getRippleProps();
return (
<button ref={domRef} className={classNames} {...getButtonProps()}>
<button ref={domRef} {...getButtonProps()}>
{startContent}
{isLoading && spinnerPlacement === "start" && spinner}
{children}
{isLoading && spinnerPlacement === "end" && spinner}
{endContent}
{!disableRipple && <Drip drips={drips} />}
{!disableRipple && <Ripple ripples={ripples} />}
</button>
);
});
@@ -38,8 +39,7 @@ MyButton.displayName = "MyButton";
export default MyButton;`;
const AppTs = `import {forwardRef} from "react";
import {useButton, Drip, Spinner, ButtonProps as BaseButtonProps} from "@nextui-org/react";
import {useButton, Ripple, Spinner, ButtonProps as BaseButtonProps} from "@nextui-org/react";
export interface ButtonProps extends BaseButtonProps {}
@@ -47,8 +47,6 @@ const MyButton = forwardRef<HTMLButtonElement, ButtonProps>((props, ref) => {
const {
domRef,
children,
classNames,
drips,
spinnerSize,
spinner = <Spinner color="current" size={spinnerSize} />,
spinnerPlacement,
@@ -57,19 +55,22 @@ const MyButton = forwardRef<HTMLButtonElement, ButtonProps>((props, ref) => {
isLoading,
disableRipple,
getButtonProps,
getRippleProps,
} = useButton({
ref,
...props,
});
const {ripples} = getRippleProps();
return (
<button ref={domRef} className={classNames} {...getButtonProps()}>
<button ref={domRef} {...getButtonProps()}>
{startContent}
{isLoading && spinnerPlacement === "start" && spinner}
{children}
{isLoading && spinnerPlacement === "end" && spinner}
{endContent}
{!disableRipple && <Drip drips={drips} />}
{!disableRipple && <Ripple ripples={ripples} />}
</button>
);
});
@@ -73,7 +73,7 @@ export default function App() {
/>
<CardFooter className="absolute bg-black/40 bottom-0 z-10 border-t-1 border-default-600 dark:border-default-100">
<div className="flex flex-grow gap-2 items-center">
<img
<Image
alt="Breathing app icon"
className="rounded-full w-10 h-11 bg-black"
src="/images/breathing-app-icon.jpeg"
@@ -4,6 +4,7 @@ import horizontal from "./horizontal";
import controlled from "./controlled";
import customStyles from "./custom-styles";
import customImplementation from "./custom-implementation";
import invalid from "./invalid";
export const checkboxGroupContent = {
usage,
@@ -11,5 +12,6 @@ export const checkboxGroupContent = {
horizontal,
controlled,
customStyles,
invalid,
customImplementation,
};
@@ -0,0 +1,31 @@
const App = `import {CheckboxGroup, Checkbox} from "@nextui-org/react";
export default function App() {
const [isInvalid, setIsInvalid] = React.useState(true);
return (
<CheckboxGroup
isRequired
description="Select the cities you want to visit"
isInvalid={isInvalid}
label="Select cities"
onValueChange={(value) => {
setIsInvalid(value.length < 1);
}}
>
<Checkbox value="buenos-aires">Buenos Aires</Checkbox>
<Checkbox value="sydney">Sydney</Checkbox>
<Checkbox value="san-francisco">San Francisco</Checkbox>
<Checkbox value="london">London</Checkbox>
<Checkbox value="tokyo">Tokyo</Checkbox>
</CheckboxGroup>
);
}`;
const react = {
"/App.jsx": App,
};
export default {
...react,
};
@@ -1,4 +1,4 @@
const App = `import {Dropdown, DropdownTrigger, DropdownMenu, DropdownItem, Button, Avatar, User} from "@nextui-org/react";
const App = `import {Dropdown, DropdownTrigger, DropdownMenu, DropdownItem, Avatar, User} from "@nextui-org/react";
export default function App() {
return (
@@ -100,7 +100,7 @@ const DeleteDocumentIcon = `export const DeleteDocumentIcon = (props) => (
</svg>
);`;
const App = `import {Dropdown, DropdownTrigger, DropdownMenu, DropdownItem, Button, cn} from "@nextui-org/react";
const App = `import {Dropdown, DropdownTrigger, DropdownMenu, DropdownSection, DropdownItem, Button, cn} from "@nextui-org/react";
import {AddNoteIcon} from "./AddNoteIcon.jsx";
import {CopyDocumentIcon} from "./CopyDocumentIcon.jsx";
import {EditDocumentIcon} from "./EditDocumentIcon.jsx";
@@ -7,7 +7,7 @@ export default function App() {
label="Email"
variant="bordered"
defaultValue="junior2nextui.org"
validationState="invalid"
isInvalid={true}
errorMessage="Please enter a valid email"
className="max-w-xs"
/>
@@ -5,10 +5,10 @@ export default function App() {
const validateEmail = (value) => value.match(/^[A-Z0-9._%+-]+@[A-Z0-9.-]+.[A-Z]{2,4}$/i);
const validationState = React.useMemo(() => {
if (value === "") return undefined;
const isInvalid = React.useMemo(() => {
if (value === "") return false;
return validateEmail(value) ? "valid" : "invalid";
return validateEmail(value) ? false : true;
}, [value]);
return (
@@ -17,9 +17,9 @@ export default function App() {
type="email"
label="Email"
variant="bordered"
color={validationState === "invalid" ? "danger" : "success"}
errorMessage={validationState === "invalid" && "Please enter a valid email"}
validationState={validationState}
isInvalid={isInvalid}
color={isInvalid ? "danger" : "success"}
errorMessage={isInvalid && "Please enter a valid email"}
onValueChange={setValue}
className="max-w-xs"
/>
@@ -100,7 +100,7 @@ const DeleteDocumentIcon = `export const DeleteDocumentIcon = (props) => (
</svg>
);`;
const ListboxWrapper = `const ListboxWrapper = ({children}) => (
const ListboxWrapper = `export 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>
@@ -1,4 +1,4 @@
const ListboxWrapper = `const ListboxWrapper = ({children}) => (
const ListboxWrapper = `export 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>
@@ -1,4 +1,4 @@
const ListboxWrapper = `const ListboxWrapper = ({children}) => (
const ListboxWrapper = `export 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>
@@ -100,7 +100,7 @@ const DeleteDocumentIcon = `export const DeleteDocumentIcon = (props) => (
</svg>
);`;
const ListboxWrapper = `const ListboxWrapper = ({children}) => (
const ListboxWrapper = `export 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>
@@ -1,4 +1,4 @@
const ListboxWrapper = `const ListboxWrapper = ({children}) => (
const ListboxWrapper = `export const ListboxWrapper = ({children}) => (
<div className="w-[260px] border-small px-1 py-2 rounded-small border-default-200 dark:border-default-100">
{children}
</div>
@@ -100,7 +100,7 @@ const DeleteDocumentIcon = `export const DeleteDocumentIcon = (props) => (
</svg>
);`;
const ListboxWrapper = `const ListboxWrapper = ({children}) => (
const ListboxWrapper = `export 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>
@@ -1,4 +1,4 @@
const ListboxWrapper = `const ListboxWrapper = ({children}) => (
const ListboxWrapper = `export const ListboxWrapper = ({children}) => (
<div className="w-[260px] border-small px-1 py-2 rounded-small border-default-200 dark:border-default-100">
{children}
</div>
@@ -1,4 +1,4 @@
const ListboxWrapper = `const ListboxWrapper = ({children}) => (
const ListboxWrapper = `export 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>
@@ -1,4 +1,4 @@
const ListboxWrapper = `const ListboxWrapper = ({children}) => (
const ListboxWrapper = `export 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>
@@ -119,10 +119,136 @@ export default function App() {
);
}`;
const AppTs = `import {Modal, ModalContent, ModalHeader, ModalBody, ModalFooter, ModalProps, Button, useDisclosure, RadioGroup, Radio} from "@nextui-org/react";
export default function App() {
const {isOpen, onOpen, onOpenChange} = useDisclosure();
const [scrollBehavior, setScrollBehavior] = React.useState<ModalProps["scrollBehavior"]>("inside");
return (
<div className="flex flex-col gap-2">
<Button onPress={onOpen}>Open Modal</Button>
<RadioGroup
label="Select scroll behavior"
orientation="horizontal"
value={scrollBehavior}
onValueChange={setScrollBehavior}
>
<Radio value="inside">inside</Radio>
<Radio value="outside">outside</Radio>
</RadioGroup>
<Modal
isOpen={isOpen}
onOpenChange={onOpenChange}
scrollBehavior={scrollBehavior}
>
<ModalContent>
{(onClose) => (
<>
<ModalHeader className="flex flex-col gap-1">
Modal Title
</ModalHeader>
<ModalBody>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Nullam pulvinar risus non risus hendrerit venenatis.
Pellentesque sit amet hendrerit risus, sed porttitor quam.
</p>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Nullam pulvinar risus non risus hendrerit venenatis.
Pellentesque sit amet hendrerit risus, sed porttitor quam.
</p>
<p>
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>
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Nullam pulvinar risus non risus hendrerit venenatis.
Pellentesque sit amet hendrerit risus, sed porttitor quam.
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>
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. Lorem ipsum dolor sit amet, consectetur
adipiscing elit. Nullam pulvinar risus non risus hendrerit
venenatis. Pellentesque sit amet hendrerit risus, sed
porttitor quam. 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>
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Nullam pulvinar risus non risus hendrerit venenatis.
Pellentesque sit amet hendrerit risus, sed porttitor quam.
</p>
<p>
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>
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. Lorem ipsum dolor sit amet, consectetur
adipiscing elit. Nullam pulvinar risus non risus hendrerit
venenatis. Pellentesque sit amet hendrerit risus, sed
porttitor quam. 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>
</ModalBody>
<ModalFooter>
<Button color="danger" variant="light" onPress={onClose}>
Close
</Button>
<Button color="primary" onPress={onClose}>
Action
</Button>
</ModalFooter>
</>
)}
</ModalContent>
</Modal>
</div>
);
}`;
const react = {
"/App.jsx": App,
};
const reactTs = {
"/App.tsx": AppTs,
};
export default {
...react,
...reactTs,
};
@@ -6,12 +6,14 @@ import defaultValue from "./default-value";
import withDescription from "./with-description";
import customStyles from "./custom-styles";
import customImpl from "./custom-impl";
import invalid from "./invalid";
export const radioGroupContent = {
usage,
disabled,
horizontal,
controlled,
invalid,
defaultValue,
withDescription,
customStyles,
@@ -0,0 +1,35 @@
const App = `import {RadioGroup, Radio} from "@nextui-org/react";
export default function App() {
const [selected, setSelected] = React.useState("london");
const validOptions = ["buenos-aires", "san-francisco", "tokyo"];
const isInvalid = !validOptions.includes(selected);
return (
<div className="flex flex-col gap-3">
<RadioGroup
label="Select your favorite city"
value={selected}
isInvalid={isInvalid}
onValueChange={setSelected}
>
<Radio value="buenos-aires">Buenos Aires</Radio>
<Radio value="sydney">Sydney</Radio>
<Radio value="san-francisco">San Francisco</Radio>
<Radio value="london">London</Radio>
<Radio value="tokyo">Tokyo</Radio>
</RadioGroup>
<p className="text-default-500 text-small">Selected: {selected}</p>
</div>
);
}`;
const react = {
"/App.jsx": App,
};
export default {
...react,
};
@@ -137,7 +137,7 @@ const usePokemonList = `export function usePokemonList({fetchDelay = 0} = {}) {
};`;
const App = `import {Select, SelectItem} from "@nextui-org/react";
import {useInfiniteScroll} from "@nextui-org/use-infinity-scroll";
import {useInfiniteScroll} from "@nextui-org/use-infinite-scroll";
import {usePokemonList} from "./usePokemonList";
export default function App() {
@@ -42,7 +42,7 @@ export default function App() {
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"}
isInvalid={isValid || !touched ? false : true}
selectedKeys={value}
className="max-w-xs"
onSelectionChange={setValue}
@@ -1,4 +1,4 @@
const App = `import {Card, Skeleton} from "@nextui-org/react";
const App = `import {Skeleton} from "@nextui-org/react";
export default function App() {
return (
@@ -1,50 +1,22 @@
const App = `import {Table, TableHeader, TableColumn, TableBody, TableRow, TableCell, Pagination, Spinner, getKeyValue} from "@nextui-org/react";
import {useAsyncList} from "@react-stately/data";
import useSWR from "swr";
const fetcher = (...args) => fetch(...args).then((res) => res.json());
export default function App() {
const [page, setPage] = React.useState(1);
const [total, setTotal] = React.useState(0);
const [isLoading, setIsLoading] = React.useState(true);
const {data, isLoading} = useSWR(\`https://swapi.py4e.com/api/people?page=\$\{page\}\`, fetcher, {
keepPreviousData: true,
});
const rowsPerPage = 10;
let list = useAsyncList({
async load({signal, cursor}) {
// If no cursor is available, then we're loading the first page.
// Otherwise, the cursor is the next URL to load, as returned from the previous page.
const res = await fetch(cursor || "https://swapi.py4e.com/api/people/?search=", {signal});
let json = await res.json();
const pages = useMemo(() => {
return data?.count ? Math.ceil(data.count / rowsPerPage) : 0;
}, [data?.count, rowsPerPage]);
setTotal(json.count);
setIsLoading(false);
return {
items: json.results,
cursor: json.next,
};
},
});
const pages = Math.ceil(total / rowsPerPage);
const items = React.useMemo(() => {
const start = (page - 1) * rowsPerPage;
const end = start + rowsPerPage;
return list.items.slice(start, end);
}, [page, list.items?.length]);
const onPaginationChange = React.useCallback(
(page) => {
setIsLoading(true);
if (page >= list.items.length / rowsPerPage) {
list.loadMore();
}
setPage(page);
},
[list.items.length],
);
const loadingState = isLoading || data?.results.length === 0 ? "loading" : "idle";
return (
<Table
@@ -59,14 +31,12 @@ export default function App() {
color="primary"
page={page}
total={pages}
onChange={onPaginationChange}
onChange={(page) => setPage(page)}
/>
</div>
) : null
}
classNames={{
table: "min-h-[400px]",
}}
{...args}
>
<TableHeader>
<TableColumn key="name">Name</TableColumn>
@@ -75,12 +45,12 @@ export default function App() {
<TableColumn key="birth_year">Birth year</TableColumn>
</TableHeader>
<TableBody
isLoading={isLoading && !items.length}
items={items}
items={data?.results ?? []}
loadingContent={<Spinner />}
loadingState={loadingState}
>
{(item) => (
<TableRow key={item.name}>
<TableRow key={item?.name}>
{(columnKey) => <TableCell>{getKeyValue(item, columnKey)}</TableCell>}
</TableRow>
)}
+344 -5
View File
@@ -220,6 +220,234 @@ const users = [
export {columns, users, statusOptions};`;
const dataTs = `const columns = [
{name: "ID", uid: "id", sortable: true},
{name: "NAME", uid: "name", sortable: true},
{name: "AGE", uid: "age", sortable: true},
{name: "ROLE", uid: "role", sortable: true},
{name: "TEAM", uid: "team"},
{name: "EMAIL", uid: "email"},
{name: "STATUS", uid: "status", sortable: true},
{name: "ACTIONS", uid: "actions"},
];
const statusOptions = [
{name: "Active", uid: "active"},
{name: "Paused", uid: "paused"},
{name: "Vacation", uid: "vacation"},
];
const users = [
{
id: 1,
name: "Tony Reichert",
role: "CEO",
team: "Management",
status: "active",
age: "29",
avatar: "https://i.pravatar.cc/150?u=a042581f4e29026024d",
email: "tony.reichert@example.com",
},
{
id: 2,
name: "Zoey Lang",
role: "Tech Lead",
team: "Development",
status: "paused",
age: "25",
avatar: "https://i.pravatar.cc/150?u=a042581f4e29026704d",
email: "zoey.lang@example.com",
},
{
id: 3,
name: "Jane Fisher",
role: "Sr. Dev",
team: "Development",
status: "active",
age: "22",
avatar: "https://i.pravatar.cc/150?u=a04258114e29026702d",
email: "jane.fisher@example.com",
},
{
id: 4,
name: "William Howard",
role: "C.M.",
team: "Marketing",
status: "vacation",
age: "28",
avatar: "https://i.pravatar.cc/150?u=a048581f4e29026701d",
email: "william.howard@example.com",
},
{
id: 5,
name: "Kristen Copper",
role: "S. Manager",
team: "Sales",
status: "active",
age: "24",
avatar: "https://i.pravatar.cc/150?u=a092581d4ef9026700d",
email: "kristen.cooper@example.com",
},
{
id: 6,
name: "Brian Kim",
role: "P. Manager",
team: "Management",
age: "29",
avatar: "https://i.pravatar.cc/150?u=a042581f4e29026024d",
email: "brian.kim@example.com",
status: "Active",
},
{
id: 7,
name: "Michael Hunt",
role: "Designer",
team: "Design",
status: "paused",
age: "27",
avatar: "https://i.pravatar.cc/150?u=a042581f4e29027007d",
email: "michael.hunt@example.com",
},
{
id: 8,
name: "Samantha Brooks",
role: "HR Manager",
team: "HR",
status: "active",
age: "31",
avatar: "https://i.pravatar.cc/150?u=a042581f4e27027008d",
email: "samantha.brooks@example.com",
},
{
id: 9,
name: "Frank Harrison",
role: "F. Manager",
team: "Finance",
status: "vacation",
age: "33",
avatar: "https://i.pravatar.cc/150?img=4",
email: "frank.harrison@example.com",
},
{
id: 10,
name: "Emma Adams",
role: "Ops Manager",
team: "Operations",
status: "active",
age: "35",
avatar: "https://i.pravatar.cc/150?img=5",
email: "emma.adams@example.com",
},
{
id: 11,
name: "Brandon Stevens",
role: "Jr. Dev",
team: "Development",
status: "active",
age: "22",
avatar: "https://i.pravatar.cc/150?img=8",
email: "brandon.stevens@example.com",
},
{
id: 12,
name: "Megan Richards",
role: "P. Manager",
team: "Product",
status: "paused",
age: "28",
avatar: "https://i.pravatar.cc/150?img=10",
email: "megan.richards@example.com",
},
{
id: 13,
name: "Oliver Scott",
role: "S. Manager",
team: "Security",
status: "active",
age: "37",
avatar: "https://i.pravatar.cc/150?img=12",
email: "oliver.scott@example.com",
},
{
id: 14,
name: "Grace Allen",
role: "M. Specialist",
team: "Marketing",
status: "active",
age: "30",
avatar: "https://i.pravatar.cc/150?img=16",
email: "grace.allen@example.com",
},
{
id: 15,
name: "Noah Carter",
role: "IT Specialist",
team: "I. Technology",
status: "paused",
age: "31",
avatar: "https://i.pravatar.cc/150?img=15",
email: "noah.carter@example.com",
},
{
id: 16,
name: "Ava Perez",
role: "Manager",
team: "Sales",
status: "active",
age: "29",
avatar: "https://i.pravatar.cc/150?img=20",
email: "ava.perez@example.com",
},
{
id: 17,
name: "Liam Johnson",
role: "Data Analyst",
team: "Analysis",
status: "active",
age: "28",
avatar: "https://i.pravatar.cc/150?img=33",
email: "liam.johnson@example.com",
},
{
id: 18,
name: "Sophia Taylor",
role: "QA Analyst",
team: "Testing",
status: "active",
age: "27",
avatar: "https://i.pravatar.cc/150?img=29",
email: "sophia.taylor@example.com",
},
{
id: 19,
name: "Lucas Harris",
role: "Administrator",
team: "Information Technology",
status: "paused",
age: "32",
avatar: "https://i.pravatar.cc/150?img=50",
email: "lucas.harris@example.com",
},
{
id: 20,
name: "Mia Robinson",
role: "Coordinator",
team: "Operations",
status: "active",
age: "26",
avatar: "https://i.pravatar.cc/150?img=45",
email: "mia.robinson@example.com",
},
];
export {columns, users, statusOptions};`;
const types = `import {SVGProps} from "react";
export type IconSvgProps = SVGProps<SVGSVGElement> & {
size?: number;
};`;
const utils = `export function capitalize(str) {
return str.charAt(0).toUpperCase() + str.slice(1);
}`;
@@ -316,6 +544,110 @@ const ChevronDownIcon = `export const ChevronDownIcon = ({strokeWidth = 1.5, ...
</svg>
);`;
const utilsTs = `export function capitalize(str: string) {
return str.charAt(0).toUpperCase() + str.slice(1);
}`;
const PlusIconTs = `import {IconSvgProps} from "./types";
export const PlusIcon = ({size = 24, width, height, ...props}: IconSvgProps) => (
<svg
aria-hidden="true"
fill="none"
focusable="false"
height={size || height}
role="presentation"
viewBox="0 0 24 24"
width={size || width}
{...props}
>
<g
fill="none"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={1.5}
>
<path d="M6 12h12" />
<path d="M12 18V6" />
</g>
</svg>
);`;
const VerticalDotsIconTs = `import {IconSvgProps} from "./types";
export const VerticalDotsIcon = ({size = 24, width, height, ...props}: IconSvgProps) => (
<svg
aria-hidden="true"
fill="none"
focusable="false"
height={size || height}
role="presentation"
viewBox="0 0 24 24"
width={size || width}
{...props}
>
<path
d="M12 10c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0-6c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2zm0 12c-1.1 0-2 .9-2 2s.9 2 2 2 2-.9 2-2-.9-2-2-2z"
fill="currentColor"
/>
</svg>
);`;
const SearchIconTs = `import {IconSvgProps} from "./types";
export const SearchIcon = (props: IconSvgProps) => (
<svg
aria-hidden="true"
fill="none"
focusable="false"
height="1em"
role="presentation"
viewBox="0 0 24 24"
width="1em"
{...props}
>
<path
d="M11.5 21C16.7467 21 21 16.7467 21 11.5C21 6.25329 16.7467 2 11.5 2C6.25329 2 2 6.25329 2 11.5C2 16.7467 6.25329 21 11.5 21Z"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
/>
<path
d="M22 22L20 20"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="2"
/>
</svg>
);`;
const ChevronDownIconTs = `import {IconSvgProps} from "./types";
export const ChevronDownIcon = ({strokeWidth = 1.5, ...otherProps}: IconSvgProps) => (
<svg
aria-hidden="true"
fill="none"
focusable="false"
height="1em"
role="presentation"
viewBox="0 0 24 24"
width="1em"
{...otherProps}
>
<path
d="m19.92 8.95-6.52 6.52c-.77.77-2.03.77-2.8 0L4.08 8.95"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeMiterlimit={10}
strokeWidth={strokeWidth}
/>
</svg>
);`;
const App = `import {
Table,
TableHeader,
@@ -479,7 +811,7 @@ export default function App() {
}
}, []);
const onClear = useCallback(()=>{
const onClear = React.useCallback(()=>{
setFilterValue("")
setPage(1)
},[])
@@ -687,7 +1019,7 @@ export default function App() {
direction: "ascending",
});
const [page, setPage] = useState(1);
const [page, setPage] = React.useState(1);
const hasSearchFilter = Boolean(filterValue);
@@ -734,7 +1066,7 @@ export default function App() {
}, [sortDescriptor, items]);
const renderCell = React.useCallback((user: User, columnKey: React.Key) => {
const cellValue = user[columnKey];
const cellValue = user[columnKey as keyof User];
switch (columnKey) {
case "name":
@@ -808,7 +1140,7 @@ export default function App() {
}
}, []);
const onClear = useCallback(()=>{
const onClear = React.useCallback(()=>{
setFilterValue("")
setPage(1)
},[])
@@ -973,13 +1305,20 @@ const react = {
"/data.js": data,
"/utils.js": utils,
"/PlusIcon.jsx": PlusIcon,
"/VerticalDotsIcon.jsx": VerticalDotsIcon,
"/SearchIcon.jsx": SearchIcon,
"/ChevronDownIcon.jsx": ChevronDownIcon,
"/VerticalDotsIcon.jsx": VerticalDotsIcon,
};
const reactTs = {
"/App.tsx": AppTs,
"/types.ts": types,
"/data.ts": dataTs,
"/utils.ts": utilsTs,
"/PlusIcon.tsx": PlusIconTs,
"/VerticalDotsIcon.tsx": VerticalDotsIconTs,
"/SearchIcon.tsx": SearchIconTs,
"/ChevronDownIcon.tsx": ChevronDownIconTs,
};
export default {
@@ -3,12 +3,12 @@ const App = `import {Textarea} from "@nextui-org/react";
export default function App() {
return (
<Textarea
isInvalid={true}
variant="bordered"
label="Description"
labelPlacement="outside"
placeholder="Enter your description"
defaultValue="NextUI is a React UI library with..."
validationState="invalid"
errorMessage="The description should be at least 255 characters long."
className="max-w-xs"
/>
@@ -194,7 +194,7 @@ Here's an example of how to customize the accordion styles:
| fullWidth | `boolean` | Whether the accordion should take up the full width of its parent container. | `true` |
| motionProps | `MotionProps` | The motion properties of the Accordion. | |
| disabledKeys | `React.Key[]` | The item keys that are disabled. These items cannot be selected, focused, or otherwise interacted with. | |
| itemClasses | [Classnames](#accordiom-item-classnames) | The accordion items classNames. | |
| itemClasses | [Classnames](#accordion-item-classnames) | The accordion items classNames. | |
| selectedKeys | `all` \| `React.Key[]` | The currently selected keys in the collection (controlled). | |
| defaultSelectedKeys | `all` \| `React.Key[]` | The initial selected keys in the collection (uncontrolled). | |
| disabledKeys | `React.Key[]` | The currently disabled keys in the collection (controlled). | |
@@ -221,7 +221,7 @@ Here's an example of how to customize the accordion styles:
| hideIndicator | `boolean` | Whether the AccordionItem indicator is hidden. | `false` |
| disableAnimation | `boolean` | Whether the AccordionItem animation is disabled. | `false` |
| disableIndicatorAnimation | `boolean` | Whether the AccordionItem indicator animation is disabled. | `false` |
| classNames | [Classnames](#accordiom-item-classnames) | Allows to set custom class names for the accordion item slots. | - |
| classNames | [Classnames](#accordion-item-classnames) | Allows to set custom class names for the accordion item slots. | - |
### Accordion Item Events
@@ -13,7 +13,7 @@ A CheckboxGroup allows users to select one or more items from a list of choices.
---
<CarbonAd/>
<CarbonAd />
## Import
@@ -47,6 +47,10 @@ You can use the `value` and `onValueChange` properties to control the checkbox i
<CodeDemo title="Controlled" files={checkboxGroupContent.controlled} />
### Invalid
<CodeDemo title="Invalid" files={checkboxGroupContent.invalid} />
## Slots
- **base**: Checkbox group root wrapper, it wraps the label and the wrapper.
@@ -57,7 +61,6 @@ You can use the `value` and `onValueChange` properties to control the checkbox i
### Custom Styles
You can customize the `CheckboxGroup` component by passing custom Tailwind CSS classes to the component slots.
<CodeDemo title="Custom Styles" files={checkboxGroupContent.customStyles} />
@@ -76,25 +79,26 @@ In case you need to customize the checkbox even further, you can use the `useChe
### Checkbox Group Props
| Attribute | Type | Description | Default |
| ---------------- | --------------------------------------------------------------------------- | -------------------------------------------------------------------------- | ---------- |
| children | `ReactNode[]` \| `ReactNode[]` | The checkboxes items. | - |
| orientation | `vertical` \| `horizontal` | The axis the checkbox group items should align with. | `vertical` |
| color | `default` \| `primary` \| `secondary` \| `success` \| `warning` \| `danger` | The color of the checkboxes. | `primary` |
| size | `xs` \| `sm` \| `md` \| `lg` \| `xl` | The size of the checkboxes. | `md` |
| radius | `none` \| `base` \| `xs` \| `sm` \| `md` \| `lg` \| `xl` \| `full` | The radius of the checkboxes. | `md` |
| name | `string` | The name of the CheckboxGroup, used when submitting an HTML form. | - |
| value | `string[]` | The current selected values. (controlled). | - |
| lineThrough | `boolean` | Whether the checkboxes label should be crossed out. | `false` |
| defaultValue | `string[]` | The default selected values. (uncontrolled). | - |
| validationState | `valid` \| `invalid` | Whether the inputs should display its "valid" or "invalid" visual styling. | `false` |
| description | `ReactNode` | The checkbox group description. | - |
| errorMessage | `ReactNode` | The checkbox group error message. | - |
| isDisabled | `boolean` | Whether the checkbox group is disabled. | `false` |
| isRequired | `boolean` | Whether user checkboxes are required on the input before form submission. | `false` |
| isReadOnly | `boolean` | Whether the checkboxes can be selected but not changed by the user. | - |
| disableAnimation | `boolean` | Whether the animation should be disabled. | `false` |
| classNames | `Record<"base" "wrapper" "label", string>` | Allows to set custom class names for the checkbox group slots. | - |
| Attribute | Type | Description | Default |
| ---------------- | --------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- | ---------- |
| children | `ReactNode[]` \| `ReactNode[]` | The checkboxes items. | - |
| orientation | `vertical` \| `horizontal` | The axis the checkbox group items should align with. | `vertical` |
| color | `default` \| `primary` \| `secondary` \| `success` \| `warning` \| `danger` | The color of the checkboxes. | `primary` |
| size | `xs` \| `sm` \| `md` \| `lg` \| `xl` | The size of the checkboxes. | `md` |
| radius | `none` \| `base` \| `xs` \| `sm` \| `md` \| `lg` \| `xl` \| `full` | The radius of the checkboxes. | `md` |
| name | `string` | The name of the CheckboxGroup, used when submitting an HTML form. | - |
| value | `string[]` | The current selected values. (controlled). | - |
| lineThrough | `boolean` | Whether the checkboxes label should be crossed out. | `false` |
| defaultValue | `string[]` | The default selected values. (uncontrolled). | - |
| isInvalid | `boolean` | Whether the checkbox group is invalid. | `false` |
| validationState | `valid` \| `invalid` | Whether the inputs should display its "valid" or "invalid" visual styling. (**Deprecated**) use **isInvalid** instead. | - |
| description | `ReactNode` | The checkbox group description. | - |
| errorMessage | `ReactNode` | The checkbox group error message. | - |
| isDisabled | `boolean` | Whether the checkbox group is disabled. | `false` |
| isRequired | `boolean` | Whether user checkboxes are required on the input before form submission. | `false` |
| isReadOnly | `boolean` | Whether the checkboxes can be selected but not changed by the user. | - |
| disableAnimation | `boolean` | Whether the animation should be disabled. | `false` |
| classNames | `Record<"base" "wrapper" "label", string>` | Allows to set custom class names for the checkbox group slots. | - |
### Checkbox Group Events
@@ -13,7 +13,7 @@ Checkboxes allow users to select multiple items from a list of individual items,
---
<CarbonAd/>
<CarbonAd />
## Import
@@ -134,19 +134,20 @@ In case you need to customize the checkbox even further, you can use the `useChe
| ---------------- | --------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- | --------- |
| children | `ReactNode` | The label of the checkbox. | - |
| icon | [CheckboxIconProps](#checkbox-icon-props) | The icon to be displayed when the checkbox is checked. | - |
| value | `string` | The value of the input element, used when submitting an HTML form. | |
| name | `string` | The name of the input element, used when submitting an HTML form. | |
| value | `string` | The value of the checkbox element, used when submitting an HTML form. | |
| name | `string` | The name of the checkbox element, used when submitting an HTML form. | |
| size | `sm` \| `md` \| `lg` | The size of the checkbox. | `md` |
| color | `default` \| `primary` \| `secondary` \| `success` \| `warning` \| `danger` | The color of the checkbox. | `primary` |
| radius | `none` \| `sm` \| `md` \| `lg` \| `full` | The radius of the checkbox. | - |
| lineThrough | `boolean` | Whether the label should be crossed out. | `false` |
| isSelected | `boolean` | Whether the element should be selected (controlled). | |
| defaultSelected | `boolean` | Whether the element should be selected (uncontrolled). | |
| validationState | `valid` \| `invalid` | Whether the input should display its "valid" or "invalid" visual styling. | - |
| isRequired | `boolean` | Whether user input is required on the input before form submission. | `false` |
| isReadOnly | `boolean` | Whether the input can be selected but not changed by the user. | |
| isRequired | `boolean` | Whether user checkbox is required on the checkbox before form submission. | `false` |
| isReadOnly | `boolean` | Whether the checkbox can be selected but not changed by the user. | |
| isDisabled | `boolean` | Whether the checkbox is disabled. | `false` |
| isIndeterminate | `boolean` | Indeterminism is presentational only. The indeterminate visual representation remains regardless of user interaction. | |
| isInvalid | `boolean` | Whether the checkbox is invalid. | `false` |
| validationState | `valid` \| `invalid` | Whether the checkbox should display its "valid" or "invalid" visual styling. (**Deprecated**) use **isInvalid** instead. | - |
| disableAnimation | `boolean` | Whether the animation should be disabled. | `false` |
| classNames | `Record<"base" "wrapper" "icon" "label", string>` | Allows to set custom class names for the checkbox slots. | - |
@@ -113,7 +113,7 @@ It is possible to add icons to the dropdown items using the `startContent` / `en
<CodeDemo title="With Icons" highlightedLines="23,30,37,47" files={dropdownContent.icons} />
> **Note**: Note: If you use `currentColor` as the icon color, the icon will have the same color as the item text.
> **Note**: If you use `currentColor` as the icon color, the icon will have the same color as the item text.
### With Description
@@ -156,7 +156,7 @@ Dropdown has 2 components with slots the `DropdownItem` and `DropdownSection` co
- **wrapper**: The `title` and `description` wrapper.
- **title**: The title of the dropdown item.
- **description**: The description of the dropdown item.
- **shortcut**: The shorcut slot.
- **shortcut**: The shortcut slot.
- **selectedIcon**: The selected icon slot. This is only visible when the item is selected.
### DropdownSection
+26 -25
View File
@@ -13,7 +13,7 @@ Input is a component that allows users to enter text. It can be used to get user
---
<CarbonAd/>
<CarbonAd />
## Import
@@ -180,30 +180,31 @@ In case you need to customize the input even further, you can use the `useInput`
### Input Props
| Attribute | Type | Description | Default |
| ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- | --------- |
| children | `ReactNode` | The content of the input. | - |
| variant | `flat` \| `bordered` \| `faded` \| `underlined` | The variant of the input. | `flat` |
| color | `default` \| `primary` \| `secondary` \| `success` \| `warning` \| `danger` | The color of the input. | `default` |
| size | `sm` \| `md` \| `lg` | The size of the input. | `md` |
| radius | `none` \| `sm` \| `md` \| `lg` \| `full` | The radius of the input. | - |
| label | `ReactNode` | The content to display as the label. | - |
| value | `string` | The current value of the input (controlled). | - |
| defaultValue | `string` | The default value of the input (uncontrolled). | - |
| placeholder | `string` | The placeholder of the input. | - |
| description | `ReactNode` | A description for the input. Provides a hint such as specific requirements for what to choose. | - |
| errorMessage | `ReactNode` | An error message for the input. | - |
| labelPlacement | `inside` \| `outside` \| `outside-left` | The position of the label. | `inside` |
| fullWidth | `boolean` | Whether the input should take up the width of its parent. | `true` |
| validationState | `valid` \| `invalid` | Whether the input should display its "valid" or "invalid" visual styling. | - |
| isClearable | `boolean` | Whether the input should have a clear button. | `false` |
| isRequired | `boolean` | Whether user input is required on the input before form submission. | `false` |
| isReadOnly | `boolean` | Whether the input can be selected but not changed by the user. | |
| isDisabled | `boolean` | Whether the input is disabled. | `false` |
| startContent | `ReactNode` | Element to be rendered in the left side of the input. | - |
| endContent | `ReactNode` | Element to be rendered in the right side of the input. | - |
| disableAnimation | `boolean` | Whether the input should be animated. | `false` |
| classNames | `Record<"base" "label" "inputWrapper" "innerWrapper" "mainWrapper" "input" "clearButton" "helperWrapper" "description" "errorMessage", string>` | Allows to set custom class names for the checkbox slots. | - |
| Attribute | Type | Description | Default |
| ---------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------- | --------- |
| children | `ReactNode` | The content of the input. | - |
| variant | `flat` \| `bordered` \| `faded` \| `underlined` | The variant of the input. | `flat` |
| color | `default` \| `primary` \| `secondary` \| `success` \| `warning` \| `danger` | The color of the input. | `default` |
| size | `sm` \| `md` \| `lg` | The size of the input. | `md` |
| radius | `none` \| `sm` \| `md` \| `lg` \| `full` | The radius of the input. | - |
| label | `ReactNode` | The content to display as the label. | - |
| value | `string` | The current value of the input (controlled). | - |
| defaultValue | `string` | The default value of the input (uncontrolled). | - |
| placeholder | `string` | The placeholder of the input. | - |
| description | `ReactNode` | A description for the input. Provides a hint such as specific requirements for what to choose. | - |
| errorMessage | `ReactNode` | An error message for the input. | - |
| startContent | `ReactNode` | Element to be rendered in the left side of the input. | - |
| endContent | `ReactNode` | Element to be rendered in the right side of the input. | - |
| labelPlacement | `inside` \| `outside` \| `outside-left` | The position of the label. | `inside` |
| fullWidth | `boolean` | Whether the input should take up the width of its parent. | `true` |
| isClearable | `boolean` | Whether the input should have a clear button. | `false` |
| isRequired | `boolean` | Whether user input is required on the input before form submission. | `false` |
| isReadOnly | `boolean` | Whether the input can be selected but not changed by the user. | |
| isDisabled | `boolean` | Whether the input is disabled. | `false` |
| isInvalid | `boolean` | Whether the input is invalid. | `false` |
| validationState | `valid` \| `invalid` | Whether the input should display its "valid" or "invalid" visual styling. (**Deprecated**) use **isInvalid** instead. | - |
| disableAnimation | `boolean` | Whether the input should be animated. | `false` |
| classNames | `Record<"base" "label" "inputWrapper" "innerWrapper" "mainWrapper" "input" "clearButton" "helperWrapper" "description" "errorMessage", string>` | Allows to set custom class names for the checkbox slots. | - |
### Input Events
@@ -93,7 +93,7 @@ It is possible to add icons to the listbox items using the `startContent` / `end
<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.
> **Note**: If you use `currentColor` as the icon color, the icon will have the same color as the item text.
### With Description
@@ -46,7 +46,7 @@ NextUI exports 3 pagination-related components:
### Colors
<CodeDemo title="Radius" files={paginationContent.colors} />
{/*
### Variants
You can use the `variant` property to change the pagination items style.
@@ -129,7 +129,7 @@ You can customize the `Pagination` component by passing custom Tailwind CSS clas
In case you need to customize the pagination even further, you can use the `usePagination` hook to create
your own implementation.
<CodeDemo title="Custom Implementation" files={paginationContent.customImpl} /> */}
<CodeDemo title="Custom Implementation" files={paginationContent.customImpl} />
<Spacer y={4} />
@@ -13,7 +13,7 @@ Radio Group allow users to select a single option from a list of mutually exclus
---
<CarbonAd/>
<CarbonAd />
## Import
@@ -53,6 +53,10 @@ You can use the `value` and `onValueChange` properties to control the radio inpu
> **Note**: NextUI `Radio` also supports native events like `onChange`, useful for form libraries
> such as [Formik](https://formik.org/) and [React Hook Form](https://react-hook-form.com/).
### Invalid
<CodeDemo title="Invalid" files={radioGroupContent.invalid} />
## Slots
- RadioGroup Slots
@@ -140,12 +144,13 @@ In case you need to customize the radio group even further, you can use the `use
| name | `string` | The name of the RadioGroup, used when submitting an HTML form. See [MDN](https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#name_and_radio_buttons). | - |
| value | `string[]` | The current selected value. (controlled). | - |
| defaultValue | `string[]` | The default selected value. (uncontrolled). | - |
| validationState | `valid` \| `invalid` | Whether the inputs should display its "valid" or "invalid" visual styling. | `false` |
| description | `ReactNode` | Radio group description . | - |
| errorMessage | `ReactNode` | Radio group error message. | - |
| isDisabled | `boolean` | Whether the radio group is disabled. | `false` |
| isRequired | `boolean` | Whether user checkboxes are required on the input before form submission. | `false` |
| isReadOnly | `boolean` | Whether the checkboxes can be selected but not changed by the user. | - |
| isInvalid | `boolean` | Whether the radio group is invalid. | `false` |
| validationState | `valid` \| `invalid` | Whether the inputs should display its "valid" or "invalid" visual styling. (**Deprecated**) use **isInvalid** instead. | `false` |
| disableAnimation | `boolean` | Whether the animation should be disabled. | `false` |
| classNames | `Record<"base" "wrapper" "label", string>` | Allows to set custom class names for the radio group slots. | - |
+51 -49
View File
@@ -91,7 +91,7 @@ the select.
<CodeDemo title="Start Content" highlightedLines="9" files={selectContent.startContent} />
### Item Start Content
### Item Start & End 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
@@ -101,7 +101,7 @@ and end of the select item.
### 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
By default the select uses a `chevron-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} />
@@ -174,22 +174,22 @@ You can customize the sections style by using the `classNames` property of the `
<CodeDemo title="Custom Sections Style" files={selectContent.customSectionsStyle} />
### Asyncronous Loading
### Asynchronous 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.
Select supports asynchronous 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 `useInfiniteScroll` 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.
The `isLoading` prop is used to show a loading indicator instead 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",
npm: "npm install @nextui-org/use-infinite-scroll",
yarn: "yarn add @nextui-org/use-infinite-scroll",
pnpm: "pnpm add @nextui-org/use-infinite-scroll",
}}
/>
```jsx
import {useInfinityScroll} from "@nextui-org/use-infinity-scroll";
import {useInfiniteScroll} from "@nextui-org/use-infinite-scroll";
```
<Spacer y={2} />
@@ -197,7 +197,7 @@ import {useInfinityScroll} from "@nextui-org/use-infinity-scroll";
<CodeDemo
asIframe
typescriptStrict={true}
title="Asyncronous Loading"
title="Asynchronous Loading"
hideWindowActions={true}
resizeEnabled={false}
displayMode="always"
@@ -230,7 +230,7 @@ Using `onChange`:
files={selectContent.multipleControlledOnChange}
/>
### Mutliple With Chips
### Multiple 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.
@@ -254,6 +254,7 @@ the popover and listbox components.
- **base**: The main wrapper of the select. This wraps the rest of the slots.
- **label**: The label of the select.
- **mainWrapper**: Wraps the `helperWrapper` and the `trigger` slots.
- **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`).
@@ -332,44 +333,45 @@ the popover and listbox components.
### 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. | - |
| 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` |
| 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` |
| isInvalid | `boolean` | Whether the select is invalid. | `false` |
| validationState | `valid` \| `invalid` | Whether the select should display its "valid" or "invalid" visual styling. (**Deprecated**) use **isInvalid** instead. | - |
| 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" "mainWrapper" "innerWrapper" "selectorIcon" "value" "listboxWrapper" "listbox" "popover" "helperWrapper" "description" "errorMessage", string>` | Allows to set custom class names for the dropdown item slots. | - |
### Select Events
+1 -1
View File
@@ -67,7 +67,7 @@ You can also add icons to start and end of the switch by using `startContent` an
- **wrapper**: The wrapper of the start icon, end icon and thumb.
- **thumb**: The thumb element of the switch. It is the circle element.
- **label**: The label slot of the switch.
- **startContent**:The icon slot at the start of the switch.
- **startContent**: The icon slot at the start of the switch.
- **endContent**: The icon slot at the end of the switch.
- **thumbIcon**: The icon slot inside the thumb.
+2 -2
View File
@@ -257,8 +257,7 @@ You can use the [Pagination](/components/pagination) component to paginate the t
### Async Pagination
It is also possible to use the [Pagination](/components/pagination) component to paginate the table asynchronously. To fetch the data, we are using the `useAsyncList` hook from [@react-stately/data](https://react-spectrum.adobe.com/react-stately/useAsyncList.html).
Please check the installation instructions in the [Sorting Rows](#sorting-rows) section.
It is also possible to use the [Pagination](/components/pagination) component to paginate the table asynchronously. To fetch the data, we are using the `useSWR` hook from [SWR](https://swr.vercel.app/docs/pagination).
<CodeDemo
asIframe
@@ -292,6 +291,7 @@ example below, we combined all these functionalities to create a complete table.
<CodeDemo
asIframe
typescriptStrict={true}
title="Table use Case Example"
resizeEnabled={false}
files={tableContent.useCase}
+6 -5
View File
@@ -13,7 +13,7 @@ Tabs organize content into multiple sections and allow users to navigate between
---
<CarbonAd/>
<CarbonAd />
## Import
@@ -157,10 +157,11 @@ You can customize the `Tabs` component by passing custom Tailwind CSS classes to
### Tab Props
| Attribute | Type | Description | Default |
| ---------- | ----------- | ----------------------- | ------- |
| children\* | `ReactNode` | The content of the tab. | - |
| title | `ReactNode` | The title of the tab. | - |
| Attribute | Type | Description | Default |
| ---------- | ----------- | ------------------------------------------------------------------------------------------ | ------- |
| children\* | `ReactNode` | The content of the tab. | - |
| title | `ReactNode` | The title of the tab. | - |
| titleValue | `string` | A string representation of the item's contents. Use this when the `title` is not readable. | - |
#### Motion Props
+27 -26
View File
@@ -13,7 +13,7 @@ Textarea component is a multi-line Input which allows you to write large texts.
---
<CarbonAd/>
<CarbonAd />
## Import
@@ -32,7 +32,7 @@ Textarea component is a multi-line Input which allows you to write large texts.
<CodeDemo title="Disabled" files={textareaContent.disabled} />
### Readonly
### Read Only
<CodeDemo title="Readonly" files={textareaContent.readonly} />
@@ -119,30 +119,31 @@ You can use the `value` and `onValueChange` properties to control the input valu
### Textarea Props
| Attribute | Type | Description | Default |
| ----------------- | ------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------- | --------- |
| children | `ReactNode` | The content of the textarea. | - |
| minRows | `number` | The minimum number of rows to display. | `3` |
| maxRows | `number` | Maximum number of rows up to which the textarea can grow. | `8` |
| cacheMeasurements | `boolean` | Reuse previously computed measurements when computing height of textarea. | `false` |
| variant | `flat` \| `bordered` \| `faded` \| `underlined` | The variant of the textarea. | `flat` |
| color | `default` \| `primary` \| `secondary` \| `success` \| `warning` \| `danger` | The color of the textarea. | `default` |
| size | `sm`\|`md`\|`lg` | The size of the textarea. | `md` |
| radius | `none` \| `sm` \| `md` \| `lg` \| `full` | The radius of the textarea. | - |
| label | `ReactNode` | The content to display as the label. | - |
| value | `string` | The current value of the textarea (controlled). | - |
| defaultValue | `string` | The default value of the textarea (uncontrolled). | - |
| placeholder | `string` | The placeholder of the textarea. | - |
| description | `ReactNode` | A description for the textarea. Provides a hint such as specific requirements for what to choose. | - |
| errorMessage | `ReactNode` | An error message for the textarea. | - |
| labelPlacement | `inside` \| `outside` \| `outside-left` | The position of the label. | `inside` |
| fullWidth | `boolean` | Whether the textarea should take up the width of its parent. | `true` |
| validationState | `valid` \| `invalid` | Whether the textarea should display its "valid" or "invalid" visual styling. | - |
| isRequired | `boolean` | Whether user input is required on the textarea before form submission. | `false` |
| isReadOnly | `boolean` | Whether the textarea can be selected but not changed by the user. | |
| isDisabled | `boolean` | Whether the textarea is disabled. | `false` |
| disableAnimation | `boolean` | Whether the textarea should be animated. | `false` |
| classNames | `Record<"base" "label" "inputWrapper" "input" "description" "errorMessage", string>` | Allows to set custom class names for the checkbox slots. | - |
| Attribute | Type | Description | Default |
| ----------------- | ------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------ | --------- |
| children | `ReactNode` | The content of the textarea. | - |
| minRows | `number` | The minimum number of rows to display. | `3` |
| maxRows | `number` | Maximum number of rows up to which the textarea can grow. | `8` |
| cacheMeasurements | `boolean` | Reuse previously computed measurements when computing height of textarea. | `false` |
| variant | `flat` \| `bordered` \| `faded` \| `underlined` | The variant of the textarea. | `flat` |
| color | `default` \| `primary` \| `secondary` \| `success` \| `warning` \| `danger` | The color of the textarea. | `default` |
| size | `sm`\|`md`\|`lg` | The size of the textarea. | `md` |
| radius | `none` \| `sm` \| `md` \| `lg` \| `full` | The radius of the textarea. | - |
| label | `ReactNode` | The content to display as the label. | - |
| value | `string` | The current value of the textarea (controlled). | - |
| defaultValue | `string` | The default value of the textarea (uncontrolled). | - |
| placeholder | `string` | The placeholder of the textarea. | - |
| description | `ReactNode` | A description for the textarea. Provides a hint such as specific requirements for what to choose. | - |
| errorMessage | `ReactNode` | An error message for the textarea. | - |
| labelPlacement | `inside` \| `outside` \| `outside-left` | The position of the label. | `inside` |
| fullWidth | `boolean` | Whether the textarea should take up the width of its parent. | `true` |
| isRequired | `boolean` | Whether user input is required on the textarea before form submission. | `false` |
| isReadOnly | `boolean` | Whether the textarea can be selected but not changed by the user. | |
| isDisabled | `boolean` | Whether the textarea is disabled. | `false` |
| isInvalid | `boolean` | Whether the textarea is invalid. | `false` |
| validationState | `valid` \| `invalid` | Whether the textarea should display its "valid" or "invalid" visual styling. (**Deprecated**) use **isInvalid** instead. | - |
| disableAnimation | `boolean` | Whether the textarea should be animated. | `false` |
| classNames | `Record<"base" "label" "inputWrapper" "input" "description" "errorMessage", string>` | Allows to set custom class names for the checkbox slots. | - |
### Input Events
@@ -6,7 +6,7 @@ description: NextUI offers a set of layout options to customize the theme.
# Layout
NextUI's plugin provides a variety of layout customization options. Alter spacing units,
font sizes, line heights, radii and more to personalize each theme to your liking.
font sizes, line heights, radius and more to personalize each theme to your liking.
<CarbonAd />
+2 -2
View File
@@ -49,7 +49,7 @@ const { nextui } = require("@nextui-org/react");
module.exports = {
content: [
// ...
'./node_modules/@nextui-org/theme/dist/**/*.{js,ts,jsx,tsx}'
"./node_modules/@nextui-org/theme/dist/**/*.{js,ts,jsx,tsx}"
],
theme: {
extend: {},
@@ -85,7 +85,7 @@ some functionalities of NextUI components may not work properly.
If you are using pnpm, you need to add the following code to your `.npmrc` file:
```bash
public-hoist-pattern[]=*@nextui-org/theme*
public-hoist-pattern[]=*@nextui-org/*
```
After modfiying the `.npmrc` file, you need to run `pnpm install` again to ensure that the dependencies are installed correctly.
+12 -8
View File
@@ -62,13 +62,13 @@ the following code to your `tailwind.config.js` file:
```js {8,13-14}
// tailwind.config.js
const { nextui } = require("@nextui-org/react");
import {nextui} from "@nextui-org/react";
/** @type {import('tailwindcss').Config} */
module.exports = {
const config = {
content: [
// ...
'./node_modules/@nextui-org/theme/dist/**/*.{js,ts,jsx,tsx}'
"./node_modules/@nextui-org/theme/dist/**/*.{js,ts,jsx,tsx}"
],
theme: {
extend: {},
@@ -76,6 +76,8 @@ module.exports = {
darkMode: "class",
plugins: [nextui()]
}
export default config;
```
### Setup Provider
@@ -146,7 +148,7 @@ export default function Page() {
If you are using pnpm, you need to add the following code to your `.npmrc` file:
```bash
public-hoist-pattern[]=*@nextui-org/theme*
public-hoist-pattern[]=*@nextui-org/*
```
After modfiying the `.npmrc` file, you need to run `pnpm install` again to ensure that the dependencies are installed correctly.
@@ -197,13 +199,13 @@ the following code to your `tailwind.config.js` file:
```js {8,13-14}
// tailwind.config.js
const { nextui } = require("@nextui-org/react");
import {nextui} from "@nextui-org/react";
/** @type {import('tailwindcss').Config} */
module.exports = {
const config = {
content: [
// ...
'./node_modules/@nextui-org/theme/dist/**/*.{js,ts,jsx,tsx}'
"./node_modules/@nextui-org/theme/dist/**/*.{js,ts,jsx,tsx}"
],
theme: {
extend: {},
@@ -211,6 +213,8 @@ module.exports = {
darkMode: "class",
plugins: [nextui()]
}
export default config;
```
### Setup Provider
@@ -253,7 +257,7 @@ export default function Page() {
If you are using pnpm, you need to add the following code to your `.npmrc` file:
```bash
public-hoist-pattern[]=*@nextui-org/theme*
public-hoist-pattern[]=*@nextui-org/*
```
After modfiying the `.npmrc` file, you need to run `pnpm install` again to ensure that the dependencies are installed correctly.
+2 -2
View File
@@ -48,7 +48,7 @@ import type { Config} from 'tailwindcss'
export default {
content: [
// ...
'./node_modules/@nextui-org/theme/dist/**/*.{js,ts,jsx,tsx}'
"./node_modules/@nextui-org/theme/dist/**/*.{js,ts,jsx,tsx}"
],
theme: {
extend: {},
@@ -100,7 +100,7 @@ export default function App() {
If you are using pnpm, you need to add the following code to your `.npmrc` file:
```bash
public-hoist-pattern[]=*@nextui-org/theme*
public-hoist-pattern[]=*@nextui-org/*
```
After modfiying the `.npmrc` file, you need to run `pnpm install` again to ensure that the dependencies are installed correctly.
+2 -2
View File
@@ -47,7 +47,7 @@ const { nextui } = require("@nextui-org/react");
module.exports = {
content: [
// ...
'./node_modules/@nextui-org/theme/dist/**/*.{js,ts,jsx,tsx}'
"./node_modules/@nextui-org/theme/dist/**/*.{js,ts,jsx,tsx}"
],
theme: {
extend: {},
@@ -85,7 +85,7 @@ ReactDOM.createRoot(document.getElementById('root')).render(
If you are using pnpm, you need to add the following code to your `.npmrc` file:
```bash
public-hoist-pattern[]=*@nextui-org/theme*
public-hoist-pattern[]=*@nextui-org/*
```
After modfiying the `.npmrc` file, you need to run `pnpm install` again to ensure that the dependencies are installed correctly.
@@ -87,7 +87,7 @@ function App() {
If you are using pnpm, you need to add the following code to your `.npmrc` file:
```bash
public-hoist-pattern[]=*@nextui-org/theme*
public-hoist-pattern[]=*@nextui-org/*
```
After modfiying the `.npmrc` file, you need to run `pnpm install` again to ensure that the dependencies are installed correctly.
@@ -203,7 +203,7 @@ function App() {
If you are using pnpm, you need to add the following code to your `.npmrc` file:
```bash
public-hoist-pattern[]=*@nextui-org/theme*
public-hoist-pattern[]=*@nextui-org/*
```
After modfiying the `.npmrc` file, you need to run `pnpm install` again to ensure that the dependencies are installed correctly.
@@ -57,7 +57,7 @@ const { nextui } = require("@nextui-org/react");
module.exports = {
content: [
// ...
'./node_modules/@nextui-org/theme/dist/**/*.{js,ts,jsx,tsx}'
"./node_modules/@nextui-org/theme/dist/**/*.{js,ts,jsx,tsx}"
],
theme: {
extend: {},
@@ -136,7 +136,7 @@ export default function Page() {
If you are using pnpm, you need to add the following code to your `.npmrc` file:
```bash
public-hoist-pattern[]=*@nextui-org/theme*
public-hoist-pattern[]=*@nextui-org/*
```
After modfiying the `.npmrc` file, you need to run `pnpm install` again to ensure that the dependencies are installed correctly.
@@ -177,7 +177,7 @@ const { nextui } = require("@nextui-org/react");
module.exports = {
content: [
// ...
'./node_modules/@nextui-org/theme/dist/**/*.{js,ts,jsx,tsx}'
"./node_modules/@nextui-org/theme/dist/**/*.{js,ts,jsx,tsx}"
],
theme: {
extend: {},
@@ -227,7 +227,7 @@ export default function Page() {
If you are using pnpm, you need to add the following code to your `.npmrc` file:
```bash
public-hoist-pattern[]=*@nextui-org/theme*
public-hoist-pattern[]=*@nextui-org/*
```
After modfiying the `.npmrc` file, you need to run `pnpm install` again to ensure that the dependencies are installed correctly.
@@ -275,7 +275,7 @@ const { nextui } = require("@nextui-org/react");
module.exports = {
content: [
// ...
'./node_modules/@nextui-org/theme/dist/**/*.{js,ts,jsx,tsx}'
"./node_modules/@nextui-org/theme/dist/**/*.{js,ts,jsx,tsx}"
],
theme: {
extend: {},
@@ -327,7 +327,7 @@ export default function Page() {
If you are using pnpm, you need to add the following code to your `.npmrc` file:
```bash
public-hoist-pattern[]=*@nextui-org/theme*
public-hoist-pattern[]=*@nextui-org/*
```
After modfiying the `.npmrc` file, you need to run `pnpm install` again to ensure that the dependencies are installed correctly.
+8 -7
View File
@@ -18,17 +18,17 @@
"@codesandbox/sandpack-react": "^2.6.4",
"@mapbox/rehype-prism": "^0.6.0",
"@nextui-org/aria-utils": "workspace:*",
"@nextui-org/badge": "workspace:*",
"@nextui-org/code": "workspace:*",
"@nextui-org/divider": "workspace:*",
"@nextui-org/kbd": "workspace:*",
"@nextui-org/react": "workspace:*",
"@nextui-org/shared-icons": "workspace:*",
"@nextui-org/shared-utils": "workspace:*",
"@nextui-org/theme": "workspace:*",
"@nextui-org/spacer": "workspace:*",
"@nextui-org/kbd": "workspace:*",
"@nextui-org/code": "workspace:*",
"@nextui-org/badge": "workspace:*",
"@nextui-org/skeleton": "workspace:*",
"@nextui-org/spacer": "workspace:*",
"@nextui-org/spinner": "workspace:*",
"@nextui-org/divider": "workspace:*",
"@nextui-org/theme": "workspace:*",
"@nextui-org/use-clipboard": "workspace:*",
"@nextui-org/use-infinite-scroll": "workspace:*",
"@nextui-org/use-is-mobile": "workspace:*",
@@ -84,7 +84,8 @@
"scroll-into-view-if-needed": "3.0.10",
"sharp": "^0.32.1",
"shelljs": "^0.8.4",
"tailwind-variants": "^0.1.13",
"swr": "^2.2.1",
"tailwind-variants": "^0.1.14",
"unified": "^9.2.2",
"unist-util-visit": "^4.1.2",
"zustand": "^4.3.8"
+4
View File
@@ -39,6 +39,10 @@
.cm-scroller::-webkit-scrollbar {
width: 0px
}
.sp-tabs {
padding-right: 110px;
}
.sp-tab-button {
@apply block !font-sans bg-transparent appearance-none;
+1 -1
View File
@@ -61,7 +61,7 @@ module.exports = {
highlighted: `${commonColors.purple[500]} 1px 0 0, ${commonColors.purple[500]} -1px 0 0`,
},
fontFamily: {
sans: ["DM Sans", ...defaultTheme.fontFamily.sans],
sans: ["var(--font-sans)", ...defaultTheme.fontFamily.sans],
serif: defaultTheme.fontFamily.serif,
mono: defaultTheme.fontFamily.mono,
},
+38
View File
@@ -0,0 +1,38 @@
import va from "@vercel/analytics";
import {__PROD__} from "./env";
export function getUniqueID(prefix: string) {
return `${prefix}-${new Date().getTime()}`;
}
export type TrackEvent = {
category: string;
action: string;
name?: string;
data?: any;
};
const getSessionId = () => {
let sessionId = getUniqueID("session");
// save session id in local storage if it doesn't exist
if (!localStorage.getItem("sessionId")) {
localStorage.setItem("sessionId", sessionId);
return sessionId;
} else {
return localStorage.getItem("sessionId") ?? sessionId;
}
};
export const trackEvent = (label: string, event: TrackEvent) => {
if (!__PROD__) return;
const sessionId = getSessionId();
va.track(label, {
...event,
sessionId,
});
};
+7 -2
View File
@@ -31,6 +31,7 @@
"lint:docs": "eslint -c .eslintrc.json ./apps/docs/**/*.{ts,tsx}",
"lint:fix": "eslint --fix -c .eslintrc.json ./packages/**/**/*.{ts,tsx}",
"lint:docs-fix": "eslint --fix -c .eslintrc.json ./apps/docs/**/*.{ts,tsx}",
"check:rap": "tsx scripts/check-rap-updates.ts",
"format:check": "prettier --check packages/**/**/src --cache",
"format:write": "prettier --write packages/**/**/src --cache",
"turbo:clean": "turbo clean && rimraf ./node_modules/.cache/turbo",
@@ -52,6 +53,7 @@
"devDependencies": {
"@babel/cli": "^7.14.5",
"@babel/core": "^7.16.7",
"tsx": "^3.8.2",
"@babel/plugin-proposal-object-rest-spread": "^7.15.6",
"@babel/plugin-transform-runtime": "^7.14.5",
"@babel/preset-env": "^7.14.5",
@@ -103,6 +105,7 @@
"eslint-plugin-react": "^7.23.2",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-unused-imports": "^2.0.0",
"npm-check-updates": "^16.10.18",
"intl-messageformat": "^10.1.0",
"execa": "^5.1.1",
"find-up": "^6.3.0",
@@ -141,6 +144,8 @@
}
},
"engines": {
"node": ">=16.x"
}
"node": ">=16.x",
"pnpm": ">=8.x"
},
"packageManager": "pnpm@8.7.0"
}
@@ -1,5 +1,91 @@
# @nextui-org/accordion
## 2.0.23
### Patch Changes
- [#1630](https://github.com/nextui-org/nextui/pull/1630) [`bc424948c`](https://github.com/nextui-org/nextui/commit/bc424948c70ddbc5b00a9d732dafcd5008c78b1f) Thanks [@jrgarciadev](https://github.com/jrgarciadev)! - Fix #1405 and #1608 accordion is no longer preventing spacebar key for Input/Textarea components
- [#1639](https://github.com/nextui-org/nextui/pull/1639) [`bb8ed5874`](https://github.com/nextui-org/nextui/commit/bb8ed58749fa50666a1c8a5fa005376fec185710) Thanks [@jrgarciadev](https://github.com/jrgarciadev)! - Fix #1402 controlled accordion
- Updated dependencies [[`bc424948c`](https://github.com/nextui-org/nextui/commit/bc424948c70ddbc5b00a9d732dafcd5008c78b1f), [`425a034bc`](https://github.com/nextui-org/nextui/commit/425a034bca4aa5a86cfe4bc47c084366a7ad7e87)]:
- @nextui-org/use-aria-accordion@2.0.1
- @nextui-org/theme@2.1.9
- @nextui-org/divider@2.0.20
- @nextui-org/system@2.0.10
- @nextui-org/react-utils@2.0.9
- @nextui-org/aria-utils@2.0.10
- @nextui-org/framer-transitions@2.0.10
## 2.0.22
### Patch Changes
- [#1600](https://github.com/nextui-org/nextui/pull/1600) [`b1b30b797`](https://github.com/nextui-org/nextui/commit/b1b30b7976f1d6652808fbf12ffde044f0861572) Thanks [@jrgarciadev](https://github.com/jrgarciadev)! - Fix npm deploy
- Updated dependencies [[`b1b30b797`](https://github.com/nextui-org/nextui/commit/b1b30b7976f1d6652808fbf12ffde044f0861572)]:
- @nextui-org/divider@2.0.19
- @nextui-org/system@2.0.9
- @nextui-org/theme@2.1.8
- @nextui-org/use-aria-accordion-item@2.0.5
- @nextui-org/aria-utils@2.0.9
- @nextui-org/framer-transitions@2.0.9
- @nextui-org/react-utils@2.0.8
- @nextui-org/shared-icons@2.0.4
- @nextui-org/shared-utils@2.0.3
## 2.0.21
### Patch Changes
- [#1589](https://github.com/nextui-org/nextui/pull/1589) [`1612532ee`](https://github.com/nextui-org/nextui/commit/1612532eeeabbc49165546b1a2e7aebf89e7a1c2) Thanks [@jrgarciadev](https://github.com/jrgarciadev)! - React aria packages upgraded
- Updated dependencies [[`a3be419cb`](https://github.com/nextui-org/nextui/commit/a3be419cb3c693ae8cace15f9a863274d759ddb1), [`5c30e0481`](https://github.com/nextui-org/nextui/commit/5c30e04811ef9f973d6b59107c909db72d9876b5), [`1612532ee`](https://github.com/nextui-org/nextui/commit/1612532eeeabbc49165546b1a2e7aebf89e7a1c2)]:
- @nextui-org/theme@2.1.7
- @nextui-org/use-aria-accordion-item@2.0.4
- @nextui-org/aria-utils@2.0.8
- @nextui-org/divider@2.0.18
- @nextui-org/system@2.0.8
- @nextui-org/framer-transitions@2.0.8
## 2.0.20
### Patch Changes
- Updated dependencies [[`7c8341035`](https://github.com/nextui-org/nextui/commit/7c8341035dbdd120cd78221b3cabab2e40e7478d)]:
- @nextui-org/theme@2.1.6
- @nextui-org/divider@2.0.17
## 2.0.19
### Patch Changes
- Updated dependencies [[`d61428d9e`](https://github.com/nextui-org/nextui/commit/d61428d9e6c1c0590593fb1f0136e226051b7e23), [`4db10a47e`](https://github.com/nextui-org/nextui/commit/4db10a47e96ad8315b5b96c2ff15574ac0fdeecc)]:
- @nextui-org/theme@2.1.5
- @nextui-org/divider@2.0.16
- @nextui-org/system@2.0.7
- @nextui-org/aria-utils@2.0.7
- @nextui-org/framer-transitions@2.0.7
## 2.0.18
### Patch Changes
- Updated dependencies [[`043b8420c`](https://github.com/nextui-org/nextui/commit/043b8420cfb659cbb6bb36404807ec3cc8ac8592), [`641bf0885`](https://github.com/nextui-org/nextui/commit/641bf0885b6af2d7f36f27d83716a441975a5ca5)]:
- @nextui-org/theme@2.1.4
- @nextui-org/system@2.0.6
- @nextui-org/divider@2.0.15
- @nextui-org/aria-utils@2.0.6
- @nextui-org/framer-transitions@2.0.6
## 2.0.17
### Patch Changes
- Updated dependencies [[`5702287e5`](https://github.com/nextui-org/nextui/commit/5702287e5622a8f0a0326c7cc0c200808c7971a8)]:
- @nextui-org/theme@2.1.3
- @nextui-org/divider@2.0.14
## 2.0.16
### Patch Changes
+11 -9
View File
@@ -1,6 +1,6 @@
{
"name": "@nextui-org/accordion",
"version": "2.0.16",
"version": "2.0.23",
"description": "Collapse display a list of high-level options that can expand/collapse to reveal more information.",
"keywords": [
"react",
@@ -49,20 +49,22 @@
"@nextui-org/shared-utils": "workspace:*",
"@nextui-org/react-utils": "workspace:*",
"@nextui-org/framer-transitions": "workspace:*",
"@nextui-org/use-aria-accordion-item": "workspace:*",
"@nextui-org/system": "workspace:*",
"@nextui-org/theme": "workspace:*",
"@nextui-org/divider": "workspace:*",
"@react-aria/accordion": "3.0.0-alpha.20",
"@react-aria/interactions": "^3.17.0",
"@react-aria/focus": "^3.14.0",
"@react-aria/utils": "^3.19.0",
"@react-stately/tree": "^3.7.1",
"@react-types/accordion": "3.0.0-alpha.15",
"@react-types/shared": "^3.19.0"
"@nextui-org/use-aria-accordion": "workspace:*",
"@react-aria/interactions": "^3.18.0",
"@react-aria/focus": "^3.14.1",
"@react-aria/utils": "^3.20.0",
"@react-stately/tree": "^3.7.2",
"@react-aria/button": "^3.8.2",
"@react-types/accordion": "3.0.0-alpha.16",
"@react-types/shared": "^3.20.0"
},
"devDependencies": {
"@nextui-org/button": "workspace:*",
"@nextui-org/avatar": "workspace:*",
"@nextui-org/input": "workspace:*",
"@nextui-org/test-utils": "workspace:*",
"framer-motion": "^10.15.1",
"clean-package": "2.2.0",
@@ -4,7 +4,7 @@ import {accordionItem} from "@nextui-org/theme";
import {clsx, callAllHandlers, dataAttr} from "@nextui-org/shared-utils";
import {ReactRef, useDOMRef, filterDOMProps} from "@nextui-org/react-utils";
import {NodeWithProps} from "@nextui-org/aria-utils";
import {useAriaAccordionItem} from "@nextui-org/use-aria-accordion-item";
import {useReactAriaAccordionItem} from "@nextui-org/use-aria-accordion";
import {useCallback, useMemo} from "react";
import {chain, mergeProps} from "@react-aria/utils";
import {useHover, usePress} from "@react-aria/interactions";
@@ -75,7 +75,7 @@ export function useAccordionItem<T extends object = {}>(props: UseAccordionItemP
const isDisabled = state.disabledKeys.has(item.key) || isDisabledProp;
const isOpen = state.selectionManager.isSelected(item.key);
const {buttonProps: buttonCompleteProps, regionProps} = useAriaAccordionItem(
const {buttonProps: buttonCompleteProps, regionProps} = useReactAriaAccordionItem(
{item, isDisabled},
{...state, focusedKey: focusedKey},
domRef,
@@ -6,12 +6,12 @@ import type {AccordionGroupVariantProps} from "@nextui-org/theme";
import {ReactRef, filterDOMProps} from "@nextui-org/react-utils";
import React, {Key, useCallback} from "react";
import {TreeState, useTreeState} from "@react-stately/tree";
import {useAccordion as useReactAriaAccordion} from "@react-aria/accordion";
import {mergeProps} from "@react-aria/utils";
import {accordion} from "@nextui-org/theme";
import {useDOMRef} from "@nextui-org/react-utils";
import {useMemo, useState} from "react";
import {DividerProps} from "@nextui-org/divider";
import {useReactAriaAccordion} from "@nextui-org/use-aria-accordion";
import {AccordionItemProps} from "./accordion-item";
@@ -198,6 +198,7 @@ export function useAccordion<T extends object>(props: UseAccordionProps<T>) {
isCompact,
isDisabled,
hideIndicator,
selectedKeys,
disableAnimation,
keepContentMounted,
state?.expandedKeys.values,
@@ -2,7 +2,7 @@ import type {Selection} from "@react-types/shared";
import React from "react";
import {Meta} from "@storybook/react";
import {accordionItem} from "@nextui-org/theme";
import {accordionItem, button} from "@nextui-org/theme";
import {
AnchorIcon,
MoonIcon,
@@ -13,6 +13,8 @@ import {
InvalidCardIcon,
} from "@nextui-org/shared-icons";
import {Avatar} from "@nextui-org/avatar";
import {Input} from "@nextui-org/input";
import {Button} from "@nextui-org/button";
import {Accordion, AccordionProps, AccordionItem} from "../src";
import {AccordionItemProps} from "../src";
@@ -230,17 +232,43 @@ const ControlledTemplate = (args: AccordionProps) => {
console.log(selectedKeys);
return (
<Accordion {...args} selectedKeys={selectedKeys} onSelectionChange={setSelectedKeys}>
<AccordionItem key="1" aria-label="Accordion 1" title="Accordion 1">
{defaultContent}
</AccordionItem>
<AccordionItem key="2" aria-label="Accordion 2" title="Accordion 2">
{defaultContent}
</AccordionItem>
<AccordionItem key="3" aria-label="Accordion 3" title="Accordion 3">
{defaultContent}
</AccordionItem>
</Accordion>
<div className="flex flex-col gap-4">
<Accordion {...args} selectedKeys={selectedKeys}>
<AccordionItem key="1" aria-label="Accordion 1" title="Accordion 1">
{defaultContent}
</AccordionItem>
<AccordionItem key="2" aria-label="Accordion 2" title="Accordion 2">
{defaultContent}
</AccordionItem>
<AccordionItem key="3" aria-label="Accordion 3" title="Accordion 3">
{defaultContent}
</AccordionItem>
</Accordion>
<div className="flex gap-2">
<Button
onPress={() => {
setSelectedKeys(new Set(["1"]));
}}
>
Open 1
</Button>
<Button
onPress={() => {
setSelectedKeys(new Set(["2"]));
}}
>
Open 2
</Button>
<Button
onPress={() => {
setSelectedKeys(new Set(["3"]));
}}
>
Open 3
</Button>
</div>
</div>
);
};
@@ -313,6 +341,42 @@ const CustomWithClassNamesTemplate = (args: AccordionProps) => {
);
};
const WithFormTemplate = (args: AccordionProps) => {
const form = (
<form className="flex flex-col gap-4">
<Input
isRequired
label="Email"
placeholder="Enter your email"
type="email"
onValueChange={(value) =>
// eslint-disable-next-line no-console
console.log(value)
}
/>
<Input isRequired label="Password" placeholder="Enter your password" type="password" />
<div className="flex gap-2 justify-end">
<button className={button({color: "primary"})}>Login</button>
</div>
</form>
);
return (
<Accordion {...args}>
<AccordionItem key="1" aria-label="Accordion 1" title="Accordion 1">
{form}
</AccordionItem>
<AccordionItem key="2" aria-label="Accordion 2" title="Accordion 2">
{defaultContent}
</AccordionItem>
<AccordionItem key="3" aria-label="Accordion 3" title="Accordion 3">
{defaultContent}
</AccordionItem>
</Accordion>
);
};
export const Default = {
render: Template,
@@ -390,6 +454,14 @@ export const Variants = {
},
};
export const WithForm = {
render: WithFormTemplate,
args: {
...defaultProps,
},
};
export const CustomMotion = {
render: Template,
+62
View File
@@ -1,5 +1,67 @@
# @nextui-org/avatar
## 2.0.21
### Patch Changes
- Updated dependencies [[`425a034bc`](https://github.com/nextui-org/nextui/commit/425a034bca4aa5a86cfe4bc47c084366a7ad7e87)]:
- @nextui-org/theme@2.1.9
- @nextui-org/system@2.0.10
- @nextui-org/react-utils@2.0.9
## 2.0.20
### Patch Changes
- [#1600](https://github.com/nextui-org/nextui/pull/1600) [`b1b30b797`](https://github.com/nextui-org/nextui/commit/b1b30b7976f1d6652808fbf12ffde044f0861572) Thanks [@jrgarciadev](https://github.com/jrgarciadev)! - Fix npm deploy
- Updated dependencies [[`b1b30b797`](https://github.com/nextui-org/nextui/commit/b1b30b7976f1d6652808fbf12ffde044f0861572)]:
- @nextui-org/system@2.0.9
- @nextui-org/theme@2.1.8
- @nextui-org/use-image@2.0.3
- @nextui-org/react-utils@2.0.8
- @nextui-org/shared-utils@2.0.3
## 2.0.19
### Patch Changes
- [#1589](https://github.com/nextui-org/nextui/pull/1589) [`1612532ee`](https://github.com/nextui-org/nextui/commit/1612532eeeabbc49165546b1a2e7aebf89e7a1c2) Thanks [@jrgarciadev](https://github.com/jrgarciadev)! - React aria packages upgraded
- Updated dependencies [[`a3be419cb`](https://github.com/nextui-org/nextui/commit/a3be419cb3c693ae8cace15f9a863274d759ddb1), [`5c30e0481`](https://github.com/nextui-org/nextui/commit/5c30e04811ef9f973d6b59107c909db72d9876b5), [`1612532ee`](https://github.com/nextui-org/nextui/commit/1612532eeeabbc49165546b1a2e7aebf89e7a1c2)]:
- @nextui-org/theme@2.1.7
- @nextui-org/system@2.0.8
## 2.0.18
### Patch Changes
- Updated dependencies [[`7c8341035`](https://github.com/nextui-org/nextui/commit/7c8341035dbdd120cd78221b3cabab2e40e7478d)]:
- @nextui-org/theme@2.1.6
## 2.0.17
### Patch Changes
- Updated dependencies [[`d61428d9e`](https://github.com/nextui-org/nextui/commit/d61428d9e6c1c0590593fb1f0136e226051b7e23), [`4db10a47e`](https://github.com/nextui-org/nextui/commit/4db10a47e96ad8315b5b96c2ff15574ac0fdeecc)]:
- @nextui-org/theme@2.1.5
- @nextui-org/system@2.0.7
## 2.0.16
### Patch Changes
- Updated dependencies [[`043b8420c`](https://github.com/nextui-org/nextui/commit/043b8420cfb659cbb6bb36404807ec3cc8ac8592), [`641bf0885`](https://github.com/nextui-org/nextui/commit/641bf0885b6af2d7f36f27d83716a441975a5ca5)]:
- @nextui-org/theme@2.1.4
- @nextui-org/system@2.0.6
## 2.0.15
### Patch Changes
- Updated dependencies [[`5702287e5`](https://github.com/nextui-org/nextui/commit/5702287e5622a8f0a0326c7cc0c200808c7971a8)]:
- @nextui-org/theme@2.1.3
## 2.0.14
### Patch Changes
+4 -4
View File
@@ -1,6 +1,6 @@
{
"name": "@nextui-org/avatar",
"version": "2.0.14",
"version": "2.0.21",
"description": "The Avatar component is used to represent a user, and displays the profile picture, initials or fallback icon.",
"keywords": [
"avatar"
@@ -42,9 +42,9 @@
"@nextui-org/shared-utils": "workspace:*",
"@nextui-org/react-utils": "workspace:*",
"@nextui-org/use-image": "workspace:*",
"@react-aria/interactions": "^3.17.0",
"@react-aria/focus": "^3.14.0",
"@react-aria/utils": "^3.19.0"
"@react-aria/interactions": "^3.18.0",
"@react-aria/focus": "^3.14.1",
"@react-aria/utils": "^3.20.0"
},
"devDependencies": {
"@nextui-org/shared-icons": "workspace:*",
+61
View File
@@ -1,5 +1,66 @@
# @nextui-org/badge
## 2.0.19
### Patch Changes
- Updated dependencies [[`f6531c5f6`](https://github.com/nextui-org/nextui/commit/f6531c5f603d7f6308a597962ec6fab62c92fa93), [`425a034bc`](https://github.com/nextui-org/nextui/commit/425a034bca4aa5a86cfe4bc47c084366a7ad7e87)]:
- @nextui-org/system-rsc@2.0.6
- @nextui-org/theme@2.1.9
- @nextui-org/react-utils@2.0.9
## 2.0.18
### Patch Changes
- [#1600](https://github.com/nextui-org/nextui/pull/1600) [`b1b30b797`](https://github.com/nextui-org/nextui/commit/b1b30b7976f1d6652808fbf12ffde044f0861572) Thanks [@jrgarciadev](https://github.com/jrgarciadev)! - Fix npm deploy
- Updated dependencies [[`b1b30b797`](https://github.com/nextui-org/nextui/commit/b1b30b7976f1d6652808fbf12ffde044f0861572)]:
- @nextui-org/system-rsc@2.0.5
- @nextui-org/theme@2.1.8
- @nextui-org/react-utils@2.0.8
- @nextui-org/shared-utils@2.0.3
## 2.0.17
### Patch Changes
- Updated dependencies [[`a3be419cb`](https://github.com/nextui-org/nextui/commit/a3be419cb3c693ae8cace15f9a863274d759ddb1), [`5c30e0481`](https://github.com/nextui-org/nextui/commit/5c30e04811ef9f973d6b59107c909db72d9876b5)]:
- @nextui-org/theme@2.1.7
- @nextui-org/system-rsc@2.0.4
## 2.0.16
### Patch Changes
- Updated dependencies [[`7c8341035`](https://github.com/nextui-org/nextui/commit/7c8341035dbdd120cd78221b3cabab2e40e7478d)]:
- @nextui-org/theme@2.1.6
- @nextui-org/system-rsc@2.0.4
## 2.0.15
### Patch Changes
- Updated dependencies [[`d61428d9e`](https://github.com/nextui-org/nextui/commit/d61428d9e6c1c0590593fb1f0136e226051b7e23), [`4db10a47e`](https://github.com/nextui-org/nextui/commit/4db10a47e96ad8315b5b96c2ff15574ac0fdeecc)]:
- @nextui-org/system-rsc@2.0.4
- @nextui-org/theme@2.1.5
## 2.0.14
### Patch Changes
- Updated dependencies [[`043b8420c`](https://github.com/nextui-org/nextui/commit/043b8420cfb659cbb6bb36404807ec3cc8ac8592)]:
- @nextui-org/theme@2.1.4
- @nextui-org/system-rsc@2.0.3
## 2.0.13
### Patch Changes
- Updated dependencies [[`5702287e5`](https://github.com/nextui-org/nextui/commit/5702287e5622a8f0a0326c7cc0c200808c7971a8)]:
- @nextui-org/theme@2.1.3
- @nextui-org/system-rsc@2.0.3
## 2.0.12
### Patch Changes
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "@nextui-org/badge",
"version": "2.0.12",
"version": "2.0.19",
"description": "Badges are used as a small numerical value or status descriptor for UI elements.",
"keywords": [
"badge"
+79
View File
@@ -1,5 +1,84 @@
# @nextui-org/button
## 2.0.21
### Patch Changes
- [#1635](https://github.com/nextui-org/nextui/pull/1635) [`ceddd0d1d`](https://github.com/nextui-org/nextui/commit/ceddd0d1d941a669bab78ef7439a29531cff99a2) Thanks [@li-jia-nan](https://github.com/li-jia-nan)! - refactor: optimize the time of ripple destroy
- Updated dependencies [[`ceddd0d1d`](https://github.com/nextui-org/nextui/commit/ceddd0d1d941a669bab78ef7439a29531cff99a2), [`425a034bc`](https://github.com/nextui-org/nextui/commit/425a034bca4aa5a86cfe4bc47c084366a7ad7e87)]:
- @nextui-org/ripple@2.0.21
- @nextui-org/theme@2.1.9
- @nextui-org/spinner@2.0.19
- @nextui-org/system@2.0.10
- @nextui-org/react-utils@2.0.9
## 2.0.20
### Patch Changes
- [#1600](https://github.com/nextui-org/nextui/pull/1600) [`b1b30b797`](https://github.com/nextui-org/nextui/commit/b1b30b7976f1d6652808fbf12ffde044f0861572) Thanks [@jrgarciadev](https://github.com/jrgarciadev)! - Fix npm deploy
- Updated dependencies [[`8b3998909`](https://github.com/nextui-org/nextui/commit/8b39989090d9cd577e886edde01b081d37e65bb7), [`b1b30b797`](https://github.com/nextui-org/nextui/commit/b1b30b7976f1d6652808fbf12ffde044f0861572)]:
- @nextui-org/ripple@2.0.20
- @nextui-org/spinner@2.0.18
- @nextui-org/system@2.0.9
- @nextui-org/theme@2.1.8
- @nextui-org/use-aria-button@2.0.5
- @nextui-org/react-utils@2.0.8
- @nextui-org/shared-utils@2.0.3
## 2.0.19
### Patch Changes
- [#1589](https://github.com/nextui-org/nextui/pull/1589) [`1612532ee`](https://github.com/nextui-org/nextui/commit/1612532eeeabbc49165546b1a2e7aebf89e7a1c2) Thanks [@jrgarciadev](https://github.com/jrgarciadev)! - React aria packages upgraded
- Updated dependencies [[`a3be419cb`](https://github.com/nextui-org/nextui/commit/a3be419cb3c693ae8cace15f9a863274d759ddb1), [`5c30e0481`](https://github.com/nextui-org/nextui/commit/5c30e04811ef9f973d6b59107c909db72d9876b5), [`1612532ee`](https://github.com/nextui-org/nextui/commit/1612532eeeabbc49165546b1a2e7aebf89e7a1c2)]:
- @nextui-org/theme@2.1.7
- @nextui-org/use-aria-button@2.0.4
- @nextui-org/system@2.0.8
- @nextui-org/ripple@2.0.19
- @nextui-org/spinner@2.0.17
## 2.0.18
### Patch Changes
- Updated dependencies [[`7c8341035`](https://github.com/nextui-org/nextui/commit/7c8341035dbdd120cd78221b3cabab2e40e7478d)]:
- @nextui-org/theme@2.1.6
- @nextui-org/ripple@2.0.18
- @nextui-org/spinner@2.0.16
## 2.0.17
### Patch Changes
- Updated dependencies [[`d61428d9e`](https://github.com/nextui-org/nextui/commit/d61428d9e6c1c0590593fb1f0136e226051b7e23), [`4db10a47e`](https://github.com/nextui-org/nextui/commit/4db10a47e96ad8315b5b96c2ff15574ac0fdeecc)]:
- @nextui-org/theme@2.1.5
- @nextui-org/spinner@2.0.15
- @nextui-org/system@2.0.7
- @nextui-org/ripple@2.0.17
## 2.0.16
### Patch Changes
- Updated dependencies [[`043b8420c`](https://github.com/nextui-org/nextui/commit/043b8420cfb659cbb6bb36404807ec3cc8ac8592), [`641bf0885`](https://github.com/nextui-org/nextui/commit/641bf0885b6af2d7f36f27d83716a441975a5ca5)]:
- @nextui-org/theme@2.1.4
- @nextui-org/system@2.0.6
- @nextui-org/ripple@2.0.16
- @nextui-org/spinner@2.0.14
## 2.0.15
### Patch Changes
- Updated dependencies [[`5702287e5`](https://github.com/nextui-org/nextui/commit/5702287e5622a8f0a0326c7cc0c200808c7971a8)]:
- @nextui-org/theme@2.1.3
- @nextui-org/ripple@2.0.15
- @nextui-org/spinner@2.0.13
## 2.0.14
### Patch Changes
+7 -7
View File
@@ -1,6 +1,6 @@
{
"name": "@nextui-org/button",
"version": "2.0.14",
"version": "2.0.21",
"description": "Buttons allow users to perform actions and choose with a single tap.",
"keywords": [
"button"
@@ -44,12 +44,12 @@
"@nextui-org/theme": "workspace:*",
"@nextui-org/ripple": "workspace:*",
"@nextui-org/spinner": "workspace:*",
"@react-aria/button": "^3.8.1",
"@react-aria/interactions": "^3.17.0",
"@react-aria/utils": "^3.19.0",
"@react-aria/focus": "^3.14.0",
"@react-types/shared": "^3.19.0",
"@react-types/button": "^3.7.4"
"@react-aria/button": "^3.8.2",
"@react-aria/interactions": "^3.18.0",
"@react-aria/utils": "^3.20.0",
"@react-aria/focus": "^3.14.1",
"@react-types/shared": "^3.20.0",
"@react-types/button": "^3.8.0"
},
"devDependencies": {
"@nextui-org/shared-icons": "workspace:*",
+3 -6
View File
@@ -12,7 +12,6 @@ const Button = forwardRef<"button", ButtonProps>((props, ref) => {
domRef,
children,
styles,
ripples,
spinnerSize,
spinner = <Spinner color="current" size={spinnerSize} />,
spinnerPlacement,
@@ -21,10 +20,8 @@ const Button = forwardRef<"button", ButtonProps>((props, ref) => {
isLoading,
disableRipple,
getButtonProps,
} = useButton({
...props,
ref,
});
getRippleProps,
} = useButton({...props, ref});
return (
<Component ref={domRef} className={styles} {...getButtonProps()}>
@@ -33,7 +30,7 @@ const Button = forwardRef<"button", ButtonProps>((props, ref) => {
{children}
{isLoading && spinnerPlacement === "end" && spinner}
{endContent}
{!disableRipple && <Ripple ripples={ripples} />}
{!disableRipple && <Ripple {...getRippleProps()} />}
</Component>
);
});
+8 -2
View File
@@ -2,6 +2,7 @@ import type {ButtonVariantProps} from "@nextui-org/theme";
import type {AriaButtonProps} from "@nextui-org/use-aria-button";
import type {HTMLNextUIProps, PropGetter} from "@nextui-org/system";
import type {ReactNode} from "react";
import type {RippleProps} from "@nextui-org/ripple";
import {dataAttr} from "@nextui-org/shared-utils";
import {ReactRef} from "@nextui-org/react-utils";
@@ -130,7 +131,7 @@ export function useButton(props: UseButtonProps) {
],
);
const {onClick: onRippleClickHandler, ripples} = useRipple();
const {onClick: onRippleClickHandler, onClear: onClearRipple, ripples} = useRipple();
const handleClick = useCallback(
(e: React.MouseEvent<HTMLButtonElement>) => {
@@ -209,11 +210,15 @@ export function useButton(props: UseButtonProps) {
return buttonSpinnerSizeMap[size];
}, [size]);
const getRippleProps = useCallback<() => RippleProps>(
() => ({ripples, onClear: onClearRipple}),
[ripples, onClearRipple],
);
return {
Component,
children,
domRef,
ripples,
spinner,
styles,
startContent,
@@ -223,6 +228,7 @@ export function useButton(props: UseButtonProps) {
spinnerSize,
disableRipple,
getButtonProps,
getRippleProps,
};
}
+74
View File
@@ -1,5 +1,79 @@
# @nextui-org/card
## 2.0.21
### Patch Changes
- [#1635](https://github.com/nextui-org/nextui/pull/1635) [`ceddd0d1d`](https://github.com/nextui-org/nextui/commit/ceddd0d1d941a669bab78ef7439a29531cff99a2) Thanks [@li-jia-nan](https://github.com/li-jia-nan)! - refactor: optimize the time of ripple destroy
- [#1611](https://github.com/nextui-org/nextui/pull/1611) [`05c966e8a`](https://github.com/nextui-org/nextui/commit/05c966e8a46accff1fa271d50a3161f10d1e203d) Thanks [@bobbychan](https://github.com/bobbychan)! - fix: corrected footerStyles in card footer
- Updated dependencies [[`ceddd0d1d`](https://github.com/nextui-org/nextui/commit/ceddd0d1d941a669bab78ef7439a29531cff99a2), [`425a034bc`](https://github.com/nextui-org/nextui/commit/425a034bca4aa5a86cfe4bc47c084366a7ad7e87)]:
- @nextui-org/ripple@2.0.21
- @nextui-org/theme@2.1.9
- @nextui-org/system@2.0.10
- @nextui-org/react-utils@2.0.9
## 2.0.20
### Patch Changes
- [#1600](https://github.com/nextui-org/nextui/pull/1600) [`b1b30b797`](https://github.com/nextui-org/nextui/commit/b1b30b7976f1d6652808fbf12ffde044f0861572) Thanks [@jrgarciadev](https://github.com/jrgarciadev)! - Fix npm deploy
- Updated dependencies [[`8b3998909`](https://github.com/nextui-org/nextui/commit/8b39989090d9cd577e886edde01b081d37e65bb7), [`b1b30b797`](https://github.com/nextui-org/nextui/commit/b1b30b7976f1d6652808fbf12ffde044f0861572)]:
- @nextui-org/ripple@2.0.20
- @nextui-org/system@2.0.9
- @nextui-org/theme@2.1.8
- @nextui-org/use-aria-button@2.0.5
- @nextui-org/react-utils@2.0.8
- @nextui-org/shared-utils@2.0.3
## 2.0.19
### Patch Changes
- [#1589](https://github.com/nextui-org/nextui/pull/1589) [`1612532ee`](https://github.com/nextui-org/nextui/commit/1612532eeeabbc49165546b1a2e7aebf89e7a1c2) Thanks [@jrgarciadev](https://github.com/jrgarciadev)! - React aria packages upgraded
- Updated dependencies [[`a3be419cb`](https://github.com/nextui-org/nextui/commit/a3be419cb3c693ae8cace15f9a863274d759ddb1), [`5c30e0481`](https://github.com/nextui-org/nextui/commit/5c30e04811ef9f973d6b59107c909db72d9876b5), [`1612532ee`](https://github.com/nextui-org/nextui/commit/1612532eeeabbc49165546b1a2e7aebf89e7a1c2)]:
- @nextui-org/theme@2.1.7
- @nextui-org/use-aria-button@2.0.4
- @nextui-org/system@2.0.8
- @nextui-org/ripple@2.0.19
## 2.0.18
### Patch Changes
- Updated dependencies [[`7c8341035`](https://github.com/nextui-org/nextui/commit/7c8341035dbdd120cd78221b3cabab2e40e7478d)]:
- @nextui-org/theme@2.1.6
- @nextui-org/ripple@2.0.18
## 2.0.17
### Patch Changes
- Updated dependencies [[`d61428d9e`](https://github.com/nextui-org/nextui/commit/d61428d9e6c1c0590593fb1f0136e226051b7e23), [`4db10a47e`](https://github.com/nextui-org/nextui/commit/4db10a47e96ad8315b5b96c2ff15574ac0fdeecc)]:
- @nextui-org/theme@2.1.5
- @nextui-org/system@2.0.7
- @nextui-org/ripple@2.0.17
## 2.0.16
### Patch Changes
- Updated dependencies [[`043b8420c`](https://github.com/nextui-org/nextui/commit/043b8420cfb659cbb6bb36404807ec3cc8ac8592), [`641bf0885`](https://github.com/nextui-org/nextui/commit/641bf0885b6af2d7f36f27d83716a441975a5ca5)]:
- @nextui-org/theme@2.1.4
- @nextui-org/system@2.0.6
- @nextui-org/ripple@2.0.16
## 2.0.15
### Patch Changes
- Updated dependencies [[`5702287e5`](https://github.com/nextui-org/nextui/commit/5702287e5622a8f0a0326c7cc0c200808c7971a8)]:
- @nextui-org/theme@2.1.3
- @nextui-org/ripple@2.0.15
## 2.0.14
### Patch Changes

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