Compare commits

...

67 Commits

Author SHA1 Message Date
shadcn
f5a0945caf chore: add changelog 2026-01-20 19:09:05 +04:00
shadcn
eecffac153 fix 2026-01-20 14:01:55 +04:00
shadcn
93b1b012f1 fix 2026-01-20 13:55:54 +04:00
shadcn
113be481d5 fix: create page 2026-01-20 13:32:33 +04:00
shadcn
90952b1b0c docs: update 2026-01-20 13:08:50 +04:00
shadcn
c470caca45 Merge branch 'main' into shadcn/base-docs 2026-01-20 12:58:40 +04:00
shadcn
63ad095a34 Merge branch 'main' into shadcn/base-docs 2026-01-20 12:53:09 +04:00
shadcn
d3b3ecde53 fi 2026-01-20 12:52:55 +04:00
shadcn
f337ccef13 fix 2026-01-20 12:42:04 +04:00
shadcn
818c060efc fix 2026-01-20 11:46:12 +04:00
shadcn
528b27a63f feat: add docs for sidebar 2026-01-20 11:35:07 +04:00
shadcn
a7bd5d2d22 fix: tabs 2026-01-20 10:22:08 +04:00
shadcn
62b1b89bcc fix: tabs 2026-01-20 09:09:41 +04:00
shadcn
97371b578e feat: add more components 2026-01-19 22:31:25 +04:00
shadcn
d6878556ba feat: add spinner and switch 2026-01-19 21:34:56 +04:00
shadcn
e7d802fc07 feat: add skeleton, slider and sonner 2026-01-19 21:18:56 +04:00
shadcn
572e5d4532 feat: more components 2026-01-19 18:04:17 +04:00
shadcn
90f8057a24 feat: more components 2026-01-19 17:23:10 +04:00
shadcn
151ae29653 feat: add more components 2026-01-19 17:05:41 +04:00
shadcn
40e5bf5eff feat: add native-select 2026-01-19 16:41:52 +04:00
shadcn
1fd52c41f9 feat: add menubar 2026-01-19 16:23:09 +04:00
shadcn
63c28a1496 feat: add kbd and label 2026-01-19 16:12:19 +04:00
shadcn
6a9d68cc2c feat: add item 2026-01-19 15:56:32 +04:00
shadcn
587c76f46f feat: add input-otp 2026-01-19 15:34:34 +04:00
shadcn
52a4b1d466 feat: add input-group 2026-01-19 13:56:42 +04:00
shadcn
7ecba59894 feat: add input 2026-01-19 12:49:14 +04:00
shadcn
4073811f64 Merge branch 'main' into shadcn/base-docs 2026-01-19 11:41:24 +04:00
shadcn
5f966a282a Merge branch 'main' into shadcn/base-docs
# Conflicts:
#	apps/v4/lib/llm.ts
#	apps/v4/lib/registry.ts
#	apps/v4/public/r/styles/base-lyra/accordion-example.json
#	apps/v4/public/r/styles/base-lyra/accordion.json
#	apps/v4/public/r/styles/base-lyra/alert-dialog-example.json
#	apps/v4/public/r/styles/base-lyra/alert-example.json
#	apps/v4/public/r/styles/base-lyra/avatar-example.json
#	apps/v4/public/r/styles/base-lyra/badge-example.json
#	apps/v4/public/r/styles/base-lyra/breadcrumb.json
#	apps/v4/public/r/styles/base-lyra/button-example.json
#	apps/v4/public/r/styles/base-lyra/button-group-example.json
#	apps/v4/public/r/styles/base-lyra/calendar-example.json
#	apps/v4/public/r/styles/base-lyra/calendar.json
#	apps/v4/public/r/styles/base-lyra/card-example.json
#	apps/v4/public/r/styles/base-lyra/carousel.json
#	apps/v4/public/r/styles/base-lyra/chart-example.json
#	apps/v4/public/r/styles/base-lyra/chatgpt.json
#	apps/v4/public/r/styles/base-lyra/checkbox.json
#	apps/v4/public/r/styles/base-lyra/collapsible-example.json
#	apps/v4/public/r/styles/base-lyra/combobox-example.json
#	apps/v4/public/r/styles/base-lyra/combobox.json
#	apps/v4/public/r/styles/base-lyra/command-example.json
#	apps/v4/public/r/styles/base-lyra/command.json
#	apps/v4/public/r/styles/base-lyra/component-example.json
#	apps/v4/public/r/styles/base-lyra/context-menu-example.json
#	apps/v4/public/r/styles/base-lyra/context-menu.json
#	apps/v4/public/r/styles/base-lyra/dialog-example.json
#	apps/v4/public/r/styles/base-lyra/dialog.json
#	apps/v4/public/r/styles/base-lyra/dropdown-menu-example.json
#	apps/v4/public/r/styles/base-lyra/dropdown-menu.json
#	apps/v4/public/r/styles/base-lyra/empty-example.json
#	apps/v4/public/r/styles/base-lyra/github.json
#	apps/v4/public/r/styles/base-lyra/input-group-example.json
#	apps/v4/public/r/styles/base-lyra/input-otp-example.json
#	apps/v4/public/r/styles/base-lyra/input-otp.json
#	apps/v4/public/r/styles/base-lyra/item-example.json
#	apps/v4/public/r/styles/base-lyra/kbd-example.json
#	apps/v4/public/r/styles/base-lyra/menubar-example.json
#	apps/v4/public/r/styles/base-lyra/menubar.json
#	apps/v4/public/r/styles/base-lyra/native-select.json
#	apps/v4/public/r/styles/base-lyra/navigation-menu-example.json
#	apps/v4/public/r/styles/base-lyra/navigation-menu.json
#	apps/v4/public/r/styles/base-lyra/pagination.json
#	apps/v4/public/r/styles/base-lyra/preview.json
#	apps/v4/public/r/styles/base-lyra/progress-example.json
#	apps/v4/public/r/styles/base-lyra/radio-group.json
#	apps/v4/public/r/styles/base-lyra/select-example.json
#	apps/v4/public/r/styles/base-lyra/select.json
#	apps/v4/public/r/styles/base-lyra/sheet.json
#	apps/v4/public/r/styles/base-lyra/sidebar-example.json
#	apps/v4/public/r/styles/base-lyra/sidebar-floating-example.json
#	apps/v4/public/r/styles/base-lyra/sidebar-icon-example.json
#	apps/v4/public/r/styles/base-lyra/sidebar-inset-example.json
#	apps/v4/public/r/styles/base-lyra/sidebar.json
#	apps/v4/public/r/styles/base-lyra/spinner-example.json
#	apps/v4/public/r/styles/base-lyra/spinner.json
#	apps/v4/public/r/styles/base-lyra/table-example.json
#	apps/v4/public/r/styles/base-lyra/tabs-example.json
#	apps/v4/public/r/styles/base-lyra/toggle-example.json
#	apps/v4/public/r/styles/base-lyra/toggle-group-example.json
#	apps/v4/public/r/styles/base-lyra/tooltip-example.json
#	apps/v4/public/r/styles/base-lyra/vercel.json
#	apps/v4/public/r/styles/base-maia/accordion-example.json
#	apps/v4/public/r/styles/base-maia/accordion.json
#	apps/v4/public/r/styles/base-maia/alert-dialog-example.json
#	apps/v4/public/r/styles/base-maia/alert-example.json
#	apps/v4/public/r/styles/base-maia/avatar-example.json
#	apps/v4/public/r/styles/base-maia/badge-example.json
#	apps/v4/public/r/styles/base-maia/breadcrumb.json
#	apps/v4/public/r/styles/base-maia/button-example.json
#	apps/v4/public/r/styles/base-maia/button-group-example.json
#	apps/v4/public/r/styles/base-maia/calendar-example.json
#	apps/v4/public/r/styles/base-maia/calendar.json
#	apps/v4/public/r/styles/base-maia/card-example.json
#	apps/v4/public/r/styles/base-maia/carousel.json
#	apps/v4/public/r/styles/base-maia/chart-example.json
#	apps/v4/public/r/styles/base-maia/chatgpt.json
#	apps/v4/public/r/styles/base-maia/checkbox.json
#	apps/v4/public/r/styles/base-maia/collapsible-example.json
#	apps/v4/public/r/styles/base-maia/combobox-example.json
#	apps/v4/public/r/styles/base-maia/combobox.json
#	apps/v4/public/r/styles/base-maia/command-example.json
#	apps/v4/public/r/styles/base-maia/command.json
#	apps/v4/public/r/styles/base-maia/component-example.json
#	apps/v4/public/r/styles/base-maia/context-menu-example.json
#	apps/v4/public/r/styles/base-maia/context-menu.json
#	apps/v4/public/r/styles/base-maia/dialog-example.json
#	apps/v4/public/r/styles/base-maia/dialog.json
#	apps/v4/public/r/styles/base-maia/dropdown-menu-example.json
#	apps/v4/public/r/styles/base-maia/dropdown-menu.json
#	apps/v4/public/r/styles/base-maia/empty-example.json
#	apps/v4/public/r/styles/base-maia/github.json
#	apps/v4/public/r/styles/base-maia/input-group-example.json
#	apps/v4/public/r/styles/base-maia/input-otp-example.json
#	apps/v4/public/r/styles/base-maia/input-otp.json
#	apps/v4/public/r/styles/base-maia/item-example.json
#	apps/v4/public/r/styles/base-maia/kbd-example.json
#	apps/v4/public/r/styles/base-maia/menubar-example.json
#	apps/v4/public/r/styles/base-maia/menubar.json
#	apps/v4/public/r/styles/base-maia/native-select.json
#	apps/v4/public/r/styles/base-maia/navigation-menu-example.json
#	apps/v4/public/r/styles/base-maia/navigation-menu.json
#	apps/v4/public/r/styles/base-maia/pagination.json
#	apps/v4/public/r/styles/base-maia/preview.json
#	apps/v4/public/r/styles/base-maia/progress-example.json
#	apps/v4/public/r/styles/base-maia/radio-group.json
#	apps/v4/public/r/styles/base-maia/select-example.json
#	apps/v4/public/r/styles/base-maia/select.json
#	apps/v4/public/r/styles/base-maia/sheet.json
#	apps/v4/public/r/styles/base-maia/sidebar-example.json
#	apps/v4/public/r/styles/base-maia/sidebar-floating-example.json
#	apps/v4/public/r/styles/base-maia/sidebar-icon-example.json
#	apps/v4/public/r/styles/base-maia/sidebar-inset-example.json
#	apps/v4/public/r/styles/base-maia/sidebar.json
#	apps/v4/public/r/styles/base-maia/spinner-example.json
#	apps/v4/public/r/styles/base-maia/spinner.json
#	apps/v4/public/r/styles/base-maia/table-example.json
#	apps/v4/public/r/styles/base-maia/tabs-example.json
#	apps/v4/public/r/styles/base-maia/toggle-example.json
#	apps/v4/public/r/styles/base-maia/toggle-group-example.json
#	apps/v4/public/r/styles/base-maia/tooltip-example.json
#	apps/v4/public/r/styles/base-maia/vercel.json
#	apps/v4/public/r/styles/base-mira/accordion-example.json
#	apps/v4/public/r/styles/base-mira/accordion.json
#	apps/v4/public/r/styles/base-mira/alert-dialog-example.json
#	apps/v4/public/r/styles/base-mira/alert-example.json
#	apps/v4/public/r/styles/base-mira/avatar-example.json
#	apps/v4/public/r/styles/base-mira/badge-example.json
#	apps/v4/public/r/styles/base-mira/breadcrumb.json
#	apps/v4/public/r/styles/base-mira/button-example.json
#	apps/v4/public/r/styles/base-mira/button-group-example.json
#	apps/v4/public/r/styles/base-mira/calendar-example.json
#	apps/v4/public/r/styles/base-mira/calendar.json
#	apps/v4/public/r/styles/base-mira/card-example.json
#	apps/v4/public/r/styles/base-mira/carousel.json
#	apps/v4/public/r/styles/base-mira/chart-example.json
#	apps/v4/public/r/styles/base-mira/chatgpt.json
#	apps/v4/public/r/styles/base-mira/checkbox.json
#	apps/v4/public/r/styles/base-mira/collapsible-example.json
#	apps/v4/public/r/styles/base-mira/combobox-example.json
#	apps/v4/public/r/styles/base-mira/combobox.json
#	apps/v4/public/r/styles/base-mira/command-example.json
#	apps/v4/public/r/styles/base-mira/command.json
#	apps/v4/public/r/styles/base-mira/component-example.json
#	apps/v4/public/r/styles/base-mira/context-menu-example.json
#	apps/v4/public/r/styles/base-mira/context-menu.json
#	apps/v4/public/r/styles/base-mira/dialog-example.json
#	apps/v4/public/r/styles/base-mira/dialog.json
#	apps/v4/public/r/styles/base-mira/dropdown-menu-example.json
#	apps/v4/public/r/styles/base-mira/dropdown-menu.json
#	apps/v4/public/r/styles/base-mira/empty-example.json
#	apps/v4/public/r/styles/base-mira/github.json
#	apps/v4/public/r/styles/base-mira/input-group-example.json
#	apps/v4/public/r/styles/base-mira/input-otp-example.json
#	apps/v4/public/r/styles/base-mira/input-otp.json
#	apps/v4/public/r/styles/base-mira/item-example.json
#	apps/v4/public/r/styles/base-mira/kbd-example.json
#	apps/v4/public/r/styles/base-mira/menubar-example.json
#	apps/v4/public/r/styles/base-mira/menubar.json
#	apps/v4/public/r/styles/base-mira/native-select.json
#	apps/v4/public/r/styles/base-mira/navigation-menu-example.json
#	apps/v4/public/r/styles/base-mira/navigation-menu.json
#	apps/v4/public/r/styles/base-mira/pagination.json
#	apps/v4/public/r/styles/base-mira/preview.json
#	apps/v4/public/r/styles/base-mira/progress-example.json
#	apps/v4/public/r/styles/base-mira/radio-group.json
#	apps/v4/public/r/styles/base-mira/select-example.json
#	apps/v4/public/r/styles/base-mira/select.json
#	apps/v4/public/r/styles/base-mira/sheet.json
#	apps/v4/public/r/styles/base-mira/sidebar-example.json
#	apps/v4/public/r/styles/base-mira/sidebar-floating-example.json
#	apps/v4/public/r/styles/base-mira/sidebar-icon-example.json
#	apps/v4/public/r/styles/base-mira/sidebar-inset-example.json
#	apps/v4/public/r/styles/base-mira/sidebar.json
#	apps/v4/public/r/styles/base-mira/spinner-example.json
#	apps/v4/public/r/styles/base-mira/spinner.json
#	apps/v4/public/r/styles/base-mira/table-example.json
#	apps/v4/public/r/styles/base-mira/tabs-example.json
#	apps/v4/public/r/styles/base-mira/toggle-example.json
#	apps/v4/public/r/styles/base-mira/toggle-group-example.json
#	apps/v4/public/r/styles/base-mira/tooltip-example.json
#	apps/v4/public/r/styles/base-mira/vercel.json
#	apps/v4/public/r/styles/base-nova/accordion-example.json
#	apps/v4/public/r/styles/base-nova/accordion.json
#	apps/v4/public/r/styles/base-nova/alert-dialog-example.json
#	apps/v4/public/r/styles/base-nova/alert-example.json
#	apps/v4/public/r/styles/base-nova/avatar-example.json
#	apps/v4/public/r/styles/base-nova/badge-example.json
#	apps/v4/public/r/styles/base-nova/breadcrumb.json
#	apps/v4/public/r/styles/base-nova/button-example.json
#	apps/v4/public/r/styles/base-nova/button-group-example.json
#	apps/v4/public/r/styles/base-nova/calendar-example.json
#	apps/v4/public/r/styles/base-nova/calendar.json
#	apps/v4/public/r/styles/base-nova/card-example.json
#	apps/v4/public/r/styles/base-nova/carousel.json
#	apps/v4/public/r/styles/base-nova/chart-example.json
#	apps/v4/public/r/styles/base-nova/chatgpt.json
#	apps/v4/public/r/styles/base-nova/checkbox.json
#	apps/v4/public/r/styles/base-nova/collapsible-example.json
#	apps/v4/public/r/styles/base-nova/combobox-example.json
#	apps/v4/public/r/styles/base-nova/combobox.json
#	apps/v4/public/r/styles/base-nova/command-example.json
#	apps/v4/public/r/styles/base-nova/command.json
#	apps/v4/public/r/styles/base-nova/component-example.json
#	apps/v4/public/r/styles/base-nova/context-menu-example.json
#	apps/v4/public/r/styles/base-nova/context-menu.json
#	apps/v4/public/r/styles/base-nova/dialog-example.json
#	apps/v4/public/r/styles/base-nova/dialog.json
#	apps/v4/public/r/styles/base-nova/dropdown-menu-example.json
#	apps/v4/public/r/styles/base-nova/dropdown-menu.json
#	apps/v4/public/r/styles/base-nova/empty-example.json
#	apps/v4/public/r/styles/base-nova/github.json
#	apps/v4/public/r/styles/base-nova/input-group-example.json
#	apps/v4/public/r/styles/base-nova/input-otp-example.json
#	apps/v4/public/r/styles/base-nova/input-otp.json
#	apps/v4/public/r/styles/base-nova/item-example.json
#	apps/v4/public/r/styles/base-nova/kbd-example.json
#	apps/v4/public/r/styles/base-nova/menubar-example.json
#	apps/v4/public/r/styles/base-nova/menubar.json
#	apps/v4/public/r/styles/base-nova/native-select.json
#	apps/v4/public/r/styles/base-nova/navigation-menu-example.json
#	apps/v4/public/r/styles/base-nova/navigation-menu.json
#	apps/v4/public/r/styles/base-nova/pagination.json
#	apps/v4/public/r/styles/base-nova/preview.json
#	apps/v4/public/r/styles/base-nova/progress-example.json
#	apps/v4/public/r/styles/base-nova/radio-group.json
#	apps/v4/public/r/styles/base-nova/select-example.json
#	apps/v4/public/r/styles/base-nova/select.json
#	apps/v4/public/r/styles/base-nova/sheet.json
#	apps/v4/public/r/styles/base-nova/sidebar-example.json
#	apps/v4/public/r/styles/base-nova/sidebar-floating-example.json
#	apps/v4/public/r/styles/base-nova/sidebar-icon-example.json
#	apps/v4/public/r/styles/base-nova/sidebar-inset-example.json
#	apps/v4/public/r/styles/base-nova/sidebar.json
#	apps/v4/public/r/styles/base-nova/spinner-example.json
#	apps/v4/public/r/styles/base-nova/spinner.json
#	apps/v4/public/r/styles/base-nova/table-example.json
#	apps/v4/public/r/styles/base-nova/tabs-example.json
#	apps/v4/public/r/styles/base-nova/toggle-example.json
#	apps/v4/public/r/styles/base-nova/toggle-group-example.json
#	apps/v4/public/r/styles/base-nova/tooltip-example.json
#	apps/v4/public/r/styles/base-nova/vercel.json
#	apps/v4/public/r/styles/base-vega/accordion-example.json
#	apps/v4/public/r/styles/base-vega/accordion.json
#	apps/v4/public/r/styles/base-vega/alert-dialog-example.json
#	apps/v4/public/r/styles/base-vega/alert-example.json
#	apps/v4/public/r/styles/base-vega/avatar-example.json
#	apps/v4/public/r/styles/base-vega/badge-example.json
#	apps/v4/public/r/styles/base-vega/breadcrumb.json
#	apps/v4/public/r/styles/base-vega/button-example.json
#	apps/v4/public/r/styles/base-vega/button-group-example.json
#	apps/v4/public/r/styles/base-vega/calendar-example.json
#	apps/v4/public/r/styles/base-vega/calendar.json
#	apps/v4/public/r/styles/base-vega/card-example.json
#	apps/v4/public/r/styles/base-vega/carousel.json
#	apps/v4/public/r/styles/base-vega/chart-example.json
#	apps/v4/public/r/styles/base-vega/chatgpt.json
#	apps/v4/public/r/styles/base-vega/checkbox.json
#	apps/v4/public/r/styles/base-vega/collapsible-example.json
#	apps/v4/public/r/styles/base-vega/combobox-example.json
#	apps/v4/public/r/styles/base-vega/combobox.json
#	apps/v4/public/r/styles/base-vega/command-example.json
#	apps/v4/public/r/styles/base-vega/command.json
#	apps/v4/public/r/styles/base-vega/component-example.json
#	apps/v4/public/r/styles/base-vega/context-menu-example.json
#	apps/v4/public/r/styles/base-vega/context-menu.json
#	apps/v4/public/r/styles/base-vega/dialog-example.json
#	apps/v4/public/r/styles/base-vega/dialog.json
#	apps/v4/public/r/styles/base-vega/dropdown-menu-example.json
#	apps/v4/public/r/styles/base-vega/dropdown-menu.json
#	apps/v4/public/r/styles/base-vega/empty-example.json
#	apps/v4/public/r/styles/base-vega/github.json
#	apps/v4/public/r/styles/base-vega/input-group-example.json
#	apps/v4/public/r/styles/base-vega/input-otp-example.json
#	apps/v4/public/r/styles/base-vega/input-otp.json
#	apps/v4/public/r/styles/base-vega/item-example.json
#	apps/v4/public/r/styles/base-vega/kbd-example.json
#	apps/v4/public/r/styles/base-vega/menubar-example.json
#	apps/v4/public/r/styles/base-vega/menubar.json
#	apps/v4/public/r/styles/base-vega/native-select.json
#	apps/v4/public/r/styles/base-vega/navigation-menu-example.json
#	apps/v4/public/r/styles/base-vega/navigation-menu.json
#	apps/v4/public/r/styles/base-vega/pagination.json
#	apps/v4/public/r/styles/base-vega/preview.json
#	apps/v4/public/r/styles/base-vega/progress-example.json
#	apps/v4/public/r/styles/base-vega/radio-group.json
#	apps/v4/public/r/styles/base-vega/select-example.json
#	apps/v4/public/r/styles/base-vega/select.json
#	apps/v4/public/r/styles/base-vega/sheet.json
#	apps/v4/public/r/styles/base-vega/sidebar-example.json
#	apps/v4/public/r/styles/base-vega/sidebar-floating-example.json
#	apps/v4/public/r/styles/base-vega/sidebar-icon-example.json
#	apps/v4/public/r/styles/base-vega/sidebar-inset-example.json
#	apps/v4/public/r/styles/base-vega/sidebar.json
#	apps/v4/public/r/styles/base-vega/spinner-example.json
#	apps/v4/public/r/styles/base-vega/spinner.json
#	apps/v4/public/r/styles/base-vega/table-example.json
#	apps/v4/public/r/styles/base-vega/tabs-example.json
#	apps/v4/public/r/styles/base-vega/toggle-example.json
#	apps/v4/public/r/styles/base-vega/toggle-group-example.json
#	apps/v4/public/r/styles/base-vega/tooltip-example.json
#	apps/v4/public/r/styles/base-vega/vercel.json
#	apps/v4/public/r/styles/radix-lyra/accordion-example.json
#	apps/v4/public/r/styles/radix-lyra/accordion.json
#	apps/v4/public/r/styles/radix-lyra/alert-dialog-example.json
#	apps/v4/public/r/styles/radix-lyra/alert-example.json
#	apps/v4/public/r/styles/radix-lyra/avatar-example.json
#	apps/v4/public/r/styles/radix-lyra/badge-example.json
#	apps/v4/public/r/styles/radix-lyra/breadcrumb.json
#	apps/v4/public/r/styles/radix-lyra/button-example.json
#	apps/v4/public/r/styles/radix-lyra/button-group-example.json
#	apps/v4/public/r/styles/radix-lyra/calendar-example.json
#	apps/v4/public/r/styles/radix-lyra/calendar.json
#	apps/v4/public/r/styles/radix-lyra/card-example.json
#	apps/v4/public/r/styles/radix-lyra/carousel.json
#	apps/v4/public/r/styles/radix-lyra/chart-example.json
#	apps/v4/public/r/styles/radix-lyra/chatgpt.json
#	apps/v4/public/r/styles/radix-lyra/checkbox.json
#	apps/v4/public/r/styles/radix-lyra/collapsible-example.json
#	apps/v4/public/r/styles/radix-lyra/combobox-example.json
#	apps/v4/public/r/styles/radix-lyra/combobox.json
#	apps/v4/public/r/styles/radix-lyra/command-example.json
#	apps/v4/public/r/styles/radix-lyra/command.json
#	apps/v4/public/r/styles/radix-lyra/component-example.json
#	apps/v4/public/r/styles/radix-lyra/context-menu-example.json
#	apps/v4/public/r/styles/radix-lyra/context-menu.json
#	apps/v4/public/r/styles/radix-lyra/dialog-example.json
#	apps/v4/public/r/styles/radix-lyra/dialog.json
#	apps/v4/public/r/styles/radix-lyra/dropdown-menu-example.json
#	apps/v4/public/r/styles/radix-lyra/dropdown-menu.json
#	apps/v4/public/r/styles/radix-lyra/empty-example.json
#	apps/v4/public/r/styles/radix-lyra/github.json
#	apps/v4/public/r/styles/radix-lyra/input-group-example.json
#	apps/v4/public/r/styles/radix-lyra/input-otp-example.json
#	apps/v4/public/r/styles/radix-lyra/input-otp.json
#	apps/v4/public/r/styles/radix-lyra/item-example.json
#	apps/v4/public/r/styles/radix-lyra/kbd-example.json
#	apps/v4/public/r/styles/radix-lyra/menubar-example.json
#	apps/v4/public/r/styles/radix-lyra/menubar.json
#	apps/v4/public/r/styles/radix-lyra/native-select.json
#	apps/v4/public/r/styles/radix-lyra/navigation-menu-example.json
#	apps/v4/public/r/styles/radix-lyra/navigation-menu.json
#	apps/v4/public/r/styles/radix-lyra/pagination.json
#	apps/v4/public/r/styles/radix-lyra/preview.json
#	apps/v4/public/r/styles/radix-lyra/progress-example.json
#	apps/v4/public/r/styles/radix-lyra/radio-group.json
#	apps/v4/public/r/styles/radix-lyra/select-example.json
#	apps/v4/public/r/styles/radix-lyra/select.json
#	apps/v4/public/r/styles/radix-lyra/sheet.json
#	apps/v4/public/r/styles/radix-lyra/sidebar-example.json
#	apps/v4/public/r/styles/radix-lyra/sidebar-floating-example.json
#	apps/v4/public/r/styles/radix-lyra/sidebar-icon-example.json
#	apps/v4/public/r/styles/radix-lyra/sidebar-inset-example.json
#	apps/v4/public/r/styles/radix-lyra/sidebar.json
#	apps/v4/public/r/styles/radix-lyra/spinner-example.json
#	apps/v4/public/r/styles/radix-lyra/spinner.json
#	apps/v4/public/r/styles/radix-lyra/table-example.json
#	apps/v4/public/r/styles/radix-lyra/tabs-example.json
#	apps/v4/public/r/styles/radix-lyra/toggle-example.json
#	apps/v4/public/r/styles/radix-lyra/toggle-group-example.json
#	apps/v4/public/r/styles/radix-lyra/tooltip-example.json
#	apps/v4/public/r/styles/radix-lyra/vercel.json
#	apps/v4/public/r/styles/radix-maia/accordion-example.json
#	apps/v4/public/r/styles/radix-maia/accordion.json
#	apps/v4/public/r/styles/radix-maia/alert-dialog-example.json
#	apps/v4/public/r/styles/radix-maia/alert-example.json
#	apps/v4/public/r/styles/radix-maia/avatar-example.json
#	apps/v4/public/r/styles/radix-maia/badge-example.json
#	apps/v4/public/r/styles/radix-maia/breadcrumb.json
#	apps/v4/public/r/styles/radix-maia/button-example.json
#	apps/v4/public/r/styles/radix-maia/button-group-example.json
#	apps/v4/public/r/styles/radix-maia/calendar-example.json
#	apps/v4/public/r/styles/radix-maia/calendar.json
#	apps/v4/public/r/styles/radix-maia/card-example.json
#	apps/v4/public/r/styles/radix-maia/carousel.json
#	apps/v4/public/r/styles/radix-maia/chart-example.json
#	apps/v4/public/r/styles/radix-maia/chatgpt.json
#	apps/v4/public/r/styles/radix-maia/checkbox.json
#	apps/v4/public/r/styles/radix-maia/collapsible-example.json
#	apps/v4/public/r/styles/radix-maia/combobox-example.json
#	apps/v4/public/r/styles/radix-maia/combobox.json
#	apps/v4/public/r/styles/radix-maia/command-example.json
#	apps/v4/public/r/styles/radix-maia/command.json
#	apps/v4/public/r/styles/radix-maia/component-example.json
#	apps/v4/public/r/styles/radix-maia/context-menu-example.json
#	apps/v4/public/r/styles/radix-maia/context-menu.json
#	apps/v4/public/r/styles/radix-maia/dialog-example.json
#	apps/v4/public/r/styles/radix-maia/dialog.json
#	apps/v4/public/r/styles/radix-maia/dropdown-menu-example.json
#	apps/v4/public/r/styles/radix-maia/dropdown-menu.json
#	apps/v4/public/r/styles/radix-maia/empty-example.json
#	apps/v4/public/r/styles/radix-maia/github.json
#	apps/v4/public/r/styles/radix-maia/input-group-example.json
#	apps/v4/public/r/styles/radix-maia/input-otp-example.json
#	apps/v4/public/r/styles/radix-maia/input-otp.json
#	apps/v4/public/r/styles/radix-maia/item-example.json
#	apps/v4/public/r/styles/radix-maia/kbd-example.json
#	apps/v4/public/r/styles/radix-maia/menubar-example.json
#	apps/v4/public/r/styles/radix-maia/menubar.json
#	apps/v4/public/r/styles/radix-maia/native-select.json
#	apps/v4/public/r/styles/radix-maia/navigation-menu-example.json
#	apps/v4/public/r/styles/radix-maia/navigation-menu.json
#	apps/v4/public/r/styles/radix-maia/pagination.json
#	apps/v4/public/r/styles/radix-maia/preview.json
#	apps/v4/public/r/styles/radix-maia/progress-example.json
#	apps/v4/public/r/styles/radix-maia/radio-group.json
#	apps/v4/public/r/styles/radix-maia/select-example.json
#	apps/v4/public/r/styles/radix-maia/select.json
#	apps/v4/public/r/styles/radix-maia/sheet.json
#	apps/v4/public/r/styles/radix-maia/sidebar-example.json
#	apps/v4/public/r/styles/radix-maia/sidebar-floating-example.json
#	apps/v4/public/r/styles/radix-maia/sidebar-icon-example.json
#	apps/v4/public/r/styles/radix-maia/sidebar-inset-example.json
#	apps/v4/public/r/styles/radix-maia/sidebar.json
#	apps/v4/public/r/styles/radix-maia/spinner-example.json
#	apps/v4/public/r/styles/radix-maia/spinner.json
#	apps/v4/public/r/styles/radix-maia/table-example.json
#	apps/v4/public/r/styles/radix-maia/tabs-example.json
#	apps/v4/public/r/styles/radix-maia/toggle-example.json
#	apps/v4/public/r/styles/radix-maia/toggle-group-example.json
#	apps/v4/public/r/styles/radix-maia/tooltip-example.json
#	apps/v4/public/r/styles/radix-maia/vercel.json
#	apps/v4/public/r/styles/radix-mira/accordion-example.json
#	apps/v4/public/r/styles/radix-mira/accordion.json
#	apps/v4/public/r/styles/radix-mira/alert-dialog-example.json
#	apps/v4/public/r/styles/radix-mira/alert-example.json
#	apps/v4/public/r/styles/radix-mira/avatar-example.json
#	apps/v4/public/r/styles/radix-mira/badge-example.json
#	apps/v4/public/r/styles/radix-mira/breadcrumb.json
#	apps/v4/public/r/styles/radix-mira/button-example.json
#	apps/v4/public/r/styles/radix-mira/button-group-example.json
#	apps/v4/public/r/styles/radix-mira/calendar-example.json
#	apps/v4/public/r/styles/radix-mira/calendar.json
#	apps/v4/public/r/styles/radix-mira/card-example.json
#	apps/v4/public/r/styles/radix-mira/carousel.json
#	apps/v4/public/r/styles/radix-mira/chart-example.json
#	apps/v4/public/r/styles/radix-mira/chatgpt.json
#	apps/v4/public/r/styles/radix-mira/checkbox.json
#	apps/v4/public/r/styles/radix-mira/collapsible-example.json
#	apps/v4/public/r/styles/radix-mira/combobox-example.json
#	apps/v4/public/r/styles/radix-mira/combobox.json
#	apps/v4/public/r/styles/radix-mira/command-example.json
#	apps/v4/public/r/styles/radix-mira/command.json
#	apps/v4/public/r/styles/radix-mira/component-example.json
#	apps/v4/public/r/styles/radix-mira/context-menu-example.json
#	apps/v4/public/r/styles/radix-mira/context-menu.json
#	apps/v4/public/r/styles/radix-mira/dialog-example.json
#	apps/v4/public/r/styles/radix-mira/dialog.json
#	apps/v4/public/r/styles/radix-mira/dropdown-menu-example.json
#	apps/v4/public/r/styles/radix-mira/dropdown-menu.json
#	apps/v4/public/r/styles/radix-mira/empty-example.json
#	apps/v4/public/r/styles/radix-mira/github.json
#	apps/v4/public/r/styles/radix-mira/input-group-example.json
#	apps/v4/public/r/styles/radix-mira/input-otp-example.json
#	apps/v4/public/r/styles/radix-mira/input-otp.json
#	apps/v4/public/r/styles/radix-mira/item-example.json
#	apps/v4/public/r/styles/radix-mira/kbd-example.json
#	apps/v4/public/r/styles/radix-mira/menubar-example.json
#	apps/v4/public/r/styles/radix-mira/menubar.json
#	apps/v4/public/r/styles/radix-mira/native-select.json
#	apps/v4/public/r/styles/radix-mira/navigation-menu-example.json
#	apps/v4/public/r/styles/radix-mira/navigation-menu.json
#	apps/v4/public/r/styles/radix-mira/pagination.json
#	apps/v4/public/r/styles/radix-mira/preview.json
#	apps/v4/public/r/styles/radix-mira/progress-example.json
#	apps/v4/public/r/styles/radix-mira/radio-group.json
#	apps/v4/public/r/styles/radix-mira/select-example.json
#	apps/v4/public/r/styles/radix-mira/select.json
#	apps/v4/public/r/styles/radix-mira/sheet.json
#	apps/v4/public/r/styles/radix-mira/sidebar-example.json
#	apps/v4/public/r/styles/radix-mira/sidebar-floating-example.json
#	apps/v4/public/r/styles/radix-mira/sidebar-icon-example.json
#	apps/v4/public/r/styles/radix-mira/sidebar-inset-example.json
#	apps/v4/public/r/styles/radix-mira/sidebar.json
#	apps/v4/public/r/styles/radix-mira/spinner-example.json
#	apps/v4/public/r/styles/radix-mira/spinner.json
#	apps/v4/public/r/styles/radix-mira/table-example.json
#	apps/v4/public/r/styles/radix-mira/tabs-example.json
#	apps/v4/public/r/styles/radix-mira/toggle-example.json
#	apps/v4/public/r/styles/radix-mira/toggle-group-example.json
#	apps/v4/public/r/styles/radix-mira/tooltip-example.json
#	apps/v4/public/r/styles/radix-mira/vercel.json
#	apps/v4/public/r/styles/radix-nova/accordion-example.json
#	apps/v4/public/r/styles/radix-nova/accordion.json
#	apps/v4/public/r/styles/radix-nova/alert-dialog-example.json
#	apps/v4/public/r/styles/radix-nova/alert-example.json
#	apps/v4/public/r/styles/radix-nova/avatar-example.json
#	apps/v4/public/r/styles/radix-nova/badge-example.json
#	apps/v4/public/r/styles/radix-nova/breadcrumb.json
#	apps/v4/public/r/styles/radix-nova/button-example.json
#	apps/v4/public/r/styles/radix-nova/button-group-example.json
#	apps/v4/public/r/styles/radix-nova/calendar-example.json
#	apps/v4/public/r/styles/radix-nova/calendar.json
#	apps/v4/public/r/styles/radix-nova/card-example.json
#	apps/v4/public/r/styles/radix-nova/carousel.json
#	apps/v4/public/r/styles/radix-nova/chart-example.json
#	apps/v4/public/r/styles/radix-nova/chatgpt.json
#	apps/v4/public/r/styles/radix-nova/checkbox.json
#	apps/v4/public/r/styles/radix-nova/collapsible-example.json
#	apps/v4/public/r/styles/radix-nova/combobox-example.json
#	apps/v4/public/r/styles/radix-nova/combobox.json
#	apps/v4/public/r/styles/radix-nova/command-example.json
#	apps/v4/public/r/styles/radix-nova/command.json
#	apps/v4/public/r/styles/radix-nova/component-example.json
#	apps/v4/public/r/styles/radix-nova/context-menu-example.json
#	apps/v4/public/r/styles/radix-nova/context-menu.json
#	apps/v4/public/r/styles/radix-nova/dialog-example.json
#	apps/v4/public/r/styles/radix-nova/dialog.json
#	apps/v4/public/r/styles/radix-nova/dropdown-menu-example.json
#	apps/v4/public/r/styles/radix-nova/dropdown-menu.json
#	apps/v4/public/r/styles/radix-nova/empty-example.json
#	apps/v4/public/r/styles/radix-nova/github.json
#	apps/v4/public/r/styles/radix-nova/input-group-example.json
#	apps/v4/public/r/styles/radix-nova/input-otp-example.json
#	apps/v4/public/r/styles/radix-nova/input-otp.json
#	apps/v4/public/r/styles/radix-nova/item-example.json
#	apps/v4/public/r/styles/radix-nova/kbd-example.json
#	apps/v4/public/r/styles/radix-nova/menubar-example.json
#	apps/v4/public/r/styles/radix-nova/menubar.json
#	apps/v4/public/r/styles/radix-nova/native-select.json
#	apps/v4/public/r/styles/radix-nova/navigation-menu-example.json
#	apps/v4/public/r/styles/radix-nova/navigation-menu.json
#	apps/v4/public/r/styles/radix-nova/pagination.json
#	apps/v4/public/r/styles/radix-nova/preview.json
#	apps/v4/public/r/styles/radix-nova/progress-example.json
#	apps/v4/public/r/styles/radix-nova/radio-group.json
#	apps/v4/public/r/styles/radix-nova/select-example.json
#	apps/v4/public/r/styles/radix-nova/select.json
#	apps/v4/public/r/styles/radix-nova/sheet.json
#	apps/v4/public/r/styles/radix-nova/sidebar-example.json
#	apps/v4/public/r/styles/radix-nova/sidebar-floating-example.json
#	apps/v4/public/r/styles/radix-nova/sidebar-icon-example.json
#	apps/v4/public/r/styles/radix-nova/sidebar-inset-example.json
#	apps/v4/public/r/styles/radix-nova/sidebar.json
#	apps/v4/public/r/styles/radix-nova/spinner-example.json
#	apps/v4/public/r/styles/radix-nova/spinner.json
#	apps/v4/public/r/styles/radix-nova/table-example.json
#	apps/v4/public/r/styles/radix-nova/tabs-example.json
#	apps/v4/public/r/styles/radix-nova/toggle-example.json
#	apps/v4/public/r/styles/radix-nova/toggle-group-example.json
#	apps/v4/public/r/styles/radix-nova/tooltip-example.json
#	apps/v4/public/r/styles/radix-nova/vercel.json
#	apps/v4/public/r/styles/radix-vega/accordion-example.json
#	apps/v4/public/r/styles/radix-vega/accordion.json
#	apps/v4/public/r/styles/radix-vega/alert-dialog-example.json
#	apps/v4/public/r/styles/radix-vega/alert-example.json
#	apps/v4/public/r/styles/radix-vega/avatar-example.json
#	apps/v4/public/r/styles/radix-vega/badge-example.json
#	apps/v4/public/r/styles/radix-vega/breadcrumb.json
#	apps/v4/public/r/styles/radix-vega/button-example.json
#	apps/v4/public/r/styles/radix-vega/button-group-example.json
#	apps/v4/public/r/styles/radix-vega/calendar-example.json
#	apps/v4/public/r/styles/radix-vega/calendar.json
#	apps/v4/public/r/styles/radix-vega/card-example.json
#	apps/v4/public/r/styles/radix-vega/carousel.json
#	apps/v4/public/r/styles/radix-vega/chart-example.json
#	apps/v4/public/r/styles/radix-vega/chatgpt.json
#	apps/v4/public/r/styles/radix-vega/checkbox.json
#	apps/v4/public/r/styles/radix-vega/collapsible-example.json
#	apps/v4/public/r/styles/radix-vega/combobox-example.json
#	apps/v4/public/r/styles/radix-vega/combobox.json
#	apps/v4/public/r/styles/radix-vega/command-example.json
#	apps/v4/public/r/styles/radix-vega/command.json
#	apps/v4/public/r/styles/radix-vega/component-example.json
#	apps/v4/public/r/styles/radix-vega/context-menu-example.json
#	apps/v4/public/r/styles/radix-vega/context-menu.json
#	apps/v4/public/r/styles/radix-vega/dialog-example.json
#	apps/v4/public/r/styles/radix-vega/dialog.json
#	apps/v4/public/r/styles/radix-vega/dropdown-menu-example.json
#	apps/v4/public/r/styles/radix-vega/dropdown-menu.json
#	apps/v4/public/r/styles/radix-vega/empty-example.json
#	apps/v4/public/r/styles/radix-vega/github.json
#	apps/v4/public/r/styles/radix-vega/input-group-example.json
#	apps/v4/public/r/styles/radix-vega/input-otp-example.json
#	apps/v4/public/r/styles/radix-vega/input-otp.json
#	apps/v4/public/r/styles/radix-vega/item-example.json
#	apps/v4/public/r/styles/radix-vega/kbd-example.json
#	apps/v4/public/r/styles/radix-vega/menubar-example.json
#	apps/v4/public/r/styles/radix-vega/menubar.json
#	apps/v4/public/r/styles/radix-vega/native-select.json
#	apps/v4/public/r/styles/radix-vega/navigation-menu-example.json
#	apps/v4/public/r/styles/radix-vega/navigation-menu.json
#	apps/v4/public/r/styles/radix-vega/pagination.json
#	apps/v4/public/r/styles/radix-vega/preview.json
#	apps/v4/public/r/styles/radix-vega/progress-example.json
#	apps/v4/public/r/styles/radix-vega/radio-group.json
#	apps/v4/public/r/styles/radix-vega/select-example.json
#	apps/v4/public/r/styles/radix-vega/select.json
#	apps/v4/public/r/styles/radix-vega/sheet.json
#	apps/v4/public/r/styles/radix-vega/sidebar-example.json
#	apps/v4/public/r/styles/radix-vega/sidebar-floating-example.json
#	apps/v4/public/r/styles/radix-vega/sidebar-icon-example.json
#	apps/v4/public/r/styles/radix-vega/sidebar-inset-example.json
#	apps/v4/public/r/styles/radix-vega/sidebar.json
#	apps/v4/public/r/styles/radix-vega/spinner-example.json
#	apps/v4/public/r/styles/radix-vega/spinner.json
#	apps/v4/public/r/styles/radix-vega/table-example.json
#	apps/v4/public/r/styles/radix-vega/tabs-example.json
#	apps/v4/public/r/styles/radix-vega/toggle-example.json
#	apps/v4/public/r/styles/radix-vega/toggle-group-example.json
#	apps/v4/public/r/styles/radix-vega/tooltip-example.json
#	apps/v4/public/r/styles/radix-vega/vercel.json
#	apps/v4/scripts/build-registry.mts
2026-01-19 11:39:57 +04:00
shadcn
ff3c1e1d95 fix: input 2026-01-15 19:48:20 +04:00
shadcn
068f7c22aa feat: add field and hover-card 2026-01-15 17:32:16 +04:00
shadcn
b1b25fe15d feat: add empty 2026-01-15 16:51:57 +04:00
shadcn
689b4c6b41 feat: add date-picker 2026-01-15 16:32:35 +04:00
shadcn
66637058fc feat: dropdown-menu 2026-01-15 15:50:35 +04:00
shadcn
da07cf6ffe feat: add data-table dialog and drawer 2026-01-15 13:17:45 +04:00
shadcn
1a5b9ce036 feat: add context menu 2026-01-15 12:57:18 +04:00
shadcn
1ce874edd2 feat: add command 2026-01-15 12:34:24 +04:00
shadcn
45480505d8 feat: add combobox 2026-01-15 12:11:27 +04:00
shadcn
bd4ef8e08c feat: add collapsible 2026-01-15 11:25:35 +04:00
shadcn
5a897b7765 feat: add checkbox 2026-01-15 10:59:58 +04:00
shadcn
3f62e7dee0 fix: chart 2026-01-15 10:26:46 +04:00
shadcn
f2d4395233 feat: add carousel 2026-01-15 09:36:08 +04:00
shadcn
3ab7d04824 feat: add calendar and card 2026-01-15 08:54:40 +04:00
shadcn
58f73f62a0 fix 2026-01-14 22:05:15 +04:00
shadcn
d9061d64aa fix 2026-01-14 22:02:57 +04:00
shadcn
4784f264c5 fix 2026-01-14 21:37:16 +04:00
shadcn
7031141cf3 feat: add button 2026-01-14 21:30:23 +04:00
shadcn
d0fe494491 fix 2026-01-14 20:55:40 +04:00
shadcn
be0b798e21 feat: add breadcrumb 2026-01-14 20:46:23 +04:00
shadcn
953107e7f9 feat: add badge 2026-01-14 20:01:05 +04:00
shadcn
c880796bf2 feat: add avatar 2026-01-14 19:26:01 +04:00
shadcn
48b069c453 feat: add aspect-ratio 2026-01-14 13:19:37 +04:00
shadcn
b5c7a014c8 fix 2026-01-14 12:59:48 +04:00
shadcn
aee10914fe feat: add more examples 2026-01-14 09:25:14 +04:00
shadcn
aadba2f859 Merge branch 'main' into shadcn/base-docs 2026-01-13 17:03:38 +04:00
shadcn
dced7f6045 fix 2026-01-08 22:25:29 +04:00
shadcn
cbe672151a chore: run format:write 2026-01-08 21:35:21 +04:00
shadcn
62aef1117f fix 2026-01-08 21:27:27 +04:00
shadcn
cbc9ed8688 fix 2026-01-08 15:26:02 +04:00
shadcn
b309b1a060 fix 2026-01-08 13:13:10 +04:00
shadcn
e003cf74d2 chore: remove claude files 2026-01-08 12:59:38 +04:00
shadcn
34f1061c6b fix 2026-01-08 12:54:08 +04:00
shadcn
ed28a348c7 fix 2026-01-08 12:05:23 +04:00
shadcn
38bcb3c2eb fix 2026-01-07 22:43:45 +04:00
shadcn
e9acf86c24 fix 2026-01-07 22:05:19 +04:00
shadcn
2f829db41d fix 2026-01-07 14:37:42 +04:00
shadcn
413dc4c01f feat: transform code for display 2026-01-06 16:58:56 +04:00
shadcn
eb098f87d2 feat: add base and radix docs 2026-01-06 16:43:01 +04:00
2309 changed files with 75081 additions and 8903 deletions

View File

@@ -1,10 +1,8 @@
"use client"
import * as React from "react"
import { IconMinus, IconPlus } from "@tabler/icons-react"
import { Button } from "@/registry/new-york-v4/ui/button"
import { ButtonGroup } from "@/registry/new-york-v4/ui/button-group"
import { Button } from "@/examples/radix/ui/button"
import { ButtonGroup } from "@/examples/radix/ui/button-group"
import {
Field,
FieldContent,
@@ -15,13 +13,11 @@ import {
FieldSeparator,
FieldSet,
FieldTitle,
} from "@/registry/new-york-v4/ui/field"
import { Input } from "@/registry/new-york-v4/ui/input"
import {
RadioGroup,
RadioGroupItem,
} from "@/registry/new-york-v4/ui/radio-group"
import { Switch } from "@/registry/new-york-v4/ui/switch"
} from "@/examples/radix/ui/field"
import { Input } from "@/examples/radix/ui/input"
import { RadioGroup, RadioGroupItem } from "@/examples/radix/ui/radio-group"
import { Switch } from "@/examples/radix/ui/switch"
import { IconMinus, IconPlus } from "@tabler/icons-react"
export function AppearanceSettings() {
const [gpuCount, setGpuCount] = React.useState(8)

View File

@@ -1,20 +1,8 @@
"use client"
import * as React from "react"
import {
ArchiveIcon,
ArrowLeftIcon,
CalendarPlusIcon,
ClockIcon,
ListFilterIcon,
MailCheckIcon,
MoreHorizontalIcon,
TagIcon,
Trash2Icon,
} from "lucide-react"
import { Button } from "@/registry/new-york-v4/ui/button"
import { ButtonGroup } from "@/registry/new-york-v4/ui/button-group"
import { Button } from "@/examples/radix/ui/button"
import { ButtonGroup } from "@/examples/radix/ui/button-group"
import {
DropdownMenu,
DropdownMenuContent,
@@ -27,7 +15,18 @@ import {
DropdownMenuSubContent,
DropdownMenuSubTrigger,
DropdownMenuTrigger,
} from "@/registry/new-york-v4/ui/dropdown-menu"
} from "@/examples/radix/ui/dropdown-menu"
import {
ArchiveIcon,
ArrowLeftIcon,
CalendarPlusIcon,
ClockIcon,
ListFilterIcon,
MailCheckIcon,
MoreHorizontalIcon,
TagIcon,
Trash2Icon,
} from "lucide-react"
export function ButtonGroupDemo() {
const [label, setLabel] = React.useState("personal")

View File

@@ -1,21 +1,20 @@
"use client"
import * as React from "react"
import { AudioLinesIcon, PlusIcon } from "lucide-react"
import { Button } from "@/registry/new-york-v4/ui/button"
import { ButtonGroup } from "@/registry/new-york-v4/ui/button-group"
import { Button } from "@/examples/radix/ui/button"
import { ButtonGroup } from "@/examples/radix/ui/button-group"
import {
InputGroup,
InputGroupAddon,
InputGroupButton,
InputGroupInput,
} from "@/registry/new-york-v4/ui/input-group"
} from "@/examples/radix/ui/input-group"
import {
Tooltip,
TooltipContent,
TooltipTrigger,
} from "@/registry/new-york-v4/ui/tooltip"
} from "@/examples/radix/ui/tooltip"
import { AudioLinesIcon, PlusIcon } from "lucide-react"
export function ButtonGroupInputGroup() {
const [voiceEnabled, setVoiceEnabled] = React.useState(false)

View File

@@ -1,10 +1,9 @@
"use client"
import { Button } from "@/examples/radix/ui/button"
import { ButtonGroup } from "@/examples/radix/ui/button-group"
import { ArrowLeftIcon, ArrowRightIcon } from "lucide-react"
import { Button } from "@/registry/new-york-v4/ui/button"
import { ButtonGroup } from "@/registry/new-york-v4/ui/button-group"
export function ButtonGroupNested() {
return (
<ButtonGroup>

View File

@@ -1,14 +1,13 @@
import { BotIcon, ChevronDownIcon } from "lucide-react"
import { Button } from "@/registry/new-york-v4/ui/button"
import { ButtonGroup } from "@/registry/new-york-v4/ui/button-group"
import { Button } from "@/examples/radix/ui/button"
import { ButtonGroup } from "@/examples/radix/ui/button-group"
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/registry/new-york-v4/ui/popover"
import { Separator } from "@/registry/new-york-v4/ui/separator"
import { Textarea } from "@/registry/new-york-v4/ui/textarea"
} from "@/examples/radix/ui/popover"
import { Separator } from "@/examples/radix/ui/separator"
import { Textarea } from "@/examples/radix/ui/textarea"
import { BotIcon, ChevronDownIcon } from "lucide-react"
export function ButtonGroupPopover() {
return (

View File

@@ -1,11 +1,5 @@
import { PlusIcon } from "lucide-react"
import {
Avatar,
AvatarFallback,
AvatarImage,
} from "@/registry/new-york-v4/ui/avatar"
import { Button } from "@/registry/new-york-v4/ui/button"
import { Avatar, AvatarFallback, AvatarImage } from "@/examples/radix/ui/avatar"
import { Button } from "@/examples/radix/ui/button"
import {
Empty,
EmptyContent,
@@ -13,7 +7,8 @@ import {
EmptyHeader,
EmptyMedia,
EmptyTitle,
} from "@/registry/new-york-v4/ui/empty"
} from "@/examples/radix/ui/empty"
import { PlusIcon } from "lucide-react"
export function EmptyAvatarGroup() {
return (

View File

@@ -1,5 +1,5 @@
import { Checkbox } from "@/registry/new-york-v4/ui/checkbox"
import { Field, FieldLabel } from "@/registry/new-york-v4/ui/field"
import { Checkbox } from "@/examples/radix/ui/checkbox"
import { Field, FieldLabel } from "@/examples/radix/ui/field"
export function FieldCheckbox() {
return (

View File

@@ -1,5 +1,5 @@
import { Button } from "@/registry/new-york-v4/ui/button"
import { Checkbox } from "@/registry/new-york-v4/ui/checkbox"
import { Button } from "@/examples/radix/ui/button"
import { Checkbox } from "@/examples/radix/ui/checkbox"
import {
Field,
FieldDescription,
@@ -8,16 +8,16 @@ import {
FieldLegend,
FieldSeparator,
FieldSet,
} from "@/registry/new-york-v4/ui/field"
import { Input } from "@/registry/new-york-v4/ui/input"
} from "@/examples/radix/ui/field"
import { Input } from "@/examples/radix/ui/input"
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/registry/new-york-v4/ui/select"
import { Textarea } from "@/registry/new-york-v4/ui/textarea"
} from "@/examples/radix/ui/select"
import { Textarea } from "@/examples/radix/ui/textarea"
export function FieldDemo() {
return (

View File

@@ -1,5 +1,5 @@
import { Card, CardContent } from "@/registry/new-york-v4/ui/card"
import { Checkbox } from "@/registry/new-york-v4/ui/checkbox"
import { Card, CardContent } from "@/examples/radix/ui/card"
import { Checkbox } from "@/examples/radix/ui/checkbox"
import {
Field,
FieldDescription,
@@ -8,7 +8,7 @@ import {
FieldLegend,
FieldSet,
FieldTitle,
} from "@/registry/new-york-v4/ui/field"
} from "@/examples/radix/ui/field"
const options = [
{

View File

@@ -1,13 +1,8 @@
"use client"
import { useState } from "react"
import {
Field,
FieldDescription,
FieldTitle,
} from "@/registry/new-york-v4/ui/field"
import { Slider } from "@/registry/new-york-v4/ui/slider"
import { Field, FieldDescription, FieldTitle } from "@/examples/radix/ui/field"
import { Slider } from "@/examples/radix/ui/slider"
export function FieldSlider() {
const [value, setValue] = useState([200, 800])

View File

@@ -1,4 +1,4 @@
import { FieldSeparator } from "@/registry/new-york-v4/ui/field"
import { FieldSeparator } from "@/examples/radix/ui/field"
import { AppearanceSettings } from "./appearance-settings"
import { ButtonGroupDemo } from "./button-group-demo"

View File

@@ -1,20 +1,19 @@
"use client"
import * as React from "react"
import { IconInfoCircle, IconStar } from "@tabler/icons-react"
import {
InputGroup,
InputGroupAddon,
InputGroupButton,
InputGroupInput,
} from "@/registry/new-york-v4/ui/input-group"
import { Label } from "@/registry/new-york-v4/ui/label"
} from "@/examples/radix/ui/input-group"
import { Label } from "@/examples/radix/ui/label"
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/registry/new-york-v4/ui/popover"
} from "@/examples/radix/ui/popover"
import { IconInfoCircle, IconStar } from "@tabler/icons-react"
export function InputGroupButtonExample() {
const [isFavorite, setIsFavorite] = React.useState(false)

View File

@@ -1,12 +1,9 @@
import { IconCheck, IconInfoCircle, IconPlus } from "@tabler/icons-react"
import { ArrowUpIcon, Search } from "lucide-react"
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuTrigger,
} from "@/registry/new-york-v4/ui/dropdown-menu"
} from "@/examples/radix/ui/dropdown-menu"
import {
InputGroup,
InputGroupAddon,
@@ -14,13 +11,15 @@ import {
InputGroupInput,
InputGroupText,
InputGroupTextarea,
} from "@/registry/new-york-v4/ui/input-group"
import { Separator } from "@/registry/new-york-v4/ui/separator"
} from "@/examples/radix/ui/input-group"
import { Separator } from "@/examples/radix/ui/separator"
import {
Tooltip,
TooltipContent,
TooltipTrigger,
} from "@/registry/new-york-v4/ui/tooltip"
} from "@/examples/radix/ui/tooltip"
import { IconCheck, IconInfoCircle, IconPlus } from "@tabler/icons-react"
import { ArrowUpIcon, Search } from "lucide-react"
export function InputGroupDemo() {
return (

View File

@@ -1,6 +1,4 @@
import { BadgeCheckIcon, ChevronRightIcon } from "lucide-react"
import { Button } from "@/registry/new-york-v4/ui/button"
import { Button } from "@/examples/radix/ui/button"
import {
Item,
ItemActions,
@@ -8,7 +6,8 @@ import {
ItemDescription,
ItemMedia,
ItemTitle,
} from "@/registry/new-york-v4/ui/item"
} from "@/examples/radix/ui/item"
import { BadgeCheckIcon, ChevronRightIcon } from "lucide-react"
export function ItemDemo() {
return (

View File

@@ -1,24 +1,8 @@
"use client"
import { useMemo, useState } from "react"
import {
IconApps,
IconArrowUp,
IconAt,
IconBook,
IconCircleDashedPlus,
IconPaperclip,
IconPlus,
IconWorld,
IconX,
} from "@tabler/icons-react"
import {
Avatar,
AvatarFallback,
AvatarImage,
} from "@/registry/new-york-v4/ui/avatar"
import { Badge } from "@/registry/new-york-v4/ui/badge"
import { Avatar, AvatarFallback, AvatarImage } from "@/examples/radix/ui/avatar"
import { Badge } from "@/examples/radix/ui/badge"
import {
Command,
CommandEmpty,
@@ -26,7 +10,7 @@ import {
CommandInput,
CommandItem,
CommandList,
} from "@/registry/new-york-v4/ui/command"
} from "@/examples/radix/ui/command"
import {
DropdownMenu,
DropdownMenuCheckboxItem,
@@ -39,25 +23,36 @@ import {
DropdownMenuSubContent,
DropdownMenuSubTrigger,
DropdownMenuTrigger,
} from "@/registry/new-york-v4/ui/dropdown-menu"
import { Field, FieldLabel } from "@/registry/new-york-v4/ui/field"
} from "@/examples/radix/ui/dropdown-menu"
import { Field, FieldLabel } from "@/examples/radix/ui/field"
import {
InputGroup,
InputGroupAddon,
InputGroupButton,
InputGroupTextarea,
} from "@/registry/new-york-v4/ui/input-group"
} from "@/examples/radix/ui/input-group"
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/registry/new-york-v4/ui/popover"
import { Switch } from "@/registry/new-york-v4/ui/switch"
} from "@/examples/radix/ui/popover"
import { Switch } from "@/examples/radix/ui/switch"
import {
Tooltip,
TooltipContent,
TooltipTrigger,
} from "@/registry/new-york-v4/ui/tooltip"
} from "@/examples/radix/ui/tooltip"
import {
IconApps,
IconArrowUp,
IconAt,
IconBook,
IconCircleDashedPlus,
IconPaperclip,
IconPlus,
IconWorld,
IconX,
} from "@tabler/icons-react"
const SAMPLE_DATA = {
mentionable: [

View File

@@ -1,5 +1,5 @@
import { Badge } from "@/registry/new-york-v4/ui/badge"
import { Spinner } from "@/registry/new-york-v4/ui/spinner"
import { Badge } from "@/examples/radix/ui/badge"
import { Spinner } from "@/examples/radix/ui/spinner"
export function SpinnerBadge() {
return (

View File

@@ -1,4 +1,4 @@
import { Button } from "@/registry/new-york-v4/ui/button"
import { Button } from "@/examples/radix/ui/button"
import {
Empty,
EmptyContent,
@@ -6,8 +6,8 @@ import {
EmptyHeader,
EmptyMedia,
EmptyTitle,
} from "@/registry/new-york-v4/ui/empty"
import { Spinner } from "@/registry/new-york-v4/ui/spinner"
} from "@/examples/radix/ui/empty"
import { Spinner } from "@/examples/radix/ui/spinner"
export function SpinnerEmpty() {
return (

View File

@@ -64,7 +64,7 @@ export default function ChartsLayout({
<PageNav id="charts">
<ChartsNav />
</PageNav>
<div className="container-wrapper section-soft flex-1">
<div className="container-wrapper flex-1">
<div className="container pb-6">
<section className="theme-container">{children}</section>
</div>

View File

@@ -1,21 +1,15 @@
import Link from "next/link"
import { notFound } from "next/navigation"
import { mdxComponents } from "@/mdx-components"
import {
IconArrowLeft,
IconArrowRight,
IconArrowUpRight,
} from "@tabler/icons-react"
import fm from "front-matter"
import { IconArrowLeft, IconArrowRight } from "@tabler/icons-react"
import { findNeighbour } from "fumadocs-core/page-tree"
import z from "zod"
import { source } from "@/lib/source"
import { absoluteUrl } from "@/lib/utils"
import { DocsBaseSwitcher } from "@/components/docs-base-switcher"
import { DocsCopyPage } from "@/components/docs-copy-page"
import { DocsTableOfContents } from "@/components/docs-toc"
import { OpenInV0Cta } from "@/components/open-in-v0-cta"
import { Badge } from "@/registry/new-york-v4/ui/badge"
import { Button } from "@/registry/new-york-v4/ui/button"
export const revalidate = false
@@ -86,126 +80,110 @@ export default async function Page(props: {
const doc = page.data
const MDX = doc.body
const neighbours = findNeighbour(source.pageTree, page.url)
const raw = await page.data.getText("raw")
const { attributes } = fm(raw)
const { links } = z
.object({
links: z
.object({
doc: z.string().optional(),
api: z.string().optional(),
})
.optional(),
})
.parse(attributes)
return (
<div className="flex items-stretch text-[1.05rem] sm:text-[15px] xl:w-full">
<div
data-slot="docs"
className="flex scroll-mt-24 items-stretch pb-8 text-[1.05rem] sm:text-[15px] xl:w-full"
>
<div className="flex min-w-0 flex-1 flex-col">
<div className="h-(--top-spacing) shrink-0" />
<div className="mx-auto flex w-full max-w-2xl min-w-0 flex-1 flex-col gap-8 px-4 py-6 text-neutral-800 md:px-0 lg:py-8 dark:text-neutral-300">
<div className="mx-auto flex w-full max-w-[40rem] min-w-0 flex-1 flex-col gap-6 px-4 py-6 text-neutral-800 md:px-0 lg:py-8 dark:text-neutral-300">
<div className="flex flex-col gap-2">
<div className="flex flex-col gap-2">
<div className="flex items-start justify-between">
<h1 className="scroll-m-20 text-4xl font-semibold tracking-tight sm:text-3xl xl:text-4xl">
<h1 className="scroll-m-24 text-4xl font-semibold tracking-tight sm:text-3xl">
{doc.title}
</h1>
<div className="docs-nav bg-background/80 border-border/50 fixed inset-x-0 bottom-0 isolate z-50 flex items-center gap-2 border-t px-6 py-4 backdrop-blur-sm sm:static sm:z-0 sm:border-t-0 sm:bg-transparent sm:px-0 sm:pt-1.5 sm:backdrop-blur-none">
<div className="docs-nav bg-background/80 border-border/50 fixed inset-x-0 bottom-0 isolate z-50 flex items-center gap-2 border-t px-6 py-4 backdrop-blur-sm sm:static sm:z-0 sm:border-t-0 sm:bg-transparent sm:px-0 sm:py-1.5 sm:backdrop-blur-none">
<DocsCopyPage page={raw} url={absoluteUrl(page.url)} />
{neighbours.previous && (
<Button
variant="secondary"
size="icon"
className="extend-touch-target ml-auto size-8 shadow-none md:size-7"
asChild
>
<Link href={neighbours.previous.url}>
<IconArrowLeft />
<span className="sr-only">Previous</span>
</Link>
</Button>
)}
{neighbours.next && (
<Button
variant="secondary"
size="icon"
className="extend-touch-target size-8 shadow-none md:size-7"
asChild
>
<Link href={neighbours.next.url}>
<span className="sr-only">Next</span>
<IconArrowRight />
</Link>
</Button>
)}
<div className="ml-auto flex gap-2">
{neighbours.previous && (
<Button
variant="secondary"
size="icon"
className="extend-touch-target size-8 shadow-none md:size-7"
asChild
>
<Link href={neighbours.previous.url}>
<IconArrowLeft />
<span className="sr-only">Previous</span>
</Link>
</Button>
)}
{neighbours.next && (
<Button
variant="secondary"
size="icon"
className="extend-touch-target size-8 shadow-none md:size-7"
asChild
>
<Link href={neighbours.next.url}>
<span className="sr-only">Next</span>
<IconArrowRight />
</Link>
</Button>
)}
</div>
</div>
</div>
{doc.description && (
<p className="text-muted-foreground text-[1.05rem] text-balance sm:text-base">
<p className="text-muted-foreground text-[1.05rem] sm:text-base sm:text-balance md:max-w-[80%]">
{doc.description}
</p>
)}
</div>
{links ? (
<div className="flex items-center gap-2 pt-4">
{links?.doc && (
<Badge asChild variant="secondary" className="rounded-full">
<a href={links.doc} target="_blank" rel="noreferrer">
Docs <IconArrowUpRight />
</a>
</Badge>
)}
{links?.api && (
<Badge asChild variant="secondary" className="rounded-full">
<a href={links.api} target="_blank" rel="noreferrer">
API Reference <IconArrowUpRight />
</a>
</Badge>
)}
</div>
) : null}
</div>
<div className="w-full flex-1 *:data-[slot=alert]:first:mt-0">
<div className="w-full flex-1 pb-16 *:data-[slot=alert]:first:mt-0 sm:pb-0">
{params.slug &&
params.slug[0] === "components" &&
params.slug[1] &&
params.slug[2] && (
<DocsBaseSwitcher
base={params.slug[1]}
component={params.slug[2]}
className="mb-4"
/>
)}
<MDX components={mdxComponents} />
</div>
</div>
<div className="mx-auto hidden h-16 w-full max-w-2xl items-center gap-2 px-4 sm:flex md:px-0">
{neighbours.previous && (
<Button
variant="secondary"
size="sm"
asChild
className="shadow-none"
>
<Link href={neighbours.previous.url}>
<IconArrowLeft /> {neighbours.previous.name}
</Link>
</Button>
)}
{neighbours.next && (
<Button
variant="secondary"
size="sm"
className="ml-auto shadow-none"
asChild
>
<Link href={neighbours.next.url}>
{neighbours.next.name} <IconArrowRight />
</Link>
</Button>
)}
<div className="hidden h-16 w-full items-center gap-2 px-4 sm:flex sm:px-0">
{neighbours.previous && (
<Button
variant="secondary"
size="sm"
asChild
className="shadow-none"
>
<Link href={neighbours.previous.url}>
<IconArrowLeft /> {neighbours.previous.name}
</Link>
</Button>
)}
{neighbours.next && (
<Button
variant="secondary"
size="sm"
className="ml-auto shadow-none"
asChild
>
<Link href={neighbours.next.url}>
{neighbours.next.name} <IconArrowRight />
</Link>
</Button>
)}
</div>
</div>
</div>
<div className="sticky top-[calc(var(--header-height)+1px)] z-30 ml-auto hidden h-[calc(100svh-var(--footer-height)+2rem)] w-72 flex-col gap-4 overflow-hidden overscroll-none pb-8 xl:flex">
<div className="h-(--top-spacing) shrink-0" />
<div className="sticky top-[calc(var(--header-height)+1px)] z-30 ml-auto hidden h-[90svh] w-72 flex-col gap-4 overflow-hidden overscroll-none pb-8 lg:flex">
<div className="h-(--top-spacing) shrink-0"></div>
{doc.toc?.length ? (
<div className="no-scrollbar overflow-y-auto px-8">
<div className="no-scrollbar flex flex-col gap-8 overflow-y-auto px-8">
<DocsTableOfContents toc={doc.toc} />
<div className="h-12" />
</div>
) : null}
<div className="flex flex-1 flex-col gap-12 px-6">
<div className="hidden flex-1 flex-col gap-6 px-6 xl:flex">
<OpenInV0Cta />
</div>
</div>

View File

@@ -9,7 +9,10 @@ export default function DocsLayout({
}) {
return (
<div className="container-wrapper flex flex-1 flex-col px-2">
<SidebarProvider className="3xl:fixed:container 3xl:fixed:px-3 min-h-min flex-1 items-start px-0 [--sidebar-width:220px] [--top-spacing:0] lg:grid lg:grid-cols-[var(--sidebar-width)_minmax(0,1fr)] lg:[--sidebar-width:240px] lg:[--top-spacing:calc(var(--spacing)*4)]">
<SidebarProvider
className="3xl:fixed:container 3xl:fixed:px-3 min-h-min flex-1 items-start px-0 [--top-spacing:0] lg:grid lg:grid-cols-[var(--sidebar-width)_minmax(0,1fr)] lg:[--top-spacing:calc(var(--spacing)*4)]"
style={{ "--sidebar-width": "220px" } as React.CSSProperties}
>
<DocsSidebar tree={source.pageTree} />
<div className="h-full w-full">{children}</div>
</SidebarProvider>

View File

@@ -3,10 +3,23 @@ import { NextResponse, type NextRequest } from "next/server"
import { processMdxForLLMs } from "@/lib/llm"
import { source } from "@/lib/source"
import { getActiveStyle } from "@/registry/_legacy-styles"
import { getActiveStyle, type Style } from "@/registry/_legacy-styles"
export const revalidate = false
function getStyleFromSlug(slug: string[] | undefined, fallbackStyle: string) {
// Detect base from URL: /docs/components/base/... or /docs/components/radix/...
if (slug && slug[0] === "components" && slug[1]) {
if (slug[1] === "base") {
return "base-nova"
}
if (slug[1] === "radix") {
return "new-york-v4"
}
}
return fallbackStyle
}
export async function GET(
_req: NextRequest,
{ params }: { params: Promise<{ slug?: string[] }> }
@@ -19,9 +32,11 @@ export async function GET(
notFound()
}
const effectiveStyle = getStyleFromSlug(slug, activeStyle.name)
const processedContent = processMdxForLLMs(
await page.data.getText("raw"),
activeStyle.name
effectiveStyle as Style["name"]
)
return new NextResponse(processedContent, {

View File

@@ -99,7 +99,7 @@ export function ItemPicker({
variant="outline"
aria-label="Select item"
size="sm"
className="data-popup-open:bg-muted dark:data-popup-open:bg-muted/50 bg-muted/50 sm:bg-background md:dark:bg-background border-foreground/10 dark:bg-muted/50 h-[calc(--spacing(13.5))] flex-1 touch-manipulation justify-between gap-2 rounded-xl pr-4! pl-2.5 text-left shadow-none select-none *:data-[slot=combobox-trigger-icon]:hidden sm:h-8 sm:max-w-56 sm:rounded-lg sm:pr-2! xl:max-w-md"
className="data-popup-open:bg-muted dark:data-popup-open:bg-muted/50 bg-muted/50 sm:bg-background md:dark:bg-background border-foreground/10 dark:bg-muted/50 h-[calc(--spacing(13.5))] flex-1 touch-manipulation justify-between gap-2 rounded-xl pr-4! pl-2.5 text-left shadow-none select-none *:data-[slot=combobox-trigger-icon]:hidden sm:h-8 sm:max-w-56 sm:rounded-lg sm:pr-2! xl:max-w-64"
/>
}
>
@@ -123,9 +123,9 @@ export function ItemPicker({
<HugeiconsIcon icon={Search01Icon} />
</ComboboxTrigger>
<ComboboxContent
className="ring-foreground/10 min-w-[calc(var(--available-width)---spacing(4))] translate-x-2 animate-none rounded-xl border-0 ring-1 data-open:animate-none sm:min-w-[calc(var(--anchor-width)+--spacing(7))] sm:translate-x-0"
className="ring-foreground/10 min-w-[calc(var(--available-width)---spacing(4))] translate-x-2 animate-none rounded-xl border-0 ring-1 data-open:animate-none sm:min-w-[calc(var(--anchor-width)+--spacing(7))] sm:translate-x-0 xl:w-96"
side="bottom"
align="center"
align="end"
>
<ComboboxInput
showTrigger={false}

View File

@@ -56,7 +56,7 @@ export function ShareButton() {
<Button
size="sm"
variant="outline"
className="rounded-lg shadow-none"
className="rounded-lg shadow-none lg:w-8 xl:w-fit"
onClick={handleCopy}
>
{hasCopied ? (
@@ -64,7 +64,7 @@ export function ShareButton() {
) : (
<HugeiconsIcon icon={Share03Icon} strokeWidth={2} />
)}
Share
<span className="lg:hidden xl:block">Share</span>
</Button>
</TooltipTrigger>
<TooltipContent>Copy Link</TooltipContent>

View File

@@ -14,7 +14,7 @@ import {
import { useDesignSystemSearchParams } from "@/app/(create)/lib/search-params"
export function V0Button({ className }: { className?: string }) {
const [params, setParams] = useDesignSystemSearchParams()
const [params] = useDesignSystemSearchParams()
const isMobile = useIsMobile()
const isMounted = useMounted()
@@ -32,7 +32,7 @@ export function V0Button({ className }: { className?: string }) {
size="sm"
variant={isMobile ? "default" : "outline"}
className={cn(
"w-24 rounded-lg shadow-none data-[variant=default]:h-[31px]",
"w-24 rounded-lg shadow-none data-[variant=default]:h-[31px] lg:w-8 xl:w-24",
className
)}
asChild
@@ -41,7 +41,8 @@ export function V0Button({ className }: { className?: string }) {
href={`${process.env.NEXT_PUBLIC_V0_URL}/chat/api/open?url=${encodeURIComponent(url)}&title=${params.item}`}
target="_blank"
>
Open in <Icons.v0 className="size-5" />
<span className="lg:hidden xl:block">Open in</span>
<Icons.v0 className="size-5" />
</a>
</Button>
</TooltipTrigger>

View File

@@ -4,7 +4,11 @@ import { ArrowLeftIcon } from "lucide-react"
import type { SearchParams } from "nuqs/server"
import { siteConfig } from "@/lib/config"
import { source } from "@/lib/source"
import { absoluteUrl } from "@/lib/utils"
import { Icons } from "@/components/icons"
import { MainNav } from "@/components/main-nav"
import { MobileNav } from "@/components/mobile-nav"
import { ModeSwitcher } from "@/components/mode-switcher"
import { SiteConfig } from "@/components/site-config"
import { BASES } from "@/registry/config"
@@ -64,6 +68,7 @@ export default async function CreatePage({
const params = await loadDesignSystemSearchParams(searchParams)
const base = BASES.find((b) => b.name === params.base) ?? BASES[0]
const pageTree = source.pageTree
const items = await getItemsForBase(base.name)
const filteredItems = items
@@ -82,38 +87,34 @@ export default async function CreatePage({
<header className="sticky top-0 z-50 w-full">
<div className="container-wrapper 3xl:fixed:px-0 px-6">
<div className="3xl:fixed:container flex h-(--header-height) items-center **:data-[slot=separator]:!h-4">
<div className="flex items-center xl:w-1/3">
<div className="3xl:fixed:container flex h-(--header-height) items-center **:data-[slot=separator]:!h-4">
<MobileNav
tree={pageTree}
items={siteConfig.navItems}
className="flex lg:hidden"
/>
<Button
asChild
variant="outline"
size="sm"
className="rounded-lg shadow-none"
variant="ghost"
size="icon"
className="hidden size-8 lg:flex"
>
<Link href="/">
<ArrowLeftIcon />
Back
<Icons.logo className="size-5" />
<span className="sr-only">{siteConfig.name}</span>
</Link>
</Button>
<Separator
orientation="vertical"
className="mx-2 hidden sm:mx-4 lg:flex"
/>
<div className="text-muted-foreground hidden text-sm font-medium lg:flex">
New Project
</div>
<MainNav items={siteConfig.navItems} className="hidden lg:flex" />
</div>
<div className="fixed inset-x-0 bottom-0 ml-auto flex flex-1 items-center gap-2 px-4.5 pb-4 sm:static sm:justify-end sm:p-0 lg:ml-0 xl:justify-center">
<div className="fixed inset-x-0 bottom-0 ml-auto flex flex-1 items-center justify-end gap-2 px-4.5 pb-4 sm:static sm:p-0 lg:ml-0">
<ItemPicker items={filteredItems} />
<div className="items-center gap-0 sm:hidden">
<RandomButton />
<ResetButton />
</div>
<Separator
orientation="vertical"
className="mr-2 hidden sm:flex xl:hidden"
/>
<Separator orientation="vertical" className="mr-2 flex" />
</div>
<div className="ml-auto flex items-center gap-2 sm:ml-0 md:justify-end xl:ml-auto xl:w-1/3">
<div className="ml-auto flex items-center gap-2 sm:ml-0 md:justify-end">
<SiteConfig className="3xl:flex hidden" />
<Separator orientation="vertical" className="3xl:flex hidden" />
<ModeSwitcher />

View File

@@ -4,7 +4,11 @@ import { type Metadata } from "next"
import { notFound } from "next/navigation"
import { siteConfig } from "@/lib/config"
import { getRegistryComponent, getRegistryItem } from "@/lib/registry"
import {
getDemoItem,
getRegistryComponent,
getRegistryItem,
} from "@/lib/registry"
import { absoluteUrl } from "@/lib/utils"
import { getStyle, legacyStyles, type Style } from "@/registry/_legacy-styles"
@@ -18,7 +22,12 @@ export const dynamicParams = false
const getCachedRegistryItem = React.cache(
async (name: string, styleName: Style["name"]) => {
return await getRegistryItem(name, styleName)
// Try registry item first, then fallback to demo item (for examples).
const item = await getRegistryItem(name, styleName)
if (item) {
return item
}
return await getDemoItem(name, styleName)
}
)
@@ -75,9 +84,54 @@ export async function generateMetadata({
export async function generateStaticParams() {
const { Index } = await import("@/registry/__index__")
// const { Index: BasesIndex } = await import("@/registry/bases/__index__")
const { ExamplesIndex } = await import("@/examples/__index__")
const params: Array<{ style: string; name: string }> = []
for (const style of legacyStyles) {
// Check if this is a base-prefixed style (e.g., base-nova, radix-nova).
const baseMatch = style.name.match(/^(base|radix)-/)
if (baseMatch) {
const baseName = baseMatch[1]
// Add examples from ExamplesIndex.
const examples = ExamplesIndex[baseName]
if (examples) {
for (const exampleName of Object.keys(examples)) {
if (exampleName.startsWith("sidebar-")) {
params.push({
style: style.name,
name: exampleName,
})
}
}
}
// // Add UI components from BasesIndex.
// const baseIndex = BasesIndex[baseName]
// if (baseIndex) {
// for (const itemName in baseIndex) {
// const item = baseIndex[itemName]
// if (
// [
// "registry:block",
// "registry:component",
// "registry:example",
// "registry:internal",
// ].includes(item.type)
// ) {
// params.push({
// style: style.name,
// name: item.name,
// })
// }
// }
// }
continue
}
// Handle legacy styles (e.g., new-york-v4).
if (!Index[style.name]) {
continue
}

View File

@@ -3,12 +3,27 @@ import { ArrowRightIcon } from "lucide-react"
import { Badge } from "@/registry/new-york-v4/ui/badge"
function BaseUILogo() {
return (
<svg width="17" height="24" viewBox="0 0 17 24" className="size-3">
<path
fill="currentColor"
d="M9.5001 7.01537C9.2245 6.99837 9 7.22385 9 7.49999V23C13.4183 23 17 19.4183 17 15C17 10.7497 13.6854 7.27351 9.5001 7.01537Z"
/>
<path
fill="currentColor"
d="M8 9.8V12V23C3.58172 23 0 19.0601 0 14.2V12V1C4.41828 1 8 4.93989 8 9.8Z"
/>
</svg>
)
}
export function Announcement() {
return (
<Badge asChild variant="secondary" className="bg-transparent">
<Link href="/docs/changelog">
<span className="flex size-2 rounded-full bg-blue-500" title="New" />
npx shadcn create <ArrowRightIcon />
<BaseUILogo />
Base UI Documentation <ArrowRightIcon />
</Link>
</Badge>
)

View File

@@ -35,7 +35,7 @@ export function ChartDisplay({
<div className="bg-background relative z-10 overflow-hidden rounded-xl">
<ChartIframe
src={`/view/${style}/${chart.name}`}
height={430}
height={460}
title={chart.name}
/>
</div>

View File

@@ -18,7 +18,7 @@ export function CodeTabs({ children }: React.ComponentProps<typeof Tabs>) {
onValueChange={(value) =>
setConfig({ ...config, installationType: value as "cli" | "manual" })
}
className="relative mt-6 w-full"
className="relative mt-6 w-full *:data-[slot=tabs-list]:gap-6"
>
{children}
</Tabs>

View File

@@ -1,15 +1,17 @@
"use client"
import * as React from "react"
import { useRouter } from "next/navigation"
import { usePathname, useRouter } from "next/navigation"
import { type DialogProps } from "@radix-ui/react-dialog"
import * as DialogPrimitive from "@radix-ui/react-dialog"
import { IconArrowRight } from "@tabler/icons-react"
import { useDocsSearch } from "fumadocs-core/search/client"
import { CornerDownLeftIcon, SquareDashedIcon } from "lucide-react"
import { CornerDownLeftIcon, SquareDashedIcon, XIcon } from "lucide-react"
import { type Color, type ColorPalette } from "@/lib/colors"
import { trackEvent } from "@/lib/events"
import { showMcpDocs } from "@/lib/flags"
import { getCurrentBase, getPagesFromFolder } from "@/lib/page-tree"
import { type source } from "@/lib/source"
import { cn } from "@/lib/utils"
import { useConfig } from "@/hooks/use-config"
@@ -26,13 +28,13 @@ import {
} from "@/registry/new-york-v4/ui/command"
import {
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogPortal,
DialogTitle,
DialogTrigger,
} from "@/registry/new-york-v4/ui/dialog"
import { Kbd, KbdGroup } from "@/registry/new-york-v4/ui/kbd"
import { Kbd } from "@/registry/new-york-v4/ui/kbd"
import { Separator } from "@/registry/new-york-v4/ui/separator"
import { Spinner } from "@/registry/new-york-v4/ui/spinner"
@@ -49,7 +51,9 @@ export function CommandMenu({
navItems?: { href: string; label: string }[]
}) {
const router = useRouter()
const pathname = usePathname()
const [config] = useConfig()
const currentBase = getCurrentBase(pathname)
const [open, setOpen] = React.useState(false)
const [selectedType, setSelectedType] = React.useState<
"color" | "page" | "component" | "block" | null
@@ -138,10 +142,13 @@ export function CommandMenu({
[setSelectedType, setCopyPayload, packageManager]
)
const runCommand = React.useCallback((command: () => unknown) => {
setOpen(false)
command()
}, [])
const runCommand = React.useCallback(
(command: () => unknown) => {
setOpen(false)
command()
},
[setOpen]
)
React.useEffect(() => {
const down = (e: KeyboardEvent) => {
@@ -207,10 +214,7 @@ export function CommandMenu({
</div>
</Button>
</DialogTrigger>
<DialogContent
showCloseButton={false}
className="rounded-xl border-none bg-clip-padding p-2 pb-11 shadow-2xl ring-4 ring-neutral-200/80 dark:bg-neutral-900 dark:ring-neutral-800"
>
<DialogContent className="rounded-xl border-none bg-clip-padding p-2 pb-11 shadow-2xl ring-4 ring-neutral-200/80 dark:bg-neutral-900 dark:ring-neutral-800">
<DialogHeader className="sr-only">
<DialogTitle>Search documentation...</DialogTitle>
<DialogDescription>Search for a command to run...</DialogDescription>
@@ -269,40 +273,37 @@ export function CommandMenu({
className="!p-0 [&_[cmdk-group-heading]]:scroll-mt-16 [&_[cmdk-group-heading]]:!p-3 [&_[cmdk-group-heading]]:!pb-1"
>
{group.type === "folder" &&
group.children.map((item) => {
if (item.type === "page") {
const isComponent = item.url.includes("/components/")
getPagesFromFolder(group, currentBase).map((item) => {
const isComponent = item.url.includes("/components/")
if (!showMcpDocs && item.url.includes("/mcp")) {
return null
}
return (
<CommandMenuItem
key={item.url}
value={
item.name?.toString()
? `${group.name} ${item.name}`
: ""
}
keywords={isComponent ? ["component"] : undefined}
onHighlight={() =>
handlePageHighlight(isComponent, item)
}
onSelect={() => {
runCommand(() => router.push(item.url))
}}
>
{isComponent ? (
<div className="border-muted-foreground aspect-square size-4 rounded-full border border-dashed" />
) : (
<IconArrowRight />
)}
{item.name}
</CommandMenuItem>
)
if (!showMcpDocs && item.url.includes("/mcp")) {
return null
}
return null
return (
<CommandMenuItem
key={item.url}
value={
item.name?.toString()
? `${group.name} ${item.name}`
: ""
}
keywords={isComponent ? ["component"] : undefined}
onHighlight={() =>
handlePageHighlight(isComponent, item)
}
onSelect={() => {
runCommand(() => router.push(item.url))
}}
>
{isComponent ? (
<div className="border-muted-foreground aspect-square size-4 rounded-full border border-dashed" />
) : (
<IconArrowRight />
)}
{item.name}
</CommandMenuItem>
)
})}
</CommandGroup>
))}
@@ -523,3 +524,30 @@ function SearchResults({
</CommandGroup>
)
}
function DialogContent({
className,
children,
...props
}: React.ComponentProps<typeof DialogPrimitive.Content> & {
showCloseButton?: boolean
}) {
return (
<DialogPortal data-slot="dialog-portal">
<DialogPrimitive.Overlay
data-slot="dialog-overlay"
className="fixed inset-0 z-50 bg-black/50"
/>
<DialogPrimitive.Content
data-slot="dialog-content"
className={cn(
"bg-background fixed top-[50%] left-[50%] z-50 grid w-full max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] gap-4 rounded-lg border p-6 shadow-lg duration-200 outline-none sm:max-w-lg",
className
)}
{...props}
>
{children}
</DialogPrimitive.Content>
</DialogPortal>
)
}

View File

@@ -3,9 +3,11 @@
import * as React from "react"
import { cn } from "@/lib/utils"
import { Button } from "@/registry/new-york-v4/ui/button"
export function ComponentPreviewTabs({
className,
previewClassName,
align = "center",
hideCode = false,
chromeLessOnMobile = false,
@@ -13,16 +15,19 @@ export function ComponentPreviewTabs({
source,
...props
}: React.ComponentProps<"div"> & {
previewClassName?: string
align?: "center" | "start" | "end"
hideCode?: boolean
chromeLessOnMobile?: boolean
component: React.ReactNode
source: React.ReactNode
}) {
const [isMobileCodeVisible, setIsMobileCodeVisible] = React.useState(false)
return (
<div
className={cn(
"group relative mt-4 mb-12 flex flex-col gap-2 rounded-lg border",
"group relative mt-4 mb-12 flex flex-col gap-2 overflow-hidden rounded-xl border",
className
)}
{...props}
@@ -30,9 +35,10 @@ export function ComponentPreviewTabs({
<div data-slot="preview">
<div
data-align={align}
data-chromeless={chromeLessOnMobile}
className={cn(
"preview flex w-full justify-center data-[align=center]:items-center data-[align=end]:items-end data-[align=start]:items-start",
chromeLessOnMobile ? "sm:p-10" : "h-[450px] p-10"
"preview flex h-72 w-full justify-center p-10 data-[align=center]:items-center data-[align=end]:items-end data-[align=start]:items-start data-[chromeless=true]:h-auto data-[chromeless=true]:p-0",
previewClassName
)}
>
{component}
@@ -40,9 +46,32 @@ export function ComponentPreviewTabs({
{!hideCode && (
<div
data-slot="code"
className="overflow-hidden [&_[data-rehype-pretty-code-figure]]:!m-0 [&_[data-rehype-pretty-code-figure]]:rounded-t-none [&_[data-rehype-pretty-code-figure]]:border-t [&_pre]:max-h-[400px]"
data-mobile-code-visible={isMobileCodeVisible}
className="relative overflow-hidden data-[mobile-code-visible=false]:max-h-24 md:max-h-none data-[mobile-code-visible=false]:md:max-h-none [&_[data-rehype-pretty-code-figure]]:!m-0 [&_[data-rehype-pretty-code-figure]]:rounded-t-none [&_[data-rehype-pretty-code-figure]]:border-t [&_pre]:max-h-72"
>
{source}
{!isMobileCodeVisible && (
<div className="absolute inset-0 flex items-center justify-center md:hidden">
<div
className="absolute inset-0"
style={{
background:
"linear-gradient(to top, var(--color-code), color-mix(in oklab, var(--color-code) 60%, transparent), transparent)",
}}
/>
<Button
type="button"
size="sm"
variant="outline"
className="bg-background text-foreground dark:bg-background dark:text-foreground relative z-10"
onClick={() => {
setIsMobileCodeVisible(true)
}}
>
View Code
</Button>
</div>
)}
</div>
)}
</div>

View File

@@ -1,45 +1,33 @@
import * as React from "react"
import Image from "next/image"
import { getRegistryComponent } from "@/lib/registry"
import { ComponentPreviewTabs } from "@/components/component-preview-tabs"
import { ComponentSource } from "@/components/component-source"
import { Index } from "@/registry/__index__"
import { type Style } from "@/registry/_legacy-styles"
export function ComponentPreview({
name,
styleName = "new-york-v4",
type,
className,
previewClassName,
align = "center",
hideCode = false,
chromeLessOnMobile = false,
styleName = "new-york-v4",
...props
}: React.ComponentProps<"div"> & {
name: string
styleName?: Style["name"]
styleName?: string
align?: "center" | "start" | "end"
description?: string
hideCode?: boolean
type?: "block" | "component" | "example"
chromeLessOnMobile?: boolean
previewClassName?: string
}) {
const Component = Index[styleName]?.[name]?.component
if (!Component) {
return (
<p className="text-muted-foreground mt-6 text-sm">
Component{" "}
<code className="bg-muted relative rounded px-[0.3rem] py-[0.2rem] font-mono text-sm">
{name}
</code>{" "}
not found in registry.
</p>
)
}
if (type === "block") {
return (
<div className="relative aspect-[4/2.5] w-full overflow-hidden rounded-md border md:-mx-1">
<div className="relative aspect-[4/2.5] w-full overflow-hidden rounded-xl border md:-mx-1">
<Image
src={`/r/styles/new-york-v4/${name}-light.png`}
alt={name}
@@ -61,12 +49,27 @@ export function ComponentPreview({
)
}
const Component = getRegistryComponent(name, styleName)
if (!Component) {
return (
<p className="text-muted-foreground mt-6 text-sm">
Component{" "}
<code className="bg-muted relative rounded px-[0.3rem] py-[0.2rem] font-mono text-sm">
{name}
</code>{" "}
not found in registry.
</p>
)
}
return (
<ComponentPreviewTabs
className={className}
previewClassName={previewClassName}
align={align}
hideCode={hideCode}
component={<Component />}
component={<DynamicComponent name={name} styleName={styleName} />}
source={
<ComponentSource
name={name}
@@ -79,3 +82,22 @@ export function ComponentPreview({
/>
)
}
function DynamicComponent({
name,
styleName,
}: {
name: string
styleName: string
}) {
const Component = React.useMemo(
() => getRegistryComponent(name, styleName),
[name, styleName]
)
if (!Component) {
return null
}
return React.createElement(Component)
}

View File

@@ -3,12 +3,12 @@ import path from "node:path"
import * as React from "react"
import { highlightCode } from "@/lib/highlight-code"
import { getRegistryItem } from "@/lib/registry"
import { getDemoItem, getRegistryItem } from "@/lib/registry"
import { formatCode } from "@/lib/rehype"
import { cn } from "@/lib/utils"
import { CodeCollapsibleWrapper } from "@/components/code-collapsible-wrapper"
import { CopyButton } from "@/components/copy-button"
import { getIconForLanguageExtension } from "@/components/icons"
import { type Style } from "@/registry/_legacy-styles"
export async function ComponentSource({
name,
@@ -24,7 +24,7 @@ export async function ComponentSource({
title?: string
language?: string
collapsible?: boolean
styleName?: Style["name"]
styleName?: string
}) {
if (!name && !src) {
return null
@@ -33,7 +33,9 @@ export async function ComponentSource({
let code: string | undefined
if (name) {
const item = await getRegistryItem(name, styleName)
const item =
(await getDemoItem(name, styleName)) ??
(await getRegistryItem(name, styleName))
code = item?.files?.[0]?.content
}
@@ -46,12 +48,7 @@ export async function ComponentSource({
return null
}
// Fix imports.
// Replace @/registry/${style}/ with @/components/.
code = code.replaceAll(`@/registry/${styleName}/`, "@/components/")
// Replace export default with export.
code = code.replaceAll("export default", "export")
code = await formatCode(code, styleName)
code = code.replaceAll("/* eslint-disable react/no-children-prop */\n", "")
const lang = language ?? title?.split(".").pop() ?? "tsx"

View File

@@ -1,20 +1,16 @@
import Link from "next/link"
import { PAGES_NEW } from "@/lib/docs"
import { source } from "@/lib/source"
import { getPagesFromFolder, type PageTreeFolder } from "@/lib/page-tree"
export function ComponentsList() {
const components = source.pageTree.children.find(
(page) => page.$id === "components"
)
if (components?.type !== "folder") {
return
}
const list = components.children.filter(
(component) => component.type === "page"
)
export function ComponentsList({
componentsFolder,
currentBase,
}: {
componentsFolder: PageTreeFolder
currentBase: string
}) {
const list = getPagesFromFolder(componentsFolder, currentBase)
return (
<div className="grid grid-cols-1 gap-4 sm:grid-cols-2 md:grid-cols-3 md:gap-x-8 lg:gap-x-16 lg:gap-y-6 xl:gap-x-20">

View File

@@ -0,0 +1,39 @@
import Link from "next/link"
import { cn } from "@/lib/utils"
import { BASES } from "@/registry/bases"
export function DocsBaseSwitcher({
base,
component,
className,
}: {
base: string
component: string
className?: string
}) {
const activeBase = BASES.find((baseItem) => base === baseItem.name)
return (
<div className={cn("inline-flex w-full items-center gap-6", className)}>
{BASES.map((baseItem) => (
<Link
key={baseItem.name}
href={`/docs/components/${baseItem.name}/${component}`}
data-active={base === baseItem.name}
className="text-muted-foreground hover:text-foreground data-[active=true]:text-foreground after:bg-foreground relative inline-flex items-center justify-center gap-1 pt-1 pb-0.5 text-base font-medium transition-colors after:absolute after:inset-x-0 after:bottom-[-4px] after:h-0.5 after:opacity-0 after:transition-opacity data-[active=true]:after:opacity-100"
>
{baseItem.title}
</Link>
))}
{activeBase?.meta?.logo && (
<div
className="text-muted-foreground ml-auto size-4 shrink-0 opacity-80 [&_svg]:size-4"
dangerouslySetInnerHTML={{
__html: activeBase.meta.logo,
}}
/>
)}
</div>
)
}

View File

@@ -183,7 +183,10 @@ export function DocsCopyPage({ page, url }: { page: string; url: string }) {
<DropdownMenuTrigger asChild className="hidden sm:flex">
{trigger}
</DropdownMenuTrigger>
<DropdownMenuContent align="end" className="shadow-none">
<DropdownMenuContent
align="end"
className="animate-none! rounded-lg shadow-none"
>
{Object.entries(menuItems).map(([key, value]) => (
<DropdownMenuItem key={key} asChild>
{value(url)}
@@ -193,13 +196,13 @@ export function DocsCopyPage({ page, url }: { page: string; url: string }) {
</DropdownMenu>
<Separator
orientation="vertical"
className="!bg-foreground/10 absolute top-0 right-8 z-0 !h-8 peer-focus-visible:opacity-0 sm:right-7 sm:!h-7"
className="!bg-foreground/5 absolute top-1 right-8 z-0 !h-6 peer-focus-visible:opacity-0 sm:right-7 sm:!h-5"
/>
<PopoverTrigger asChild className="flex sm:hidden">
{trigger}
</PopoverTrigger>
<PopoverContent
className="bg-background/70 dark:bg-background/60 w-52 !origin-center rounded-lg p-1 shadow-sm backdrop-blur-sm"
className="bg-background/70 dark:bg-background/60 w-52 !origin-center rounded-lg p-1 shadow-none backdrop-blur-sm"
align="start"
>
{Object.entries(menuItems).map(([key, value]) => (

View File

@@ -0,0 +1,179 @@
"use client"
import { IconCheck, IconCopy } from "@tabler/icons-react"
import { useCopyToClipboard } from "@/hooks/use-copy-to-clipboard"
function getPromptUrl(baseURL: string, url: string) {
return `${baseURL}?q=${encodeURIComponent(
`I'm looking at this shadcn/ui documentation: ${url}.
Help me understand how to use it. Be ready to explain concepts, give examples, or help debug based on it.
`
)}`
}
export function DocsPageLinks({ page, url }: { page: string; url: string }) {
const { copyToClipboard, isCopied } = useCopyToClipboard()
return (
<div className="flex flex-col gap-3 px-6">
<ul className="text-muted-foreground flex flex-col gap-2 text-[0.8rem]">
<li>
<button
onClick={() => copyToClipboard(page)}
className="hover:text-foreground inline-flex items-center gap-2 transition-colors"
>
{isCopied ? (
<IconCheck className="size-4" />
) : (
<IconCopy className="size-4" />
)}
Copy page
</button>
</li>
<li>
<a
href={`${url}.md`}
target="_blank"
rel="noopener noreferrer"
className="hover:text-foreground inline-flex items-center gap-2 transition-colors"
>
<svg strokeLinejoin="round" viewBox="0 0 22 16" className="size-4">
<path
fillRule="evenodd"
clipRule="evenodd"
d="M19.5 2.25H2.5C1.80964 2.25 1.25 2.80964 1.25 3.5V12.5C1.25 13.1904 1.80964 13.75 2.5 13.75H19.5C20.1904 13.75 20.75 13.1904 20.75 12.5V3.5C20.75 2.80964 20.1904 2.25 19.5 2.25ZM2.5 1C1.11929 1 0 2.11929 0 3.5V12.5C0 13.8807 1.11929 15 2.5 15H19.5C20.8807 15 22 13.8807 22 12.5V3.5C22 2.11929 20.8807 1 19.5 1H2.5ZM3 4.5H4H4.25H4.6899L4.98715 4.82428L7 7.02011L9.01285 4.82428L9.3101 4.5H9.75H10H11V5.5V11.5H9V7.79807L7.73715 9.17572L7 9.97989L6.26285 9.17572L5 7.79807V11.5H3V5.5V4.5ZM15 8V4.5H17V8H19.5L17 10.5L16 11.5L15 10.5L12.5 8H15Z"
fill="currentColor"
/>
</svg>
View as Markdown
</a>
</li>
<li>
<a
href={getPromptUrl("https://v0.dev", url)}
target="_blank"
rel="noopener noreferrer"
className="hover:text-foreground inline-flex items-center gap-2 transition-colors"
>
<svg
xmlns="http://www.w3.org/2000/svg"
fill="currentColor"
viewBox="0 0 147 70"
className="size-4"
>
<path d="M56 50.203V14h14v46.156C70 65.593 65.593 70 60.156 70c-2.596 0-5.158-1-7-2.843L0 14h19.797L56 50.203ZM147 56h-14V23.953L100.953 56H133v14H96.687C85.814 70 77 61.186 77 50.312V14h14v32.156L123.156 14H91V0h36.312C138.186 0 147 8.814 147 19.688V56Z" />
</svg>
Open in v0
</a>
</li>
<li>
<a
href={getPromptUrl("https://chatgpt.com", url)}
target="_blank"
rel="noopener noreferrer"
className="hover:text-foreground inline-flex items-center gap-2 transition-colors"
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
className="size-4"
>
<path
d="M22.282 9.821a5.985 5.985 0 0 0-.516-4.91 6.046 6.046 0 0 0-6.51-2.9A6.065 6.065 0 0 0 4.981 4.18a5.985 5.985 0 0 0-3.998 2.9 6.046 6.046 0 0 0 .743 7.097 5.98 5.98 0 0 0 .51 4.911 6.051 6.051 0 0 0 6.515 2.9A5.985 5.985 0 0 0 13.26 24a6.056 6.056 0 0 0 5.772-4.206 5.99 5.99 0 0 0 3.997-2.9 6.056 6.056 0 0 0-.747-7.073zM13.26 22.43a4.476 4.476 0 0 1-2.876-1.04l.141-.081 4.779-2.758a.795.795 0 0 0 .392-.681v-6.737l2.02 1.168a.071.071 0 0 1 .038.052v5.583a4.504 4.504 0 0 1-4.494 4.494zM3.6 18.304a4.47 4.47 0 0 1-.535-3.014l.142.085 4.783 2.759a.771.771 0 0 0 .78 0l5.843-3.369v2.332a.08.08 0 0 1-.033.062L9.74 19.95a4.5 4.5 0 0 1-6.14-1.646zM2.34 7.896a4.485 4.485 0 0 1 2.366-1.973V11.6a.766.766 0 0 0 .388.676l5.815 3.355-2.02 1.168a.076.076 0 0 1-.071 0l-4.83-2.786A4.504 4.504 0 0 1 2.34 7.872zm16.597 3.855-5.833-3.387L15.119 7.2a.076.076 0 0 1 .071 0l4.83 2.791a4.494 4.494 0 0 1-.676 8.105v-5.678a.79.79 0 0 0-.407-.667zm2.01-3.023-.141-.085-4.774-2.782a.776.776 0 0 0-.785 0L9.409 9.23V6.897a.066.066 0 0 1 .028-.061l4.83-2.787a4.5 4.5 0 0 1 6.68 4.66zm-12.64 4.135-2.02-1.164a.08.08 0 0 1-.038-.057V6.075a4.5 4.5 0 0 1 7.375-3.453l-.142.08-4.778 2.758a.795.795 0 0 0-.393.681zm1.097-2.365 2.602-1.5 2.607 1.5v2.999l-2.597 1.5-2.607-1.5Z"
fill="currentColor"
/>
</svg>
Open in ChatGPT
</a>
</li>
<li>
<a
href={getPromptUrl("https://claude.ai/new", url)}
target="_blank"
rel="noopener noreferrer"
className="hover:text-foreground inline-flex items-center gap-2 transition-colors"
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
className="size-4"
>
<path
d="m4.714 15.956 4.718-2.648.079-.23-.08-.128h-.23l-.79-.048-2.695-.073-2.337-.097-2.265-.122-.57-.121-.535-.704.055-.353.48-.321.685.06 1.518.104 2.277.157 1.651.098 2.447.255h.389l.054-.158-.133-.097-.103-.098-2.356-1.596-2.55-1.688-1.336-.972-.722-.491L2 6.223l-.158-1.008.655-.722.88.06.225.061.893.686 1.906 1.476 2.49 1.833.364.304.146-.104.018-.072-.164-.274-1.354-2.446-1.445-2.49-.644-1.032-.17-.619a2.972 2.972 0 0 1-.103-.729L6.287.133 6.7 0l.995.134.42.364.619 1.415L9.735 4.14l1.555 3.03.455.898.243.832.09.255h.159V9.01l.127-1.706.237-2.095.23-2.695.08-.76.376-.91.747-.492.583.28.48.685-.067.444-.286 1.851-.558 2.903-.365 1.942h.213l.243-.242.983-1.306 1.652-2.064.728-.82.85-.904.547-.431h1.032l.759 1.129-.34 1.166-1.063 1.347-.88 1.142-1.263 1.7-.79 1.36.074.11.188-.02 2.853-.606 1.542-.28 1.84-.315.832.388.09.395-.327.807-1.967.486-2.307.462-3.436.813-.043.03.049.061 1.548.146.662.036h1.62l3.018.225.79.522.473.638-.08.485-1.213.62-1.64-.389-3.825-.91-1.31-.329h-.183v.11l1.093 1.068 2.003 1.81 2.508 2.33.127.578-.321.455-.34-.049-2.204-1.657-.85-.747-1.925-1.62h-.127v.17l.443.649 2.343 3.521.122 1.08-.17.353-.607.213-.668-.122-1.372-1.924-1.415-2.168-1.141-1.943-.14.08-.674 7.254-.316.37-.728.28-.607-.461-.322-.747.322-1.476.388-1.924.316-1.53.285-1.9.17-.632-.012-.042-.14.018-1.432 1.967-2.18 2.945-1.724 1.845-.413.164-.716-.37.066-.662.401-.589 2.386-3.036 1.439-1.882.929-1.086-.006-.158h-.055L4.138 18.56l-1.13.146-.485-.456.06-.746.231-.243 1.907-1.312Z"
fill="currentColor"
/>
</svg>
Open in Claude
</a>
</li>
<li>
<a
href={getPromptUrl("https://scira.ai/", url)}
target="_blank"
rel="noopener noreferrer"
className="hover:text-foreground inline-flex items-center gap-2 transition-colors"
>
<svg
width="910"
height="934"
viewBox="0 0 910 934"
fill="none"
xmlns="http://www.w3.org/2000/svg"
className="size-4"
>
<path
d="M647.664 197.775C569.13 189.049 525.5 145.419 516.774 66.8849C508.048 145.419 464.418 189.049 385.884 197.775C464.418 206.501 508.048 250.131 516.774 328.665C525.5 250.131 569.13 206.501 647.664 197.775Z"
fill="currentColor"
stroke="currentColor"
strokeWidth="8"
strokeLinejoin="round"
/>
<path
d="M516.774 304.217C510.299 275.491 498.208 252.087 480.335 234.214C462.462 216.341 439.058 204.251 410.333 197.775C439.059 191.3 462.462 179.209 480.335 161.336C498.208 143.463 510.299 120.06 516.774 91.334C523.25 120.059 535.34 143.463 553.213 161.336C571.086 179.209 594.49 191.3 623.216 197.775C594.49 204.251 571.086 216.341 553.213 234.214C535.34 252.087 523.25 275.491 516.774 304.217Z"
fill="currentColor"
stroke="currentColor"
strokeWidth="8"
strokeLinejoin="round"
/>
<path
d="M857.5 508.116C763.259 497.644 710.903 445.288 700.432 351.047C689.961 445.288 637.605 497.644 543.364 508.116C637.605 518.587 689.961 570.943 700.432 665.184C710.903 570.943 763.259 518.587 857.5 508.116Z"
stroke="currentColor"
strokeWidth="20"
strokeLinejoin="round"
/>
<path
d="M700.432 615.957C691.848 589.05 678.575 566.357 660.383 548.165C642.191 529.973 619.499 516.7 592.593 508.116C619.499 499.533 642.191 486.258 660.383 468.066C678.575 449.874 691.848 427.181 700.432 400.274C709.015 427.181 722.289 449.874 740.481 468.066C758.673 486.258 781.365 499.533 808.271 508.116C781.365 516.7 758.673 529.973 740.481 548.165C722.289 566.357 709.015 589.05 700.432 615.957Z"
stroke="currentColor"
strokeWidth="20"
strokeLinejoin="round"
/>
<path
d="M889.949 121.237C831.049 114.692 798.326 81.9698 791.782 23.0692C785.237 81.9698 752.515 114.692 693.614 121.237C752.515 127.781 785.237 160.504 791.782 219.404C798.326 160.504 831.049 127.781 889.949 121.237Z"
fill="currentColor"
stroke="currentColor"
strokeWidth="8"
strokeLinejoin="round"
/>
<path
d="M791.782 196.795C786.697 176.937 777.869 160.567 765.16 147.858C752.452 135.15 736.082 126.322 716.226 121.237C736.082 116.152 752.452 107.324 765.16 94.6152C777.869 81.9065 786.697 65.5368 791.782 45.6797C796.867 65.5367 805.695 81.9066 818.403 94.6152C831.112 107.324 847.481 116.152 867.338 121.237C847.481 126.322 831.112 135.15 818.403 147.858C805.694 160.567 796.867 176.937 791.782 196.795Z"
fill="currentColor"
stroke="currentColor"
strokeWidth="8"
strokeLinejoin="round"
/>
<path
d="M760.632 764.337C720.719 814.616 669.835 855.1 611.872 882.692C553.91 910.285 490.404 924.255 426.213 923.533C362.022 922.812 298.846 907.419 241.518 878.531C184.19 849.643 134.228 808.026 95.4548 756.863C56.6815 705.7 30.1238 646.346 17.8129 583.343C5.50207 520.339 7.76433 455.354 24.4266 393.359C41.089 331.364 71.7099 274.001 113.947 225.658C156.184 177.315 208.919 139.273 268.117 114.442"
stroke="currentColor"
strokeWidth="30"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>
Open in Scira
</a>
</li>
</ul>
</div>
)
}

View File

@@ -5,6 +5,7 @@ import { usePathname } from "next/navigation"
import { PAGES_NEW } from "@/lib/docs"
import { showMcpDocs } from "@/lib/flags"
import { getCurrentBase, getPagesFromFolder } from "@/lib/page-tree"
import type { source } from "@/lib/source"
import {
Sidebar,
@@ -18,11 +19,15 @@ import {
} from "@/registry/new-york-v4/ui/sidebar"
const TOP_LEVEL_SECTIONS = [
{ name: "Get Started", href: "/docs" },
{ name: "Introduction", href: "/docs" },
{
name: "Components",
href: "/docs/components",
},
{
name: "Installation",
href: "/docs/installation",
},
{
name: "Directory",
href: "/docs/directory",
@@ -31,6 +36,10 @@ const TOP_LEVEL_SECTIONS = [
name: "MCP Server",
href: "/docs/mcp",
},
{
name: "Registry",
href: "/docs/registry",
},
{
name: "Forms",
href: "/docs/forms",
@@ -48,10 +57,11 @@ export function DocsSidebar({
...props
}: React.ComponentProps<typeof Sidebar> & { tree: typeof source.pageTree }) {
const pathname = usePathname()
const currentBase = getCurrentBase(pathname)
return (
<Sidebar
className="sticky top-[calc(var(--header-height)+1px)] z-30 hidden h-[calc(100svh-var(--footer-height)-4rem)] overscroll-none bg-transparent lg:flex"
className="sticky top-[calc(var(--header-height)+1px)] z-30 hidden h-[calc(100svh-6rem)] overscroll-none bg-transparent lg:flex"
collapsible="none"
{...props}
>
@@ -102,37 +112,34 @@ export function DocsSidebar({
<SidebarGroupContent>
{item.type === "folder" && (
<SidebarMenu className="gap-0.5">
{item.children.map((item) => {
if (
!showMcpDocs &&
item.type === "page" &&
item.url?.includes("/mcp")
) {
{getPagesFromFolder(item, currentBase).map((page) => {
if (!showMcpDocs && page.url.includes("/mcp")) {
return null
}
if (EXCLUDED_PAGES.includes(page.url)) {
return null
}
return (
item.type === "page" &&
!EXCLUDED_PAGES.includes(item.url) && (
<SidebarMenuItem key={item.url}>
<SidebarMenuButton
asChild
isActive={item.url === pathname}
className="data-[active=true]:bg-accent data-[active=true]:border-accent 3xl:fixed:w-full 3xl:fixed:max-w-48 relative h-[30px] w-fit overflow-visible border border-transparent text-[0.8rem] font-medium after:absolute after:inset-x-0 after:-inset-y-1 after:z-0 after:rounded-md"
>
<Link href={item.url}>
<span className="absolute inset-0 flex w-(--sidebar-width) bg-transparent" />
{item.name}
{PAGES_NEW.includes(item.url) && (
<span
className="flex size-2 rounded-full bg-blue-500"
title="New"
/>
)}
</Link>
</SidebarMenuButton>
</SidebarMenuItem>
)
<SidebarMenuItem key={page.url}>
<SidebarMenuButton
asChild
isActive={page.url === pathname}
className="data-[active=true]:bg-accent data-[active=true]:border-accent 3xl:fixed:w-full 3xl:fixed:max-w-48 relative h-[30px] w-fit overflow-visible border border-transparent text-[0.8rem] font-medium after:absolute after:inset-x-0 after:-inset-y-1 after:z-0 after:rounded-md"
>
<Link href={page.url}>
<span className="absolute inset-0 flex w-(--sidebar-width) bg-transparent" />
{page.name}
{PAGES_NEW.includes(page.url) && (
<span
className="flex size-2 rounded-full bg-blue-500"
title="New"
/>
)}
</Link>
</SidebarMenuButton>
</SidebarMenuItem>
)
})}
</SidebarMenu>

View File

@@ -107,7 +107,7 @@ export function DocsTableOfContents({
return (
<div className={cn("flex flex-col gap-2 p-4 pt-0 text-sm", className)}>
<p className="text-muted-foreground bg-background sticky top-0 h-6 text-xs">
<p className="text-muted-foreground bg-background sticky top-0 h-6 text-xs font-medium">
On This Page
</p>
{toc.map((item) => (

View File

@@ -2,10 +2,11 @@
import * as React from "react"
import Link, { type LinkProps } from "next/link"
import { useRouter } from "next/navigation"
import { usePathname, useRouter } from "next/navigation"
import { PAGES_NEW } from "@/lib/docs"
import { showMcpDocs } from "@/lib/flags"
import { getCurrentBase, getPagesFromFolder } from "@/lib/page-tree"
import { type source } from "@/lib/source"
import { cn } from "@/lib/utils"
import { Button } from "@/registry/new-york-v4/ui/button"
@@ -16,11 +17,15 @@ import {
} from "@/registry/new-york-v4/ui/popover"
const TOP_LEVEL_SECTIONS = [
{ name: "Get Started", href: "/docs" },
{ name: "Introduction", href: "/docs" },
{
name: "Components",
href: "/docs/components",
},
{
name: "Installation",
href: "/docs/installation",
},
{
name: "Directory",
href: "/docs/directory",
@@ -29,6 +34,10 @@ const TOP_LEVEL_SECTIONS = [
name: "MCP Server",
href: "/docs/mcp",
},
{
name: "Registry",
href: "/docs/registry",
},
{
name: "Forms",
href: "/docs/forms",
@@ -49,6 +58,8 @@ export function MobileNav({
className?: string
}) {
const [open, setOpen] = React.useState(false)
const pathname = usePathname()
const currentBase = getCurrentBase(pathname)
return (
<Popover open={open} onOpenChange={setOpen}>
@@ -125,31 +136,30 @@ export function MobileNav({
<div className="flex flex-col gap-8">
{tree?.children?.map((group, index) => {
if (group.type === "folder") {
const pages = getPagesFromFolder(group, currentBase)
return (
<div key={index} className="flex flex-col gap-4">
<div className="text-muted-foreground text-sm font-medium">
{group.name}
</div>
<div className="flex flex-col gap-3">
{group.children.map((item) => {
if (item.type === "page") {
if (!showMcpDocs && item.url.includes("/mcp")) {
return null
}
return (
<MobileLink
key={`${item.url}-${index}`}
href={item.url}
onOpenChange={setOpen}
className="flex items-center gap-2"
>
{item.name}{" "}
{PAGES_NEW.includes(item.url) && (
<span className="flex size-2 rounded-full bg-blue-500" />
)}
</MobileLink>
)
{pages.map((item) => {
if (!showMcpDocs && item.url.includes("/mcp")) {
return null
}
return (
<MobileLink
key={`${item.url}-${index}`}
href={item.url}
onOpenChange={setOpen}
className="flex items-center gap-2"
>
{item.name}{" "}
{PAGES_NEW.includes(item.url) && (
<span className="flex size-2 rounded-full bg-blue-500" />
)}
</MobileLink>
)
})}
</div>
</div>

View File

@@ -2,7 +2,7 @@ import { siteConfig } from "@/lib/config"
export function SiteFooter() {
return (
<footer className="group-has-[.section-soft]/body:bg-surface/40 3xl:fixed:bg-transparent group-has-[.docs-nav]/body:pb-20 group-has-[[data-slot=designer]]/body:hidden group-has-[.docs-nav]/body:sm:pb-0 dark:bg-transparent">
<footer className="group-has-[.section-soft]/body:bg-surface/40 3xl:fixed:bg-transparent group-has-[.docs-nav]/body:pb-20 group-has-[[data-slot=designer]]/body:hidden group-has-[[data-slot=docs]]/body:hidden group-has-[.docs-nav]/body:sm:pb-0 dark:bg-transparent dark:group-has-[.section-soft]/body:bg-surface/40">
<div className="container-wrapper px-4 xl:px-6">
<div className="flex h-(--footer-height) items-center justify-between">
<div className="text-muted-foreground w-full px-1 text-center text-xs leading-loose sm:text-sm">

View File

@@ -1,4 +1,4 @@
const SHOW = false
const SHOW = true
export function TailwindIndicator({
forceMount = false,

View File

@@ -4,6 +4,50 @@ description: Latest updates and announcements.
toc: false
---
## January 2026 - Base UI Documentation
We've shipped full documentation for Base UI components.
<div className="bg-muted/50 mt-6 flex w-full items-center justify-center rounded-lg border py-32">
<svg width="17" height="24" viewBox="0 0 17 24" className="size-12">
<path
fill="currentColor"
d="M9.5001 7.01537C9.2245 6.99837 9 7.22385 9 7.49999V23C13.4183 23 17 19.4183 17 15C17 10.7497 13.6854 7.27351 9.5001 7.01537Z"
/>
<path
fill="currentColor"
d="M8 9.8V12V23C3.58172 23 0 19.0601 0 14.2V12V1C4.41828 1 8 4.93989 8 9.8Z"
/>
</svg>
</div>
When we launched `npx shadcn create` in December, we introduced the ability to choose between Radix and Base UI as your component library. Today, we're following up with complete documentation for all Base UI components.
### What's New
- **Full Base UI docs** - Every component now has dedicated documentation for Base UI, covering usage, props, and examples.
- **Rebuilt examples** - All component examples have been rebuilt for both Radix and Base UI. Switch between them to see the implementation differences.
- **Side-by-side comparison** - The docs make it easy to compare how components work across both libraries.
### Same Abstraction, Different Primitives
The goal remains the same: give you a consistent API regardless of which primitive library you choose. The components look and behave the same way. Only the underlying implementation changes.
```tsx
// Works the same whether you're using Radix or Base UI.
import { Dialog, DialogContent, DialogTrigger } from "@/components/ui/dialog"
```
If you're starting a new project, run `npx shadcn create` and pick your preferred library. The CLI handles the rest.
<Button asChild size="sm">
<Link href="/create" className="mt-6 no-underline!">
Try shadcn/create
</Link>
</Button>
---
## December 2025 - npx shadcn create
From the very first commit, the goal of shadcn/ui was to make it customizable.

View File

@@ -9,12 +9,10 @@ These registries are built into the CLI with no additional configuration require
<Callout
type="warning"
icon={<TriangleAlertIcon />}
className="gap-2! border-amber-200 bg-amber-50 p-2 font-semibold dark:border-amber-900 dark:bg-amber-950/80 *:[svg]:translate-y-1"
className="border-amber-200 bg-amber-50 font-semibold dark:border-amber-900 dark:bg-amber-950"
>
Community registries are maintained by third-party developers and are not
officially curated. Always review code on installation to ensure it meets your
security and quality standards.
Community registries are maintained by third-party developers. Always review
code on installation to ensure it meets your security and quality standards.
</Callout>
Don't see a registry? Learn how to [add it here](/docs/registry/registry-index).

View File

@@ -1,76 +0,0 @@
---
title: Accordion
description: A vertically stacked set of interactive headings that each reveal a section of content.
component: true
links:
doc: https://www.radix-ui.com/docs/primitives/components/accordion
api: https://www.radix-ui.com/docs/primitives/components/accordion#api-reference
---
<ComponentPreview
name="accordion-demo"
className="[&_.preview>[data-orientation=vertical]]:sm:max-w-[80%] **:[.preview]:min-h-[400px]"
description="An accordion with three items"
align="start"
/>
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">CLI</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add accordion
```
</TabsContent>
<TabsContent value="manual">
<Steps>
<Step>Install the following dependencies:</Step>
```bash
npm install @radix-ui/react-accordion
```
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource name="accordion" title="components/ui/accordion.tsx" />
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx showLineNumbers
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from "@/components/ui/accordion"
```
```tsx showLineNumbers
<Accordion type="single" collapsible>
<AccordionItem value="item-1">
<AccordionTrigger>Is it accessible?</AccordionTrigger>
<AccordionContent>
Yes. It adheres to the WAI-ARIA design pattern.
</AccordionContent>
</AccordionItem>
</Accordion>
```

View File

@@ -1,88 +0,0 @@
---
title: Alert Dialog
description: A modal dialog that interrupts the user with important content and expects a response.
featured: true
component: true
links:
doc: https://www.radix-ui.com/docs/primitives/components/alert-dialog
api: https://www.radix-ui.com/docs/primitives/components/alert-dialog#api-reference
---
<ComponentPreview
name="alert-dialog-demo"
title="An alert dialog with cancel and continue buttons."
description="An alert dialog with cancel and continue buttons."
/>
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">CLI</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add alert-dialog
```
</TabsContent>
<TabsContent value="manual">
<Steps>
<Step>Install the following dependencies:</Step>
```bash
npm install @radix-ui/react-alert-dialog
```
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource name="alert-dialog" title="components/ui/alert-dialog.tsx" />
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx showLineNumbers
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
AlertDialogTrigger,
} from "@/components/ui/alert-dialog"
```
```tsx showLineNumbers
<AlertDialog>
<AlertDialogTrigger>Open</AlertDialogTrigger>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>Are you absolutely sure?</AlertDialogTitle>
<AlertDialogDescription>
This action cannot be undone. This will permanently delete your account
and remove your data from our servers.
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>Cancel</AlertDialogCancel>
<AlertDialogAction>Continue</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
```

View File

@@ -1,59 +0,0 @@
---
title: Alert
description: Displays a callout for user attention.
component: true
---
<ComponentPreview
name="alert-demo"
title="An alert with an icon, title and description."
description="An alert with an icon, title and description. The title says 'Heads up!' and the description is 'You can add components to your app using the cli.'."
/>
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">CLI</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add alert
```
</TabsContent>
<TabsContent value="manual">
<Steps>
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource name="alert" title="components/ui/alert.tsx" />
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx showLineNumbers
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert"
```
```tsx showLineNumbers
<Alert variant="default | destructive">
<Terminal />
<AlertTitle>Heads up!</AlertTitle>
<AlertDescription>
You can add components and dependencies to your app using the cli.
</AlertDescription>
</Alert>
```

View File

@@ -1,64 +0,0 @@
---
title: Aspect Ratio
description: Displays content within a desired ratio.
component: true
links:
doc: https://www.radix-ui.com/docs/primitives/components/aspect-ratio
api: https://www.radix-ui.com/docs/primitives/components/aspect-ratio#api-reference
---
<ComponentPreview
name="aspect-ratio-demo"
title="Aspect Ratio"
description="A component that displays an image with a 16:9 aspect ratio."
/>
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">CLI</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add aspect-ratio
```
</TabsContent>
<TabsContent value="manual">
<Steps>
<Step>Install the following dependencies:</Step>
```bash
npm install @radix-ui/react-aspect-ratio
```
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource name="aspect-ratio" title="components/ui/aspect-ratio.tsx" />
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx showLineNumbers
import { AspectRatio } from "@/components/ui/aspect-ratio"
```
```tsx showLineNumbers
<AspectRatio ratio={16 / 9}>
<Image src="..." alt="Image" className="rounded-md object-cover" />
</AspectRatio>
```

View File

@@ -1,65 +0,0 @@
---
title: Avatar
description: An image element with a fallback for representing the user.
component: true
links:
doc: https://www.radix-ui.com/docs/primitives/components/avatar
api: https://www.radix-ui.com/docs/primitives/components/avatar#api-reference
---
<ComponentPreview
name="avatar-demo"
title="Avatar"
description="An avatar with a fallback."
/>
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">CLI</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add avatar
```
</TabsContent>
<TabsContent value="manual">
<Steps>
<Step>Install the following dependencies:</Step>
```bash
npm install @radix-ui/react-avatar
```
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource name="avatar" title="components/ui/avatar.tsx" />
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx showLineNumbers
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"
```
```tsx showLineNumbers
<Avatar>
<AvatarImage src="https://github.com/shadcn.png" />
<AvatarFallback>CN</AvatarFallback>
</Avatar>
```

View File

@@ -1,71 +0,0 @@
---
title: Badge
description: Displays a badge or a component that looks like a badge.
component: true
---
<ComponentPreview
name="badge-demo"
title="Badge"
description="A default badge"
/>
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">CLI</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add badge
```
</TabsContent>
<TabsContent value="manual">
<Steps>
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource name="badge" title="components/ui/badge.tsx" />
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx
import { Badge } from "@/components/ui/badge"
```
```tsx
<Badge variant="default | outline | secondary | destructive">Badge</Badge>
```
### Link
You can use the `asChild` prop to make another component look like a badge. Here's an example of a link that looks like a badge.
```tsx showLineNumbers
import Link from "next/link"
import { Badge } from "@/components/ui/badge"
export function LinkAsBadge() {
return (
<Badge asChild>
<Link href="/">Badge</Link>
</Badge>
)
}
```

View File

@@ -0,0 +1,142 @@
---
title: Accordion
description: A vertically stacked set of interactive headings that each reveal a section of content.
base: base
component: true
links:
doc: https://base-ui.com/react/components/accordion
api: https://base-ui.com/react/components/accordion#api-reference
---
<ComponentPreview
styleName="base-nova"
name="accordion-demo"
align="start"
previewClassName="*:data-[slot=accordion]:max-w-sm h-[300px]"
/>
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">Command</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add accordion
```
</TabsContent>
<TabsContent value="manual">
<Steps className="mb-0 pt-2">
<Step>Install the following dependencies:</Step>
```bash
npm install @base-ui/react
```
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="accordion"
title="components/ui/accordion.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx showLineNumbers
import {
Accordion,
AccordionContent,
AccordionItem,
AccordionTrigger,
} from "@/components/ui/accordion"
```
```tsx showLineNumbers
<Accordion defaultValue={["item-1"]}>
<AccordionItem value="item-1">
<AccordionTrigger>Is it accessible?</AccordionTrigger>
<AccordionContent>
Yes. It adheres to the WAI-ARIA design pattern.
</AccordionContent>
</AccordionItem>
</Accordion>
```
## Examples
### Basic
A basic accordion that shows one item at a time. The first item is open by default.
<ComponentPreview
styleName="base-nova"
name="accordion-basic"
align="start"
previewClassName="*:data-[slot=accordion]:max-w-sm h-[300px]"
/>
### Multiple
Use the `multiple` prop to allow multiple items to be open at the same time.
<ComponentPreview
styleName="base-nova"
name="accordion-multiple"
align="start"
previewClassName="*:data-[slot=accordion]:max-w-sm h-[450px]"
/>
### Disabled
Use the `disabled` prop on `AccordionItem` to disable individual items.
<ComponentPreview
styleName="base-nova"
name="accordion-disabled"
align="start"
previewClassName="*:data-[slot=accordion]:max-w-sm h-[300px]"
/>
### Borders
Add `border` to the `Accordion` and `border-b last:border-b-0` to the `AccordionItem` to add borders to the items.
<ComponentPreview
styleName="base-nova"
name="accordion-borders"
align="start"
previewClassName="*:data-[slot=accordion]:max-w-sm h-[300px]"
/>
### Card
Wrap the `Accordion` in a `Card` component.
<ComponentPreview
styleName="base-nova"
name="accordion-card"
align="start"
previewClassName="*:data-[slot=accordion]:max-w-sm h-[435px]"
/>
## API Reference
See the [Base UI](https://base-ui.com/react/components/accordion#api-reference) documentation for more information.

View File

@@ -0,0 +1,159 @@
---
title: Alert Dialog
description: A modal dialog that interrupts the user with important content and expects a response.
featured: true
base: base
component: true
links:
doc: https://base-ui.com/react/components/alert-dialog
api: https://base-ui.com/react/components/alert-dialog#api-reference
---
<ComponentPreview
styleName="base-nova"
name="alert-dialog-demo"
previewClassName="h-56"
/>
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">Command</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add alert-dialog
```
</TabsContent>
<TabsContent value="manual">
<Steps className="mb-0 pt-2">
<Step>Install the following dependencies:</Step>
```bash
npm install @base-ui/react
```
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="alert-dialog"
title="components/ui/alert-dialog.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx showLineNumbers
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
AlertDialogDescription,
AlertDialogFooter,
AlertDialogHeader,
AlertDialogTitle,
AlertDialogTrigger,
} from "@/components/ui/alert-dialog"
```
```tsx showLineNumbers
<AlertDialog>
<AlertDialogTrigger render={<Button variant="outline" />}>
Show Dialog
</AlertDialogTrigger>
<AlertDialogContent>
<AlertDialogHeader>
<AlertDialogTitle>Are you absolutely sure?</AlertDialogTitle>
<AlertDialogDescription>
This action cannot be undone. This will permanently delete your account
from our servers.
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel>Cancel</AlertDialogCancel>
<AlertDialogAction>Continue</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
```
## Examples
### Basic
A basic alert dialog with a title, description, and cancel and continue buttons.
<ComponentPreview
styleName="base-nova"
name="alert-dialog-basic"
previewClassName="h-56"
/>
### Small
Use the `size="sm"` prop to make the alert dialog smaller.
<ComponentPreview
styleName="base-nova"
name="alert-dialog-small"
previewClassName="h-56"
/>
### Media
Use the `AlertDialogMedia` component to add a media element such as an icon or image to the alert dialog.
<ComponentPreview
styleName="base-nova"
name="alert-dialog-media"
previewClassName="h-56"
/>
### Small with Media
Use the `size="sm"` prop to make the alert dialog smaller and the `AlertDialogMedia` component to add a media element such as an icon or image to the alert dialog.
<ComponentPreview
styleName="base-nova"
name="alert-dialog-small-media"
previewClassName="h-56"
/>
### Destructive
Use the `AlertDialogAction` component to add a destructive action button to the alert dialog.
<ComponentPreview
styleName="base-nova"
name="alert-dialog-destructive"
previewClassName="h-56"
/>
## API Reference
### size
Use the `size` props on the `AlertDialogContent` component to control the size of the alert dialog. It accepts the following values:
| Prop | Type | Default |
| ------ | ------------------- | ----------- |
| `size` | `"default" \| "sm"` | `"default"` |
For more information about the other components and their props, see the [Base UI documentation](https://base-ui.com/react/components/alert-dialog#api-reference).

View File

@@ -0,0 +1,144 @@
---
title: Alert
description: Displays a callout for user attention.
base: base
component: true
---
<ComponentPreview
styleName="base-nova"
name="alert-demo"
previewClassName="h-auto sm:h-72 p-6"
/>
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">Command</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add alert
```
</TabsContent>
<TabsContent value="manual">
<Steps className="mb-0 pt-2">
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource name="alert" title="components/ui/alert.tsx" />
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx showLineNumbers
import {
Alert,
AlertAction,
AlertDescription,
AlertTitle,
} from "@/components/ui/alert"
```
```tsx showLineNumbers
<Alert>
<InfoIcon />
<AlertTitle>Heads up!</AlertTitle>
<AlertDescription>
You can add components and dependencies to your app using the cli.
</AlertDescription>
<AlertAction>
<Button variant="outline">Enable</Button>
</AlertAction>
</Alert>
```
## Examples
### Basic
A basic alert with an icon, title and description.
<ComponentPreview
styleName="base-nova"
name="alert-basic"
previewClassName="h-auto sm:h-72 p-6"
/>
### Destructive
Use `variant="destructive"` to create a destructive alert.
<ComponentPreview
styleName="base-nova"
name="alert-destructive"
previewClassName="h-auto sm:h-72 p-6"
/>
### Action
Use `AlertAction` to add a button or other action element to the alert.
<ComponentPreview
styleName="base-nova"
name="alert-action"
previewClassName="h-auto sm:h-72 p-6"
/>
### Custom Colors
You can customize the alert colors by adding custom classes such as `bg-amber-50 dark:bg-amber-950` to the `Alert` component.
<ComponentPreview
styleName="base-nova"
name="alert-colors"
previewClassName="h-auto sm:h-72 p-6"
/>
## API Reference
### Alert
The `Alert` component displays a callout for user attention.
| Prop | Type | Default |
| --------- | ---------------------------- | ----------- |
| `variant` | `"default" \| "destructive"` | `"default"` |
### AlertTitle
The `AlertTitle` component displays the title of the alert.
| Prop | Type | Default |
| ----------- | -------- | ------- |
| `className` | `string` | - |
### AlertDescription
The `AlertDescription` component displays the description or content of the alert.
| Prop | Type | Default |
| ----------- | -------- | ------- |
| `className` | `string` | - |
### AlertAction
The `AlertAction` component displays an action element (like a button) positioned absolutely in the top-right corner of the alert.
| Prop | Type | Default |
| ----------- | -------- | ------- |
| `className` | `string` | - |

View File

@@ -0,0 +1,93 @@
---
title: Aspect Ratio
description: Displays content within a desired ratio.
base: base
component: true
---
<ComponentPreview name="aspect-ratio-demo" styleName="base-nova" />
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">Command</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add aspect-ratio
```
</TabsContent>
<TabsContent value="manual">
<Steps className="mb-0 pt-2">
<Step>Install the following dependencies:</Step>
```bash
npm install @base-ui/react
```
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="aspect-ratio"
title="components/ui/aspect-ratio.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx showLineNumbers
import { AspectRatio } from "@/components/ui/aspect-ratio"
```
```tsx showLineNumbers
<AspectRatio ratio={16 / 9}>
<Image src="..." alt="Image" className="rounded-md object-cover" />
</AspectRatio>
```
## Examples
### Square
A square aspect ratio component using the `ratio={1 / 1}` prop. This is useful for displaying images in a square format.
<ComponentPreview name="aspect-ratio-square" styleName="base-nova" />
### Portrait
A portrait aspect ratio component using the `ratio={9 / 16}` prop. This is useful for displaying images in a portrait format.
<ComponentPreview
styleName="base-nova"
name="aspect-ratio-portrait"
previewClassName="h-96"
/>
## API Reference
### AspectRatio
The `AspectRatio` component displays content within a desired ratio.
| Prop | Type | Default | Required |
| ----------- | -------- | ------- | -------- |
| `ratio` | `number` | - | Yes |
| `className` | `string` | - | No |
For more information, see the [Base UI documentation](https://base-ui.com/react/components/aspect-ratio#api-reference).

View File

@@ -0,0 +1,185 @@
---
title: Avatar
description: An image element with a fallback for representing the user.
base: base
component: true
links:
doc: https://base-ui.com/react/components/avatar
api: https://base-ui.com/react/components/avatar#api-reference
---
<ComponentPreview
styleName="base-nova"
name="avatar-demo"
previewClassName="h-72"
/>
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">Command</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add avatar
```
</TabsContent>
<TabsContent value="manual">
<Steps className="mb-0 pt-2">
<Step>Install the following dependencies:</Step>
```bash
npm install @base-ui/react
```
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="avatar"
title="components/ui/avatar.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx showLineNumbers
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"
```
```tsx showLineNumbers
<Avatar>
<AvatarImage src="https://github.com/shadcn.png" />
<AvatarFallback>CN</AvatarFallback>
</Avatar>
```
## Examples
### Basic
A basic avatar component with an image and a fallback.
<ComponentPreview styleName="base-nova" name="avatar-basic" />
### Badge
Use the `AvatarBadge` component to add a badge to the avatar. The badge is positioned at the bottom right of the avatar.
<ComponentPreview styleName="base-nova" name="avatar-badge" />
Use the `className` prop to add custom styles to the badge such as custom colors, sizes, etc.
```tsx showLineNumbers
<Avatar>
<AvatarImage src="https://github.com/shadcn.png" alt="@shadcn" />
<AvatarFallback>CN</AvatarFallback>
<AvatarBadge className="bg-green-600 dark:bg-green-800" />
</Avatar>
```
### Badge with Icon
You can also use an icon inside `<AvatarBadge>`.
<ComponentPreview styleName="base-nova" name="avatar-badge-icon" />
### Avatar Group
Use the `AvatarGroup` component to add a group of avatars.
<ComponentPreview styleName="base-nova" name="avatar-group" />
### Avatar Group Count
Use `<AvatarGroupCount>` to add a count to the group.
<ComponentPreview styleName="base-nova" name="avatar-group-count" />
### Avatar Group with Icon
You can also use an icon inside `<AvatarGroupCount>`.
<ComponentPreview styleName="base-nova" name="avatar-group-count-icon" />
### Sizes
Use the `size` prop to change the size of the avatar.
<ComponentPreview styleName="base-nova" name="avatar-size" />
### Dropdown
You can use the `Avatar` component as a trigger for a dropdown menu.
<ComponentPreview styleName="base-nova" name="avatar-dropdown" />
## API Reference
### Avatar
The `Avatar` component is the root component that wraps the avatar image and fallback.
| Prop | Type | Default |
| ----------- | --------------------------- | ----------- |
| `size` | `"default" \| "sm" \| "lg"` | `"default"` |
| `className` | `string` | - |
### AvatarImage
The `AvatarImage` component displays the avatar image. It accepts all Base UI Avatar Image props.
| Prop | Type | Default |
| ----------- | -------- | ------- |
| `src` | `string` | - |
| `alt` | `string` | - |
| `className` | `string` | - |
### AvatarFallback
The `AvatarFallback` component displays a fallback when the image fails to load. It accepts all Base UI Avatar Fallback props.
| Prop | Type | Default |
| ----------- | -------- | ------- |
| `className` | `string` | - |
### AvatarBadge
The `AvatarBadge` component displays a badge indicator on the avatar, typically positioned at the bottom right.
| Prop | Type | Default |
| ----------- | -------- | ------- |
| `className` | `string` | - |
### AvatarGroup
The `AvatarGroup` component displays a group of avatars with overlapping styling.
| Prop | Type | Default |
| ----------- | -------- | ------- |
| `className` | `string` | - |
### AvatarGroupCount
The `AvatarGroupCount` component displays a count indicator in an avatar group, typically showing the number of additional avatars.
| Prop | Type | Default |
| ----------- | -------- | ------- |
| `className` | `string` | - |
For more information about Base UI Avatar props, see the [Base UI documentation](https://base-ui.com/react/components/avatar#api-reference).

View File

@@ -0,0 +1,97 @@
---
title: Badge
description: Displays a badge or a component that looks like a badge.
base: base
component: true
---
<ComponentPreview styleName="base-nova" name="badge-demo" />
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">Command</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add badge
```
</TabsContent>
<TabsContent value="manual">
<Steps className="mb-0 pt-2">
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="badge"
title="components/ui/badge.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx
import { Badge } from "@/components/ui/badge"
```
```tsx
<Badge variant="default | outline | secondary | destructive">Badge</Badge>
```
## Examples
### Variants
Use the `variant` prop to change the variant of the badge.
<ComponentPreview styleName="base-nova" name="badge-variants" />
### With Icon
You can render an icon inside the badge. Use `data-icon="inline-start"` to render the icon on the left and `data-icon="inline-end"` to render the icon on the right.
<ComponentPreview styleName="base-nova" name="badge-icon" />
### With Spinner
You can render a spinner inside the badge. Remember to add the `data-icon="inline-start"` or `data-icon="inline-end"` prop to the spinner.
<ComponentPreview styleName="base-nova" name="badge-spinner" />
### Link
Use the `render` prop to render a link as a badge.
<ComponentPreview styleName="base-nova" name="badge-link" />
### Custom Colors
You can customize the colors of a badge by adding custom classes such as `bg-green-50 dark:bg-green-800` to the `Badge` component.
<ComponentPreview styleName="base-nova" name="badge-colors" />
## API Reference
### Badge
The `Badge` component displays a badge or a component that looks like a badge.
| Prop | Type | Default |
| ----------- | ----------------------------------------------------------------------------- | ----------- |
| `variant` | `"default" \| "secondary" \| "destructive" \| "outline" \| "ghost" \| "link"` | `"default"` |
| `className` | `string` | - |

View File

@@ -0,0 +1,176 @@
---
title: Breadcrumb
description: Displays the path to the current resource using a hierarchy of links.
base: base
component: true
---
<ComponentPreview
styleName="base-nova"
name="breadcrumb-demo"
previewClassName="p-2"
/>
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">Command</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add breadcrumb
```
</TabsContent>
<TabsContent value="manual">
<Steps className="mb-0 pt-2">
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="breadcrumb"
title="components/ui/breadcrumb.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx showLineNumbers
import {
Breadcrumb,
BreadcrumbItem,
BreadcrumbLink,
BreadcrumbList,
BreadcrumbPage,
BreadcrumbSeparator,
} from "@/components/ui/breadcrumb"
```
```tsx showLineNumbers
<Breadcrumb>
<BreadcrumbList>
<BreadcrumbItem>
<BreadcrumbLink render={<a href="/" />}>Home</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbLink render={<a href="/components" />}>
Components
</BreadcrumbLink>
</BreadcrumbItem>
<BreadcrumbSeparator />
<BreadcrumbItem>
<BreadcrumbPage>Breadcrumb</BreadcrumbPage>
</BreadcrumbItem>
</BreadcrumbList>
</Breadcrumb>
```
## Examples
### Basic
A basic breadcrumb with a home link and a components link.
<ComponentPreview styleName="base-nova" name="breadcrumb-basic" />
### Custom separator
Use a custom component as `children` for `<BreadcrumbSeparator />` to create a custom separator.
<ComponentPreview styleName="base-nova" name="breadcrumb-separator" />
### Dropdown
You can compose `<BreadcrumbItem />` with a `<DropdownMenu />` to create a dropdown in the breadcrumb.
<ComponentPreview styleName="base-nova" name="breadcrumb-dropdown" />
### Collapsed
We provide a `<BreadcrumbEllipsis />` component to show a collapsed state when the breadcrumb is too long.
<ComponentPreview
styleName="base-nova"
name="breadcrumb-ellipsis"
previewClassName="p-2"
/>
### Link component
To use a custom link component from your routing library, you can use the `render` prop on `<BreadcrumbLink />`.
<ComponentPreview styleName="base-nova" name="breadcrumb-link" />
## API Reference
### Breadcrumb
The `Breadcrumb` component is the root navigation element that wraps all breadcrumb components.
| Prop | Type | Default |
| ----------- | -------- | ------- |
| `className` | `string` | - |
### BreadcrumbList
The `BreadcrumbList` component displays the ordered list of breadcrumb items.
| Prop | Type | Default |
| ----------- | -------- | ------- |
| `className` | `string` | - |
### BreadcrumbItem
The `BreadcrumbItem` component wraps individual breadcrumb items.
| Prop | Type | Default |
| ----------- | -------- | ------- |
| `className` | `string` | - |
### BreadcrumbLink
The `BreadcrumbLink` component displays a clickable link in the breadcrumb.
| Prop | Type | Default |
| ----------- | -------- | ------- |
| `className` | `string` | - |
### BreadcrumbPage
The `BreadcrumbPage` component displays the current page in the breadcrumb (non-clickable).
| Prop | Type | Default |
| ----------- | -------- | ------- |
| `className` | `string` | - |
### BreadcrumbSeparator
The `BreadcrumbSeparator` component displays a separator between breadcrumb items. You can pass custom children to override the default separator icon.
| Prop | Type | Default |
| ----------- | ----------------- | ------- |
| `children` | `React.ReactNode` | - |
| `className` | `string` | - |
### BreadcrumbEllipsis
The `BreadcrumbEllipsis` component displays an ellipsis indicator for collapsed breadcrumb items.
| Prop | Type | Default |
| ----------- | -------- | ------- |
| `className` | `string` | - |

View File

@@ -1,17 +1,18 @@
---
title: Button Group
description: A container that groups related buttons together with consistent styling.
base: base
component: true
---
<ComponentPreview name="button-group-demo" />
<ComponentPreview styleName="base-nova" name="button-group-demo" />
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">CLI</TabsTrigger>
<TabsTrigger value="cli">Command</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
@@ -24,17 +25,21 @@ npx shadcn@latest add button-group
<TabsContent value="manual">
<Steps>
<Steps className="mb-0 pt-2">
<Step>Install the following dependencies:</Step>
```bash
npm install @radix-ui/react-slot
npm install @base-ui/react
```
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource name="button-group" title="components/ui/button-group.tsx" />
<ComponentSource
name="button-group"
title="components/ui/button-group.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
@@ -85,19 +90,19 @@ import {
Set the `orientation` prop to change the button group layout.
<ComponentPreview name="button-group-orientation" />
<ComponentPreview styleName="base-nova" name="button-group-orientation" />
### Size
Control the size of buttons using the `size` prop on individual buttons.
<ComponentPreview name="button-group-size" />
<ComponentPreview styleName="base-nova" name="button-group-size" />
### Nested
Nest `<ButtonGroup>` components to create button groups with spacing.
<ComponentPreview name="button-group-nested" />
<ComponentPreview styleName="base-nova" name="button-group-nested" />
### Separator
@@ -105,43 +110,43 @@ The `ButtonGroupSeparator` component visually divides buttons within a group.
Buttons with variant `outline` do not need a separator since they have a border. For other variants, a separator is recommended to improve the visual hierarchy.
<ComponentPreview name="button-group-separator" />
<ComponentPreview styleName="base-nova" name="button-group-separator" />
### Split
Create a split button group by adding two buttons separated by a `ButtonGroupSeparator`.
<ComponentPreview name="button-group-split" />
<ComponentPreview styleName="base-nova" name="button-group-split" />
### Input
Wrap an `Input` component with buttons.
<ComponentPreview name="button-group-input" />
<ComponentPreview styleName="base-nova" name="button-group-input" />
### Input Group
Wrap an `InputGroup` component to create complex input layouts.
<ComponentPreview name="button-group-input-group" />
<ComponentPreview styleName="base-nova" name="button-group-input-group" />
### Dropdown Menu
Create a split button group with a `DropdownMenu` component.
<ComponentPreview name="button-group-dropdown" />
<ComponentPreview styleName="base-nova" name="button-group-dropdown" />
### Select
Pair with a `Select` component.
<ComponentPreview name="button-group-select" />
<ComponentPreview styleName="base-nova" name="button-group-select" />
### Popover
Use with a `Popover` component.
<ComponentPreview name="button-group-popover" />
<ComponentPreview styleName="base-nova" name="button-group-popover" />
## API Reference

View File

@@ -0,0 +1,153 @@
---
title: Button
description: Displays a button or a component that looks like a button.
featured: true
base: base
component: true
---
<ComponentPreview styleName="base-nova" name="button-demo" />
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">Command</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add button
```
</TabsContent>
<TabsContent value="manual">
<Steps className="mb-0 pt-2">
<Step>Install the following dependencies:</Step>
```bash
npm install @base-ui/react
```
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="button"
title="components/ui/button.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx
import { Button } from "@/components/ui/button"
```
```tsx
<Button variant="outline">Button</Button>
```
## Cursor
Tailwind v4 [switched](https://tailwindcss.com/docs/upgrade-guide#buttons-use-the-default-cursor) from `cursor: pointer` to `cursor: default` for the button component.
If you want to keep the `cursor: pointer` behavior, add the following code to your CSS file:
```css showLineNumbers title="globals.css"
@layer base {
button:not(:disabled),
[role="button"]:not(:disabled) {
cursor: pointer;
}
}
```
## Examples
### Size
Use the `size` prop to change the size of the button.
<ComponentPreview styleName="base-nova" name="button-size" />
### Default
<ComponentPreview styleName="base-nova" name="button-default" />
### Outline
<ComponentPreview styleName="base-nova" name="button-outline" />
### Secondary
<ComponentPreview styleName="base-nova" name="button-secondary" />
### Ghost
<ComponentPreview styleName="base-nova" name="button-ghost" />
### Destructive
<ComponentPreview styleName="base-nova" name="button-destructive" />
### Link
<ComponentPreview styleName="base-nova" name="button-link" />
### Icon
<ComponentPreview styleName="base-nova" name="button-icon" />
### With Icon
Remember to add the `data-icon="inline-start"` or `data-icon="inline-end"` attribute to the icon for the correct spacing.
<ComponentPreview styleName="base-nova" name="button-with-icon" />
### Rounded
Use the `rounded-full` class to make the button rounded.
<ComponentPreview styleName="base-nova" name="button-rounded" />
### Spinner
Render a `<Spinner />` component inside the button to show a loading state. Remember to add the `data-icon="inline-start"` or `data-icon="inline-end"` attribute to the spinner for the correct spacing.
<ComponentPreview styleName="base-nova" name="button-spinner" />
### Button Group
To create a button group, use the `ButtonGroup` component. See the [Button Group](/docs/components/base/button-group) documentation for more details.
<ComponentPreview styleName="base-nova" name="button-group-demo" />
### Link
You can use the `render` prop on `<Button />` to make another component look like a button. Here's an example of a link that looks like a button.
<ComponentPreview styleName="base-nova" name="button-render" />
## API Reference
### Button
The `Button` component is a wrapper around the `button` element that adds a variety of styles and functionality.
| Prop | Type | Default |
| --------- | ------------------------------------------------------------------------------------ | ----------- |
| `variant` | `"default" \| "outline" \| "ghost" \| "destructive" \| "secondary" \| "link"` | `"default"` |
| `size` | `"default" \| "xs" \| "sm" \| "lg" \| "icon" \| "icon-xs" \| "icon-sm" \| "icon-lg"` | `"default"` |

View File

@@ -1,15 +1,16 @@
---
title: Calendar
description: A date field component that allows users to enter and edit date.
description: A calendar component that allows users to select a date or a range of dates.
base: base
component: true
links:
doc: https://react-day-picker.js.org
---
<ComponentPreview
styleName="base-nova"
name="calendar-demo"
title="Calendar"
description="A calendar showing the current date."
previewClassName="h-96"
/>
## Blocks
@@ -23,7 +24,7 @@ See all calendar blocks in the [Blocks Library](/blocks/calendar) page.
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">CLI</TabsTrigger>
<TabsTrigger value="cli">Command</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
@@ -36,7 +37,7 @@ npx shadcn@latest add calendar
<TabsContent value="manual">
<Steps>
<Steps className="mb-0 pt-2">
<Step>Install the following dependencies:</Step>
@@ -50,7 +51,11 @@ The `Calendar` component uses the `Button` component. Make sure you have it inst
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource name="calendar" title="components/ui/calendar.tsx" />
<ComponentSource
name="calendar"
title="components/ui/calendar.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
@@ -85,13 +90,9 @@ See the [React DayPicker](https://react-day-picker.js.org) documentation for mor
The `Calendar` component is built on top of [React DayPicker](https://react-day-picker.js.org).
## Customization
See the [React DayPicker](https://react-day-picker.js.org/docs/customization) documentation for more information on how to customize the `Calendar` component.
## Date Picker
You can use the `<Calendar>` component to build a date picker. See the [Date Picker](/docs/components/date-picker) page for more information.
You can use the `<Calendar>` component to build a date picker. See the [Date Picker](/docs/components/base/date-picker) page for more information.
## Persian / Hijri / Jalali Calendar
@@ -103,9 +104,11 @@ To use the Persian calendar, edit `components/ui/calendar.tsx` and replace `reac
```
<ComponentPreview
styleName="base-nova"
name="calendar-hijri"
title="Persian / Hijri / Jalali Calendar"
description="A Persian calendar."
previewClassName="h-[400px]"
/>
## Selected Date (With TimeZone)
@@ -138,53 +141,65 @@ export function CalendarWithTimezone() {
## Examples
### Range Calendar
### Basic
A basic calendar component. We used `className="rounded-lg border"` to style the calendar.
<ComponentPreview
name="calendar-05"
title="Range Calendar"
description="A calendar showing the current date and range selection."
className="**:[.preview]:h-auto lg:**:[.preview]:h-[450px]"
styleName="base-nova"
name="calendar-basic"
previewClassName="h-96"
/>
### Range Calendar
Use the `mode="range"` prop to enable range selection.
<ComponentPreview
styleName="base-nova"
name="calendar-range"
previewClassName="h-[36rem] md:h-96"
/>
### Month and Year Selector
Use `captionLayout="dropdown"` to show month and year dropdowns.
<ComponentPreview
name="calendar-13"
title="Month and Year Selector"
description="A calendar with month and year dropdowns."
styleName="base-nova"
name="calendar-caption"
previewClassName="h-96"
/>
### Date of Birth Picker
### Presets
<ComponentPreview
name="calendar-22"
title="Date of Birth Picker"
description="A calendar with date of birth picker."
styleName="base-nova"
name="calendar-presets"
previewClassName="h-[650px]"
/>
### Date and Time Picker
<ComponentPreview
name="calendar-24"
title="Date and Time Picker"
description="A calendar with date and time picker."
styleName="base-nova"
name="calendar-time"
previewClassName="h-[600px]"
/>
### Natural Language Picker
This component uses the `chrono-node` library to parse natural language dates.
### Booked dates
<ComponentPreview
name="calendar-29"
title="Natural Language Picker"
description="A calendar with natural language picker."
styleName="base-nova"
name="calendar-booked-dates"
previewClassName="h-96"
/>
### Custom Cell Size
<ComponentPreview
name="calendar-18"
styleName="base-nova"
name="calendar-custom-days"
title="Custom Cell Size"
description="A calendar with custom cell size that's responsive."
className="**:[.preview]:h-[560px]"
@@ -212,6 +227,16 @@ Or use fixed values:
/>
```
### Week Numbers
Use `showWeekNumber` to show week numbers.
<ComponentPreview
styleName="base-nova"
name="calendar-week-numbers"
previewClassName="h-96"
/>
## Upgrade Guide
### Tailwind v4
@@ -448,7 +473,7 @@ function CalendarDayButton({
data-range-end={modifiers.range_end}
data-range-middle={modifiers.range_middle}
className={cn(
"data-[selected-single=true]:bg-primary data-[selected-single=true]:text-primary-foreground data-[range-middle=true]:bg-accent data-[range-middle=true]:text-accent-foreground data-[range-start=true]:bg-primary data-[range-start=true]:text-primary-foreground data-[range-end=true]:bg-primary data-[range-end=true]:text-primary-foreground group-data-[focused=true]/day:border-ring group-data-[focused=true]/day:ring-ring/50 flex aspect-square h-auto w-full min-w-[--cell-size] flex-col gap-1 font-normal leading-none data-[range-end=true]:rounded-md data-[range-middle=true]:rounded-none data-[range-start=true]:rounded-md group-data-[focused=true]/day:relative group-data-[focused=true]/day:z-10 group-data-[focused=true]/day:ring-[3px] [&>span]:text-xs [&>span]:opacity-70",
"data-[selected-single=true]:bg-primary data-[selected-single=true]:text-primary-foreground data-[range-middle=true]:bg-accent data-[range-middle=true]:text-accent-foreground data-[range-start=true]:bg-primary data-[range-start=true]:text-primary-foreground data-[range-end=true]:bg-primary data-[range-end=true]:text-primary-foreground group-data-[focused=true]/day:border-ring group-data-[focused=true]/day:ring-ring/50 flex aspect-square h-auto w-full min-w-[--cell-size] flex-col gap-1 leading-none font-normal group-data-[focused=true]/day:relative group-data-[focused=true]/day:z-10 group-data-[focused=true]/day:ring-[3px] data-[range-end=true]:rounded-md data-[range-middle=true]:rounded-none data-[range-start=true]:rounded-md [&>span]:text-xs [&>span]:opacity-70",
defaultClassNames.day,
className
)}
@@ -476,24 +501,6 @@ npx shadcn@latest add calendar-02
This will install the latest version of the calendar blocks.
## Changelog
## API Reference
### 2025-10-26 Fixed day radius with week numbers
We have fixed an issue where the selected day's left border radius was not applied correctly when week numbers were displayed. The fix ensures that when `showWeekNumber` is enabled, the first day (which is the second child due to the week number column) correctly receives the rounded left border.
To apply this fix, edit `components/ui/calendar.tsx` and update the `day` class in `classNames`:
```tsx showLineNumbers title="components/ui/calendar.tsx" {5-7}
classNames={{
// ... other classNames
day: cn(
"relative w-full h-full p-0 text-center [&:last-child[data-selected=true]_button]:rounded-r-md group/day aspect-square select-none",
props.showWeekNumber
? "[&:nth-child(2)[data-selected=true]_button]:rounded-l-md"
: "[&:first-child[data-selected=true]_button]:rounded-l-md",
defaultClassNames.day
),
// ... other classNames
}}
```
See the [React DayPicker](https://react-day-picker.js.org) documentation for more information on the `Calendar` component API.

View File

@@ -0,0 +1,159 @@
---
title: Card
description: Displays a card with header, content, and footer.
base: base
component: true
---
<ComponentPreview
name="card-demo"
styleName="base-nova"
previewClassName="h-[30rem]"
/>
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">Command</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add card
```
</TabsContent>
<TabsContent value="manual">
<Steps className="mb-0 pt-2">
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="card"
title="components/ui/card.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx showLineNumbers
import {
Card,
CardAction,
CardContent,
CardDescription,
CardFooter,
CardHeader,
CardTitle,
} from "@/components/ui/card"
```
```tsx showLineNumbers
<Card>
<CardHeader>
<CardTitle>Card Title</CardTitle>
<CardDescription>Card Description</CardDescription>
<CardAction>Card Action</CardAction>
</CardHeader>
<CardContent>
<p>Card Content</p>
</CardContent>
<CardFooter>
<p>Card Footer</p>
</CardFooter>
</Card>
```
## Examples
### Size
Use the `size="sm"` prop to set the size of the card to small. The small size variant uses smaller spacing.
<ComponentPreview
styleName="base-nova"
name="card-small"
previewClassName="h-96"
/>
### Image
Add an image before the card header to create a card with an image.
<ComponentPreview
styleName="base-nova"
name="card-image"
previewClassName="h-[32rem]"
/>
## API Reference
### Card
The `Card` component is the root container for card content.
| Prop | Type | Default |
| ----------- | ------------------- | ----------- |
| `size` | `"default" \| "sm"` | `"default"` |
| `className` | `string` | - |
### CardHeader
The `CardHeader` component is used for a title, description, and optional action.
| Prop | Type | Default |
| ----------- | -------- | ------- |
| `className` | `string` | - |
### CardTitle
The `CardTitle` component is used for the card title.
| Prop | Type | Default |
| ----------- | -------- | ------- |
| `className` | `string` | - |
### CardDescription
The `CardDescription` component is used for helper text under the title.
| Prop | Type | Default |
| ----------- | -------- | ------- |
| `className` | `string` | - |
### CardAction
The `CardAction` component places content in the top-right of the header (for example, a button or a badge).
| Prop | Type | Default |
| ----------- | -------- | ------- |
| `className` | `string` | - |
### CardContent
The `CardContent` component is used for the main card body.
| Prop | Type | Default |
| ----------- | -------- | ------- |
| `className` | `string` | - |
### CardFooter
The `CardFooter` component is used for actions and secondary content at the bottom of the card.
| Prop | Type | Default |
| ----------- | -------- | ------- |
| `className` | `string` | - |

View File

@@ -1,6 +1,7 @@
---
title: Carousel
description: A carousel with motion and swipe built using Embla.
base: base
component: true
links:
doc: https://www.embla-carousel.com/get-started/react
@@ -8,9 +9,9 @@ links:
---
<ComponentPreview
styleName="base-nova"
name="carousel-demo"
title="Carousel"
description="A carousel with 5 items and a previous and next button."
previewClassName="h-80 sm:h-[32rem]"
/>
## About
@@ -22,7 +23,7 @@ The carousel component is built using the [Embla Carousel](https://www.embla-car
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">CLI</TabsTrigger>
<TabsTrigger value="cli">Command</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
@@ -36,7 +37,7 @@ npx shadcn@latest add carousel
<TabsContent value="manual">
<Steps>
<Steps className="mb-0 pt-2">
<Step>Install the following dependencies:</Step>
@@ -46,7 +47,11 @@ npm install embla-carousel-react
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource name="carousel" title="components/ui/carousel.tsx" />
<ComponentSource
name="carousel"
title="components/ui/carousel.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
@@ -86,11 +91,7 @@ import {
To set the size of the items, you can use the `basis` utility class on the `<CarouselItem />`.
<ComponentPreview
name="carousel-size"
title="Carousel"
description="A carousel with 3 active items of equal size."
/>
<ComponentPreview styleName="base-nova" name="carousel-size" />
```tsx showLineNumbers {4-6}
// 33% of the carousel width.
@@ -118,21 +119,7 @@ To set the size of the items, you can use the `basis` utility class on the `<Car
To set the spacing between the items, we use a `pl-[VALUE]` utility on the `<CarouselItem />` and a negative `-ml-[VALUE]` on the `<CarouselContent />`.
<Callout className="mt-6">
**Why:** I tried to use the `gap` property or a `grid` layout on the `
<CarouselContent />` but it required a lot of math and mental effort to get the
spacing right. I found `pl-[VALUE]` and `-ml-[VALUE]` utilities much easier to
use.
You can always adjust this in your own project if you need to.
</Callout>
<ComponentPreview
name="carousel-spacing"
title="Carousel"
description="A carousel with 3 items with a spacing of 1rem."
/>
<ComponentPreview styleName="base-nova" name="carousel-spacing" />
```tsx showLineNumbers /-ml-4/ /pl-4/
<Carousel>
@@ -159,9 +146,9 @@ You can always adjust this in your own project if you need to.
Use the `orientation` prop to set the orientation of the carousel.
<ComponentPreview
styleName="base-nova"
name="carousel-orientation"
title="Carousel"
description="A vertical carousel."
previewClassName="h-[32rem]"
/>
```tsx showLineNumbers /vertical | horizontal/
@@ -198,9 +185,9 @@ You can pass options to the carousel using the `opts` prop. See the [Embla Carou
Use a state and the `setApi` props to get an instance of the carousel API.
<ComponentPreview
styleName="base-nova"
name="carousel-api"
title="Carousel"
description="A carousel with a slide counter."
previewClassName="sm:h-[32rem]"
/>
```tsx showLineNumbers {1,4,22}
@@ -293,9 +280,11 @@ export function Example() {
```
<ComponentPreview
styleName="base-nova"
name="carousel-plugin"
title="Carousel"
description="A carousel with the autoplay plugin."
previewClassName="sm:h-[32rem]"
/>
See the [Embla Carousel docs](https://www.embla-carousel.com/api/plugins/) for more information on using plugins.
## API Reference
See the [Embla Carousel docs](https://www.embla-carousel.com/api/plugins/) for more information on props and plugins.

View File

@@ -1,6 +1,7 @@
---
title: Chart
description: Beautiful charts. Built using Recharts. Copy and paste into your apps.
base: base
component: true
---
@@ -11,7 +12,8 @@ component: true
</Callout>
<ComponentPreview
name="chart-bar-interactive"
styleName="base-nova"
name="chart-demo"
className="theme-blue [&_.preview]:h-auto [&_.preview]:p-0 [&_.preview]:lg:min-h-[404px] [&_.preview>div]:w-full [&_.preview>div]:border-none [&_.preview>div]:shadow-none"
hideCode
/>
@@ -51,57 +53,23 @@ We do not wrap Recharts. This means you're not locked into an abstraction. When
## Installation
<Callout className="mt-4">
**Note:** If you are using charts with **React 19** or the **Next.js 15**, see the note [here](/docs/react-19#recharts).
</Callout>
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">CLI</TabsTrigger>
<TabsTrigger value="cli">Command</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
<Steps>
<Step>Run the following command to install `chart.tsx`</Step>
```bash
npx shadcn@latest add chart
```
<Step>Add the following colors to your CSS file</Step>
```css title="app/globals.css" showLineNumbers
@layer base {
:root {
--chart-1: oklch(0.646 0.222 41.116);
--chart-2: oklch(0.6 0.118 184.704);
--chart-3: oklch(0.398 0.07 227.392);
--chart-4: oklch(0.828 0.189 84.429);
--chart-5: oklch(0.769 0.188 70.08);
}
.dark {
--chart-1: oklch(0.488 0.243 264.376);
--chart-2: oklch(0.696 0.17 162.48);
--chart-3: oklch(0.769 0.188 70.08);
--chart-4: oklch(0.627 0.265 303.9);
--chart-5: oklch(0.645 0.246 16.439);
}
}
```
</Steps>
</TabsContent>
<TabsContent value="manual">
<Steps>
<Steps className="mb-0 pt-2">
<Step>Install the following dependencies:</Step>
@@ -111,7 +79,11 @@ npm install recharts
<Step>Copy and paste the following code into `components/ui/chart.tsx`.</Step>
<ComponentSource name="chart" title="components/ui/chart.tsx" />
<ComponentSource
name="chart"
title="components/ui/chart.tsx"
styleName="base-nova"
/>
<Step>Add the following colors to your CSS file</Step>
@@ -197,11 +169,10 @@ You can now build your chart using Recharts components.
</Callout>
<ComponentSource name="chart-bar-demo" title="components/example-chart.tsx" />
<ComponentPreview
name="chart-bar-demo"
className="[&_.preview]:min-h-[250px] [&_.preview]:p-4"
styleName="base-nova"
name="chart-example"
previewClassName="h-80"
/>
</Steps>
@@ -210,7 +181,7 @@ You can now build your chart using Recharts components.
Let's add a grid to the chart.
<Steps>
<Steps className="mb-0 pt-2">
<Step>Import the `CartesianGrid` component.</Step>
@@ -231,8 +202,9 @@ import { Bar, BarChart, CartesianGrid } from "recharts"
```
<ComponentPreview
name="chart-bar-demo-grid"
className="[&_.preview]:min-h-[250px] [&_.preview]:p-4"
styleName="base-nova"
name="chart-example-grid"
previewClassName="h-80"
/>
</Steps>
@@ -241,7 +213,7 @@ import { Bar, BarChart, CartesianGrid } from "recharts"
To add an x-axis to the chart, we'll use the `XAxis` component.
<Steps>
<Steps className="mb-0 pt-2">
<Step>Import the `XAxis` component.</Step>
@@ -269,8 +241,9 @@ import { Bar, BarChart, CartesianGrid, XAxis } from "recharts"
```
<ComponentPreview
name="chart-bar-demo-axis"
className="[&_.preview]:min-h-[250px] [&_.preview]:p-4"
styleName="base-nova"
name="chart-example-axis"
previewClassName="h-80"
/>
</Steps>
@@ -281,7 +254,7 @@ So far we've only used components from Recharts. They look great out of the box
To add a tooltip, we'll use the custom `ChartTooltip` and `ChartTooltipContent` components from `chart`.
<Steps>
<Steps className="mb-0 pt-2">
<Step>Import the `ChartTooltip` and `ChartTooltipContent` components.</Step>
@@ -310,8 +283,9 @@ import { ChartTooltip, ChartTooltipContent } from "@/components/ui/chart"
```
<ComponentPreview
name="chart-bar-demo-tooltip"
className="[&_.preview]:min-h-[250px] [&_.preview]:p-4"
styleName="base-nova"
name="chart-example-tooltip"
previewClassName="h-80"
/>
Hover to see the tooltips. Easy, right? Two components, and we've got a beautiful tooltip.
@@ -322,7 +296,7 @@ Hover to see the tooltips. Easy, right? Two components, and we've got a beautifu
We'll do the same for the legend. We'll use the `ChartLegend` and `ChartLegendContent` components from `chart`.
<Steps>
<Steps className="mb-0 pt-2">
<Step>Import the `ChartLegend` and `ChartLegendContent` components.</Step>
@@ -352,8 +326,9 @@ import { ChartLegend, ChartLegendContent } from "@/components/ui/chart"
```
<ComponentPreview
name="chart-bar-demo-legend"
className="[&_.preview]:min-h-[250px] [&_.preview]:p-4"
styleName="base-nova"
name="chart-example-legend"
previewClassName="h-80"
/>
</Steps>
@@ -398,11 +373,11 @@ Charts have built-in support for theming. You can use css variables (recommended
### CSS Variables
<Steps>
<Steps className="mb-0 pt-2">
<Step>Define your colors in your css file</Step>
```css {6-7,14-15} title="app/globals.css" showLineNumbers
```css title="app/globals.css" showLineNumbers
@layer base {
:root {
--chart-1: oklch(0.646 0.222 41.116);
@@ -418,7 +393,7 @@ Charts have built-in support for theming. You can use css variables (recommended
<Step>Add the color to your `chartConfig`</Step>
```tsx {4,8} showLineNumbers
```tsx title="components/example-chart.tsx" showLineNumbers
const chartConfig = {
desktop: {
label: "Desktop",
@@ -437,12 +412,24 @@ const chartConfig = {
You can also define your colors directly in the chart config. Use the color format you prefer.
```tsx showLineNumbers
```tsx title="components/example-chart.tsx" showLineNumbers
const chartConfig = {
desktop: {
label: "Desktop",
color: "#2563eb",
},
mobile: {
label: "Mobile",
color: "hsl(220, 98%, 61%)",
},
tablet: {
label: "Tablet",
color: "oklch(0.5 0.2 240)",
},
laptop: {
label: "Laptop",
color: "var(--chart-2)",
},
} satisfies ChartConfig
```
@@ -458,7 +445,7 @@ To use the theme colors in your chart, reference the colors using the format `va
#### Chart Data
```tsx showLineNumbers
```tsx title="components/example-chart.tsx" showLineNumbers
const chartData = [
{ browser: "chrome", visitors: 275, fill: "var(--color-chrome)" },
{ browser: "safari", visitors: 200, fill: "var(--color-safari)" },
@@ -467,7 +454,7 @@ const chartData = [
#### Tailwind
```tsx
```tsx title="components/example-chart.tsx"
<LabelList className="fill-[--color-desktop]" />
```
@@ -475,11 +462,7 @@ const chartData = [
A chart tooltip contains a label, name, indicator and value. You can use a combination of these to customize your tooltip.
<ComponentPreview
name="chart-tooltip-demo"
className="[&_.preview]:py-0"
hideCode
/>
<ComponentPreview styleName="base-nova" name="chart-tooltip" hideCode />
You can turn on/off any of these using the `hideLabel`, `hideIndicator` props and customize the indicator style using the `indicator` prop.
@@ -487,11 +470,11 @@ Use `labelKey` and `nameKey` to use a custom key for the tooltip label and name.
Chart comes with the `<ChartTooltip>` and `<ChartTooltipContent>` components. You can use these two components to add custom tooltips to your chart.
```tsx
```tsx title="components/example-chart.tsx"
import { ChartTooltip, ChartTooltipContent } from "@/components/ui/chart"
```
```tsx
```tsx title="components/example-chart.tsx"
<ChartTooltip content={<ChartTooltipContent />} />
```
@@ -536,7 +519,7 @@ const chartConfig = {
} satisfies ChartConfig
```
```tsx
```tsx title="components/example-chart.tsx"
<ChartTooltip
content={<ChartTooltipContent labelKey="visitors" nameKey="browser" />}
/>
@@ -548,11 +531,11 @@ This will use `Total Visitors` for label and `Chrome` and `Safari` for the toolt
You can use the custom `<ChartLegend>` and `<ChartLegendContent>` components to add a legend to your chart.
```tsx
```tsx title="components/example-chart.tsx"
import { ChartLegend, ChartLegendContent } from "@/components/ui/chart"
```
```tsx
```tsx title="components/example-chart.tsx"
<ChartLegend content={<ChartLegendContent />} />
```
@@ -582,7 +565,7 @@ const chartConfig = {
} satisfies ChartConfig
```
```tsx
```tsx title="components/example-chart.tsx"
<ChartLegend content={<ChartLegendContent nameKey="browser" />} />
```
@@ -594,6 +577,6 @@ You can turn on the `accessibilityLayer` prop to add an accessible layer to your
This prop adds keyboard access and screen reader support to your charts.
```tsx
```tsx title="components/example-chart.tsx"
<LineChart accessibilityLayer />
```

View File

@@ -0,0 +1,127 @@
---
title: Checkbox
description: A control that allows the user to toggle between checked and not checked.
base: base
component: true
links:
doc: https://base-ui.com/react/components/checkbox
api: https://base-ui.com/react/components/checkbox#api-reference
---
<ComponentPreview
styleName="base-nova"
name="checkbox-demo"
previewClassName="h-80"
/>
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">Command</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add checkbox
```
</TabsContent>
<TabsContent value="manual">
<Steps className="mb-0 pt-2">
<Step>Install the following dependencies:</Step>
```bash
npm install @base-ui/react
```
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="checkbox"
title="components/ui/checkbox.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx
import { Checkbox } from "@/components/ui/checkbox"
```
```tsx
<Checkbox />
```
## Checked State
Use `defaultChecked` for uncontrolled checkboxes, or `checked` and
`onCheckedChange` to control the state.
```tsx showLineNumbers
import * as React from "react"
export function Example() {
const [checked, setChecked] = React.useState(false)
return <Checkbox checked={checked} onCheckedChange={setChecked} />
}
```
## Invalid State
Set `aria-invalid` on the checkbox and `data-invalid` on the field wrapper to
show the invalid styles.
<ComponentPreview styleName="base-nova" name="checkbox-invalid" />
## Examples
### Basic
Pair the checkbox with `Field` and `FieldLabel` for proper layout and labeling.
<ComponentPreview styleName="base-nova" name="checkbox-basic" />
### Description
Use `FieldContent` and `FieldDescription` for helper text.
<ComponentPreview styleName="base-nova" name="checkbox-description" />
### Disabled
Use the `disabled` prop to prevent interaction and add the `data-disabled` attribute to the `<Field>` component for disabled styles.
<ComponentPreview styleName="base-nova" name="checkbox-disabled" />
### Group
Use multiple fields to create a checkbox list.
<ComponentPreview styleName="base-nova" name="checkbox-group" />
### Table
<ComponentPreview
styleName="base-nova"
name="checkbox-table"
previewClassName="p-4 md:p-8"
/>
## API Reference
See the [Base UI](https://base-ui.com/react/components/checkbox#api-reference) documentation for more information.

View File

@@ -0,0 +1,123 @@
---
title: Collapsible
description: An interactive component which expands/collapses a panel.
base: base
component: true
featured: true
links:
doc: https://base-ui.com/react/components/collapsible
api: https://base-ui.com/react/components/collapsible#api-reference
---
<ComponentPreview styleName="base-nova" name="collapsible-demo" align="start" />
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">Command</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add collapsible
```
</TabsContent>
<TabsContent value="manual">
<Steps className="mb-0 pt-2">
<Step>Install the following dependencies:</Step>
```bash
npm install @base-ui/react
```
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="collapsible"
title="components/ui/collapsible.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx showLineNumbers
import {
Collapsible,
CollapsibleContent,
CollapsibleTrigger,
} from "@/components/ui/collapsible"
```
```tsx showLineNumbers
<Collapsible>
<CollapsibleTrigger>Can I use this in my project?</CollapsibleTrigger>
<CollapsibleContent>
Yes. Free to use for personal and commercial projects. No attribution
required.
</CollapsibleContent>
</Collapsible>
```
## Controlled State
Use the `open` and `onOpenChange` props to control the state.
```tsx showLineNumbers
import * as React from "react"
export function Example() {
const [open, setOpen] = React.useState(false)
return (
<Collapsible open={open} onOpenChange={setOpen}>
<CollapsibleTrigger>Toggle</CollapsibleTrigger>
<CollapsibleContent>Content</CollapsibleContent>
</Collapsible>
)
}
```
## Examples
### Basic
<ComponentPreview
styleName="base-nova"
name="collapsible-basic"
align="start"
/>
### Settings Panel
Use a trigger button to reveal additional settings.
<ComponentPreview styleName="base-nova" name="collapsible-settings" />
### File Tree
Use nested collapsibles to build a file tree.
<ComponentPreview
styleName="base-nova"
name="collapsible-file-tree"
previewClassName="h-[36rem]"
/>
## API Reference
See the [Base UI](https://base-ui.com/react/components/collapsible#api-reference) documentation for more information.

View File

@@ -0,0 +1,261 @@
---
title: Combobox
description: Autocomplete input with a list of suggestions.
base: base
component: true
links:
doc: https://base-ui.com/react/components/combobox
api: https://base-ui.com/react/components/combobox#api-reference
---
<ComponentPreview
styleName="base-nova"
name="combobox-demo"
description="A combobox with a list of frameworks."
/>
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">Command</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add combobox
```
</TabsContent>
<TabsContent value="manual">
<Steps className="mb-0 pt-2">
<Step>Install the following dependencies:</Step>
```bash
npm install @base-ui/react
```
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="combobox"
title="components/ui/combobox.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx showLineNumbers
import {
Combobox,
ComboboxContent,
ComboboxEmpty,
ComboboxInput,
ComboboxItem,
ComboboxList,
} from "@/components/ui/combobox"
```
```tsx showLineNumbers
const frameworks = ["Next.js", "SvelteKit", "Nuxt.js", "Remix", "Astro"]
export function ExampleCombobox() {
return (
<Combobox items={frameworks}>
<ComboboxInput placeholder="Select a framework" />
<ComboboxContent>
<ComboboxEmpty>No items found.</ComboboxEmpty>
<ComboboxList>
{(item) => (
<ComboboxItem key={item} value={item}>
{item}
</ComboboxItem>
)}
</ComboboxList>
</ComboboxContent>
</Combobox>
)
}
```
## Custom Items
Use `itemToStringValue` when your items are objects.
```tsx showLineNumbers
import * as React from "react"
import {
Combobox,
ComboboxContent,
ComboboxEmpty,
ComboboxInput,
ComboboxItem,
ComboboxList,
} from "@/components/ui/combobox"
type Framework = {
label: string
value: string
}
const frameworks: Framework[] = [
{ label: "Next.js", value: "next" },
{ label: "SvelteKit", value: "sveltekit" },
{ label: "Nuxt", value: "nuxt" },
]
export function ExampleComboboxCustomItems() {
return (
<Combobox
items={frameworks}
itemToStringValue={(framework) => framework.label}
>
<ComboboxInput placeholder="Select a framework" />
<ComboboxContent>
<ComboboxEmpty>No items found.</ComboboxEmpty>
<ComboboxList>
{(framework) => (
<ComboboxItem key={framework.value} value={framework}>
{framework.label}
</ComboboxItem>
)}
</ComboboxList>
</ComboboxContent>
</Combobox>
)
}
```
## Multiple Selection
Use `multiple` with chips for multi-select behavior.
```tsx showLineNumbers
import * as React from "react"
import {
Combobox,
ComboboxChip,
ComboboxChips,
ComboboxChipsInput,
ComboboxContent,
ComboboxEmpty,
ComboboxInput,
ComboboxItem,
ComboboxList,
ComboboxValue,
} from "@/components/ui/combobox"
const frameworks = ["Next.js", "SvelteKit", "Nuxt.js", "Remix", "Astro"]
export function ExampleComboboxMultiple() {
const [value, setValue] = React.useState<string[]>([])
return (
<Combobox
items={frameworks}
multiple
value={value}
onValueChange={setValue}
>
<ComboboxChips>
<ComboboxValue>
{value.map((item) => (
<ComboboxChip key={item}>{item}</ComboboxChip>
))}
</ComboboxValue>
<ComboboxChipsInput placeholder="Add framework" />
</ComboboxChips>
<ComboboxContent>
<ComboboxEmpty>No items found.</ComboboxEmpty>
<ComboboxList>
{(item) => (
<ComboboxItem key={item} value={item}>
{item}
</ComboboxItem>
)}
</ComboboxList>
</ComboboxContent>
</Combobox>
)
}
```
## Examples
### Basic
A simple combobox with a list of frameworks.
<ComponentPreview styleName="base-nova" name="combobox-basic" />
### Multiple
A combobox with multiple selection using `multiple` and `ComboboxChips`.
<ComponentPreview styleName="base-nova" name="combobox-multiple" />
### Clear Button
Use the `showClear` prop to show a clear button.
<ComponentPreview styleName="base-nova" name="combobox-clear" />
### Groups
Use `ComboboxGroup` and `ComboboxSeparator` to group items.
<ComponentPreview styleName="base-nova" name="combobox-groups" />
### Custom Items
You can render custom component inside `ComboboxItem`.
<ComponentPreview styleName="base-nova" name="combobox-custom" />
### Invalid
Use the `aria-invalid` prop to make the combobox invalid.
<ComponentPreview styleName="base-nova" name="combobox-invalid" />
### Disabled
Use the `disabled` prop to disable the combobox.
<ComponentPreview styleName="base-nova" name="combobox-disabled" />
### Auto Highlight
Use the `autoHighlight` prop automatically highlight the first item on filter.
<ComponentPreview styleName="base-nova" name="combobox-auto-highlight" />
### Popup
You can trigger the combobox from a button or any other component by using the `render` prop. Move the `ComboboxInput` inside the `ComboboxContent`.
<ComponentPreview styleName="base-nova" name="combobox-popup" />
### Input Group
You can add an addon to the combobox by using the `InputGroupAddon` component inside the `ComboboxInput`.
<ComponentPreview styleName="base-nova" name="combobox-input-group" />
## API Reference
See the [Base UI](https://base-ui.com/react/components/combobox#api-reference) documentation for more information.

View File

@@ -0,0 +1,125 @@
---
title: Command
description: Command menu for search and quick actions.
base: base
component: true
links:
doc: https://github.com/dip/cmdk
---
<ComponentPreview
styleName="base-nova"
name="command-demo"
align="start"
previewClassName="h-[24.5rem]"
/>
## About
The `<Command />` component uses the [`cmdk`](https://github.com/dip/cmdk) component by [Dip](https://www.dip.org/).
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">Command</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add command
```
</TabsContent>
<TabsContent value="manual">
<Steps className="mb-0 pt-2">
<Step>Install the following dependencies:</Step>
```bash
npm install cmdk
```
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="command"
title="components/ui/command.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx showLineNumbers
import {
Command,
CommandDialog,
CommandEmpty,
CommandGroup,
CommandInput,
CommandItem,
CommandList,
CommandSeparator,
CommandShortcut,
} from "@/components/ui/command"
```
```tsx showLineNumbers
<Command className="max-w-sm rounded-lg border">
<CommandInput placeholder="Type a command or search..." />
<CommandList>
<CommandEmpty>No results found.</CommandEmpty>
<CommandGroup heading="Suggestions">
<CommandItem>Calendar</CommandItem>
<CommandItem>Search Emoji</CommandItem>
<CommandItem>Calculator</CommandItem>
</CommandGroup>
<CommandSeparator />
<CommandGroup heading="Settings">
<CommandItem>Profile</CommandItem>
<CommandItem>Billing</CommandItem>
<CommandItem>Settings</CommandItem>
</CommandGroup>
</CommandList>
</Command>
```
## Examples
### Basic
A simple command menu in a dialog.
<ComponentPreview styleName="base-nova" name="command-basic" />
### Shortcuts
<ComponentPreview styleName="base-nova" name="command-shortcuts" />
### Groups
A command menu with groups, icons and separators.
<ComponentPreview styleName="base-nova" name="command-groups" />
### Scrollable
Scrollable command menu with multiple items.
<ComponentPreview styleName="base-nova" name="command-scrollable" />
## API Reference
See the [cmdk](https://github.com/dip/cmdk) documentation for more information.

View File

@@ -0,0 +1,140 @@
---
title: Context Menu
description: Displays a menu of actions triggered by a right click.
base: base
component: true
links:
doc: https://base-ui.com/react/components/context-menu
api: https://base-ui.com/react/components/context-menu#api-reference
---
<ComponentPreview
styleName="base-nova"
name="context-menu-demo"
description="A context menu with sub menu items."
/>
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">Command</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add context-menu
```
</TabsContent>
<TabsContent value="manual">
<Steps className="mb-0 pt-2">
<Step>Install the following dependencies:</Step>
```bash
npm install @base-ui/react
```
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="context-menu"
title="components/ui/context-menu.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx showLineNumbers
import {
ContextMenu,
ContextMenuContent,
ContextMenuItem,
ContextMenuTrigger,
} from "@/components/ui/context-menu"
```
```tsx showLineNumbers
<ContextMenu>
<ContextMenuTrigger>Right click here</ContextMenuTrigger>
<ContextMenuContent>
<ContextMenuItem>Profile</ContextMenuItem>
<ContextMenuItem>Billing</ContextMenuItem>
<ContextMenuItem>Team</ContextMenuItem>
<ContextMenuItem>Subscription</ContextMenuItem>
</ContextMenuContent>
</ContextMenu>
```
## Examples
### Basic
A simple context menu with a few actions.
<ComponentPreview styleName="base-nova" name="context-menu-basic" />
### Submenu
Use `ContextMenuSub` to nest secondary actions.
<ComponentPreview styleName="base-nova" name="context-menu-submenu" />
### Shortcuts
Add `ContextMenuShortcut` to show keyboard hints.
<ComponentPreview styleName="base-nova" name="context-menu-shortcuts" />
### Groups
Group related actions and separate them with dividers.
<ComponentPreview styleName="base-nova" name="context-menu-groups" />
### Icons
Combine icons with labels for quick scanning.
<ComponentPreview styleName="base-nova" name="context-menu-icons" />
### Checkboxes
Use `ContextMenuCheckboxItem` for toggles.
<ComponentPreview styleName="base-nova" name="context-menu-checkboxes" />
### Radio
Use `ContextMenuRadioItem` for exclusive choices.
<ComponentPreview styleName="base-nova" name="context-menu-radio" />
### Destructive
Use `variant="destructive"` to style the menu item as destructive.
<ComponentPreview styleName="base-nova" name="context-menu-destructive" />
### Sides
Control submenu placement with side and align props.
<ComponentPreview styleName="base-nova" name="context-menu-sides" />
## API Reference
See the [Base UI](https://base-ui.com/react/components/context-menu#api-reference) documentation for more information.

View File

@@ -1,12 +1,18 @@
---
title: Data Table
description: Powerful table and datagrids built using TanStack Table.
base: base
component: true
links:
doc: https://tanstack.com/table/v8/docs/introduction
---
<ComponentPreview name="data-table-demo" className="[&_.preview]:items-start" />
<ComponentPreview
styleName="radix-nova"
name="data-table-demo"
align="start"
previewClassName="items-start h-[28rem] px-4 md:px-8"
/>
## Introduction
@@ -102,7 +108,7 @@ I'm using a Next.js example here but this works for any other React framework.
Let's start by building a basic table.
<Steps>
<Steps className="mb-0 pt-2">
### Column Definitions
@@ -279,7 +285,7 @@ export default async function DemoPage() {
Let's format the amount cell to display the dollar amount. We'll also align the cell to the right.
<Steps>
<Steps className="mb-0 pt-2">
### Update columns definition
@@ -311,7 +317,7 @@ You can use the same approach to format other cells and headers.
Let's add row actions to our table. We'll use a `<Dropdown />` component for this.
<Steps>
<Steps className="mb-0 pt-2">
### Update columns definition
@@ -375,7 +381,7 @@ You can access the row data using `row.original` in the `cell` function. Use thi
Next, we'll add pagination to our table.
<Steps>
<Steps className="mb-0 pt-2">
### Update `<DataTable>`
@@ -461,7 +467,7 @@ See [Reusable Components](#reusable-components) section for a more advanced pagi
Let's make the email column sortable.
<Steps>
<Steps className="mb-0 pt-2">
### Update `<DataTable>`
@@ -543,7 +549,7 @@ This will automatically sort the table (asc and desc) when the user toggles on t
Let's add a search input to filter emails in our table.
<Steps>
<Steps className="mb-0 pt-2">
### Update `<DataTable>`
@@ -618,7 +624,7 @@ Filtering is now enabled for the `email` column. You can add filters to other co
Adding column visibility is fairly simple using `@tanstack/react-table` visibility API.
<Steps>
<Steps className="mb-0 pt-2">
### Update `<DataTable>`
@@ -731,7 +737,7 @@ This adds a dropdown menu that you can use to toggle column visibility.
Next, we're going to add row selection to our table.
<Steps>
<Steps className="mb-0 pt-2">
### Update column definitions
@@ -856,7 +862,10 @@ export const columns = [
Add pagination controls to your table including page size and selection count.
<ComponentSource src="/app/(app)/examples/tasks/components/data-table-pagination.tsx" />
<ComponentSource
src="/app/(app)/examples/tasks/components/data-table-pagination.tsx"
styleName="radix-nova"
/>
```tsx
<DataTablePagination table={table} />
@@ -866,7 +875,10 @@ Add pagination controls to your table including page size and selection count.
A component to toggle column visibility.
<ComponentSource src="/app/(app)/examples/tasks/components/data-table-view-options.tsx" />
<ComponentSource
src="/app/(app)/examples/tasks/components/data-table-view-options.tsx"
styleName="radix-nova"
/>
```tsx
<DataTableViewOptions table={table} />

View File

@@ -0,0 +1,97 @@
---
title: Date Picker
description: A date picker component with range and presets.
base: base
component: true
---
<ComponentPreview styleName="base-nova" name="date-picker-demo" />
## Installation
The Date Picker is built using a composition of the `<Popover />` and the `<Calendar />` components.
See installation instructions for the [Popover](/docs/components/base/popover#installation) and the [Calendar](/docs/components/base/calendar#installation) components.
## Usage
```tsx showLineNumbers title="components/example-date-picker.tsx"
"use client"
import * as React from "react"
import { format } from "date-fns"
import { Calendar as CalendarIcon } from "lucide-react"
import { cn } from "@/lib/utils"
import { Button } from "@/components/ui/button"
import { Calendar } from "@/components/ui/calendar"
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover"
export function DatePickerDemo() {
const [date, setDate] = React.useState<Date>()
return (
<Popover>
<PopoverTrigger
render={
<Button
variant="outline"
data-empty={!date}
className="data-[empty=true]:text-muted-foreground justify-start text-left font-normal"
/>
}
>
<CalendarIcon />
{date ? format(date, "PPP") : <span>Pick a date</span>}
</PopoverTrigger>
<PopoverContent className="w-auto p-0">
<Calendar mode="single" selected={date} onSelect={setDate} />
</PopoverContent>
</Popover>
)
}
```
See the [React DayPicker](https://react-day-picker.js.org) documentation for more information.
## Examples
### Basic
A basic date picker component.
<ComponentPreview styleName="base-nova" name="date-picker-basic" />
### Range Picker
A date picker component for selecting a range of dates.
<ComponentPreview styleName="base-nova" name="date-picker-range" />
### Date of Birth
A date picker component for selecting a date of birth. This component includes a dropdown caption layout for date and month selection.
<ComponentPreview styleName="base-nova" name="date-picker-dob" />
### Input
A date picker component with an input field for selecting a date.
<ComponentPreview styleName="base-nova" name="date-picker-input" />
### Time Picker
A date picker component with a time input field for selecting a time.
<ComponentPreview styleName="base-nova" name="date-picker-time" />
### Natural Language Picker
This component uses the `chrono-node` library to parse natural language dates.
<ComponentPreview styleName="base-nova" name="date-picker-natural-language" />

View File

@@ -0,0 +1,116 @@
---
title: Dialog
description: A window overlaid on either the primary window or another dialog window, rendering the content underneath inert.
featured: true
base: base
component: true
links:
doc: https://base-ui.com/react/components/dialog
api: https://base-ui.com/react/components/dialog#api-reference
---
<ComponentPreview
styleName="base-nova"
name="dialog-demo"
description="A dialog for editing profile details."
/>
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">Command</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add dialog
```
</TabsContent>
<TabsContent value="manual">
<Steps className="mb-0 pt-2">
<Step>Install the following dependencies:</Step>
```bash
npm install @base-ui/react
```
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="dialog"
title="components/ui/dialog.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx showLineNumbers
import {
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog"
```
```tsx showLineNumbers
<Dialog>
<DialogTrigger>Open</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Are you absolutely sure?</DialogTitle>
<DialogDescription>
This action cannot be undone. This will permanently delete your account
and remove your data from our servers.
</DialogDescription>
</DialogHeader>
</DialogContent>
</Dialog>
```
## Examples
### Custom Close Button
Replace the default close control with your own button.
<ComponentPreview styleName="base-nova" name="dialog-close-button" />
### No Close Button
Use `showCloseButton={false}` to hide the close button.
<ComponentPreview styleName="base-nova" name="dialog-no-close-button" />
### Sticky Footer
Keep actions visible while the content scrolls.
<ComponentPreview styleName="base-nova" name="dialog-sticky-footer" />
### Scrollable Content
Long content can scroll while the header stays in view.
<ComponentPreview styleName="base-nova" name="dialog-scrollable-content" />
## API Reference
See the [Base UI](https://base-ui.com/react/components/dialog#api-reference) documentation for more information.

View File

@@ -1,12 +1,13 @@
---
title: Drawer
description: A drawer component for React.
base: base
component: true
links:
doc: https://vaul.emilkowal.ski/getting-started
---
<ComponentPreview name="drawer-demo" description="A drawer component." />
<ComponentPreview styleName="base-nova" name="drawer-demo" />
## About
@@ -17,7 +18,7 @@ Drawer is built on top of [Vaul](https://github.com/emilkowalski/vaul) by [emilk
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">CLI</TabsTrigger>
<TabsTrigger value="cli">Command</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
@@ -30,7 +31,7 @@ npx shadcn@latest add drawer
<TabsContent value="manual">
<Steps>
<Steps className="mb-0 pt-2">
<Step>Install the following dependencies:</Step>
@@ -40,7 +41,11 @@ npm install vaul
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource name="drawer" title="components/ui/drawer.tsx" />
<ComponentSource
name="drawer"
title="components/ui/drawer.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
@@ -85,8 +90,24 @@ import {
## Examples
### Scrollable Content
Keep actions visible while the content scrolls.
<ComponentPreview styleName="base-nova" name="drawer-scrollable-content" />
### Sides
Use the `direction` prop to set the side of the drawer. Available options are `top`, `right`, `bottom`, and `left`.
<ComponentPreview styleName="base-nova" name="drawer-sides" />
### Responsive Dialog
You can combine the `Dialog` and `Drawer` components to create a responsive dialog. This renders a `Dialog` component on desktop and a `Drawer` on mobile.
<ComponentPreview name="drawer-dialog" />
<ComponentPreview styleName="base-nova" name="drawer-dialog" />
## API Reference
See the [Vaul documentation](https://vaul.emilkowal.ski/components/drawer) for the full API reference.

View File

@@ -0,0 +1,165 @@
---
title: Dropdown Menu
description: Displays a menu to the user — such as a set of actions or functions — triggered by a button.
featured: true
base: base
component: true
links:
doc: https://base-ui.com/react/components/dropdown-menu
api: https://base-ui.com/react/components/dropdown-menu#api-reference
---
<ComponentPreview
styleName="base-nova"
name="dropdown-menu-demo"
description="A dropdown menu with icons, shortcuts and sub menu items."
/>
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">Command</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add dropdown-menu
```
</TabsContent>
<TabsContent value="manual">
<Steps className="mb-0 pt-2">
<Step>Install the following dependencies:</Step>
```bash
npm install @base-ui/react
```
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="dropdown-menu"
title="components/ui/dropdown-menu.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx showLineNumbers
import { Button } from "@/components/ui/button"
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuGroup,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"
```
```tsx showLineNumbers
<DropdownMenu>
<DropdownMenuTrigger render={<Button variant="outline" />}>
Open
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuGroup>
<DropdownMenuLabel>My Account</DropdownMenuLabel>
<DropdownMenuItem>Profile</DropdownMenuItem>
<DropdownMenuItem>Billing</DropdownMenuItem>
<DropdownMenuSeparator />
</DropdownMenuGroup>
<DropdownMenuGroup>
<DropdownMenuItem>Team</DropdownMenuItem>
<DropdownMenuItem>Subscription</DropdownMenuItem>
</DropdownMenuGroup>
</DropdownMenuContent>
</DropdownMenu>
```
## Examples
### Basic
A basic dropdown menu with labels and separators.
<ComponentPreview styleName="base-nova" name="dropdown-menu-basic" />
### Submenu
Use `DropdownMenuSub` to nest secondary actions.
<ComponentPreview styleName="base-nova" name="dropdown-menu-submenu" />
### Shortcuts
Add `DropdownMenuShortcut` to show keyboard hints.
<ComponentPreview styleName="base-nova" name="dropdown-menu-shortcuts" />
### Icons
Combine icons with labels for quick scanning.
<ComponentPreview styleName="base-nova" name="dropdown-menu-icons" />
### Checkboxes
Use `DropdownMenuCheckboxItem` for toggles.
<ComponentPreview styleName="base-nova" name="dropdown-menu-checkboxes" />
### Checkboxes Icons
Add icons to checkbox items.
<ComponentPreview styleName="base-nova" name="dropdown-menu-checkboxes-icons" />
### Radio Group
Use `DropdownMenuRadioGroup` for exclusive choices.
<ComponentPreview styleName="base-nova" name="dropdown-menu-radio-group" />
### Radio Icons
Show radio options with icons.
<ComponentPreview styleName="base-nova" name="dropdown-menu-radio-icons" />
### Destructive
Use `variant="destructive"` for irreversible actions.
<ComponentPreview styleName="base-nova" name="dropdown-menu-destructive" />
### Avatar
An account switcher dropdown triggered by an avatar.
<ComponentPreview styleName="base-nova" name="dropdown-menu-avatar" />
### Complex
A richer example combining groups, icons, and submenus.
<ComponentPreview styleName="base-nova" name="dropdown-menu-complex" />
## API Reference
See the [Base UI documentation](https://base-ui.com/react/components/dropdown-menu) for the full API reference.

View File

@@ -1,17 +1,22 @@
---
title: Empty
description: Use the Empty component to display an empty state.
base: base
component: true
---
<ComponentPreview name="empty-demo" className="[&_.preview]:p-0" />
<ComponentPreview
styleName="base-nova"
name="empty-demo"
previewClassName="h-96 p-0"
/>
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">CLI</TabsTrigger>
<TabsTrigger value="cli">Command</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
@@ -24,11 +29,15 @@ npx shadcn@latest add empty
<TabsContent value="manual">
<Steps>
<Steps className="mb-0 pt-2">
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource name="empty" title="components/ui/empty.tsx" />
<ComponentSource
name="empty"
title="components/ui/empty.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
@@ -73,33 +82,50 @@ import {
Use the `border` utility class to create an outline empty state.
<ComponentPreview
styleName="base-nova"
name="empty-outline"
className="[&_.preview]:p-6 md:[&_.preview]:p-10"
previewClassName="h-96 p-6 md:p-10"
/>
### Background
Use the `bg-*` and `bg-gradient-*` utilities to add a background to the empty state.
<ComponentPreview name="empty-background" className="[&_.preview]:p-0" />
<ComponentPreview
styleName="base-nova"
name="empty-background"
previewClassName="h-96 p-0"
/>
### Avatar
Use the `EmptyMedia` component to display an avatar in the empty state.
<ComponentPreview name="empty-avatar" className="[&_.preview]:p-0" />
<ComponentPreview
styleName="base-nova"
name="empty-avatar"
previewClassName="h-96 p-0"
/>
### Avatar Group
Use the `EmptyMedia` component to display an avatar group in the empty state.
<ComponentPreview name="empty-avatar-group" className="[&_.preview]:p-0" />
<ComponentPreview
styleName="base-nova"
name="empty-avatar-group"
previewClassName="h-96 p-0"
/>
### InputGroup
You can add an `InputGroup` component to the `EmptyContent` component.
<ComponentPreview name="empty-input-group" className="[&_.preview]:p-0" />
<ComponentPreview
styleName="base-nova"
name="empty-input-group"
previewClassName="h-96 p-0"
/>
## API Reference

View File

@@ -1,12 +1,14 @@
---
title: Field
description: Combine labels, controls, and help text to compose accessible form fields and grouped inputs.
base: base
component: true
---
<ComponentPreview
styleName="base-nova"
name="field-demo"
className="[&_.preview]:h-[800px] [&_.preview]:p-6 md:[&_.preview]:h-[850px]"
previewClassName="h-[800px] p-6 md:h-[850px]"
/>
## Installation
@@ -14,7 +16,7 @@ component: true
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">CLI</TabsTrigger>
<TabsTrigger value="cli">Command</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
@@ -27,11 +29,15 @@ npx shadcn@latest add field
<TabsContent value="manual">
<Steps>
<Steps className="mb-0 pt-2">
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource name="field" title="components/ui/field.tsx" />
<ComponentSource
name="field"
title="components/ui/field.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
@@ -106,47 +112,55 @@ See the [Form](/docs/forms) documentation for building forms with the `Field` co
### Input
<ComponentPreview name="field-input" className="!mb-4 [&_.preview]:p-6" />
<ComponentPreview styleName="base-nova" name="field-input" />
### Textarea
<ComponentPreview name="field-textarea" className="!mb-4 [&_.preview]:p-6" />
<ComponentPreview styleName="base-nova" name="field-textarea" />
### Select
<ComponentPreview name="field-select" className="!mb-4 [&_.preview]:p-6" />
<ComponentPreview styleName="base-nova" name="field-select" />
### Slider
<ComponentPreview name="field-slider" className="!mb-4 [&_.preview]:p-6" />
<ComponentPreview styleName="base-nova" name="field-slider" />
### Fieldset
<ComponentPreview name="field-fieldset" className="!mb-4 [&_.preview]:p-6" />
<ComponentPreview styleName="base-nova" name="field-fieldset" />
### Checkbox
<ComponentPreview name="field-checkbox" className="!mb-4 [&_.preview]:p-6" />
<ComponentPreview
styleName="base-nova"
name="field-checkbox"
previewClassName="h-[32rem]"
/>
### Radio
<ComponentPreview name="field-radio" className="!mb-4 [&_.preview]:p-6" />
<ComponentPreview styleName="base-nova" name="field-radio" />
### Switch
<ComponentPreview name="field-switch" className="!mb-4 [&_.preview]:p-6" />
<ComponentPreview styleName="base-nova" name="field-switch" />
### Choice Card
Wrap `Field` components inside `FieldLabel` to create selectable field groups. This works with `RadioItem`, `Checkbox` and `Switch` components.
<ComponentPreview name="field-choice-card" className="!mb-4 [&_.preview]:p-6" />
<ComponentPreview styleName="base-nova" name="field-choice-card" />
### Field Group
Stack `Field` components with `FieldGroup`. Add `FieldSeparator` to divide them.
<ComponentPreview name="field-group" className="!mb-4 [&_.preview]:p-6" />
<ComponentPreview
styleName="base-nova"
name="field-group"
previewClassName="h-96"
/>
## Responsive Layout
@@ -155,8 +169,9 @@ Stack `Field` components with `FieldGroup`. Add `FieldSeparator` to divide them.
- **Responsive fields:** Set `orientation="responsive"` for automatic column layouts inside container-aware parents. Apply `@container/field-group` classes on `FieldGroup` to switch orientations at specific breakpoints.
<ComponentPreview
styleName="base-nova"
name="field-responsive"
className="!mb-4 [&_.preview]:h-[650px] [&_.preview]:p-6 [&_.preview]:md:h-[500px] [&_.preview]:md:p-10"
previewClassName="h-[650px] p-6 md:h-[500px] md:p-10"
/>
## Validation and Errors

View File

@@ -0,0 +1,125 @@
---
title: Hover Card
description: For sighted users to preview content available behind a link.
base: base
component: true
links:
doc: https://base-ui.com/react/components/hover-card
api: https://base-ui.com/react/components/hover-card#api-reference
---
<ComponentPreview
styleName="base-nova"
name="hover-card-demo"
previewClassName="h-80"
/>
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">Command</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add hover-card
```
</TabsContent>
<TabsContent value="manual">
<Steps className="mb-0 pt-2">
<Step>Install the following dependencies:</Step>
```bash
npm install @base-ui/react
```
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="hover-card"
title="components/ui/hover-card.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx showLineNumbers
import {
HoverCard,
HoverCardContent,
HoverCardTrigger,
} from "@/components/ui/hover-card"
```
```tsx showLineNumbers
<HoverCard>
<HoverCardTrigger>Hover</HoverCardTrigger>
<HoverCardContent>
The React Framework created and maintained by @vercel.
</HoverCardContent>
</HoverCard>
```
## Trigger Delays
Use `delay` and `closeDelay` on the trigger to control when the card opens and
closes.
```tsx showLineNumbers
<HoverCard>
<HoverCardTrigger delay={100} closeDelay={200}>
Hover
</HoverCardTrigger>
<HoverCardContent>Content</HoverCardContent>
</HoverCard>
```
## Positioning
Use the `side` and `align` props on `HoverCardContent` to control placement.
```tsx showLineNumbers
<HoverCard>
<HoverCardTrigger>Hover</HoverCardTrigger>
<HoverCardContent side="top" align="start">
Content
</HoverCardContent>
</HoverCard>
```
## Examples
### Basic
<ComponentPreview
styleName="base-nova"
name="hover-card-demo"
previewClassName="h-80"
/>
### Sides
<ComponentPreview
styleName="base-nova"
name="hover-card-sides"
previewClassName="h-[22rem]"
/>
## API Reference
See the [Base UI](https://base-ui.com/react/components/hover-card#api-reference) documentation for more information.

View File

@@ -0,0 +1,295 @@
---
title: Input Group
description: Add addons, buttons, and helper content to inputs.
base: base
component: true
---
import { IconInfoCircle } from "@tabler/icons-react"
<ComponentPreview
styleName="base-nova"
name="input-group-demo"
previewClassName="h-[26rem]"
/>
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">Command</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add input-group
```
</TabsContent>
<TabsContent value="manual">
<Steps className="mb-0 pt-2">
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="input-group"
title="components/ui/input-group.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx showLineNumbers
import {
InputGroup,
InputGroupAddon,
InputGroupButton,
InputGroupInput,
InputGroupText,
InputGroupTextarea,
} from "@/components/ui/input-group"
```
```tsx showLineNumbers
<InputGroup>
<InputGroupInput placeholder="Search..." />
<InputGroupAddon>
<SearchIcon />
</InputGroupAddon>
</InputGroup>
```
## Align
Use the `align` prop on `InputGroupAddon` to position the addon relative to the input.
<Callout>
For proper focus management, `InputGroupAddon` should always be placed after
`InputGroupInput` or `InputGroupTextarea` in the DOM. Use the `align` prop to
visually position the addon.
</Callout>
### inline-start
Use `align="inline-start"` to position the addon at the start of the input. This is the default.
<ComponentPreview
styleName="base-nova"
name="input-group-inline-start"
previewClassName="h-48"
/>
### inline-end
Use `align="inline-end"` to position the addon at the end of the input.
<ComponentPreview
styleName="base-nova"
name="input-group-inline-end"
previewClassName="h-48"
/>
### block-start
Use `align="block-start"` to position the addon above the input.
<ComponentPreview
styleName="base-nova"
name="input-group-block-start"
previewClassName="h-96"
/>
### block-end
Use `align="block-end"` to position the addon below the input.
<ComponentPreview
styleName="base-nova"
name="input-group-block-end"
previewClassName="h-[26rem]"
/>
## Examples
### Icon
<ComponentPreview
styleName="base-nova"
name="input-group-icon"
previewClassName="h-80"
/>
### Text
<ComponentPreview
styleName="base-nova"
name="input-group-text"
previewClassName="h-80"
/>
### Button
<ComponentPreview
styleName="base-nova"
name="input-group-button"
previewClassName="h-72"
/>
### Kbd
<ComponentPreview
styleName="base-nova"
name="input-group-kbd"
previewClassName="h-40"
/>
### Dropdown
<ComponentPreview
styleName="base-nova"
name="input-group-dropdown"
previewClassName="h-56"
/>
### Spinner
<ComponentPreview
styleName="base-nova"
name="input-group-spinner"
previewClassName="h-80"
/>
### Textarea
<ComponentPreview
styleName="base-nova"
name="input-group-textarea"
previewClassName="h-96"
/>
### Custom Input
Add the `data-slot="input-group-control"` attribute to your custom input for automatic focus state handling.
Here's an example of a custom resizable textarea from a third-party library.
<ComponentPreview
styleName="base-nova"
name="input-group-custom"
previewClassName="h-56"
/>
## API Reference
### InputGroup
The main component that wraps inputs and addons.
| Prop | Type | Default |
| ----------- | -------- | ------- |
| `className` | `string` | |
```tsx
<InputGroup>
<InputGroupInput />
<InputGroupAddon />
</InputGroup>
```
### InputGroupAddon
Displays icons, text, buttons, or other content alongside inputs.
<Callout icon={<IconInfoCircle />} title="Focus Navigation">
For proper focus navigation, the `InputGroupAddon` component should be placed
after the input. Set the `align` prop to position the addon.
</Callout>
| Prop | Type | Default |
| ----------- | ---------------------------------------------------------------- | ---------------- |
| `align` | `"inline-start" \| "inline-end" \| "block-start" \| "block-end"` | `"inline-start"` |
| `className` | `string` | |
```tsx
<InputGroupAddon align="inline-end">
<SearchIcon />
</InputGroupAddon>
```
**For `<InputGroupInput />`, use the `inline-start` or `inline-end` alignment. For `<InputGroupTextarea />`, use the `block-start` or `block-end` alignment.**
The `InputGroupAddon` component can have multiple `InputGroupButton` components and icons.
```tsx
<InputGroupAddon>
<InputGroupButton>Button</InputGroupButton>
<InputGroupButton>Button</InputGroupButton>
</InputGroupAddon>
```
### InputGroupButton
Displays buttons within input groups.
| Prop | Type | Default |
| ----------- | ----------------------------------------------------------------------------- | --------- |
| `size` | `"xs" \| "icon-xs" \| "sm" \| "icon-sm"` | `"xs"` |
| `variant` | `"default" \| "destructive" \| "outline" \| "secondary" \| "ghost" \| "link"` | `"ghost"` |
| `className` | `string` | |
```tsx
<InputGroupButton>Button</InputGroupButton>
<InputGroupButton size="icon-xs" aria-label="Copy">
<CopyIcon />
</InputGroupButton>
```
### InputGroupInput
Replacement for `<Input />` when building input groups. This component has the input group styles pre-applied and uses the unified `data-slot="input-group-control"` for focus state handling.
| Prop | Type | Default |
| ----------- | -------- | ------- |
| `className` | `string` | |
All other props are passed through to the underlying `<Input />` component.
```tsx
<InputGroup>
<InputGroupInput placeholder="Enter text..." />
<InputGroupAddon>
<SearchIcon />
</InputGroupAddon>
</InputGroup>
```
### InputGroupTextarea
Replacement for `<Textarea />` when building input groups. This component has the textarea group styles pre-applied and uses the unified `data-slot="input-group-control"` for focus state handling.
| Prop | Type | Default |
| ----------- | -------- | ------- |
| `className` | `string` | |
All other props are passed through to the underlying `<Textarea />` component.
```tsx
<InputGroup>
<InputGroupTextarea placeholder="Enter message..." />
<InputGroupAddon align="block-end">
<InputGroupButton>Send</InputGroupButton>
</InputGroupAddon>
</InputGroup>
```

View File

@@ -0,0 +1,147 @@
---
title: Input OTP
description: Accessible one-time password component with copy paste functionality.
base: base
component: true
links:
doc: https://input-otp.rodz.dev
---
<ComponentPreview styleName="base-nova" name="input-otp-demo" />
## About
Input OTP is built on top of [input-otp](https://github.com/guilhermerodz/input-otp) by [@guilherme_rodz](https://twitter.com/guilherme_rodz).
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">Command</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add input-otp
```
</TabsContent>
<TabsContent value="manual">
<Steps className="mb-0 pt-2">
<Step>Install the following dependencies:</Step>
```bash
npm install input-otp
```
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="input-otp"
title="components/ui/input-otp.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx showLineNumbers
import {
InputOTP,
InputOTPGroup,
InputOTPSeparator,
InputOTPSlot,
} from "@/components/ui/input-otp"
```
```tsx showLineNumbers
<InputOTP maxLength={6}>
<InputOTPGroup>
<InputOTPSlot index={0} />
<InputOTPSlot index={1} />
<InputOTPSlot index={2} />
</InputOTPGroup>
<InputOTPSeparator />
<InputOTPGroup>
<InputOTPSlot index={3} />
<InputOTPSlot index={4} />
<InputOTPSlot index={5} />
</InputOTPGroup>
</InputOTP>
```
## Pattern
Use the `pattern` prop to define a custom pattern for the OTP input.
```tsx showLineNumbers {1,5}
import { REGEXP_ONLY_DIGITS_AND_CHARS } from "input-otp"
;<InputOTP maxLength={6} pattern={REGEXP_ONLY_DIGITS_AND_CHARS}>
...
</InputOTP>
```
<ComponentPreview styleName="base-nova" name="input-otp-pattern" />
## Examples
### Separator
Use the `<InputOTPSeparator />` component to add a separator between input groups.
<ComponentPreview styleName="base-nova" name="input-otp-separator" />
### Disabled
Use the `disabled` prop to disable the input.
<ComponentPreview styleName="base-nova" name="input-otp-disabled" />
### Controlled
Use the `value` and `onChange` props to control the input value.
<ComponentPreview styleName="base-nova" name="input-otp-controlled" />
### Invalid
Use `aria-invalid` on the slots to show an error state.
<ComponentPreview styleName="base-nova" name="input-otp-invalid" />
### Four Digits
A common pattern for PIN codes. This uses the `pattern={REGEXP_ONLY_DIGITS}` prop.
<ComponentPreview styleName="base-nova" name="input-otp-four-digits" />
### Alphanumeric
Use `REGEXP_ONLY_DIGITS_AND_CHARS` to accept both letters and numbers.
<ComponentPreview styleName="base-nova" name="input-otp-alphanumeric" />
### Form
<ComponentPreview
styleName="base-nova"
name="input-otp-form"
previewClassName="h-[30rem]"
/>
## API Reference
See the [input-otp](https://input-otp.rodz.dev) documentation for more information.

View File

@@ -0,0 +1,190 @@
---
title: Input
description: A text input component for forms and user data entry with built-in styling and accessibility features.
base: base
component: true
---
<ComponentPreview
styleName="base-nova"
name="input-demo"
previewClassName="*:max-w-xs"
/>
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">Command</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add input
```
</TabsContent>
<TabsContent value="manual">
<Steps className="mb-0 pt-2">
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="input"
title="components/ui/input.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx
import { Input } from "@/components/ui/input"
```
```tsx
<Input />
```
## Examples
### Basic
<ComponentPreview
styleName="base-nova"
name="input-basic"
previewClassName="*:max-w-xs"
/>
### Field
Use `Field`, `FieldLabel`, and `FieldDescription` to create an input with a
label and description.
<ComponentPreview
styleName="base-nova"
name="input-field"
previewClassName="*:max-w-xs"
/>
### Field Group
Use `FieldGroup` to show multiple `Field` blocks and to build forms.
<ComponentPreview
styleName="base-nova"
name="input-fieldgroup"
previewClassName="*:max-w-xs"
/>
### Disabled
Use the `disabled` prop to disable the input. To style the disabled state, add the `data-disabled` attribute to the `Field` component.
<ComponentPreview
styleName="base-nova"
name="input-disabled"
previewClassName="*:max-w-xs"
/>
### Invalid
Use the `aria-invalid` prop to mark the input as invalid. To style the invalid state, add the `data-invalid` attribute to the `Field` component.
<ComponentPreview
styleName="base-nova"
name="input-invalid"
previewClassName="*:max-w-xs"
/>
### File
Use the `type="file"` prop to create a file input.
<ComponentPreview
styleName="base-nova"
name="input-file"
previewClassName="*:max-w-xs"
/>
### Inline
Use `Field` with `orientation="horizontal"` to create an inline input.
Pair with `Button` to create a search input with a button.
<ComponentPreview
styleName="base-nova"
name="input-inline"
previewClassName="*:max-w-xs"
/>
### Grid
Use a grid layout to place multiple inputs side by side.
<ComponentPreview
styleName="base-nova"
name="input-grid"
previewClassName="p-6"
/>
### Required
Use the `required` attribute to indicate required inputs.
<ComponentPreview
styleName="base-nova"
name="input-required"
previewClassName="*:max-w-xs"
/>
### Badge
Use `Badge` in the label to highlight a recommended field.
<ComponentPreview
styleName="base-nova"
name="input-badge"
previewClassName="*:max-w-xs"
/>
### Input Group
To add icons, text, or buttons inside an input, use the `InputGroup` component. See the [Input Group](/docs/components/input-group) component for more examples.
<ComponentPreview
styleName="base-nova"
name="input-input-group"
previewClassName="*:max-w-xs"
/>
### Button Group
To add buttons to an input, use the `ButtonGroup` component. See the [Button Group](/docs/components/button-group) component for more examples.
<ComponentPreview
styleName="base-nova"
name="input-button-group"
previewClassName="*:max-w-xs"
/>
### Form
A full form example with multiple inputs, a select, and a button.
<ComponentPreview
styleName="base-nova"
name="input-form"
previewClassName="h-[32rem]"
/>

View File

@@ -0,0 +1,276 @@
---
title: Item
description: A versatile component for displaying content with media, title, description, and actions.
base: base
component: true
---
<ComponentPreview styleName="base-nova" name="item-demo" />
The `Item` component is a straightforward flex container that can house nearly any type of content. Use it to display a title, description, and actions. Group it with the `ItemGroup` component to create a list of items.
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">Command</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add item
```
</TabsContent>
<TabsContent value="manual">
<Steps className="mb-0 pt-2">
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="item"
title="components/ui/item.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx showLineNumbers
import {
Item,
ItemActions,
ItemContent,
ItemDescription,
ItemMedia,
ItemTitle,
} from "@/components/ui/item"
```
```tsx showLineNumbers
<Item>
<ItemMedia variant="icon">
<Icon />
</ItemMedia>
<ItemContent>
<ItemTitle>Title</ItemTitle>
<ItemDescription>Description</ItemDescription>
</ItemContent>
<ItemActions>
<Button>Action</Button>
</ItemActions>
</Item>
```
## Item vs Field
Use `Field` if you need to display a form input such as a checkbox, input, radio, or select.
If you only need to display content such as a title, description, and actions, use `Item`.
## Variant
Use the `variant` prop to change the visual style of the item.
<ComponentPreview
styleName="base-nova"
name="item-variant"
previewClassName="h-96"
/>
## Size
Use the `size` prop to change the size of the item. Available sizes are `default`, `sm`, and `xs`.
<ComponentPreview
styleName="base-nova"
name="item-size"
previewClassName="h-96"
/>
## Examples
### Icon
Use `ItemMedia` with `variant="icon"` to display an icon.
<ComponentPreview styleName="base-nova" name="item-icon" />
### Avatar
You can use `ItemMedia` with `variant="avatar"` to display an avatar.
<ComponentPreview styleName="base-nova" name="item-avatar" />
### Image
Use `ItemMedia` with `variant="image"` to display an image.
<ComponentPreview styleName="base-nova" name="item-image" />
### Group
Use `ItemGroup` to group related items together.
<ComponentPreview
styleName="base-nova"
name="item-group"
previewClassName="h-96"
/>
### Header
Use `ItemHeader` to add a header above the item content.
<ComponentPreview
styleName="base-nova"
name="item-header"
previewClassName="h-96"
/>
### Link
Use the `render` prop to render the item as a link. The hover and focus states will be applied to the anchor element.
<ComponentPreview styleName="base-nova" name="item-link" />
```tsx showLineNumbers
<Item render={<a href="/dashboard" />}>
<ItemMedia variant="icon">
<HomeIcon />
</ItemMedia>
<ItemContent>
<ItemTitle>Dashboard</ItemTitle>
<ItemDescription>Overview of your account and activity.</ItemDescription>
</ItemContent>
</Item>
```
### Dropdown
<ComponentPreview styleName="base-nova" name="item-dropdown" />
## API Reference
### Item
The main component for displaying content with media, title, description, and actions.
| Prop | Type | Default |
| --------- | ----------------------------------- | ----------- |
| `variant` | `"default" \| "outline" \| "muted"` | `"default"` |
| `size` | `"default" \| "sm" \| "xs"` | `"default"` |
| `render` | `React.ReactElement` | |
### ItemGroup
A container that groups related items together with consistent styling.
```tsx
<ItemGroup>
<Item />
<Item />
</ItemGroup>
```
### ItemSeparator
A separator between items in a group.
```tsx
<ItemGroup>
<Item />
<ItemSeparator />
<Item />
</ItemGroup>
```
### ItemMedia
Use `ItemMedia` to display media content such as icons, images, or avatars.
| Prop | Type | Default |
| --------- | -------------------------------- | ----------- |
| `variant` | `"default" \| "icon" \| "image"` | `"default"` |
```tsx
<ItemMedia variant="icon">
<Icon />
</ItemMedia>
```
```tsx
<ItemMedia variant="image">
<img src="..." alt="..." />
</ItemMedia>
```
### ItemContent
Wraps the title and description of the item.
```tsx
<ItemContent>
<ItemTitle>Title</ItemTitle>
<ItemDescription>Description</ItemDescription>
</ItemContent>
```
### ItemTitle
Displays the title of the item.
```tsx
<ItemTitle>Item Title</ItemTitle>
```
### ItemDescription
Displays the description of the item.
```tsx
<ItemDescription>Item description</ItemDescription>
```
### ItemActions
Container for action buttons or other interactive elements.
```tsx
<ItemActions>
<Button>Action</Button>
</ItemActions>
```
### ItemHeader
Displays a header above the item content.
```tsx
<Item>
<ItemHeader>Header</ItemHeader>
<ItemContent>...</ItemContent>
</Item>
```
### ItemFooter
Displays a footer below the item content.
```tsx
<Item>
<ItemContent>...</ItemContent>
<ItemFooter>Footer</ItemFooter>
</Item>
```

View File

@@ -1,17 +1,18 @@
---
title: Kbd
description: Used to display textual user input from keyboard.
base: base
component: true
---
<ComponentPreview name="kbd-demo" />
<ComponentPreview styleName="base-nova" name="kbd-demo" />
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">CLI</TabsTrigger>
<TabsTrigger value="cli">Command</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
@@ -24,11 +25,15 @@ npx shadcn@latest add kbd
<TabsContent value="manual">
<Steps>
<Steps className="mb-0 pt-2">
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource name="kbd" title="components/ui/kbd.tsx" />
<ComponentSource
name="kbd"
title="components/ui/kbd.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
@@ -54,25 +59,25 @@ import { Kbd } from "@/components/ui/kbd"
Use the `KbdGroup` component to group keyboard keys together.
<ComponentPreview name="kbd-group" />
<ComponentPreview styleName="base-nova" name="kbd-group" />
### Button
Use the `Kbd` component inside a `Button` component to display a keyboard key inside a button.
<ComponentPreview name="kbd-button" />
<ComponentPreview styleName="base-nova" name="kbd-button" />
### Tooltip
You can use the `Kbd` component inside a `Tooltip` component to display a tooltip with a keyboard key.
<ComponentPreview name="kbd-tooltip" />
<ComponentPreview styleName="base-nova" name="kbd-tooltip" />
### Input Group
You can use the `Kbd` component inside a `InputGroupAddon` component to display a keyboard key inside an input group.
<ComponentPreview name="kbd-input-group" />
<ComponentPreview styleName="base-nova" name="kbd-input-group" />
## API Reference

View File

@@ -0,0 +1,90 @@
---
title: Label
description: Renders an accessible label associated with controls.
base: base
component: true
links:
doc: https://base-ui.com/react/components/label
api: https://base-ui.com/react/components/label#api-reference
---
<ComponentPreview styleName="base-nova" name="label-demo" />
<Callout>
For form fields, use the [Field](/docs/components/base/field) component which
includes built-in label, description, and error handling.
</Callout>
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">Command</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add label
```
</TabsContent>
<TabsContent value="manual">
<Steps className="mb-0 pt-2">
<Step>Install the following dependencies:</Step>
```bash
npm install @base-ui/react
```
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="label"
title="components/ui/label.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx
import { Label } from "@/components/ui/label"
```
```tsx
<Label htmlFor="email">Your email address</Label>
```
## Label in Field
For form fields, use the [Field](/docs/components/base/field) component which
includes built-in `FieldLabel`, `FieldDescription`, and `FieldError` components.
```tsx
<Field>
<FieldLabel htmlFor="email">Your email address</FieldLabel>
<Input id="email" />
</Field>
```
<ComponentPreview
styleName="base-nova"
name="field-demo"
previewClassName="h-[44rem]"
/>
## API Reference
See the [Base UI Label](https://base-ui.com/react/components/label#api-reference) documentation for more information.

View File

@@ -0,0 +1,117 @@
---
title: Menubar
description: A visually persistent menu common in desktop applications that provides quick access to a consistent set of commands.
base: base
component: true
links:
doc: https://base-ui.com/react/components/menubar
api: https://base-ui.com/react/components/menubar#api-reference
---
<ComponentPreview styleName="base-nova" name="menubar-demo" />
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">Command</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add menubar
```
</TabsContent>
<TabsContent value="manual">
<Steps className="mb-0 pt-2">
<Step>Install the following dependencies:</Step>
```bash
npm install @base-ui/react
```
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="menubar"
title="components/ui/menubar.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx showLineNumbers
import {
Menubar,
MenubarContent,
MenubarGroup,
MenubarItem,
MenubarMenu,
MenubarSeparator,
MenubarShortcut,
MenubarTrigger,
} from "@/components/ui/menubar"
```
```tsx showLineNumbers
<Menubar>
<MenubarMenu>
<MenubarTrigger>File</MenubarTrigger>
<MenubarContent>
<MenubarGroup>
<MenubarItem>
New Tab <MenubarShortcut>⌘T</MenubarShortcut>
</MenubarItem>
<MenubarItem>New Window</MenubarItem>
</MenubarGroup>
<MenubarSeparator />
<MenubarGroup>
<MenubarItem>Share</MenubarItem>
<MenubarItem>Print</MenubarItem>
</MenubarGroup>
</MenubarContent>
</MenubarMenu>
</Menubar>
```
## Examples
### Checkbox
Use `MenubarCheckboxItem` for toggleable options.
<ComponentPreview styleName="base-nova" name="menubar-checkbox" />
### Radio
Use `MenubarRadioGroup` and `MenubarRadioItem` for single-select options.
<ComponentPreview styleName="base-nova" name="menubar-radio" />
### Submenu
Use `MenubarSub`, `MenubarSubTrigger`, and `MenubarSubContent` for nested menus.
<ComponentPreview styleName="base-nova" name="menubar-submenu" />
### With Icons
<ComponentPreview styleName="base-nova" name="menubar-icons" />
## API Reference
See the [Base UI Menubar](https://base-ui.com/react/components/menubar#api-reference) documentation.

View File

@@ -0,0 +1,64 @@
{
"title": "Base UI",
"pages": [
"accordion",
"alert",
"alert-dialog",
"aspect-ratio",
"avatar",
"badge",
"breadcrumb",
"button",
"button-group",
"calendar",
"card",
"carousel",
"chart",
"checkbox",
"collapsible",
"combobox",
"command",
"context-menu",
"data-table",
"date-picker",
"dialog",
"drawer",
"dropdown-menu",
"empty",
"field",
"form",
"hover-card",
"input",
"input-group",
"input-otp",
"item",
"kbd",
"label",
"menubar",
"native-select",
"navigation-menu",
"pagination",
"popover",
"progress",
"radio-group",
"resizable",
"scroll-area",
"select",
"separator",
"sheet",
"sidebar",
"skeleton",
"slider",
"sonner",
"spinner",
"switch",
"table",
"tabs",
"textarea",
"toast",
"toggle",
"toggle-group",
"tooltip",
"typography"
]
}

View File

@@ -0,0 +1,134 @@
---
title: Native Select
description: A styled native HTML select element with consistent design system integration.
base: base
component: true
---
import { InfoIcon } from "lucide-react"
<Callout variant="info" icon={<InfoIcon className="!translate-y-[3px]" />}>
For a styled select component, see the [Select](/docs/components/select)
component.
</Callout>
<ComponentPreview styleName="base-nova" name="native-select-demo" />
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">Command</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add native-select
```
</TabsContent>
<TabsContent value="manual">
<Steps className="mb-0 pt-2">
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="native-select"
title="components/ui/native-select.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx showLineNumbers
import {
NativeSelect,
NativeSelectOptGroup,
NativeSelectOption,
} from "@/components/ui/native-select"
```
```tsx showLineNumbers
<NativeSelect>
<NativeSelectOption value="">Select a fruit</NativeSelectOption>
<NativeSelectOption value="apple">Apple</NativeSelectOption>
<NativeSelectOption value="banana">Banana</NativeSelectOption>
<NativeSelectOption value="blueberry">Blueberry</NativeSelectOption>
<NativeSelectOption value="pineapple">Pineapple</NativeSelectOption>
</NativeSelect>
```
## Examples
### Groups
Use `NativeSelectOptGroup` to organize options into categories.
<ComponentPreview styleName="base-nova" name="native-select-groups" />
### Disabled
Add the `disabled` prop to the `NativeSelect` component to disable the select.
<ComponentPreview styleName="base-nova" name="native-select-disabled" />
### Invalid
Use `aria-invalid` to show validation errors and the `data-invalid` attribute to the `Field` component for styling.
<ComponentPreview styleName="base-nova" name="native-select-invalid" />
## Native Select vs Select
- Use `NativeSelect` for native browser behavior, better performance, or mobile-optimized dropdowns.
- Use `Select` for custom styling, animations, or complex interactions.
## API Reference
### NativeSelect
The main select component that wraps the native HTML select element.
```tsx
<NativeSelect>
<NativeSelectOption value="option1">Option 1</NativeSelectOption>
<NativeSelectOption value="option2">Option 2</NativeSelectOption>
</NativeSelect>
```
### NativeSelectOption
Represents an individual option within the select.
| Prop | Type | Default |
| ---------- | --------- | ------- |
| `value` | `string` | |
| `disabled` | `boolean` | `false` |
### NativeSelectOptGroup
Groups related options together for better organization.
| Prop | Type | Default |
| ---------- | --------- | ------- |
| `label` | `string` | |
| `disabled` | `boolean` | `false` |
```tsx
<NativeSelectOptGroup label="Fruits">
<NativeSelectOption value="apple">Apple</NativeSelectOption>
<NativeSelectOption value="banana">Banana</NativeSelectOption>
</NativeSelectOptGroup>
```

View File

@@ -0,0 +1,113 @@
---
title: Navigation Menu
description: A collection of links for navigating websites.
base: base
component: true
links:
doc: https://base-ui.com/react/components/navigation-menu
api: https://base-ui.com/react/components/navigation-menu#api-reference
---
<ComponentPreview
styleName="base-nova"
name="navigation-menu-demo"
previewClassName="h-96"
/>
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">Command</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add navigation-menu
```
</TabsContent>
<TabsContent value="manual">
<Steps className="mb-0 pt-2">
<Step>Install the following dependencies:</Step>
```bash
npm install @base-ui-components/react
```
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="navigation-menu"
title="components/ui/navigation-menu.tsx"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx showLineNumbers
import {
NavigationMenu,
NavigationMenuContent,
NavigationMenuItem,
NavigationMenuLink,
NavigationMenuList,
NavigationMenuTrigger,
} from "@/components/ui/navigation-menu"
```
```tsx showLineNumbers
<NavigationMenu>
<NavigationMenuList>
<NavigationMenuItem>
<NavigationMenuTrigger>Item One</NavigationMenuTrigger>
<NavigationMenuContent>
<NavigationMenuLink>Link</NavigationMenuLink>
</NavigationMenuContent>
</NavigationMenuItem>
</NavigationMenuList>
</NavigationMenu>
```
## Link Component
Use the `render` prop to compose a custom link component such as Next.js `Link`.
```tsx showLineNumbers
import Link from "next/link"
import {
NavigationMenuItem,
NavigationMenuLink,
navigationMenuTriggerStyle,
} from "@/components/ui/navigation-menu"
export function NavigationMenuDemo() {
return (
<NavigationMenuItem>
<NavigationMenuLink
render={<Link href="/docs" />}
className={navigationMenuTriggerStyle()}
>
Documentation
</NavigationMenuLink>
</NavigationMenuItem>
)
}
```
## API Reference
See the [Base UI Navigation Menu](https://base-ui.com/react/components/navigation-menu#api-reference) documentation for more information.

View File

@@ -1,20 +1,18 @@
---
title: Pagination
description: Pagination with page navigation, next and previous links.
base: base
component: true
---
<ComponentPreview
name="pagination-demo"
description="A pagination with previous and next links."
/>
<ComponentPreview styleName="base-nova" name="pagination-demo" />
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">CLI</TabsTrigger>
<TabsTrigger value="cli">Command</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
@@ -27,11 +25,15 @@ npx shadcn@latest add pagination
<TabsContent value="manual">
<Steps>
<Steps className="mb-0 pt-2">
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource name="pagination" title="components/ui/pagination.tsx" />
<ComponentSource
name="pagination"
title="components/ui/pagination.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
@@ -64,6 +66,14 @@ import {
<PaginationItem>
<PaginationLink href="#">1</PaginationLink>
</PaginationItem>
<PaginationItem>
<PaginationLink href="#" isActive>
2
</PaginationLink>
</PaginationItem>
<PaginationItem>
<PaginationLink href="#">3</PaginationLink>
</PaginationItem>
<PaginationItem>
<PaginationEllipsis />
</PaginationItem>
@@ -74,7 +84,21 @@ import {
</Pagination>
```
### Next.js
## Examples
### Simple
A simple pagination with only page numbers.
<ComponentPreview styleName="base-nova" name="pagination-simple" />
### Icons Only
Use just the previous and next buttons without page numbers. This is useful for data tables with a rows per page selector.
<ComponentPreview styleName="base-nova" name="pagination-icons-only" />
## Next.js
By default the `<PaginationLink />` component will render an `<a />` tag.

View File

@@ -0,0 +1,104 @@
---
title: Popover
description: Displays rich content in a portal, triggered by a button.
base: base
component: true
links:
doc: https://base-ui.com/react/components/popover
api: https://base-ui.com/react/components/popover#api-reference
---
<ComponentPreview styleName="base-nova" name="popover-demo" />
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">Command</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add popover
```
</TabsContent>
<TabsContent value="manual">
<Steps className="mb-0 pt-2">
<Step>Install the following dependencies:</Step>
```bash
npm install @base-ui/react
```
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="popover"
title="components/ui/popover.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx showLineNumbers
import {
Popover,
PopoverContent,
PopoverDescription,
PopoverHeader,
PopoverTitle,
PopoverTrigger,
} from "@/components/ui/popover"
```
```tsx showLineNumbers
<Popover>
<PopoverTrigger render={<Button variant="outline" />}>
Open Popover
</PopoverTrigger>
<PopoverContent>
<PopoverHeader>
<PopoverTitle>Title</PopoverTitle>
<PopoverDescription>Description text here.</PopoverDescription>
</PopoverHeader>
</PopoverContent>
</Popover>
```
## Examples
### Basic
A simple popover with a header, title, and description.
<ComponentPreview styleName="base-nova" name="popover-basic" />
### Align
Use the `align` prop on `PopoverContent` to control the horizontal alignment.
<ComponentPreview styleName="base-nova" name="popover-alignments" />
### With Form
A popover with form fields inside.
<ComponentPreview styleName="base-nova" name="popover-form" />
## API Reference
See the [Base UI Popover](https://base-ui.com/react/components/popover#api-reference) documentation.

View File

@@ -0,0 +1,81 @@
---
title: Progress
description: Displays an indicator showing the completion progress of a task, typically displayed as a progress bar.
base: base
component: true
links:
doc: https://base-ui.com/react/components/progress
api: https://base-ui.com/react/components/progress#api-reference
---
<ComponentPreview styleName="base-nova" name="progress-demo" />
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">Command</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add progress
```
</TabsContent>
<TabsContent value="manual">
<Steps className="mb-0 pt-2">
<Step>Install the following dependencies:</Step>
```bash
npm install @base-ui/react
```
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="progress"
title="components/ui/progress.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx showLineNumbers
import { Progress } from "@/components/ui/progress"
```
```tsx showLineNumbers
<Progress value={33} />
```
## Examples
### Label
Use `ProgressLabel` and `ProgressValue` to add a label and value display.
<ComponentPreview styleName="base-nova" name="progress-label" />
### Controlled
A progress bar that can be controlled by a slider.
<ComponentPreview styleName="base-nova" name="progress-controlled" />
## API Reference
See the [Base UI Progress](https://base-ui.com/react/components/progress#api-reference) documentation.

View File

@@ -0,0 +1,109 @@
---
title: Radio Group
description: A set of checkable buttons—known as radio buttons—where no more than one of the buttons can be checked at a time.
base: base
component: true
links:
doc: https://base-ui.com/react/components/radio-group
api: https://base-ui.com/react/components/radio-group#api-reference
---
<ComponentPreview styleName="base-nova" name="radio-group-demo" />
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">Command</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add radio-group
```
</TabsContent>
<TabsContent value="manual">
<Steps className="mb-0 pt-2">
<Step>Install the following dependencies:</Step>
```bash
npm install @base-ui/react
```
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="radio-group"
title="components/ui/radio-group.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx showLineNumbers
import { Label } from "@/components/ui/label"
import { RadioGroup, RadioGroupItem } from "@/components/ui/radio-group"
```
```tsx showLineNumbers
<RadioGroup defaultValue="option-one">
<div className="flex items-center gap-3">
<RadioGroupItem value="option-one" id="option-one" />
<Label htmlFor="option-one">Option One</Label>
</div>
<div className="flex items-center gap-3">
<RadioGroupItem value="option-two" id="option-two" />
<Label htmlFor="option-two">Option Two</Label>
</div>
</RadioGroup>
```
## Examples
### Description
Radio group items with a description using the `Field` component.
<ComponentPreview styleName="base-nova" name="radio-group-description" />
### Choice Card
Use `FieldLabel` to wrap the entire `Field` for a clickable card-style selection.
<ComponentPreview styleName="base-nova" name="radio-group-choice-card" />
### Fieldset
Use `FieldSet` and `FieldLegend` to group radio items with a label and description.
<ComponentPreview styleName="base-nova" name="radio-group-fieldset" />
### Disabled
Use the `disabled` prop on `RadioGroup` to disable all items.
<ComponentPreview styleName="base-nova" name="radio-group-disabled" />
### Invalid
Use `aria-invalid` on `RadioGroupItem` and `data-invalid` on `Field` to show validation errors.
<ComponentPreview styleName="base-nova" name="radio-group-invalid" />
## API Reference
See the [Base UI Radio Group](https://base-ui.com/react/components/radio-group#api-reference) documentation.

View File

@@ -1,6 +1,7 @@
---
title: Resizable
description: Accessible resizable panel groups and layouts with keyboard support.
base: base
component: true
links:
doc: https://github.com/bvaughn/react-resizable-panels
@@ -8,8 +9,9 @@ links:
---
<ComponentPreview
styleName="base-nova"
name="resizable-demo"
description="A group of resizable horizontal and vertical panels."
previewClassName="h-80"
/>
## About
@@ -21,7 +23,7 @@ The `Resizable` component is built on top of [react-resizable-panels](https://gi
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">CLI</TabsTrigger>
<TabsTrigger value="cli">Command</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
@@ -34,7 +36,7 @@ npx shadcn@latest add resizable
<TabsContent value="manual">
<Steps>
<Steps className="mb-0 pt-2">
<Step>Install the following dependencies:</Step>
@@ -44,7 +46,11 @@ npm install react-resizable-panels
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource name="resizable" title="components/ui/resizable.tsx" />
<ComponentSource
name="resizable"
title="components/ui/resizable.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
@@ -76,54 +82,16 @@ import {
### Vertical
Use the `direction` prop to set the direction of the resizable panels.
Use `direction="vertical"` for vertical resizing.
<ComponentPreview
name="resizable-vertical"
description="A group of resizable vertical panels."
/>
```tsx showLineNumbers {9}
import {
ResizableHandle,
ResizablePanel,
ResizablePanelGroup,
} from "@/components/ui/resizable"
export default function Example() {
return (
<ResizablePanelGroup direction="vertical">
<ResizablePanel>One</ResizablePanel>
<ResizableHandle />
<ResizablePanel>Two</ResizablePanel>
</ResizablePanelGroup>
)
}
```
<ComponentPreview styleName="base-nova" name="resizable-vertical" />
### Handle
You can set or hide the handle by using the `withHandle` prop on the `ResizableHandle` component.
Use the `withHandle` prop on `ResizableHandle` to show a visible handle.
<ComponentPreview
name="resizable-handle"
description="A group of resizable panels with a handle."
/>
<ComponentPreview styleName="base-nova" name="resizable-handle" />
```tsx showLineNumbers {11}
import {
ResizableHandle,
ResizablePanel,
ResizablePanelGroup,
} from "@/components/ui/resizable"
## API Reference
export default function Example() {
return (
<ResizablePanelGroup direction="horizontal">
<ResizablePanel>One</ResizablePanel>
<ResizableHandle withHandle />
<ResizablePanel>Two</ResizablePanel>
</ResizablePanelGroup>
)
}
```
See the [react-resizable-panels](https://github.com/bvaughn/react-resizable-panels/tree/main/packages/react-resizable-panels) documentation.

View File

@@ -0,0 +1,81 @@
---
title: Scroll Area
description: Augments native scroll functionality for custom, cross-browser styling.
base: base
component: true
links:
doc: https://base-ui.com/react/components/scroll-area
api: https://base-ui.com/react/components/scroll-area#api-reference
---
<ComponentPreview
styleName="base-nova"
name="scroll-area-demo"
previewClassName="h-96"
/>
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">Command</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add scroll-area
```
</TabsContent>
<TabsContent value="manual">
<Steps className="mb-0 pt-2">
<Step>Install the following dependencies:</Step>
```bash
npm install @base-ui/react
```
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="scroll-area"
title="components/ui/scroll-area.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx showLineNumbers
import { ScrollArea } from "@/components/ui/scroll-area"
```
```tsx showLineNumbers
<ScrollArea className="h-[200px] w-[350px] rounded-md border p-4">
Your scrollable content here.
</ScrollArea>
```
## Examples
### Horizontal
Use `ScrollBar` with `orientation="horizontal"` for horizontal scrolling.
<ComponentPreview styleName="base-nova" name="scroll-area-horizontal-demo" />
## API Reference
See the [Base UI Scroll Area](https://base-ui.com/react/components/scroll-area#api-reference) documentation.

View File

@@ -0,0 +1,122 @@
---
title: Select
description: Displays a list of options for the user to pick from—triggered by a button.
base: base
component: true
featured: true
links:
doc: https://base-ui.com/react/components/select
api: https://base-ui.com/react/components/select#api-reference
---
<ComponentPreview styleName="base-nova" name="select-demo" />
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">Command</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add select
```
</TabsContent>
<TabsContent value="manual">
<Steps className="mb-0 pt-2">
<Step>Install the following dependencies:</Step>
```bash
npm install @base-ui/react
```
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="select"
title="components/ui/select.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx showLineNumbers
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select"
```
```tsx showLineNumbers
<Select>
<SelectTrigger className="w-[180px]">
<SelectValue placeholder="Theme" />
</SelectTrigger>
<SelectContent>
<SelectItem value="light">Light</SelectItem>
<SelectItem value="dark">Dark</SelectItem>
<SelectItem value="system">System</SelectItem>
</SelectContent>
</Select>
```
## Examples
### Align Item With Trigger
Use `alignItemWithTrigger` on `SelectContent` to control whether the selected item aligns with the trigger. When `true` (default), the popup positions so the selected item appears over the trigger. When `false`, the popup aligns to the trigger edge.
<ComponentPreview styleName="base-nova" name="select-align-item" />
### Groups
Use `SelectGroup`, `SelectLabel`, and `SelectSeparator` to organize items.
<ComponentPreview styleName="base-nova" name="select-groups" />
### Scrollable
A select with many items that scrolls.
<ComponentPreview styleName="base-nova" name="select-scrollable" />
### Disabled
<ComponentPreview styleName="base-nova" name="select-disabled" />
### Invalid
Add the `data-invalid` attribute to the `Field` component and the `aria-invalid` attribute to the `SelectTrigger` component to show an error state.
```tsx showLineNumbers /data-invalid/ /aria-invalid/
<Field data-invalid>
<FieldLabel>Fruit</FieldLabel>
<SelectTrigger aria-invalid>
<SelectValue />
</SelectTrigger>
</Field>
```
<ComponentPreview styleName="base-nova" name="select-invalid" />
## API Reference
See the [Base UI Select](https://base-ui.com/react/components/select#api-reference) documentation.

View File

@@ -0,0 +1,87 @@
---
title: Separator
description: Visually or semantically separates content.
base: base
component: true
links:
doc: https://base-ui.com/react/components/separator
api: https://base-ui.com/react/components/separator#api-reference
---
<ComponentPreview styleName="base-nova" name="separator-demo" />
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">Command</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add separator
```
</TabsContent>
<TabsContent value="manual">
<Steps className="mb-0 pt-2">
<Step>Install the following dependencies:</Step>
```bash
npm install @base-ui/react
```
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="separator"
title="components/ui/separator.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx showLineNumbers
import { Separator } from "@/components/ui/separator"
```
```tsx showLineNumbers
<Separator />
```
## Examples
### Vertical
Use `orientation="vertical"` for a vertical separator.
<ComponentPreview styleName="base-nova" name="separator-vertical" />
### Menu
Vertical separators between menu items with descriptions.
<ComponentPreview styleName="base-nova" name="separator-menu" />
### List
Horizontal separators between list items.
<ComponentPreview styleName="base-nova" name="separator-list" />
## API Reference
See the [Base UI Separator](https://base-ui.com/react/components/separator#api-reference) documentation.

View File

@@ -0,0 +1,98 @@
---
title: Sheet
description: Extends the Dialog component to display content that complements the main content of the screen.
base: base
component: true
links:
doc: https://base-ui.com/react/components/dialog
api: https://base-ui.com/react/components/dialog#api-reference
---
<ComponentPreview styleName="base-nova" name="sheet-demo" />
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">Command</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add sheet
```
</TabsContent>
<TabsContent value="manual">
<Steps className="mb-0 pt-2">
<Step>Install the following dependencies:</Step>
```bash
npm install @base-ui/react
```
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="sheet"
title="components/ui/sheet.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx showLineNumbers
import {
Sheet,
SheetClose,
SheetContent,
SheetDescription,
SheetFooter,
SheetHeader,
SheetTitle,
SheetTrigger,
} from "@/components/ui/sheet"
```
```tsx showLineNumbers
<Sheet>
<SheetTrigger>Open</SheetTrigger>
<SheetContent>
<SheetHeader>
<SheetTitle>Are you absolutely sure?</SheetTitle>
<SheetDescription>This action cannot be undone.</SheetDescription>
</SheetHeader>
</SheetContent>
</Sheet>
```
## Examples
### Side
Use the `side` prop on `SheetContent` to set the edge of the screen where the sheet appears. Values are `top`, `right`, `bottom`, or `left`.
<ComponentPreview styleName="base-nova" name="sheet-side" />
### No Close Button
Use `showCloseButton={false}` on `SheetContent` to hide the close button.
<ComponentPreview styleName="base-nova" name="sheet-no-close-button" />
## API Reference
See the [Base UI Dialog](https://base-ui.com/react/components/dialog#api-reference) documentation.

File diff suppressed because it is too large Load Diff

View File

@@ -1,17 +1,18 @@
---
title: Skeleton
description: Use to show a placeholder while content is loading.
base: base
component: true
---
<ComponentPreview name="skeleton-demo" description="A skeleton component." />
<ComponentPreview styleName="base-nova" name="skeleton-demo" />
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">CLI</TabsTrigger>
<TabsTrigger value="cli">Command</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
@@ -24,11 +25,15 @@ npx shadcn@latest add skeleton
<TabsContent value="manual">
<Steps>
<Steps className="mb-0 pt-2">
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource name="skeleton" title="components/ui/skeleton.tsx" />
<ComponentSource
name="skeleton"
title="components/ui/skeleton.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
@@ -50,9 +55,26 @@ import { Skeleton } from "@/components/ui/skeleton"
## Examples
### Avatar
<ComponentPreview styleName="base-nova" name="skeleton-avatar" />
### Card
<ComponentPreview
styleName="base-nova"
name="skeleton-card"
description="A card with skeleton showing a loading state."
previewClassName="h-80"
/>
### Text
<ComponentPreview styleName="base-nova" name="skeleton-text" />
### Form
<ComponentPreview styleName="base-nova" name="skeleton-form" />
### Table
<ComponentPreview styleName="base-nova" name="skeleton-table" />

View File

@@ -0,0 +1,97 @@
---
title: Slider
description: An input where the user selects a value from within a given range.
base: base
component: true
links:
doc: https://base-ui.com/react/components/slider
api: https://base-ui.com/react/components/slider#api-reference
---
<ComponentPreview styleName="base-nova" name="slider-demo" />
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">Command</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
```bash
npx shadcn@latest add slider
```
</TabsContent>
<TabsContent value="manual">
<Steps className="mb-0 pt-2">
<Step>Install the following dependencies:</Step>
```bash
npm install @base-ui/react
```
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="slider"
title="components/ui/slider.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx
import { Slider } from "@/components/ui/slider"
```
```tsx
<Slider defaultValue={[33]} max={100} step={1} />
```
## Examples
### Range
Use an array with two values for a range slider.
<ComponentPreview styleName="base-nova" name="slider-range" />
### Multiple Thumbs
Use an array with multiple values for multiple thumbs.
<ComponentPreview styleName="base-nova" name="slider-multiple" />
### Vertical
Use `orientation="vertical"` for a vertical slider.
<ComponentPreview styleName="base-nova" name="slider-vertical" />
### Controlled
<ComponentPreview styleName="base-nova" name="slider-controlled" />
### Disabled
Use the `disabled` prop to disable the slider.
<ComponentPreview styleName="base-nova" name="slider-disabled" />
## API Reference
See the [Base UI Slider](https://base-ui.com/react/components/slider#api-reference) documentation.

View File

@@ -0,0 +1,126 @@
---
title: Sonner
description: An opinionated toast component for React.
base: base
component: true
links:
doc: https://sonner.emilkowal.ski
---
<ComponentPreview styleName="base-nova" name="sonner-demo" />
## About
Sonner is built and maintained by [emilkowalski](https://twitter.com/emilkowalski).
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">Command</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
<Steps className="mb-0 pt-2">
<Step>Run the following command:</Step>
```bash
npx shadcn@latest add sonner
```
<Step>Add the Toaster component</Step>
```tsx title="app/layout.tsx" {1,9} showLineNumbers
import { Toaster } from "@/components/ui/sonner"
export default function RootLayout({ children }) {
return (
<html lang="en">
<head />
<body>
<main>{children}</main>
<Toaster />
</body>
</html>
)
}
```
</Steps>
</TabsContent>
<TabsContent value="manual">
<Steps className="mb-0 pt-2">
<Step>Install the following dependencies:</Step>
```bash
npm install sonner next-themes
```
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource
name="sonner"
title="components/ui/sonner.tsx"
styleName="base-nova"
/>
<Step>Add the Toaster component</Step>
```tsx showLineNumbers title="app/layout.tsx" {1,8}
import { Toaster } from "@/components/ui/sonner"
export default function RootLayout({ children }) {
return (
<html lang="en">
<head />
<body>
<Toaster />
<main>{children}</main>
</body>
</html>
)
}
```
</Steps>
</TabsContent>
</CodeTabs>
## Usage
```tsx
import { toast } from "sonner"
```
```tsx
toast("Event has been created.")
```
## Examples
### Types
<ComponentPreview styleName="base-nova" name="sonner-types" />
### Description
<ComponentPreview styleName="base-nova" name="sonner-description" />
### Position
Use the `position` prop to change the position of the toast.
<ComponentPreview styleName="base-nova" name="sonner-position" />
## API Reference
See the [Sonner API Reference](https://sonner.emilkowal.ski/api) for more information.

View File

@@ -1,17 +1,18 @@
---
title: Spinner
description: An indicator that can be used to show a loading state.
base: base
component: true
---
<ComponentPreview name="spinner-demo" className="[&_.preview]:p-6" />
<ComponentPreview styleName="base-nova" name="spinner-demo" />
## Installation
<CodeTabs>
<TabsList>
<TabsTrigger value="cli">CLI</TabsTrigger>
<TabsTrigger value="cli">Command</TabsTrigger>
<TabsTrigger value="manual">Manual</TabsTrigger>
</TabsList>
<TabsContent value="cli">
@@ -24,11 +25,15 @@ npx shadcn@latest add spinner
<TabsContent value="manual">
<Steps>
<Steps className="mb-0 pt-2">
<Step>Copy and paste the following code into your project.</Step>
<ComponentSource name="spinner" title="components/ui/spinner.tsx" />
<ComponentSource
name="spinner"
title="components/ui/spinner.tsx"
styleName="base-nova"
/>
<Step>Update the import paths to match your project setup.</Step>
@@ -52,7 +57,7 @@ import { Spinner } from "@/components/ui/spinner"
You can replace the default spinner icon with any other icon by editing the `Spinner` component.
<ComponentPreview name="spinner-custom" />
<ComponentPreview styleName="base-nova" name="spinner-custom" />
```tsx showLineNumbers title="components/ui/spinner.tsx"
import { LoaderIcon } from "lucide-react"
@@ -79,52 +84,24 @@ export { Spinner }
Use the `size-*` utility class to change the size of the spinner.
<ComponentPreview name="spinner-size" />
### Color
Use the `text-` utility class to change the color of the spinner.
<ComponentPreview name="spinner-color" />
<ComponentPreview styleName="base-nova" name="spinner-size" />
### Button
Add a spinner to a button to indicate a loading state. The `<Button />` will handle the spacing between the spinner and the text.
Add a spinner to a button to indicate a loading state. Remember to use the `data-icon="inline-start"` prop to add the spinner to the start of the button and the `data-icon="inline-end"` prop to add the spinner to the end of the button.
<ComponentPreview name="spinner-button" />
<ComponentPreview styleName="base-nova" name="spinner-button" />
### Badge
You can also use a spinner inside a badge.
Add a spinner to a badge to indicate a loading state. Remember to use the `data-icon="inline-start"` prop to add the spinner to the start of the badge and the `data-icon="inline-end"` prop to add the spinner to the end of the badge.
<ComponentPreview name="spinner-badge" />
<ComponentPreview styleName="base-nova" name="spinner-badge" />
### Input Group
Input Group can have spinners inside `<InputGroupAddon>`.
<ComponentPreview name="spinner-input-group" />
<ComponentPreview styleName="base-nova" name="spinner-input-group" />
### Empty
<ComponentPreview name="spinner-empty" />
### Item
Use the spinner inside `<ItemMedia>` to indicate a loading state.
<ComponentPreview name="spinner-item" />
## API Reference
### Spinner
Use the `Spinner` component to display a spinner.
| Prop | Type | Default |
| ----------- | -------- | ------- |
| `className` | `string` | `` |
```tsx
<Spinner />
```
<ComponentPreview styleName="base-nova" name="spinner-empty" />

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