Compare commits

...

184 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
github-actions[bot] e3dabac9f5 ci(changesets): version packages (#1461) 2023-08-21 12:28:39 -03:00
Junior Garcia 4e94c11528 fix(dropdown): popover and dropdown fixes (#1458) 2023-08-21 12:07:28 -03:00
João Vitor a17b6c7502 docs(tooltip): decrease zIndex so it doesn't overlap other elements (#1454)
* fix(navbar): z-index issue on desktop

* Revert "fix(navbar): z-index issue on desktop"

This reverts commit 227b79e5c6493084ee31a62fd5b13079c8a4a2e4.

* docs(tooltip): decrease the zIndex
2023-08-21 14:29:03 +00:00
github-actions[bot] bd72301b01 ci(changesets): version packages (#1456)
Co-authored-by: Junior Garcia <jrgarciadev@gmail.com>
2023-08-21 13:40:21 +00:00
Junior Garcia cc839cdd1f Fix/select label closes the popover (#1455)
* fix(select): label pointer events removed

* chore(select): changeset
2023-08-21 13:29:49 +00:00
Yannik Hewlik c9e5c2ef7f docs: correct default value for popover radius (#1451)
* Update popover.mdx

* Update apps/docs/content/docs/components/popover.mdx

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

---------

Co-authored-by: Jakob Guddas <github@jguddas.de>
2023-08-21 13:22:50 +00:00
Junior Garcia e8f5264cf8 fix(blog): v2.1.0 date 2023-08-21 10:11:10 -03:00
Junior Garcia df7f773f3d fix(blog): async typo 2023-08-21 09:49:59 -03:00
github-actions[bot] af925d56d1 ci(changesets): version packages (#1453)
Co-authored-by: Junior Garcia <jrgarciadev@gmail.com>
2023-08-21 12:41:43 +00:00
Junior Garcia baec55029d Feat/select component (#1313)
* chore(root): menu and select components in progress

* chore(root): merged with main

* feat(menu): stories created

* feat(dropdown): menu migrated to menu component

* feat(select): base implementation in progress

* feat(select): listbox implemented

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

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

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

* feat(select): scroll shadow integrated

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

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

* chore(listbox): overflow hidden removed

* feat(select): variants and styles completed

* chore(select): description story added

* feat(select): more stories added

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

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

* chore(select): scroll behavior changed to nearest

* feat(select): custom item story added

* fix(select): autoscroll fixed

* feat(select): multi select support added

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

* chore(modal): useImperativeHandle removed

* feat(select): render value story improved

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

* feat(docs): select documentation in progress

* fix: select aria label (#1425)

* feat(docs): more examples added

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

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

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

* fix(popover): dialog role removed

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

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

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

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

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

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

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

* chore(select): focus scope removed

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

* feat(select): blog post added

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

* chore(root): changeset added

---------

Co-authored-by: Jakob Guddas <github@jguddas.de>
2023-08-21 12:28:01 +00:00
Gaurav Pandey ea2868e58e updated doc handling hydration mismatch error (#1449)
Co-authored-by: btsb78 <gaurav.pandey@kratikal.com>
2023-08-20 20:42:01 +00:00
Junior Garcia 691f380dff fix(docs): client directive added to next app examples on dark mode page 2023-08-20 11:45:23 -03:00
Junior Garcia ac8afec964 fix(modal): docs issues 2023-08-19 18:33:51 -03:00
Loïc GREFFIER 5fe5521a7c fix(docs): replaced ghost by dot in chip variants (#1436) 2023-08-18 20:49:36 -03:00
github-actions[bot] 15403bc67e ci(changesets): version packages (#1435) 2023-08-18 18:16:55 -03:00
Junior Garcia c186f37c98 fix(accordion): hide indicator prop in accordion item (#1433) 2023-08-18 20:59:49 +00:00
github-actions[bot] 1bc2a50e2c ci(changesets): version packages (#1434)
Co-authored-by: Junior Garcia <jrgarciadev@gmail.com>
2023-08-18 20:57:44 +00:00
Junior Garcia 453f792a7a fix(link): warning onClick removed (#1432) 2023-08-18 20:50:13 +00:00
Junior Garcia 3f6fd48eee fix(docs): modal mail icon imports (#1421) 2023-08-17 12:48:06 +00:00
github-actions[bot] d7c6c79f38 ci(changesets): version packages (#1414)
Co-authored-by: Junior Garcia <jrgarciadev@gmail.com>
2023-08-15 20:35:07 -03:00
Junior Garcia f068552774 refactor(tooltip): style prop merged with the passed one (#1413) 2023-08-15 20:28:23 -03:00
Cesar Leonardo Insuasty Moreno 6d7372ede1 fix: Import CardFooter in the card component doc (#1412) 2023-08-15 18:52:16 -03:00
github-actions[bot] 1487219a1c ci(changesets): version packages (#1411)
Co-authored-by: Junior Garcia <jrgarciadev@gmail.com>
2023-08-15 18:30:06 -03:00
Junior Garcia 6e7e834c2d fix(popover): allow pass custom z-index (#1410) 2023-08-15 18:22:08 -03:00
Victor Bejas 80a8f7e94c fix/add import CardFooter at Card component composition (#1408) 2023-08-15 16:19:39 -03:00
github-actions[bot] fae7467b64 ci(changesets): version packages (#1407)
Co-authored-by: Junior Garcia <jrgarciadev@gmail.com>
2023-08-15 14:41:45 -03:00
Tommaso De Rossi 4e7789c1f6 fix(input): don't always use controlled mode (#1406)
* fix(input): don't always use controlled mode

* fix(input): don't pass value to useTextField

* test(input): added test for mutating input via ref

* chore(input): changelog
2023-08-15 14:24:55 -03:00
Junior Garcia 6694b934e6 fix(docs): accordion item isOpen prop removed 2023-08-14 10:06:07 -03:00
github-actions[bot] 4d341081e3 ci(changesets): version packages (#1393)
Co-authored-by: Junior Garcia <jrgarciadev@gmail.com>
2023-08-13 22:07:15 -03:00
github-actions[bot] df562449fb ci(changesets): version packages (#1392)
Co-authored-by: Junior Garcia <jrgarciadev@gmail.com>
2023-08-13 21:50:12 -03:00
Junior Garcia 4063362699 fix(popover): use layout effect on the server warning 2023-08-13 21:42:57 -03:00
Junior Garcia 94d65df533 fix(root): filter dom props function fixed, slot prop added (#1391)
* fix(root): filter dom props function fixed, slot prop added

* chore(root): changeset added
2023-08-13 21:41:42 -03:00
Junior Garcia 8f66c6b564 fix(docs): individual installation highlights 2023-08-13 15:32:22 -03:00
Junior Garcia 4a19a3c906 Merge branch 'main' of github.com:nextui-org/nextui 2023-08-13 15:25:03 -03:00
Junior Garcia 0be398ade9 fix(docs): individual components styles 2023-08-13 15:24:48 -03:00
github-actions[bot] 50d23e5378 ci(changesets): version packages (#1385)
Co-authored-by: Junior Garcia <jrgarciadev@gmail.com>
2023-08-13 00:03:39 -03:00
Junior Garcia d0341020e6 fix(docs): navbar with search input example (#1384) 2023-08-12 23:53:22 -03:00
github-actions[bot] 4170ecdc76 ci(changesets): version packages (#1383)
Co-authored-by: Junior Garcia <jrgarciadev@gmail.com>
2023-08-12 23:33:09 -03:00
Junior Garcia e2b0076b53 chore(root): version field moved to bug report template 2023-08-12 23:27:55 -03:00
Junior Garcia e2b0497b07 fix(root): checkbox and radio onChange event types fixed (#1381) 2023-08-12 23:26:07 -03:00
Junior Garcia df3b309542 Merge branch 'main' of github.com:nextui-org/nextui 2023-08-12 22:56:11 -03:00
Junior Garcia 6c35a502fe chore(root): feature request template updated, version added 2023-08-12 22:55:37 -03:00
github-actions[bot] a629f8c088 ci(changesets): version packages (#1378)
Co-authored-by: Junior Garcia <jrgarciadev@gmail.com>
2023-08-12 11:40:59 -03:00
Junior Garcia fd4e01dcfa fix(dropdown): spread key warning (#1377) 2023-08-12 11:33:13 -03:00
github-actions[bot] e9c08abd55 ci(changesets): version packages (#1374)
Co-authored-by: Junior Garcia <jrgarciadev@gmail.com>
2023-08-11 21:10:32 -03:00
Junior Garcia 3e263aa882 fix(table): layout property (#1372) 2023-08-11 20:58:57 -03:00
Junior Garcia 9add9aba97 chore(docs): current version added to navbar dropdown (#1373) 2023-08-11 20:48:00 -03:00
Tudor Comparan 0311ae43f1 individual instalation, tailwind setup, require correct nextui package (#1371) 2023-08-11 16:07:23 -03:00
github-actions[bot] 79c5fb9a94 ci(changesets): version packages (#1370)
Co-authored-by: Junior Garcia <jrgarciadev@gmail.com>
2023-08-11 15:02:25 -03:00
Junior Garcia abe1ba58de Fix/input undefined value (#1369)
* fix(input): undefined value uncontrolled

* fix(input): undefined value uncontrolled
2023-08-11 14:54:29 -03:00
Jakob Guddas e6c3747153 chore: added custom title for release PRs (#1368) 2023-08-11 14:12:11 -03:00
github-actions[bot] d15b16ecab ci(changesets): version packages (#1366)
Co-authored-by: Junior Garcia <jrgarciadev@gmail.com>
2023-08-11 12:20:17 -03:00
Junior Garcia fe03c42fa1 fix(tooltip): filter dom props function fixed (#1365)
* fix(tooltip): filter dom props function fixed

* fix(root): react types pkg updated
2023-08-11 12:06:47 -03:00
navedqb 25a918d146 Fixed incorrect import in card component (#1364) 2023-08-11 09:04:17 -03:00
github-actions[bot] 87918ac5b4 ci(changesets): version packages (#1360)
Co-authored-by: Junior Garcia <jrgarciadev@gmail.com>
2023-08-10 23:47:40 -03:00
Junior Garcia a30cec4810 chore(root): react-aria packages upgraded (#1359) 2023-08-10 23:25:24 -03:00
github-actions[bot] 1b0653c97a ci(changesets): version packages (#1353)
Co-authored-by: Junior Garcia <jrgarciadev@gmail.com>
2023-08-10 17:35:26 -03:00
Junior Garcia 710395f3a2 Refactor/remove needless exports system (#1350)
* fix(root): filter dom props func, accordion keep content mounted, navbaropen menu callbacks

* refactor(system): needeless exports removed

* refactor(system): needeless exports removed
2023-08-10 17:27:53 -03:00
github-actions[bot] e7e58e854a ci(changesets): version packages (#1352)
Co-authored-by: Junior Garcia <jrgarciadev@gmail.com>
2023-08-10 17:19:51 -03:00
Junior Garcia d13a14facc Fix/events and props issues (#1351)
* fix(root): filter dom props func, accordion keep content mounted, navbaropen menu callbacks

* fix(docs): examples keys
2023-08-10 17:10:53 -03:00
Junior Garcia cef7235c4b fix(docs): compound variants typo 2023-08-10 08:54:38 -03:00
Junior Garcia fcff1a1d36 Merge branch 'main' of github.com:nextui-org/nextui 2023-08-09 23:39:57 -03:00
Junior Garcia c7ba9e1508 fix(docs): customize theme button example, color added 2023-08-09 23:39:44 -03:00
github-actions[bot] 1d8dc4b9d8 ci(changesets): version packages (#1339)
Co-authored-by: Junior Garcia <jrgarciadev@gmail.com>
2023-08-09 21:51:25 -03:00
github-actions[bot] ea5e0fb096 ci(changesets): version packages (#1338)
Co-authored-by: Junior Garcia <jrgarciadev@gmail.com>
2023-08-09 21:42:53 -03:00
Junior Garcia 26f64d043d fix(storybook): padding 2023-08-09 21:40:54 -03:00
Jakob Guddas a078c3dcd2 chore: storybook improvements (#1335) 2023-08-09 21:36:54 -03:00
Jakob Guddas 5a50390e3f fix: moved sr only modal close buttons to not show unnecessary scroll bar (#1333)
* fix: moved sr only modal close buttons to not show unnecessary scroll bar

* Create sour-lizards-allow.md
2023-08-09 21:36:14 -03:00
Tianen Pang 894d85d059 docs(table): use case example (#1326) 2023-08-08 14:43:40 -03:00
github-actions[bot] 0ef41d27e7 ci(changesets): version packages (#1324)
Co-authored-by: Junior Garcia <jrgarciadev@gmail.com>
2023-08-08 12:28:30 -03:00
Tianen Pang 4200164712 fix(input): duplicate triggering of input events (#1323)
* feat(utils): support for omit-names

* fix(input): exclude duplicate event props

* fix(input): exclude duplicate event fn only

* test(input): event fn call count

* chore(changeset): changeset added
2023-08-08 12:19:08 -03:00
Tianen Pang 6d4c6980d5 fix(docs): typo in the loading more data section (#1319) 2023-08-08 09:10:10 -03:00
github-actions[bot] f3f36a7146 ci(changesets): version packages (#1316)
Co-authored-by: Junior Garcia <jrgarciadev@gmail.com>
2023-08-08 01:04:01 -03:00
Junior Garcia 8de209bff7 feat(root): new changeset 2023-08-08 00:56:56 -03:00
Junior Garcia e9d01be74d chore(root): eslint and prettier ignore updated 2023-08-08 00:45:14 -03:00
Junior Garcia 66ac2e67ae feat(root): new changeset 2023-08-08 00:44:58 -03:00
Junior Garcia 7ed88f39c1 chore(pagination): fix prettier 2023-08-08 00:41:58 -03:00
vaynevayne 32d18bfd41 Update pagination-item.tsx (#1315) 2023-08-08 00:41:09 -03:00
vaynevayne a1b32c1ceb Update use-pagination.ts (#1314) 2023-08-08 00:39:01 -03:00
Junior Garcia 9e683b32ba Merge branch 'main' of github.com:nextui-org/nextui 2023-08-08 00:12:35 -03:00
Junior Garcia b7c947805d feat(storybook): logo adapted to light/dark theme, favicon added 2023-08-08 00:12:21 -03:00
github-actions[bot] a76fdfa774 ci(changesets): version packages (#1310)
Co-authored-by: Junior Garcia <jrgarciadev@gmail.com>
2023-08-07 23:40:34 -03:00
Junior Garcia ac605eb71f Fix/1307 input on value change (#1309)
* fix(input): inner event handler implemented

* chore(root): changeset added
2023-08-07 23:31:16 -03:00
Junior Garcia 5b343b6181 chore(root): storybook static files removed 2023-08-06 15:56:24 -03:00
Junior Garcia 05562dcf90 feat(root): storybook v7 2023-08-06 15:41:25 -03:00
github-actions[bot] 0a60388258 ci(changesets): version packages (#1302)
Co-authored-by: Junior Garcia <jrgarciadev@gmail.com>
2023-08-06 15:23:26 -03:00
Junior Garcia d794225cb7 Pr/1224 (#1301)
* chore: storybook migration

* chore: storybook migration

* chore: storybook migration

* fix: moved options in arg types out of control

* fix: fixed type issues

* fix: renamed sb:start script to start

* chore: migrate csf 2 to csf 3

* fix: removed storybook build from root build script

* chore: kick

* chore(root): pnpm lock updated

* chore(root): new changeset

---------

Co-authored-by: Jakob Guddas <github@jguddas.de>
2023-08-06 15:04:26 -03:00
Junior Garcia ec2ed200f5 fix(docs): navbar imports 2023-08-06 14:53:19 -03:00
Junior Garcia 2f7703ec8e fix(docs): navbar imports 2023-08-06 14:53:12 -03:00
Junior Garcia 25cbe1146f chore(root): qa action parallelized again 2023-08-06 12:06:57 -03:00
Junior Garcia 3db9b6248e chore(root): qa action parallelized again 2023-08-06 11:59:43 -03:00
github-actions[bot] b1b5eda15b ci(changesets): version packages (#1293)
Co-authored-by: Junior Garcia <jrgarciadev@gmail.com>
2023-08-06 00:02:27 -03:00
Junior Garcia e3e13a095f chore(root): new changeset 2023-08-05 23:49:42 -03:00
Junior Garcia 86f921d098 Feat/server components (#1291)
* feat(root): rsc components added, packages modified, filter dom props function adapted

* fix(root): eslint/prettier issues

* feat(root): exports changed to named, new pkg for system rsc compatible functions
2023-08-05 23:35:28 -03:00
Junior Garcia eefda8d6e2 feat(root): RSC components added, packages modified, filter dom props function adapted (#1289)
* feat(root): rsc components added, packages modified, filter dom props function adapted

* fix(root): eslint/prettier issues
2023-08-05 18:53:34 -03:00
Junior Garcia 2e4ce7bcee chore(root): all qa processes joined into a single one 2023-08-05 18:40:08 -03:00
Junior Garcia 5a4c4f498d chore(root): build step added to tests QA 2023-08-05 18:34:17 -03:00
Junior Garcia ec30a9adbd refactor(root): sotybook build folder added to repo 2023-08-05 11:14:27 -03:00
Junior Garcia a6954c4156 Merge branch 'main' of github.com:nextui-org/nextui 2023-08-05 11:13:53 -03:00
Junior Garcia b887a2f503 refactor(root): sotybook build folder added to repo 2023-08-05 11:13:37 -03:00
github-actions[bot] edc2bc741e ci(changesets): version packages (#1284)
Co-authored-by: Junior Garcia <jrgarciadev@gmail.com>
2023-08-05 10:54:54 -03:00
Tianen Pang a1a02dc0db fix(tooltip): behavior of tooltip trigger with delay (#1278)
* fix(tooltip): use trigger-props instead of custom on-pointer events

* chore(changeset): add tooltip changeset
2023-08-05 10:46:01 -03:00
602 changed files with 37704 additions and 14230 deletions
+1
View File
@@ -1,6 +1,7 @@
.now/*
.next/*
*.css
.changeset
dist
esm/*
public/*
+10
View File
@@ -21,6 +21,16 @@ body:
- NextUI's [Discussions tab](https://github.com/nextui-org/nextui/discussions)
The more information you fill in, the better the community can help you.
- type: input
id: version
attributes:
label: NextUI Version
description: |
Please provide the version of NextUI you are using.
You can find the version number in the package.json file.
placeholder: ex. 2.0.10
validations:
required: true
- type: textarea
id: description
attributes:
+2 -1
View File
@@ -33,6 +33,7 @@ jobs:
uses: changesets/action@v1
with:
publish: pnpm release
title: "ci(changesets): :package: version packages"
commit: "ci(changesets): version packages"
setupGitUser: false
env:
@@ -48,4 +49,4 @@ jobs:
pnpm release:dev
env:
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
+1
View File
@@ -20,6 +20,7 @@ coverage
dist/
storybook-static
/packages/storybook/public/tailwind.css
# misc
.DS_Store
.env
+2 -2
View File
@@ -13,12 +13,12 @@ const removeIgnoredFiles = async (files) => {
};
module.exports = {
"**/*.{cjs,mjs,js,ts,jsx,tsx}": async (files) => {
"**/*.{js,ts,jsx,tsx}": async (files) => {
const filesToLint = await removeIgnoredFiles(files);
return [`eslint -c .eslintrc.json --max-warnings=0 --fix ${filesToLint}`];
},
"**/*.{css,json,md}": async (files) => {
"**/*.css": async (files) => {
const filesToLint = await removeIgnoredFiles(files);
return [`prettier --config .prettierrc.json --ignore-path --write ${filesToLint}`];
+1
View File
@@ -2,6 +2,7 @@ dist
node_modules
plop
coverage
.changeset
.next
build
scripts
+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:
@@ -61,7 +61,8 @@ export default function Page() {
classNames={{
base: "max-w-full sm:max-w-[10rem] h-10",
input: "text-small",
inputWrapper: "font-normal text-default-500 bg-default-400/20 dark:bg-default-500/20",
inputWrapper:
"h-full font-normal text-default-500 bg-default-400/20 dark:bg-default-500/20",
}}
placeholder="Type to search..."
startContent={<SearchLinearIcon size={18} />}
+3 -3
View File
@@ -179,9 +179,9 @@ const MyButton2 = extendVariants(Button, {
});
export default function NextUIPerf() {
const [textA, setTextA] = useState<string | undefined>("");
const [textB, setTextB] = useState<string | undefined>("");
const [textC, setTextC] = useState<string | undefined>("");
const [textA, setTextA] = useState<string>("");
const [textB, setTextB] = useState<string>("");
const [textC, setTextC] = useState<string>("");
return (
<div className="w-full p-24 gap-4 flex flex-col">
@@ -0,0 +1,113 @@
/* eslint-disable no-console */
"use client";
import {Select, SelectItem} from "@nextui-org/react";
import {useEffect, useState} from "react";
import {useInfiniteScroll} from "@nextui-org/use-infinite-scroll";
type Pokemon = {
name: string;
url: string;
};
type UsePokemonListProps = {
/** Delay to wait before fetching more items */
fetchDelay?: number;
};
function usePokemonList({fetchDelay = 0}: UsePokemonListProps = {}) {
const [items, setItems] = useState<Pokemon[]>([]);
const [hasMore, setHasMore] = useState(true);
const [isLoading, setIsLoading] = useState(false);
const [offset, setOffset] = useState(0);
const limit = 10; // Number of items per page, adjust as necessary
const loadPokemon = async (currentOffset: number) => {
const controller = new AbortController();
const {signal} = controller;
try {
setIsLoading(true);
if (offset > 0) {
// Delay to simulate network latency
await new Promise((resolve) => setTimeout(resolve, fetchDelay));
}
let res = await fetch(
`https://pokeapi.co/api/v2/pokemon?offset=${currentOffset}&limit=${limit}`,
{signal},
);
if (!res.ok) {
throw new Error("Network response was not ok");
}
let json = await res.json();
setHasMore(json.next !== null);
// Append new results to existing ones
setItems((prevItems) => [...prevItems, ...json.results]);
} catch (error) {
// @ts-ignore
if (error.name === "AbortError") {
console.log("Fetch aborted");
} else {
console.error("There was an error with the fetch operation:", error);
}
} finally {
setIsLoading(false);
}
};
useEffect(() => {
loadPokemon(offset);
}, []);
const onLoadMore = () => {
const newOffset = offset + limit;
setOffset(newOffset);
loadPokemon(newOffset);
};
return {
items,
hasMore,
isLoading,
onLoadMore,
};
}
export default function Page() {
const [isOpen, setIsOpen] = useState(false);
const {items, hasMore, isLoading, onLoadMore} = usePokemonList({fetchDelay: 1500});
const [, scrollerRef] = useInfiniteScroll({
hasMore,
isEnabled: isOpen,
shouldUseLoader: false, // We don't want to show the loader at the bottom of the list
onLoadMore,
});
return (
<div className="p-6">
<Select
className="max-w-xs"
isLoading={isLoading}
items={items}
label="Pick a Pokemon"
placeholder="Select a Pokemon"
scrollRef={scrollerRef}
selectionMode="single"
onOpenChange={setIsOpen}
>
{(item) => (
<SelectItem key={item.name} className="capitalize">
{item.name}
</SelectItem>
)}
</Select>
</div>
);
}
@@ -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) => (
@@ -105,7 +105,7 @@ const users = [
email: "kristen.cooper@example.com",
},
{
key: 6,
id: 6,
name: "Brian Kim",
role: "P. Manager",
team: "Management",
@@ -256,7 +256,7 @@ const users = [
},
];
type User = typeof users[0];
type User = (typeof users)[number];
export default function Page() {
const [filterValue, setFilterValue] = useState("");
+13 -9
View File
@@ -105,7 +105,7 @@ const users = [
email: "kristen.cooper@example.com",
},
{
key: 6,
id: 6,
name: "Brian Kim",
role: "P. Manager",
team: "Management",
@@ -256,7 +256,7 @@ const users = [
},
];
type User = typeof users[0];
type User = (typeof users)[number];
export default function Page() {
const [filterValue, setFilterValue] = useState("");
@@ -271,8 +271,6 @@ export default function Page() {
const [page, setPage] = useState(1);
const pages = Math.ceil(users.length / rowsPerPage);
const hasSearchFilter = Boolean(filterValue);
const headerColumns = useMemo(() => {
@@ -298,6 +296,8 @@ export default function Page() {
return filteredUsers;
}, [users, filterValue, statusFilter]);
const pages = Math.ceil(filteredItems.length / rowsPerPage);
const items = useMemo(() => {
const start = (page - 1) * rowsPerPage;
const end = start + rowsPerPage;
@@ -390,6 +390,11 @@ export default function Page() {
}
}, []);
const onClear = useCallback(() => {
setFilterValue("");
setPage(1);
}, []);
const topContent = useMemo(() => {
return (
<div className="flex flex-col gap-4">
@@ -400,7 +405,7 @@ export default function Page() {
placeholder="Search by name..."
startContent={<SearchIcon />}
value={filterValue}
onClear={() => setFilterValue("")}
onClear={() => onClear()}
onValueChange={onSearchChange}
/>
<div className="flex gap-3">
@@ -483,23 +488,22 @@ export default function Page() {
<span className="w-[30%] text-small text-default-400">
{selectedKeys === "all"
? "All items selected"
: `${selectedKeys.size} of ${items.length} selected`}
: `${selectedKeys.size} of ${filteredItems.length} selected`}
</span>
<Pagination
isCompact
showControls
showShadow
color="primary"
isDisabled={hasSearchFilter}
page={page}
total={pages}
onChange={setPage}
/>
<div className="hidden sm:flex w-[30%] justify-end gap-2">
<Button isDisabled={hasSearchFilter} size="sm" variant="flat" onPress={onPreviousPage}>
<Button isDisabled={pages === 1} size="sm" variant="flat" onPress={onPreviousPage}>
Previous
</Button>
<Button isDisabled={hasSearchFilter} size="sm" variant="flat" onPress={onNextPage}>
<Button isDisabled={pages === 1} size="sm" variant="flat" onPress={onNextPage}>
Next
</Button>
</div>
+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",
};
+1 -1
View File
@@ -1,4 +1,4 @@
import {Spacer} from "@nextui-org/react";
import {Spacer} from "@nextui-org/spacer";
import {Hero} from "@/components/marketing/hero";
import {FeaturesGrid} from "@/components/marketing/features-grid";
+20 -9
View File
@@ -1,21 +1,31 @@
"use client";
import {BlogPost} from "contentlayer/generated";
import {Card, CardFooter, CardBody, CardHeader, Link, Avatar} from "@nextui-org/react";
import {Card, CardFooter, CardBody, CardHeader, Link, Avatar, Image} from "@nextui-org/react";
import Balancer from "react-wrap-balancer";
import {format, parseISO} from "date-fns";
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 && (
<motion.div
<motion.article
animate={{opacity: 1, y: 0}}
exit={{opacity: 0, y: 5}}
initial={{opacity: 0, y: 5}}
@@ -24,9 +34,10 @@ const BlogPostCard = (post: BlogPost) => {
<Card
isBlurred
as={NextLink}
className="p-2 border-transparent text-start bg-white/5 dark:bg-default-400/10 backdrop-blur-lg backdrop-saturate-[1.8]"
className="p-2 h-full border-transparent text-start bg-white/5 dark:bg-default-400/10 backdrop-blur-lg backdrop-saturate-[1.8]"
href={post.url}
isPressable={!!post.url}
onPress={handlePress}
>
<CardHeader>
<Link
@@ -35,14 +46,14 @@ const BlogPostCard = (post: BlogPost) => {
href={post.url}
size="lg"
underline="hover"
onPress={handlePress}
>
<Balancer>{post.title}</Balancer>
</Link>
</CardHeader>
<CardBody className="px-3 pt-0 pb-1">
<p className="font-normal text-default-600">
<Balancer>{post.description}</Balancer>
</p>
<CardBody className="pt-0 px-2 pb-1">
<Image className="mb-4" src={post.image} />
<p className="font-normal w-full text-default-600">{post.description}</p>
</CardBody>
<CardFooter className="flex justify-between items-center">
<time className="block text-small text-default-500" dateTime={post.date}>
@@ -51,7 +62,7 @@ const BlogPostCard = (post: BlogPost) => {
<Avatar size="sm" src={post.author?.avatar} />
</CardFooter>
</Card>
</motion.div>
</motion.article>
)}
</AnimatePresence>
);
@@ -59,7 +70,7 @@ const BlogPostCard = (post: BlogPost) => {
export const BlogPostList = ({posts}: {posts: BlogPost[]}) => {
return (
<div className="mt-10 grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4">
<div className="mt-10 grid gap-4 grid-cols-[repeat(auto-fill,minmax(300px,1fr))]">
{posts.map((post, idx) => (
<BlogPostCard key={idx} {...post} />
))}
+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),
@@ -33,9 +34,11 @@ interface CodeDemoProps extends UseCodeDemoProps, WindowResizerProps {
enableResize?: boolean;
showTabs?: boolean;
showPreview?: boolean;
hideWindowActions?: boolean;
showOpenInCodeSandbox?: boolean;
isPreviewCentered?: boolean;
resizeEnabled?: boolean;
typescriptStrict?: boolean;
displayMode?: "always" | "visible";
isGradientBox?: boolean;
gradientColor?: GradientBoxProps["color"];
@@ -52,8 +55,11 @@ export const CodeDemo: React.FC<CodeDemoProps> = ({
showPreview = true,
asIframe = false,
resizeEnabled = true,
hideWindowActions = false,
showSandpackPreview = false,
isPreviewCentered = false,
// when false .js files will be used
typescriptStrict = false,
showOpenInCodeSandbox,
isGradientBox = false,
defaultExpanded = false,
@@ -96,6 +102,7 @@ export const CodeDemo: React.FC<CodeDemoProps> = ({
const content = asIframe ? (
<WindowResizer
hideWindowActions={hideWindowActions}
iframeHeight={previewHeight}
iframeInitialWidth={iframeInitialWidth}
iframeSrc={iframeSrc}
@@ -121,6 +128,7 @@ export const CodeDemo: React.FC<CodeDemoProps> = ({
isGradientBox,
gradientColor,
previewHeight,
hideWindowActions,
asIframe,
showPreview,
isInView,
@@ -138,6 +146,7 @@ export const CodeDemo: React.FC<CodeDemoProps> = ({
showEditor={showEditor}
showOpenInCodeSandbox={showOpenInCodeSandbox || showPreview}
showPreview={showSandpackPreview}
typescriptStrict={typescriptStrict}
/>
);
@@ -172,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}
@@ -49,6 +49,7 @@ const resizer = tv({
export interface WindowResizerProps {
resizeEnabled?: boolean;
hideWindowActions?: boolean;
iframeHeight?: string | number;
iframeMinWidth?: number;
iframeSrc?: string;
@@ -70,6 +71,7 @@ const WindowResizer: React.FC<WindowResizerProps> = (props) => {
iframeSrc,
iframeTitle,
resizeEnabled,
hideWindowActions = false,
iframeHeight: height = "420px",
iframeInitialWidth,
iframeMinWidth: minWidth = MIN_WIDTH,
@@ -120,7 +122,7 @@ const WindowResizer: React.FC<WindowResizerProps> = (props) => {
width: isMobile ? "100%" : browserWidth,
}}
>
<WindowActions className="bg-default-100 dark:bg-default-50" />
{!hideWindowActions && <WindowActions className="bg-default-100 dark:bg-default-50" />}
<motion.iframe ref={iframeRef} className={iframe()} src={iframeSrc} title={iframeTitle} />
</motion.div>
{resizeEnabled && (
@@ -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}
@@ -1,12 +1,16 @@
import {Button, ButtonProps, Link} from "@nextui-org/react";
import {Button, ButtonProps, Code, Link, Tooltip} from "@nextui-org/react";
import {ReactNode} from "react";
import Balancer from "react-wrap-balancer";
import {GithubIcon, NpmIcon, AdobeIcon, StorybookIcon} from "@/components/icons";
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;
styles?: string;
storybook?: string;
rscCompatible?: boolean;
reactAriaHook?: string;
}
@@ -14,27 +18,51 @@ const ButtonLink = ({
children,
href,
startContent,
tooltip,
...props
}: ButtonProps & {
href: string;
}) => (
<Button
isExternal
as={Link}
className="!text-small py-4 bg-default-100 dark:bg-default-50 text-default-700"
href={href}
size="sm"
startContent={startContent}
{...props}
>
{children}
</Button>
);
tooltip?: string | ReactNode;
}) => {
const handlePress = () => {
if (!href) return;
trackEvent("ComponentLinks - Click", {
category: "docs",
action: "click",
data: href || "",
});
};
const button = (
<Button
isExternal
as={Link}
className="!text-small py-4 bg-default-100 dark:bg-default-50 text-default-700"
href={href}
size="sm"
startContent={startContent}
onPress={handlePress}
{...props}
>
{children}
</Button>
);
return tooltip ? (
<Tooltip className="max-w-[230px]" content={tooltip}>
{button}
</Tooltip>
) : (
button
);
};
export const ComponentLinks = ({
component,
storybook,
styles,
rscCompatible,
reactAriaHook,
}: ComponentLinksProps) => {
if (!component) {
@@ -63,6 +91,26 @@ export const ComponentLinks = ({
React Aria
</ButtonLink>
)}
{rscCompatible && (
<ButtonLink
href="https://nextjs.org/docs/app/building-your-application/rendering/server-components"
startContent={<NextJsIcon size={18} />}
tooltip={
<p>
<Balancer>
This component doesn&apos;t use the
<Code className="font-normal bg-transparent px-0 py-0 text-code-mdx">
`use client;`
</Code>
directive making it compatible with RSC.
</Balancer>
</p>
}
>
Server component
</ButtonLink>
)}
<ButtonLink href={`${COMPONENT_PATH}/${component}`} startContent={<GithubIcon size={20} />}>
Source
</ButtonLink>
@@ -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,12 +105,14 @@ export const FloatingComponents: React.FC<{}> = () => {
{isMounted && (
<Tooltip
showArrow
className="text-sm animate-[levitate_14s_ease_infinite]"
color="secondary"
content="Developers love Next.js"
isOpen={!isTablet}
placement="top"
style={{
zIndex: 39,
}}
>
<Button
className="absolute left-[200px] top-[160px] max-w-fit animate-[levitate_14s_ease_infinite_0.5s]"
@@ -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>
);
+58 -9
View File
@@ -30,6 +30,7 @@ import {useEffect} from "react";
import {usePress} from "@react-aria/interactions";
import {useFocusRing} from "@react-aria/focus";
import {currentVersion} from "@/utils/version";
import {siteConfig} from "@/config/site";
import {Route} from "@/libs/docs/page";
import {LargeLogo, SmallLogo, ThemeSwitch} from "@/components";
@@ -43,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[];
@@ -73,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();
@@ -100,7 +111,7 @@ export const Navbar: FC<NavbarProps> = ({children, routes, mobileRoutes = [], sl
strokeWidth={2}
/>
}
onPress={() => cmdkStore.onOpen()}
onPress={handleOpenCmdk}
>
Quick Search...
</Button>
@@ -120,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}
@@ -137,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" />
@@ -154,7 +175,7 @@ export const Navbar: FC<NavbarProps> = ({children, routes, mobileRoutes = [], sl
size="sm"
variant="flat"
>
v2.0.0
v{currentVersion}
</Button>
</DropdownTrigger>
</motion.div>
@@ -166,7 +187,7 @@ export const Navbar: FC<NavbarProps> = ({children, routes, mobileRoutes = [], sl
selectionMode="single"
onAction={handleVersionChange}
>
<DropdownItem key="v2">v2.0.0</DropdownItem>
<DropdownItem key="v2">v{currentVersion}</DropdownItem>
<DropdownItem key="v1" endContent={<LinkIcon />}>
v1.0.0
</DropdownItem>
@@ -183,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>
@@ -193,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>
@@ -203,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>
@@ -213,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>
@@ -222,10 +247,14 @@ export const Navbar: FC<NavbarProps> = ({children, routes, mobileRoutes = [], sl
as={NextLink}
className="hover:bg-default-100 border-default-200/80 dark:border-default-100/80 transition-colors cursor-pointer"
color="secondary"
href="/blog/nextui-v2"
href="/blog/v2.1.0"
variant="dot"
onClick={() => handlePressNavbarItem("New components v2.1.0", "/blog/v2.1.0")}
>
Introducing NextUI v2.0
New components v2.1.0&nbsp;
<span aria-label="party emoji" role="img">
🎉
</span>
</Chip>
</NavbarItem>
</ul>
@@ -238,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>
@@ -269,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 />
@@ -291,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]);
@@ -26,6 +26,7 @@ export const Sandpack: FC<SandpackProps> = ({
files: filesProp,
template,
highlightedLines,
typescriptStrict = false,
showPreview = false,
showEditor = true,
defaultExpanded = false,
@@ -41,6 +42,7 @@ export const Sandpack: FC<SandpackProps> = ({
useSandpack({
files: filesProp,
template,
typescriptStrict,
highlightedLines,
});
+1 -2
View File
@@ -30,8 +30,7 @@ export const nextuiTheme: SandpackTheme = {
},
font: {
body: "Inter var",
mono:
'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace',
mono: 'ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace',
size: "14px",
lineHeight: "1.5rem",
},
+14 -1
View File
@@ -10,6 +10,7 @@ import {useLocalStorage} from "@/hooks/use-local-storage";
export interface UseSandpackProps {
files?: SandpackFiles;
typescriptStrict?: boolean;
template?: SandpackPredefinedTemplate;
highlightedLines?: HighlightedLines;
}
@@ -19,6 +20,7 @@ const importAllReact = 'import * as React from "react";';
export const useSandpack = ({
files = {},
typescriptStrict = false,
template = "vite-react",
highlightedLines,
}: UseSandpackProps) => {
@@ -57,6 +59,12 @@ export const useSandpack = ({
if (key.includes("App") && !key.includes(mimeType)) {
return acc;
}
if (typescriptStrict && currentTemplate === "vite-react-ts" && key.includes(".js")) {
return acc;
}
if (currentTemplate === "vite-react" && key.includes(".ts")) {
return acc;
}
// @ts-ignore
acc[key] = files[key];
@@ -76,6 +84,11 @@ export const useSandpack = ({
const aName = getFileName(a);
const bName = getFileName(b);
// if bName includes "App" should be first
if (bName.includes("App")) {
return 1;
}
if (aFile?.includes(bName)) {
return -1;
}
@@ -90,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",
+26 -11
View File
@@ -164,8 +164,7 @@
"key": "chip",
"title": "Chip",
"keywords": "chip, tag, label, small actionable entity",
"path": "/docs/components/chip.mdx",
"newPost": true
"path": "/docs/components/chip.mdx"
},
{
"key": "circular-progress",
@@ -183,8 +182,7 @@
"key": "divider",
"title": "Divider",
"keywords": "divider, boundary, separator, section divider",
"path": "/docs/components/divider.mdx",
"newPost": true
"path": "/docs/components/divider.mdx"
},
{
"key": "dropdown",
@@ -208,8 +206,7 @@
"key": "kbd",
"title": "Kbd",
"keywords": "keyboard input, shortcut, keys, user input display",
"path": "/docs/components/kbd.mdx",
"newPost": true
"path": "/docs/components/kbd.mdx"
},
{
"key": "link",
@@ -217,6 +214,13 @@
"keywords": "link, navigation, href, web page connection",
"path": "/docs/components/link.mdx"
},
{
"key": "listbox",
"title": "Listbox",
"keywords": "listbox, selection, option list, multiple choice",
"path": "/docs/components/listbox.mdx",
"newPost": true
},
{
"key": "modal",
"title": "Modal",
@@ -253,18 +257,30 @@
"keywords": "radio group, selection set, option selection, exclusive choices",
"path": "/docs/components/radio-group.mdx"
},
{
"key": "select",
"title": "Select",
"keywords": "select, selection, option list, multiple choice",
"path": "/docs/components/select.mdx",
"newPost": true
},
{
"key": "skeleton",
"title": "Skeleton",
"keywords": "skeleton, loading state, placeholder, content preview",
"path": "/docs/components/skeleton.mdx",
"newPost": true
"path": "/docs/components/skeleton.mdx"
},
{
"key": "snippet",
"title": "Snippet",
"keywords": "snippet, code block, programming, code example",
"path": "/docs/components/snippet.mdx",
"path": "/docs/components/snippet.mdx"
},
{
"key": "scroll-shadow",
"title": "Scroll Shadow",
"keywords": "scroll shadow, scroll indicator, scroll bar, scroll position",
"path": "/docs/components/scroll-shadow.mdx",
"newPost": true
},
{
@@ -295,8 +311,7 @@
"key": "tabs",
"title": "Tabs",
"keywords": "tabs, section navigation, categorized content, tabbed interface",
"path": "/docs/components/tabs.mdx",
"newPost": true
"path": "/docs/components/tabs.mdx"
},
{
"key": "textarea",
File diff suppressed because it is too large Load Diff
+14 -1
View File
@@ -175,7 +175,7 @@ We've added a new function, `extendVariants`, that allows you to customize any N
height={350}
/>
You can create or override the component `variants`, `defaultVariants` and `componentVariants`.
You can create or override the component `variants`, `defaultVariants` and `compoundVariants`.
> Check out the [Custom Variants](/docs/customization/custom-variants) documentation for more information.
@@ -310,3 +310,16 @@ file helps streamline the process of transforming design ideas into functioning
To start using **NextUI v2.0**, head over to our [installation guide](/docs/guide/installation).
We can't wait to see the amazing things you'll build with **NextUI v2.0**!
---
## Community
We're excited to see the community adopt NextUI, raise issues, and provide feedback.
Whether it's a feature request, bug report, or a project to showcase, please get involved!
<Community />
## Contributing
PR's on NextUI are always welcome, please see our [contribution guidelines](https://github.com/nextui-org/nextui/blob/main/CONTRIBUTING.MD) to learn how you can contribute to this project.
+167
View File
@@ -0,0 +1,167 @@
---
title: "New components v2.1.0 🎉"
description: "NextUI v2.1.0 is here with new components, Select, Listbox and ScrollShadow."
date: "2023-08-21"
image: "/blog/v2.1.0.jpg"
tags: ["nextui", "select", "listbox", "scroll-shadow", "multi-select"]
author:
name: "Junior Garcia"
username: "@jrgarciadev"
link: "https://twitter.com/jrgarciadev"
avatar: "/avatars/junior-garcia.jpeg"
---
import {selectContent} from "@/content/components/select";
import {listboxContent} from "@/content/components/listbox";
import {scrollShadowContent} from "@/content/components/scroll-shadow";
<img
src="/blog/v2.1.0.jpg"
width={700}
height={350}
alt="NextUI v2"
className="w-full border border-transparent dark:border-default-200/50 object-fit rounded-xl shadow-lg"
/>
We are thrilled to announce the latest update to NextUI, version **2.1.0**! This release introduces some game-changing
additions that many of you have eagerly been waiting for.
First on the list is the highly-anticipated **Select** component. Fully customizable and beautifully designed, supports both single and
multi-select modes and is accessible out of the box.
But that's not all. We're also rolling out two more incredible components **Listbox** and **ScrollShadow**. The new
**Listbox** allows you to make list manipulations more efficient and visually appealing. Meanwhile, the
**ScrollShadow** component adds an elegant shadow effect to scrollable areas, enhancing the UI aesthetics while
also improving usability.
## Select
Creating a select component that is both accessible and customizable is a challenging task. We've spent a lot of time
researching and testing different approaches to come up with a solution that works for everyone. The result is a
component that is easy to use, fully accessible, and highly customizable.
The new **Select** component includes:
- Support for selecting a single option.
- Support for selecting multiple options.
- Support for disabled options.
- Support for sections.
- Labeling support for accessibility.
- Exposed to assistive technology as a button with a listbox popup using ARIA (combined with [Listbox](/docs/components/listbox)).
- Support for description and error message help text linked to the input via ARIA.
- Support for mouse, touch, and keyboard interactions.
- Tab stop focus management.
- Asynchronous options loading.
- Keyboard support for opening the listbox using the arrow keys, including automatically focusing the first or last item accordingly.
- Typeahead to allow selecting options by typing text, even without opening the listbox.
- Browser autofill integration via a hidden native `<select>` element.
- Support for mobile form navigation via software keyboard.
- Mobile screen reader listbox dismissal support.
- And much more...
### Single Select
The single select component is used to select a single option from a list of options. It is a combination of a button
and a listbox. The button displays the currently selected option and the listbox displays the available options.
<CodeDemo title="Usage" files={selectContent.usage} />
### Multiple Select
The multiple select component can be used to select multiple options from a list of options.
You only need to pass the `selectionMode="multiple"` prop to the `Select` component.
<CodeDemo title="Multiple Selection" files={selectContent.multiple} />
### Multiple Variants
The select component comes with multiple variants.
<CodeDemo title="Variants" files={selectContent.variants} />
### Chips Support
The select component is flexible and allows you to render any component as an option and as a selected option.
<CodeDemo title="Multiple Selection with Chips" files={selectContent.multipleWithChips} />
### Customizable
The select component is highly customizable, you can customize the selected option, the options, the listbox,
the popover and the scrollable area.
<CodeDemo title="Custom Styles" files={selectContent.customStyles} />
Go to the [Select](/docs/components/select) component page to learn more about sizes, colors, and more.
## Listbox
The listbox component allows you to make list manipulations more efficient and visually appealing.
The new **Listbox** component includes:
- Support for single, multiple, or no selection.
- Exposed to assistive technology as a `listbox` using ARIA.
- Support for disabled items.
- Support for sections.
- Labeling support for accessibility.
- Support for mouse, touch, and keyboard interactions.
- Tab stop focus management.
- Keyboard navigation support including arrow keys, home/end, page up/down, select all, and clear.
- Automatic scrolling support during keyboard navigation.
- Typeahead to allow focusing options by typing text.
### Usage
<CodeDemo title="Usage" files={listboxContent.usage} />
### Custom Styles
The Listbox components offers multiple customization options.
<CodeDemo title="Custom Styles" files={listboxContent.customStyles} />
> **Note**: In the above example, we've utilized the [Boxicons](https://boxicons.com/) icons collection.
Go to the [Listbox](/docs/components/listbox) component page to learn more about it.
## ScrollShadow
The ScrollShadow component gives a nice shadow effect to scrollable areas. These shadows are handled by using
the CSS `mask-image` property, which makes the shadows adapt to the background color.
### Usage
<CodeDemo title="Usage" files={scrollShadowContent.usage} />
You can hide the scrollbars, customize the shadows size, change the orientation, and more.
Go to the [ScrollShadow](/docs/components/scroll-shadow) component page to learn more about it.
<Spacer y={6}/>
We hope you enjoy these new components and the new features. We're excited to see what you build with them!
Thanks for reading and happy coding! 🚀
---
## Community
We're excited to see the community adopt NextUI, raise issues, and provide feedback.
Whether it's a feature request, bug report, or a project to showcase, please get involved!
<Community />
## Contributing
PR's on NextUI are always welcome, please see our [contribution guidelines](https://github.com/nextui-org/nextui/blob/main/CONTRIBUTING.MD) to learn how you can contribute to this project.
@@ -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>
);
});
+1 -1
View File
@@ -140,7 +140,7 @@ const ShuffleIcon = `export const ShuffleIcon = ({size = 24, width, height, ...p
</svg>
);`;
const App = `import {Card, CardFooter, Image, Button, Progress} from "@nextui-org/react";
const App = `import {Card, CardBody, Image, Button, Progress} from "@nextui-org/react";
import {HeartIcon} from "./HeartIcon";
import {PauseCircleIcon} from "./PauseCircleIcon";
import {NextIcon} from "./NextIcon";
@@ -1,4 +1,4 @@
const App = `import {Card, CardHeader, CardBody, Avatar, Button} from "@nextui-org/react";
const App = `import {Card, CardHeader, CardBody, CardFooter, Avatar, Button} from "@nextui-org/react";
export default function App() {
const [isFollowed, setIsFollowed] = React.useState(false);
@@ -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,
};
@@ -49,6 +49,7 @@ export default function App() {
"data-[hover=true]:text-foreground",
"data-[hover=true]:bg-default-100",
"dark:data-[hover=true]:bg-default-50",
"data-[selectable=true]:focus:bg-default-50",
"data-[pressed=true]:opacity-70",
"data-[focus-visible=true]:ring-default-500",
],
@@ -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 (
@@ -138,6 +138,7 @@ export default function App() {
<DropdownItem
key="edit"
shortcut="⌘⇧E"
showDivider
description="Allows you to edit the file"
startContent={<EditDocumentIcon className={iconClasses} />}
>
@@ -145,7 +146,6 @@ export default function App() {
</DropdownItem>
<DropdownItem
key="delete"
showDivider
className="text-danger"
color="danger"
shortcut="⌘⇧D"
@@ -142,7 +142,6 @@ export default function App() {
</DropdownItem>
<DropdownItem
key="delete"
showDivider
className="text-danger"
color="danger"
shortcut="⌘⇧D"
@@ -19,7 +19,7 @@ export default function App() {
</Button>
</DropdownTrigger>
<DropdownMenu
aria-label="Single selection actions"
aria-label="Multiple selection example"
variant="flat"
closeOnSelect={false}
disallowEmptySelection
@@ -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";
@@ -14,7 +14,7 @@ export default function App() {
<DropdownItem key="new" shortcut="⌘N">New file</DropdownItem>
<DropdownItem key="copy" shortcut="⌘C">Copy link</DropdownItem>
<DropdownItem key="edit" shortcut="⌘⇧E">Edit file</DropdownItem>
<DropdownItem key="delete" showDivider shortcut="⌘⇧D" className="text-danger" color="danger">
<DropdownItem key="delete" shortcut="⌘⇧D" className="text-danger" color="danger">
Delete file
</DropdownItem>
</DropdownMenu>
@@ -19,7 +19,7 @@ export default function App() {
</Button>
</DropdownTrigger>
<DropdownMenu
aria-label="Single selection actions"
aria-label="Single selection example"
variant="flat"
disallowEmptySelection
selectionMode="single"
@@ -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"
/>
+2 -2
View File
@@ -6,7 +6,7 @@ import sizes from "./sizes";
import colors from "./colors";
import variants from "./variants";
import radius from "./radius";
import labelPositions from "./label-positions";
import labelPlacements from "./label-placements";
import description from "./description";
import password from "./password";
import clearButton from "./clear-button";
@@ -26,7 +26,7 @@ export const inputContent = {
colors,
variants,
radius,
labelPositions,
labelPlacements,
description,
password,
clearButton,
@@ -1,7 +1,7 @@
const App = `import {Input} from "@nextui-org/react";
export default function App() {
const positions = [
const placements = [
"inside",
"outside",
"outside-left",
@@ -12,13 +12,13 @@ export default function App() {
<div className="flex flex-col gap-2">
<h3 className="text-default-500 text-small">Without placeholder</h3>
<div className="flex w-full flex-wrap items-end md:flex-nowrap mb-6 md:mb-0 gap-4">
{positions.map((position) => (
{placements.map((placement) => (
<Input
key={position}
key={placement}
type="email"
label="Email"
labelPlacement={position}
description={position}
labelPlacement={placement}
description={placement}
/>
))}
</div>
@@ -26,14 +26,14 @@ export default function App() {
<div className="flex flex-col gap-2">
<h3 className="text-default-500 text-small">With placeholder</h3>
<div className="flex w-full flex-wrap items-end md:flex-nowrap mb-6 md:mb-0 gap-4">
{positions.map((position) => (
{placements.map((placement) => (
<Input
key={position}
key={placement}
type="email"
label="Email"
labelPlacement={position}
labelPlacement={placement}
placeholder="Enter your email"
description={position}
description={placement}
/>
))}
</div>
@@ -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"
/>
@@ -1,4 +1,4 @@
const MailFilledIcon = `export const MailFilledIcon = (props) => (
const MailIcon = `export const MailIcon = (props) => (
<svg
aria-hidden="true"
fill="none"
@@ -17,7 +17,7 @@ const MailFilledIcon = `export const MailFilledIcon = (props) => (
);`;
const App = `import {Input} from "@nextui-org/react";
import {MailFilledIcon} from './MailFilledIcon';
import {MailIcon} from './MailIcon';
export default function App() {
return (
@@ -29,7 +29,7 @@ export default function App() {
placeholder="you@example.com"
labelPlacement="outside"
startContent={
<MailFilledIcon className="text-2xl text-default-400 pointer-events-none flex-shrink-0" />
<MailIcon className="text-2xl text-default-400 pointer-events-none flex-shrink-0" />
}
/>
<Input
@@ -62,7 +62,7 @@ export default function App() {
placeholder="you@example.com"
labelPlacement="outside"
endContent={
<MailFilledIcon className="text-2xl text-default-400 pointer-events-none flex-shrink-0" />
<MailIcon className="text-2xl text-default-400 pointer-events-none flex-shrink-0" />
}
/>
<Input
@@ -94,7 +94,7 @@ export default function App() {
placeholder="nextui"
labelPlacement="outside"
startContent={
<MailFilledIcon className="text-xl text-default-400 pointer-events-none flex-shrink-0" />
<MailIcon className="text-xl text-default-400 pointer-events-none flex-shrink-0" />
}
endContent={
<div className="pointer-events-none flex items-center">
@@ -152,7 +152,7 @@ export default function App() {
const react = {
"/App.jsx": App,
"/MailFilledIcon.jsx": MailFilledIcon,
"/MailIcon.jsx": MailIcon,
};
export default {
@@ -1,7 +1,6 @@
const App = `import {Input} from "@nextui-org/react";
export default function App() {
const variants = ["flat", "bordered", "underlined", "faded"];
return (
@@ -0,0 +1,284 @@
const BugIcon = `export const BugIcon = (props) => (
<svg height="1em" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg" {...props}>
<path
d="M16.895,6.519l2.813-2.812l-1.414-1.414l-2.846,2.846c-0.233-0.166-0.473-0.321-0.723-0.454 c-1.723-0.91-3.726-0.911-5.45,0c-0.25,0.132-0.488,0.287-0.722,0.453L5.707,2.293L4.293,3.707l2.813,2.812 C6.53,7.242,6.08,8.079,5.756,9H2v2h2.307C4.242,11.495,4.2,11.997,4.2,12.5c0,0.507,0.042,1.013,0.107,1.511H2v2h2.753 c0.013,0.039,0.021,0.08,0.034,0.118c0.188,0.555,0.421,1.093,0.695,1.6c0.044,0.081,0.095,0.155,0.141,0.234l-2.33,2.33 l1.414,1.414l2.11-2.111c0.235,0.254,0.478,0.498,0.736,0.716c0.418,0.354,0.867,0.657,1.332,0.903 c0.479,0.253,0.982,0.449,1.496,0.58C10.911,21.931,11.455,22,12,22s1.089-0.069,1.618-0.204c0.514-0.131,1.017-0.327,1.496-0.58 c0.465-0.246,0.914-0.55,1.333-0.904c0.258-0.218,0.5-0.462,0.734-0.716l2.111,2.111l1.414-1.414l-2.33-2.33 c0.047-0.08,0.098-0.155,0.142-0.236c0.273-0.505,0.507-1.043,0.694-1.599c0.013-0.039,0.021-0.079,0.034-0.118H22v-2h-2.308 c0.065-0.499,0.107-1.004,0.107-1.511c0-0.503-0.042-1.005-0.106-1.5H22V9h-3.756C17.92,8.079,17.47,7.242,16.895,6.519z M8.681,7.748c0.445-0.558,0.96-0.993,1.528-1.294c1.141-0.603,2.442-0.602,3.581,0c0.569,0.301,1.084,0.736,1.53,1.295 c0.299,0.373,0.54,0.8,0.753,1.251H7.927C8.141,8.549,8.381,8.121,8.681,7.748z M17.8,12.5c0,0.522-0.042,1.044-0.126,1.553 c-0.079,0.49-0.199,0.973-0.355,1.436c-0.151,0.449-0.34,0.882-0.559,1.288c-0.217,0.399-0.463,0.772-0.733,1.11 c-0.267,0.333-0.56,0.636-0.869,0.898c-0.31,0.261-0.639,0.484-0.979,0.664s-0.695,0.317-1.057,0.41 c-0.04,0.01-0.082,0.014-0.122,0.023V14h-2v5.881c-0.04-0.009-0.082-0.013-0.122-0.023c-0.361-0.093-0.717-0.23-1.057-0.41 s-0.669-0.403-0.978-0.664c-0.311-0.263-0.604-0.565-0.871-0.899c-0.27-0.337-0.516-0.71-0.731-1.108 c-0.22-0.407-0.408-0.84-0.56-1.289c-0.156-0.463-0.276-0.946-0.356-1.438C6.242,13.544,6.2,13.022,6.2,12.5 c0-0.505,0.041-1.009,0.119-1.5h11.361C17.759,11.491,17.8,11.995,17.8,12.5z"
fill="currentColor"
/>
</svg>
);
`;
const PullRequestIcon = `export const PullRequestIcon = (props) => (
<svg height="1em" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg" {...props}>
<path
d="M19.01 15.163V7.997C19.005 6.391 17.933 4 15 4V2l-4 3 4 3V6c1.829 0 2.001 1.539 2.01 2v7.163c-1.44.434-2.5 1.757-2.5 3.337 0 1.93 1.57 3.5 3.5 3.5s3.5-1.57 3.5-3.5c0-1.58-1.06-2.903-2.5-3.337zm-1 4.837c-.827 0-1.5-.673-1.5-1.5s.673-1.5 1.5-1.5 1.5.673 1.5 1.5-.673 1.5-1.5 1.5zM9.5 5.5C9.5 3.57 7.93 2 6 2S2.5 3.57 2.5 5.5c0 1.58 1.06 2.903 2.5 3.337v6.326c-1.44.434-2.5 1.757-2.5 3.337C2.5 20.43 4.07 22 6 22s3.5-1.57 3.5-3.5c0-1.58-1.06-2.903-2.5-3.337V8.837C8.44 8.403 9.5 7.08 9.5 5.5zm-5 0C4.5 4.673 5.173 4 6 4s1.5.673 1.5 1.5S6.827 7 6 7s-1.5-.673-1.5-1.5zm3 13c0 .827-.673 1.5-1.5 1.5s-1.5-.673-1.5-1.5S5.173 17 6 17s1.5.673 1.5 1.5z"
fill="currentColor"
/>
</svg>
);`;
const ChatIcon = `export const ChatIcon = (props) => (
<svg height="1em" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg" {...props}>
<path
d="M5 18v3.766l1.515-.909L11.277 18H16c1.103 0 2-.897 2-2V8c0-1.103-.897-2-2-2H4c-1.103 0-2 .897-2 2v8c0 1.103.897 2 2 2h1zM4 8h12v8h-5.277L7 18.234V16H4V8z"
fill="currentColor"
/>
<path
d="M20 2H8c-1.103 0-2 .897-2 2h12c1.103 0 2 .897 2 2v8c1.103 0 2-.897 2-2V4c0-1.103-.897-2-2-2z"
fill="currentColor"
/>
</svg>
);`;
const PlayCircleIcon = `export const PlayCircleIcon = (props) => (
<svg height="1em" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg" {...props}>
<path
d="M12 2C6.486 2 2 6.486 2 12s4.486 10 10 10 10-4.486 10-10S17.514 2 12 2zm0 18c-4.411 0-8-3.589-8-8s3.589-8 8-8 8 3.589 8 8-3.589 8-8 8z"
fill="currentColor"
/>
<path d="m9 17 8-5-8-5z" fill="currentColor" />
</svg>
);`;
const LayoutIcon = `export const LayoutIcon = (props) => (
<svg height="1em" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg" {...props}>
<path
d="M19 3H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h14c1.103 0 2-.897 2-2V5c0-1.103-.897-2-2-2zm0 2 .001 4H5V5h14zM5 11h8v8H5v-8zm10 8v-8h4.001l.001 8H15z"
fill="currentColor"
/>
</svg>
);`;
const TagIcon = `export const TagIcon = (props) => (
<svg height="1em" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg" {...props}>
<path
d="M11.707 2.293A.997.997 0 0 0 11 2H6a.997.997 0 0 0-.707.293l-3 3A.996.996 0 0 0 2 6v5c0 .266.105.52.293.707l10 10a.997.997 0 0 0 1.414 0l8-8a.999.999 0 0 0 0-1.414l-10-10zM13 19.586l-9-9V6.414L6.414 4h4.172l9 9L13 19.586z"
fill="currentColor"
/>
<circle cx="8.353" cy="8.353" fill="currentColor" r="1.647" />
</svg>
);`;
const UsersIcon = `export const UsersIcon = (props) => (
<svg height="1em" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg" {...props}>
<path
d="M16.604 11.048a5.67 5.67 0 0 0 .751-3.44c-.179-1.784-1.175-3.361-2.803-4.44l-1.105 1.666c1.119.742 1.8 1.799 1.918 2.974a3.693 3.693 0 0 1-1.072 2.986l-1.192 1.192 1.618.475C18.951 13.701 19 17.957 19 18h2c0-1.789-.956-5.285-4.396-6.952z"
fill="currentColor"
/>
<path
d="M9.5 12c2.206 0 4-1.794 4-4s-1.794-4-4-4-4 1.794-4 4 1.794 4 4 4zm0-6c1.103 0 2 .897 2 2s-.897 2-2 2-2-.897-2-2 .897-2 2-2zm1.5 7H8c-3.309 0-6 2.691-6 6v1h2v-1c0-2.206 1.794-4 4-4h3c2.206 0 4 1.794 4 4v1h2v-1c0-3.309-2.691-6-6-6z"
fill="currentColor"
/>
</svg>
);`;
const WatchersIcon = `export const WatchersIcons = (props) => (
<svg height="1em" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg" {...props}>
<path
d="m21.977 13.783-2-9A1.002 1.002 0 0 0 19 4h-3v2h2.198l.961 4.326A4.467 4.467 0 0 0 17.5 10c-1.953 0-3.603 1.258-4.224 3h-2.553c-.621-1.742-2.271-3-4.224-3-.587 0-1.145.121-1.659.326L5.802 6H8V4H5a1 1 0 0 0-.976.783l-2 9 .047.011A4.552 4.552 0 0 0 2 14.5C2 16.981 4.019 19 6.5 19c2.31 0 4.197-1.756 4.449-4h2.102c.252 2.244 2.139 4 4.449 4 2.481 0 4.5-2.019 4.5-4.5 0-.242-.034-.475-.071-.706l.048-.011zM6.5 17C5.122 17 4 15.878 4 14.5S5.122 12 6.5 12 9 13.122 9 14.5 7.878 17 6.5 17zm11 0c-1.379 0-2.5-1.122-2.5-2.5s1.121-2.5 2.5-2.5 2.5 1.122 2.5 2.5-1.121 2.5-2.5 2.5z"
fill="currentColor"
/>
</svg>
);`;
const BookIcon = `export const BookIcon = (props) => (
<svg height="1em" viewBox="0 0 24 24" width="1em" xmlns="http://www.w3.org/2000/svg" {...props}>
<path
d="M6 22h15v-2H6.012C5.55 19.988 5 19.805 5 19s.55-.988 1.012-1H21V4c0-1.103-.897-2-2-2H6c-1.206 0-3 .799-3 3v14c0 2.201 1.794 3 3 3zM5 8V5c0-.805.55-.988 1-1h13v12H5V8z"
fill="currentColor"
/>
<path d="M8 6h9v2H8z" fill="currentColor" />
</svg>
);`;
const ChevronRightIcon = `export const ChevronRightIcon = (props) => (
<svg
aria-hidden="true"
fill="none"
focusable="false"
height="1em"
role="presentation"
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth="1.5"
viewBox="0 0 24 24"
width="1em"
{...props}
>
<path d="m9 18 6-6-6-6" />
</svg>
);`;
const IconWrapper = `import {cn} from "@nextui-org/react";
const IconWrapper = ({children, className}) => (
<div className={cn(className, "flex items-center rounded-small justify-center w-7 h-7")}>
{children}
</div>
);`;
const ItemCounter = `const ItemCounter = ({number}) => (
<div className="flex items-center gap-1 text-default-400">
<span className="text-small">{number}</span>
<ChevronRightIcon className="text-xl" />
</div>
);`;
const App = `import {Listbox, ListboxItem} from "@nextui-org/react";
import {IconWrapper} from "./IconWrapper";
import {ItemCounter} from "./ItemCounter";
import {BugIcon} from "./BugIcon";
import {PullRequestIcon} from "./PullRequestIcon";
import {ChatIcon} from "./ChatIcon";
import {PlayCircleIcon} from "./PlayCircleIcon";
import {LayoutIcon} from "./LayoutIcon";
import {TagIcon} from "./TagIcon";
import {UsersIcon} from "./UsersIcon";
import {WatchersIcon} from "./WatchersIcon";
import {BookIcon} from "./BookIcon";
import {ChevronRightIcon} from "./ChevronRightIcon";
export default function App() {
return (
<Listbox
aria-label="User Menu"
onAction={(key) => alert(key)}
className="p-0 gap-0 divide-y divide-default-300/50 dark:divide-default-100/80 bg-content1 max-w-[300px] overflow-visible shadow-small rounded-medium"
itemClasses={{
base: "px-3 first:rounded-t-medium last:rounded-b-medium rounded-none gap-3 h-12 data-[hover=true]:bg-default-100/80",
}}
>
<ListboxItem
key="issues"
endContent={<ItemCounter number={13} />}
startContent={
<IconWrapper className="bg-success/10 text-success">
<BugIcon className="text-lg " />
</IconWrapper>
}
>
Issues
</ListboxItem>
<ListboxItem
key="pull_requests"
endContent={<ItemCounter number={6} />}
startContent={
<IconWrapper className="bg-primary/10 text-primary">
<PullRequestIcon className="text-lg " />
</IconWrapper>
}
>
Pull Requests
</ListboxItem>
<ListboxItem
key="discussions"
endContent={<ItemCounter number={293} />}
startContent={
<IconWrapper className="bg-secondary/10 text-secondary">
<ChatIcon className="text-lg " />
</IconWrapper>
}
>
Discussions
</ListboxItem>
<ListboxItem
key="actions"
endContent={<ItemCounter number={2} />}
startContent={
<IconWrapper className="bg-warning/10 text-warning">
<PlayCircleIcon className="text-lg " />
</IconWrapper>
}
>
Actions
</ListboxItem>
<ListboxItem
key="projects"
endContent={<ItemCounter number={4} />}
startContent={
<IconWrapper className="bg-default/50 text-foreground">
<LayoutIcon className="text-lg " />
</IconWrapper>
}
>
Projects
</ListboxItem>
<ListboxItem
key="releases"
className="group h-auto py-3"
endContent={<ItemCounter number={399} />}
startContent={
<IconWrapper className="bg-primary/10 text-primary">
<TagIcon className="text-lg" />
</IconWrapper>
}
textValue="Releases"
>
<div className="flex flex-col gap-1">
<span>Releases</span>
<div className="px-2 py-1 rounded-small bg-default-100 group-data-[hover=true]:bg-default-200">
<span className="text-tiny text-default-600">@nextui-org/react@2.0.10</span>
<div className="flex gap-2 text-tiny">
<span className="text-default-500">49 minutes ago</span>
<span className="text-success">Latest</span>
</div>
</div>
</div>
</ListboxItem>
<ListboxItem
key="contributors"
endContent={<ItemCounter number={79} />}
startContent={
<IconWrapper className="bg-warning/10 text-warning">
<UsersIcon />
</IconWrapper>
}
>
Contributors
</ListboxItem>
<ListboxItem
key="watchers"
endContent={<ItemCounter number={82} />}
startContent={
<IconWrapper className="bg-default/50 text-foreground">
<WatchersIcons />
</IconWrapper>
}
>
Watchers
</ListboxItem>
<ListboxItem
key="license"
endContent={<span className="text-small text-default-400">MIT</span>}
startContent={
<IconWrapper className="bg-danger/10 text-danger dark:text-danger-500">
<BookIcon />
</IconWrapper>
}
>
License
</ListboxItem>
</Listbox>
);
}`;
const react = {
"/App.jsx": App,
"/IconWrapper.jsx": IconWrapper,
"/ItemCounter.jsx": ItemCounter,
"/BugIcon.jsx": BugIcon,
"/PullRequestIcon.jsx": PullRequestIcon,
"/ChatIcon.jsx": ChatIcon,
"/PlayCircleIcon.jsx": PlayCircleIcon,
"/LayoutIcon.jsx": LayoutIcon,
"/TagIcon.jsx": TagIcon,
"/UsersIcon.jsx": UsersIcon,
"/WatchersIcons.jsx": WatchersIcon,
"/BookIcon.jsx": BookIcon,
"/ChevronRightIcon.jsx": ChevronRightIcon,
};
export default {
...react,
};
@@ -0,0 +1,169 @@
const AddNoteIcon = `export const AddNoteIcon = (props) => (
<svg
aria-hidden="true"
fill="none"
focusable="false"
height="1em"
role="presentation"
viewBox="0 0 24 24"
width="1em"
{...props}
>
<path
d="M7.37 22h9.25a4.87 4.87 0 0 0 4.87-4.87V8.37a4.87 4.87 0 0 0-4.87-4.87H7.37A4.87 4.87 0 0 0 2.5 8.37v8.75c0 2.7 2.18 4.88 4.87 4.88Z"
fill="currentColor"
opacity={0.4}
/>
<path
d="M8.29 6.29c-.42 0-.75-.34-.75-.75V2.75a.749.749 0 1 1 1.5 0v2.78c0 .42-.33.76-.75.76ZM15.71 6.29c-.42 0-.75-.34-.75-.75V2.75a.749.749 0 1 1 1.5 0v2.78c0 .42-.33.76-.75.76ZM12 14.75h-1.69V13c0-.41-.34-.75-.75-.75s-.75.34-.75.75v1.75H7c-.41 0-.75.34-.75.75s.34.75.75.75h1.81V18c0 .41.34.75.75.75s.75-.34.75-.75v-1.75H12c.41 0 .75-.34.75-.75s-.34-.75-.75-.75Z"
fill="currentColor"
/>
</svg>
);`;
const CopyDocumentIcon = `export const CopyDocumentIcon = (props) => (
<svg
aria-hidden="true"
fill="none"
focusable="false"
height="1em"
role="presentation"
viewBox="0 0 24 24"
width="1em"
{...props}
>
<path
d="M15.5 13.15h-2.17c-1.78 0-3.23-1.44-3.23-3.23V7.75c0-.41-.33-.75-.75-.75H6.18C3.87 7 2 8.5 2 11.18v6.64C2 20.5 3.87 22 6.18 22h5.89c2.31 0 4.18-1.5 4.18-4.18V13.9c0-.42-.34-.75-.75-.75Z"
fill="currentColor"
opacity={0.4}
/>
<path
d="M17.82 2H11.93C9.67 2 7.84 3.44 7.76 6.01c.06 0 .11-.01.17-.01h5.89C16.13 6 18 7.5 18 10.18V16.83c0 .06-.01.11-.01.16 2.23-.07 4.01-1.55 4.01-4.16V6.18C22 3.5 20.13 2 17.82 2Z"
fill="currentColor"
/>
<path
d="M11.98 7.15c-.31-.31-.84-.1-.84.33v2.62c0 1.1.93 2 2.07 2 .71.01 1.7.01 2.55.01.43 0 .65-.5.35-.8-1.09-1.09-3.03-3.04-4.13-4.16Z"
fill="currentColor"
/>
</svg>
);`;
const EditDocumentIcon = `export const EditDocumentIcon = (props) => (
<svg
aria-hidden="true"
fill="none"
focusable="false"
height="1em"
role="presentation"
viewBox="0 0 24 24"
width="1em"
{...props}
>
<path
d="M15.48 3H7.52C4.07 3 2 5.06 2 8.52v7.95C2 19.94 4.07 22 7.52 22h7.95c3.46 0 5.52-2.06 5.52-5.52V8.52C21 5.06 18.93 3 15.48 3Z"
fill="currentColor"
opacity={0.4}
/>
<path
d="M21.02 2.98c-1.79-1.8-3.54-1.84-5.38 0L14.51 4.1c-.1.1-.13.24-.09.37.7 2.45 2.66 4.41 5.11 5.11.03.01.08.01.11.01.1 0 .2-.04.27-.11l1.11-1.12c.91-.91 1.36-1.78 1.36-2.67 0-.9-.45-1.79-1.36-2.71ZM17.86 10.42c-.27-.13-.53-.26-.77-.41-.2-.12-.4-.25-.59-.39-.16-.1-.34-.25-.52-.4-.02-.01-.08-.06-.16-.14-.31-.25-.64-.59-.95-.96-.02-.02-.08-.08-.13-.17-.1-.11-.25-.3-.38-.51-.11-.14-.24-.34-.36-.55-.15-.25-.28-.5-.4-.76-.13-.28-.23-.54-.32-.79L7.9 10.72c-.35.35-.69 1.01-.76 1.5l-.43 2.98c-.09.63.08 1.22.47 1.61.33.33.78.5 1.28.5.11 0 .22-.01.33-.02l2.97-.42c.49-.07 1.15-.4 1.5-.76l5.38-5.38c-.25-.08-.5-.19-.78-.31Z"
fill="currentColor"
/>
</svg>
);`;
const DeleteDocumentIcon = `export const DeleteDocumentIcon = (props) => (
<svg
aria-hidden="true"
fill="none"
focusable="false"
height="1em"
role="presentation"
viewBox="0 0 24 24"
width="1em"
{...props}
>
<path
d="M21.07 5.23c-1.61-.16-3.22-.28-4.84-.37v-.01l-.22-1.3c-.15-.92-.37-2.3-2.71-2.3h-2.62c-2.33 0-2.55 1.32-2.71 2.29l-.21 1.28c-.93.06-1.86.12-2.79.21l-2.04.2c-.42.04-.72.41-.68.82.04.41.4.71.82.67l2.04-.2c5.24-.52 10.52-.32 15.82.21h.08c.38 0 .71-.29.75-.68a.766.766 0 0 0-.69-.82Z"
fill="currentColor"
/>
<path
d="M19.23 8.14c-.24-.25-.57-.39-.91-.39H5.68c-.34 0-.68.14-.91.39-.23.25-.36.59-.34.94l.62 10.26c.11 1.52.25 3.42 3.74 3.42h6.42c3.49 0 3.63-1.89 3.74-3.42l.62-10.25c.02-.36-.11-.7-.34-.95Z"
fill="currentColor"
opacity={0.399}
/>
<path
clipRule="evenodd"
d="M9.58 17a.75.75 0 0 1 .75-.75h3.33a.75.75 0 0 1 0 1.5h-3.33a.75.75 0 0 1-.75-.75ZM8.75 13a.75.75 0 0 1 .75-.75h5a.75.75 0 0 1 0 1.5h-5a.75.75 0 0 1-.75-.75Z"
fill="currentColor"
fillRule="evenodd"
/>
</svg>
);`;
const ListboxWrapper = `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>
);`;
const App = `import {Listbox, ListboxItem, cn} from "@nextui-org/react";
import {ListboxWrapper} from "./ListboxWrapper";
import {AddNoteIcon} from "./AddNoteIcon.jsx";
import {CopyDocumentIcon} from "./CopyDocumentIcon.jsx";
import {EditDocumentIcon} from "./EditDocumentIcon.jsx";
import {DeleteDocumentIcon} from "./DeleteDocumentIcon.jsx";
export default function App() {
const iconClasses = "text-xl text-default-500 pointer-events-none flex-shrink-0";
return (
<ListboxWrapper>
<Listbox variant="flat" aria-label="Listbox menu with descriptions">
<ListboxItem
key="new"
description="Create a new file"
startContent={<AddNoteIcon className={iconClasses} />}
>
New file
</ListboxItem>
<ListboxItem
key="copy"
description="Copy the file link"
startContent={<CopyDocumentIcon className={iconClasses} />}
>
Copy link
</ListboxItem>
<ListboxItem
key="edit"
showDivider
description="Allows you to edit the file"
startContent={<EditDocumentIcon className={iconClasses} />}
>
Edit file
</ListboxItem>
<ListboxItem
key="delete"
className="text-danger"
color="danger"
description="Permanently delete the file"
startContent={<DeleteDocumentIcon className={cn(iconClasses, "text-danger")} />}
>
Delete file
</ListboxItem>
</Listbox>
</ListboxWrapper>
);
}`;
const react = {
"/App.jsx": App,
"/ListboxWrapper.jsx": ListboxWrapper,
"/AddNoteIcon.jsx": AddNoteIcon,
"/CopyDocumentIcon.jsx": CopyDocumentIcon,
"/EditDocumentIcon.jsx": EditDocumentIcon,
"/DeleteDocumentIcon.jsx": DeleteDocumentIcon,
};
export default {
...react,
};
@@ -0,0 +1,36 @@
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>
);`;
const App = `import {Listbox, ListboxItem} from "@nextui-org/react";
import {ListboxWrapper} from "./ListboxWrapper";
export default function App() {
return (
<ListboxWrapper>
<Listbox
aria-label="Example with disabled actions"
disabledKeys={["edit", "delete"]}
onAction={(key) => alert(key)}
>
<ListboxItem key="new">New file</ListboxItem>
<ListboxItem key="copy">Copy link</ListboxItem>
<ListboxItem key="edit">Edit file</ListboxItem>
<ListboxItem key="delete" className="text-danger" color="danger">
Delete file
</ListboxItem>
</Listbox>
</ListboxWrapper>
);
}`;
const react = {
"/App.jsx": App,
"/ListboxWrapper.jsx": ListboxWrapper,
};
export default {
...react,
};
@@ -0,0 +1,58 @@
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>
);`;
const App = `import {Listbox, ListboxItem} from "@nextui-org/react";
import {ListboxWrapper} from "./ListboxWrapper";
export default function App() {
const items = [
{
key: "new",
label: "New file",
},
{
key: "copy",
label: "Copy link",
},
{
key: "edit",
label: "Edit file",
},
{
key: "delete",
label: "Delete file",
}
];
return (
<ListboxWrapper>
<Listbox
items={items}
aria-label="Dynamic Actions"
onAction={(key) => alert(key)}
>
{(item) => (
<ListboxItem
key={item.key}
color={item.key === "delete" ? "danger" : "default"}
className={item.key === "delete" ? "text-danger" : ""}
>
{item.label}
</ListboxItem>
)}
</Listbox>
</ListboxWrapper>
);
}`;
const react = {
"/App.jsx": App,
"/ListboxWrapper.jsx": ListboxWrapper,
};
export default {
...react,
};
@@ -0,0 +1,165 @@
const AddNoteIcon = `export const AddNoteIcon = (props) => (
<svg
aria-hidden="true"
fill="none"
focusable="false"
height="1em"
role="presentation"
viewBox="0 0 24 24"
width="1em"
{...props}
>
<path
d="M7.37 22h9.25a4.87 4.87 0 0 0 4.87-4.87V8.37a4.87 4.87 0 0 0-4.87-4.87H7.37A4.87 4.87 0 0 0 2.5 8.37v8.75c0 2.7 2.18 4.88 4.87 4.88Z"
fill="currentColor"
opacity={0.4}
/>
<path
d="M8.29 6.29c-.42 0-.75-.34-.75-.75V2.75a.749.749 0 1 1 1.5 0v2.78c0 .42-.33.76-.75.76ZM15.71 6.29c-.42 0-.75-.34-.75-.75V2.75a.749.749 0 1 1 1.5 0v2.78c0 .42-.33.76-.75.76ZM12 14.75h-1.69V13c0-.41-.34-.75-.75-.75s-.75.34-.75.75v1.75H7c-.41 0-.75.34-.75.75s.34.75.75.75h1.81V18c0 .41.34.75.75.75s.75-.34.75-.75v-1.75H12c.41 0 .75-.34.75-.75s-.34-.75-.75-.75Z"
fill="currentColor"
/>
</svg>
);`;
const CopyDocumentIcon = `export const CopyDocumentIcon = (props) => (
<svg
aria-hidden="true"
fill="none"
focusable="false"
height="1em"
role="presentation"
viewBox="0 0 24 24"
width="1em"
{...props}
>
<path
d="M15.5 13.15h-2.17c-1.78 0-3.23-1.44-3.23-3.23V7.75c0-.41-.33-.75-.75-.75H6.18C3.87 7 2 8.5 2 11.18v6.64C2 20.5 3.87 22 6.18 22h5.89c2.31 0 4.18-1.5 4.18-4.18V13.9c0-.42-.34-.75-.75-.75Z"
fill="currentColor"
opacity={0.4}
/>
<path
d="M17.82 2H11.93C9.67 2 7.84 3.44 7.76 6.01c.06 0 .11-.01.17-.01h5.89C16.13 6 18 7.5 18 10.18V16.83c0 .06-.01.11-.01.16 2.23-.07 4.01-1.55 4.01-4.16V6.18C22 3.5 20.13 2 17.82 2Z"
fill="currentColor"
/>
<path
d="M11.98 7.15c-.31-.31-.84-.1-.84.33v2.62c0 1.1.93 2 2.07 2 .71.01 1.7.01 2.55.01.43 0 .65-.5.35-.8-1.09-1.09-3.03-3.04-4.13-4.16Z"
fill="currentColor"
/>
</svg>
);`;
const EditDocumentIcon = `export const EditDocumentIcon = (props) => (
<svg
aria-hidden="true"
fill="none"
focusable="false"
height="1em"
role="presentation"
viewBox="0 0 24 24"
width="1em"
{...props}
>
<path
d="M15.48 3H7.52C4.07 3 2 5.06 2 8.52v7.95C2 19.94 4.07 22 7.52 22h7.95c3.46 0 5.52-2.06 5.52-5.52V8.52C21 5.06 18.93 3 15.48 3Z"
fill="currentColor"
opacity={0.4}
/>
<path
d="M21.02 2.98c-1.79-1.8-3.54-1.84-5.38 0L14.51 4.1c-.1.1-.13.24-.09.37.7 2.45 2.66 4.41 5.11 5.11.03.01.08.01.11.01.1 0 .2-.04.27-.11l1.11-1.12c.91-.91 1.36-1.78 1.36-2.67 0-.9-.45-1.79-1.36-2.71ZM17.86 10.42c-.27-.13-.53-.26-.77-.41-.2-.12-.4-.25-.59-.39-.16-.1-.34-.25-.52-.4-.02-.01-.08-.06-.16-.14-.31-.25-.64-.59-.95-.96-.02-.02-.08-.08-.13-.17-.1-.11-.25-.3-.38-.51-.11-.14-.24-.34-.36-.55-.15-.25-.28-.5-.4-.76-.13-.28-.23-.54-.32-.79L7.9 10.72c-.35.35-.69 1.01-.76 1.5l-.43 2.98c-.09.63.08 1.22.47 1.61.33.33.78.5 1.28.5.11 0 .22-.01.33-.02l2.97-.42c.49-.07 1.15-.4 1.5-.76l5.38-5.38c-.25-.08-.5-.19-.78-.31Z"
fill="currentColor"
/>
</svg>
);`;
const DeleteDocumentIcon = `export const DeleteDocumentIcon = (props) => (
<svg
aria-hidden="true"
fill="none"
focusable="false"
height="1em"
role="presentation"
viewBox="0 0 24 24"
width="1em"
{...props}
>
<path
d="M21.07 5.23c-1.61-.16-3.22-.28-4.84-.37v-.01l-.22-1.3c-.15-.92-.37-2.3-2.71-2.3h-2.62c-2.33 0-2.55 1.32-2.71 2.29l-.21 1.28c-.93.06-1.86.12-2.79.21l-2.04.2c-.42.04-.72.41-.68.82.04.41.4.71.82.67l2.04-.2c5.24-.52 10.52-.32 15.82.21h.08c.38 0 .71-.29.75-.68a.766.766 0 0 0-.69-.82Z"
fill="currentColor"
/>
<path
d="M19.23 8.14c-.24-.25-.57-.39-.91-.39H5.68c-.34 0-.68.14-.91.39-.23.25-.36.59-.34.94l.62 10.26c.11 1.52.25 3.42 3.74 3.42h6.42c3.49 0 3.63-1.89 3.74-3.42l.62-10.25c.02-.36-.11-.7-.34-.95Z"
fill="currentColor"
opacity={0.399}
/>
<path
clipRule="evenodd"
d="M9.58 17a.75.75 0 0 1 .75-.75h3.33a.75.75 0 0 1 0 1.5h-3.33a.75.75 0 0 1-.75-.75ZM8.75 13a.75.75 0 0 1 .75-.75h5a.75.75 0 0 1 0 1.5h-5a.75.75 0 0 1-.75-.75Z"
fill="currentColor"
fillRule="evenodd"
/>
</svg>
);`;
const ListboxWrapper = `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>
);`;
const App = `import {Listbox, ListboxItem, cn} from "@nextui-org/react";
import {ListboxWrapper} from "./ListboxWrapper";
import {AddNoteIcon} from "./AddNoteIcon.jsx";
import {CopyDocumentIcon} from "./CopyDocumentIcon.jsx";
import {EditDocumentIcon} from "./EditDocumentIcon.jsx";
import {DeleteDocumentIcon} from "./DeleteDocumentIcon.jsx";
export default function App() {
const iconClasses = "text-xl text-default-500 pointer-events-none flex-shrink-0";
return (
<ListboxWrapper>
<Listbox variant="faded" aria-label="Listbox menu with icons">
<ListboxItem
key="new"
startContent={<AddNoteIcon className={iconClasses} />}
>
New file
</ListboxItem>
<ListboxItem
key="copy"
startContent={<CopyDocumentIcon className={iconClasses} />}
>
Copy link
</ListboxItem>
<ListboxItem
key="edit"
showDivider
startContent={<EditDocumentIcon className={iconClasses} />}
>
Edit file
</ListboxItem>
<ListboxItem
key="delete"
className="text-danger"
color="danger"
startContent={<DeleteDocumentIcon className={cn(iconClasses, "text-danger")} />}
>
Delete file
</ListboxItem>
</Listbox>
</ListboxWrapper>
);
}`;
const react = {
"/App.jsx": App,
"/ListboxWrapper.jsx": ListboxWrapper,
"/AddNoteIcon.jsx": AddNoteIcon,
"/CopyDocumentIcon.jsx": CopyDocumentIcon,
"/EditDocumentIcon.jsx": EditDocumentIcon,
"/DeleteDocumentIcon.jsx": DeleteDocumentIcon,
};
export default {
...react,
};
@@ -0,0 +1,23 @@
import usage from "./usage";
import dynamic from "./dynamic";
import disabledKeys from "./disabled-keys";
import variants from "./variants";
import singleSelection from "./single-selection";
import multipleSelection from "./multiple-selection";
import icons from "./icons";
import description from "./description";
import sections from "./sections";
import customStyles from "./custom-styles";
export const listboxContent = {
usage,
dynamic,
disabledKeys,
variants,
singleSelection,
multipleSelection,
icons,
description,
sections,
customStyles,
};
@@ -0,0 +1,48 @@
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>
);`;
const App = `import {Listbox, ListboxItem} from "@nextui-org/react";
import {ListboxWrapper} from "./ListboxWrapper";
export default function App() {
const [selectedKeys, setSelectedKeys] = React.useState(new Set(["text"]));
const selectedValue = React.useMemo(
() => Array.from(selectedKeys).join(", "),
[selectedKeys]
);
return (
<div className="flex flex-col gap-2">
<ListboxWrapper>
<Listbox
aria-label="Multiple selection example"
variant="flat"
disallowEmptySelection
selectionMode="multiple"
selectedKeys={selectedKeys}
onSelectionChange={setSelectedKeys}
>
<ListboxItem key="text">Text</ListboxItem>
<ListboxItem key="number">Number</ListboxItem>
<ListboxItem key="date">Date</ListboxItem>
<ListboxItem key="single_date">Single Date</ListboxItem>
<ListboxItem key="iteration">Iteration</ListboxItem>
</Listbox>
</ListboxWrapper>
<p className="text-small text-default-500">Selected value: {selectedValue}</p>
</div>
);
}`;
const react = {
"/App.jsx": App,
"/ListboxWrapper.jsx": ListboxWrapper,
};
export default {
...react,
};
@@ -0,0 +1,172 @@
const AddNoteIcon = `export const AddNoteIcon = (props) => (
<svg
aria-hidden="true"
fill="none"
focusable="false"
height="1em"
role="presentation"
viewBox="0 0 24 24"
width="1em"
{...props}
>
<path
d="M7.37 22h9.25a4.87 4.87 0 0 0 4.87-4.87V8.37a4.87 4.87 0 0 0-4.87-4.87H7.37A4.87 4.87 0 0 0 2.5 8.37v8.75c0 2.7 2.18 4.88 4.87 4.88Z"
fill="currentColor"
opacity={0.4}
/>
<path
d="M8.29 6.29c-.42 0-.75-.34-.75-.75V2.75a.749.749 0 1 1 1.5 0v2.78c0 .42-.33.76-.75.76ZM15.71 6.29c-.42 0-.75-.34-.75-.75V2.75a.749.749 0 1 1 1.5 0v2.78c0 .42-.33.76-.75.76ZM12 14.75h-1.69V13c0-.41-.34-.75-.75-.75s-.75.34-.75.75v1.75H7c-.41 0-.75.34-.75.75s.34.75.75.75h1.81V18c0 .41.34.75.75.75s.75-.34.75-.75v-1.75H12c.41 0 .75-.34.75-.75s-.34-.75-.75-.75Z"
fill="currentColor"
/>
</svg>
);`;
const CopyDocumentIcon = `export const CopyDocumentIcon = (props) => (
<svg
aria-hidden="true"
fill="none"
focusable="false"
height="1em"
role="presentation"
viewBox="0 0 24 24"
width="1em"
{...props}
>
<path
d="M15.5 13.15h-2.17c-1.78 0-3.23-1.44-3.23-3.23V7.75c0-.41-.33-.75-.75-.75H6.18C3.87 7 2 8.5 2 11.18v6.64C2 20.5 3.87 22 6.18 22h5.89c2.31 0 4.18-1.5 4.18-4.18V13.9c0-.42-.34-.75-.75-.75Z"
fill="currentColor"
opacity={0.4}
/>
<path
d="M17.82 2H11.93C9.67 2 7.84 3.44 7.76 6.01c.06 0 .11-.01.17-.01h5.89C16.13 6 18 7.5 18 10.18V16.83c0 .06-.01.11-.01.16 2.23-.07 4.01-1.55 4.01-4.16V6.18C22 3.5 20.13 2 17.82 2Z"
fill="currentColor"
/>
<path
d="M11.98 7.15c-.31-.31-.84-.1-.84.33v2.62c0 1.1.93 2 2.07 2 .71.01 1.7.01 2.55.01.43 0 .65-.5.35-.8-1.09-1.09-3.03-3.04-4.13-4.16Z"
fill="currentColor"
/>
</svg>
);`;
const EditDocumentIcon = `export const EditDocumentIcon = (props) => (
<svg
aria-hidden="true"
fill="none"
focusable="false"
height="1em"
role="presentation"
viewBox="0 0 24 24"
width="1em"
{...props}
>
<path
d="M15.48 3H7.52C4.07 3 2 5.06 2 8.52v7.95C2 19.94 4.07 22 7.52 22h7.95c3.46 0 5.52-2.06 5.52-5.52V8.52C21 5.06 18.93 3 15.48 3Z"
fill="currentColor"
opacity={0.4}
/>
<path
d="M21.02 2.98c-1.79-1.8-3.54-1.84-5.38 0L14.51 4.1c-.1.1-.13.24-.09.37.7 2.45 2.66 4.41 5.11 5.11.03.01.08.01.11.01.1 0 .2-.04.27-.11l1.11-1.12c.91-.91 1.36-1.78 1.36-2.67 0-.9-.45-1.79-1.36-2.71ZM17.86 10.42c-.27-.13-.53-.26-.77-.41-.2-.12-.4-.25-.59-.39-.16-.1-.34-.25-.52-.4-.02-.01-.08-.06-.16-.14-.31-.25-.64-.59-.95-.96-.02-.02-.08-.08-.13-.17-.1-.11-.25-.3-.38-.51-.11-.14-.24-.34-.36-.55-.15-.25-.28-.5-.4-.76-.13-.28-.23-.54-.32-.79L7.9 10.72c-.35.35-.69 1.01-.76 1.5l-.43 2.98c-.09.63.08 1.22.47 1.61.33.33.78.5 1.28.5.11 0 .22-.01.33-.02l2.97-.42c.49-.07 1.15-.4 1.5-.76l5.38-5.38c-.25-.08-.5-.19-.78-.31Z"
fill="currentColor"
/>
</svg>
);`;
const DeleteDocumentIcon = `export const DeleteDocumentIcon = (props) => (
<svg
aria-hidden="true"
fill="none"
focusable="false"
height="1em"
role="presentation"
viewBox="0 0 24 24"
width="1em"
{...props}
>
<path
d="M21.07 5.23c-1.61-.16-3.22-.28-4.84-.37v-.01l-.22-1.3c-.15-.92-.37-2.3-2.71-2.3h-2.62c-2.33 0-2.55 1.32-2.71 2.29l-.21 1.28c-.93.06-1.86.12-2.79.21l-2.04.2c-.42.04-.72.41-.68.82.04.41.4.71.82.67l2.04-.2c5.24-.52 10.52-.32 15.82.21h.08c.38 0 .71-.29.75-.68a.766.766 0 0 0-.69-.82Z"
fill="currentColor"
/>
<path
d="M19.23 8.14c-.24-.25-.57-.39-.91-.39H5.68c-.34 0-.68.14-.91.39-.23.25-.36.59-.34.94l.62 10.26c.11 1.52.25 3.42 3.74 3.42h6.42c3.49 0 3.63-1.89 3.74-3.42l.62-10.25c.02-.36-.11-.7-.34-.95Z"
fill="currentColor"
opacity={0.399}
/>
<path
clipRule="evenodd"
d="M9.58 17a.75.75 0 0 1 .75-.75h3.33a.75.75 0 0 1 0 1.5h-3.33a.75.75 0 0 1-.75-.75ZM8.75 13a.75.75 0 0 1 .75-.75h5a.75.75 0 0 1 0 1.5h-5a.75.75 0 0 1-.75-.75Z"
fill="currentColor"
fillRule="evenodd"
/>
</svg>
);`;
const ListboxWrapper = `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>
);`;
const App = `import {Listbox, ListboxItem, ListboxSection, cn} from "@nextui-org/react";
import {ListboxWrapper} from "./ListboxWrapper";
import {AddNoteIcon} from "./AddNoteIcon.jsx";
import {CopyDocumentIcon} from "./CopyDocumentIcon.jsx";
import {EditDocumentIcon} from "./EditDocumentIcon.jsx";
import {DeleteDocumentIcon} from "./DeleteDocumentIcon.jsx";
export default function App() {
const iconClasses = "text-xl text-default-500 pointer-events-none flex-shrink-0";
return (
<ListboxWrapper>
<Listbox variant="flat" aria-label="Listbox menu with sections">
<ListboxSection title="Actions" showDivider>
<ListboxItem
key="new"
description="Create a new file"
startContent={<AddNoteIcon className={iconClasses} />}
>
New file
</ListboxItem>
<ListboxItem
key="copy"
description="Copy the file link"
startContent={<CopyDocumentIcon className={iconClasses} />}
>
Copy link
</ListboxItem>
<ListboxItem
key="edit"
description="Allows you to edit the file"
startContent={<EditDocumentIcon className={iconClasses} />}
>
Edit file
</ListboxItem>
</ListboxSection>
<ListboxSection title="Danger zone">
<ListboxItem
key="delete"
className="text-danger"
color="danger"
description="Permanently delete the file"
startContent={<DeleteDocumentIcon className={cn(iconClasses, "text-danger")} />}
>
Delete file
</ListboxItem>
</ListboxSection>
</Listbox>
</ListboxWrapper>
);
}`;
const react = {
"/App.jsx": App,
"/ListboxWrapper.jsx": ListboxWrapper,
"/AddNoteIcon.jsx": AddNoteIcon,
"/CopyDocumentIcon.jsx": CopyDocumentIcon,
"/EditDocumentIcon.jsx": EditDocumentIcon,
"/DeleteDocumentIcon.jsx": DeleteDocumentIcon,
};
export default {
...react,
};
@@ -0,0 +1,48 @@
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>
);`;
const App = `import {Listbox, ListboxItem} from "@nextui-org/react";
import {ListboxWrapper} from "./ListboxWrapper";
export default function App() {
const [selectedKeys, setSelectedKeys] = React.useState(new Set(["text"]));
const selectedValue = React.useMemo(
() => Array.from(selectedKeys).join(", "),
[selectedKeys]
);
return (
<div className="flex flex-col gap-2">
<ListboxWrapper>
<Listbox
aria-label="Single selection example"
variant="flat"
disallowEmptySelection
selectionMode="single"
selectedKeys={selectedKeys}
onSelectionChange={setSelectedKeys}
>
<ListboxItem key="text">Text</ListboxItem>
<ListboxItem key="number">Number</ListboxItem>
<ListboxItem key="date">Date</ListboxItem>
<ListboxItem key="single_date">Single Date</ListboxItem>
<ListboxItem key="iteration">Iteration</ListboxItem>
</Listbox>
</ListboxWrapper>
<p className="text-small text-default-500">Selected value: {selectedValue}</p>
</div>
);
}`;
const react = {
"/App.jsx": App,
"/ListboxWrapper.jsx": ListboxWrapper,
};
export default {
...react,
};
@@ -0,0 +1,35 @@
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>
);`;
const App = `import {Listbox, ListboxItem} from "@nextui-org/react";
import {ListboxWrapper} from "./ListboxWrapper";
export default function App() {
return (
<ListboxWrapper>
<Listbox
aria-label="Actions"
onAction={(key) => alert(key)}
>
<ListboxItem key="new">New file</ListboxItem>
<ListboxItem key="copy">Copy link</ListboxItem>
<ListboxItem key="edit">Edit file</ListboxItem>
<ListboxItem key="delete" className="text-danger" color="danger">
Delete file
</ListboxItem>
</Listbox>
</ListboxWrapper>
);
}`;
const react = {
"/App.jsx": App,
"/ListboxWrapper.jsx": ListboxWrapper,
};
export default {
...react,
};
@@ -0,0 +1,72 @@
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>
);`;
const App = `import {Listbox, ListboxItem, RadioGroup, Radio} from "@nextui-org/react";
import {ListboxWrapper} from "./ListboxWrapper";
export default function App() {
const [selectedVariant, setSelectedVariant] = React.useState("solid")
const [selectedColor, setSelectedColor] = React.useState("default")
const variants = ["solid", "bordered", "light", "flat", "faded", "shadow"];
const colors = ["default", "primary", "secondary", "success", "warning", "danger"];
return (
<div className="flex flex-col gap-4">
<ListboxWrapper>
<Listbox
aria-label="Listbox Variants"
color={selectedColor}
variant={selectedVariant}
>
<ListboxItem key="new">New file</ListboxItem>
<ListboxItem key="copy">Copy link</ListboxItem>
<ListboxItem key="edit">Edit file</ListboxItem>
<ListboxItem key="delete" className="text-danger" color="danger">
Delete file
</ListboxItem>
</Listbox>
</ListboxWrapper>
<div className="flex flex-col gap-2">
<RadioGroup
label="Select listbox item variant"
orientation="horizontal"
color={selectedVariant}
defaultValue="solid"
onValueChange={setSelectedVariant}
>
{variants.map((variant) => (
<Radio key={variant} value={variant} className="capitalize">
{variant}
</Radio>
))}
</RadioGroup>
<RadioGroup
label="Select listbox item color"
orientation="horizontal"
color={selectedColor}
defaultValue="default"
onValueChange={setSelectedColor}
>
{colors.map((color) => (
<Radio key={color} value={color} className="capitalize">
{color}
</Radio>
))}
</RadioGroup>
</div>
</div>
);
}`;
const react = {
"/App.jsx": App,
"/ListboxWrapper.jsx": ListboxWrapper,
};
export default {
...react,
};
@@ -16,6 +16,7 @@ export default function App() {
<div className="flex flex-wrap gap-3">
{backdrops.map((b) => (
<Button
key={b}
variant="flat"
color="warning"
onPress={() => handleOpen(b)}
@@ -50,7 +51,7 @@ export default function App() {
</p>
</ModalBody>
<ModalFooter>
<Button color="danger" variant="light" onClick={onClose}>
<Button color="danger" variant="light" onPress={onClose}>
Close
</Button>
<Button color="primary" onPress={onClose}>
@@ -38,7 +38,7 @@ export default function App() {
</p>
</ModalBody>
<ModalFooter>
<Button color="danger" variant="light" onClick={onClose}>
<Button color="danger" variant="light" onPress={onClose}>
Close
</Button>
<Button color="primary" onPress={onClose}>
@@ -55,7 +55,7 @@ export default function App() {
</p>
</ModalBody>
<ModalFooter>
<Button color="danger" variant="light" onClick={onClose}>
<Button color="danger" variant="light" onPress={onClose}>
Close
</Button>
<Button color="primary" onPress={onClose}>
@@ -44,7 +44,7 @@ export default function App() {
</p>
</ModalBody>
<ModalFooter>
<Button color="foreground" variant="light" onClick={onClose}>
<Button color="foreground" variant="light" onPress={onClose}>
Close
</Button>
<Button className="bg-[#6f4ef2] shadow-lg shadow-indigo-500/20" onPress={onClose}>
+2 -2
View File
@@ -40,7 +40,7 @@ const LockIcon = `export const LockIcon = (props) => (
);`;
const App = `import {Modal, ModalContent, ModalHeader, ModalBody, ModalFooter, Button, useDisclosure, Checkbox, Input, Link} from "@nextui-org/react";
import {MailFilledIcon} from './MailIcon.jsx';
import {MailIcon} from './MailIcon.jsx';
import {LockIcon} from './LockIcon.jsx';
export default function App() {
@@ -91,7 +91,7 @@ export default function App() {
</div>
</ModalBody>
<ModalFooter>
<Button color="danger" variant="flat" onClick={onClose}>
<Button color="danger" variant="flat" onPress={onClose}>
Close
</Button>
<Button color="primary" onPress={onClose}>
@@ -31,7 +31,7 @@ export default function App() {
</p>
</ModalBody>
<ModalFooter>
<Button color="danger" variant="light" onClick={onClose}>
<Button color="danger" variant="light" onPress={onClose}>
Close
</Button>
<Button color="primary" onPress={onClose}>
+127 -1
View File
@@ -104,7 +104,128 @@ export default function App() {
</p>
</ModalBody>
<ModalFooter>
<Button color="danger" variant="light" onClick={onClose}>
<Button color="danger" variant="light" onPress={onClose}>
Close
</Button>
<Button color="primary" onPress={onClose}>
Action
</Button>
</ModalFooter>
</>
)}
</ModalContent>
</Modal>
</div>
);
}`;
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}>
@@ -123,6 +244,11 @@ const react = {
"/App.jsx": App,
};
const reactTs = {
"/App.tsx": AppTs,
};
export default {
...react,
...reactTs,
};
@@ -42,7 +42,7 @@ export default function App() {
</p>
</ModalBody>
<ModalFooter>
<Button color="danger" variant="light" onClick={onClose}>
<Button color="danger" variant="light" onPress={onClose}>
Close
</Button>
<Button color="primary" onPress={onClose}>
+2 -2
View File
@@ -16,7 +16,7 @@ export default function App() {
<>
<div className="flex flex-wrap gap-3">
{sizes.map((size) => (
<Button onPress={() => handleOpen(size)}>Open {size}</Button>
<Button key={size} onPress={() => handleOpen(size)}>Open {size}</Button>
))}
</div>
<Modal
@@ -46,7 +46,7 @@ export default function App() {
</p>
</ModalBody>
<ModalFooter>
<Button color="danger" variant="light" onClick={onClose}>
<Button color="danger" variant="light" onPress={onClose}>
Close
</Button>
<Button color="primary" onPress={onClose}>
+1 -1
View File
@@ -31,7 +31,7 @@ export default function App() {
</p>
</ModalBody>
<ModalFooter>
<Button color="danger" variant="light" onClick={onClose}>
<Button color="danger" variant="light" onPress={onClose}>
Close
</Button>
<Button color="primary" onPress={onClose}>
@@ -79,12 +79,13 @@ export default function App() {
<Input
classNames={{
base: "max-w-full sm:max-w-[10rem] h-10",
mainWrapper: "h-full",
input: "text-small",
inputWrapper: "font-normal text-default-500 bg-default-400/20 dark:bg-default-500/20",
inputWrapper: "h-full font-normal text-default-500 bg-default-400/20 dark:bg-default-500/20",
}}
placeholder="Type to search..."
size="sm"
startContent={<SearchLinearIcon size={18} />}
startContent={<SearchIcon size={18} />}
type="search"
/>
<Dropdown placement="bottom-end">
@@ -7,7 +7,7 @@ export default function App() {
return (
<div className="flex flex-wrap gap-4 items-center">
{colors.map((color) => (
<Pagination total={10} initialPage={1} color={color} />
<Pagination key={color} total={10} initialPage={1} color={color} />
))}
</div>
);
@@ -5,7 +5,7 @@ export default function App() {
return (
<div className="flex flex-col gap-5">
<p className="text-default-500">Selected Page: {currentPage}</p>
<p className="text-small text-default-500">Selected Page: {currentPage}</p>
<Pagination
total={10}
color="secondary"
@@ -7,7 +7,7 @@ export default function App() {
return (
<div className="flex flex-wrap gap-4 items-center">
{radius.map((r) => (
<Pagination total={10} initialPage={1} radius={r} />
<Pagination key={r} total={10} initialPage={1} radius={r} />
))}
</div>
);
@@ -7,7 +7,7 @@ export default function App() {
return (
<div className="flex flex-wrap gap-4 items-center">
{sizes.map((size) => (
<Pagination total={10} initialPage={1} size={size} />
<Pagination key={size} total={10} initialPage={1} size={size} />
))}
</div>
);
@@ -7,7 +7,7 @@ export default function App() {
return (
<div className="flex flex-wrap gap-4 items-center">
{variants.map((variant) => (
<Pagination total={10} initialPage={1} variant={variant} />
<Pagination key={variant} total={10} initialPage={1} variant={variant} />
))}
</div>
);
@@ -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,

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