mirror of
https://github.com/shadcn-ui/ui.git
synced 2026-06-12 10:21:39 +00:00
Compare commits
41 Commits
shadcn@4.1
...
shadcn@4.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
14bb486174 | ||
|
|
12b49c986f | ||
|
|
64c8cd99ee | ||
|
|
7d718ddaa9 | ||
|
|
5570b3e24a | ||
|
|
214b1b8479 | ||
|
|
8bd161d453 | ||
|
|
64b88b6cdb | ||
|
|
6a070bf8c5 | ||
|
|
124495f0df | ||
|
|
43f64065b7 | ||
|
|
8bec9c1234 | ||
|
|
ba6ac6ec63 | ||
|
|
b75796ed76 | ||
|
|
d82b4a7d98 | ||
|
|
5b79499d23 | ||
|
|
d78ff8b858 | ||
|
|
ef78384bfd | ||
|
|
d3ab7fb00b | ||
|
|
bebc4356af | ||
|
|
14bc966fee | ||
|
|
6a4b27b80d | ||
|
|
c5b4080649 | ||
|
|
408b25c82a | ||
|
|
228b0e3ecd | ||
|
|
f900bd57d0 | ||
|
|
6b190c6a18 | ||
|
|
c43bc4f5d6 | ||
|
|
9cd14a684f | ||
|
|
fc1675e54d | ||
|
|
a5abe1aa0f | ||
|
|
031998436f | ||
|
|
29cb65c26b | ||
|
|
179c0c0b23 | ||
|
|
03430e03bf | ||
|
|
169682d87a | ||
|
|
336eee688e | ||
|
|
32e4827559 | ||
|
|
7a81328b23 | ||
|
|
5b40b9de5a | ||
|
|
e327cef2c1 |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -15,6 +15,7 @@ build
|
||||
|
||||
# misc
|
||||
.DS_Store
|
||||
.eslintcache
|
||||
*.pem
|
||||
|
||||
# debug
|
||||
@@ -43,3 +44,4 @@ tsconfig.tsbuildinfo
|
||||
.notes
|
||||
.playwright-mcp
|
||||
shadcn-workspace
|
||||
.codex-artifacts
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
"use client"
|
||||
|
||||
import * as React from "react"
|
||||
import { Button } from "@/examples/radix/ui/button"
|
||||
import { ButtonGroup } from "@/examples/radix/ui/button-group"
|
||||
import { IconMinus, IconPlus } from "@tabler/icons-react"
|
||||
|
||||
import { Button } from "@/styles/radix-nova/ui/button"
|
||||
import { ButtonGroup } from "@/styles/radix-nova/ui/button-group"
|
||||
import {
|
||||
Field,
|
||||
FieldContent,
|
||||
@@ -13,11 +15,10 @@ import {
|
||||
FieldSeparator,
|
||||
FieldSet,
|
||||
FieldTitle,
|
||||
} 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"
|
||||
} from "@/styles/radix-nova/ui/field"
|
||||
import { Input } from "@/styles/radix-nova/ui/input"
|
||||
import { RadioGroup, RadioGroupItem } from "@/styles/radix-nova/ui/radio-group"
|
||||
import { Switch } from "@/styles/radix-nova/ui/switch"
|
||||
|
||||
export function AppearanceSettings() {
|
||||
const [gpuCount, setGpuCount] = React.useState(8)
|
||||
|
||||
@@ -1,8 +1,20 @@
|
||||
"use client"
|
||||
|
||||
import * as React from "react"
|
||||
import { Button } from "@/examples/radix/ui/button"
|
||||
import { ButtonGroup } from "@/examples/radix/ui/button-group"
|
||||
import {
|
||||
ArchiveIcon,
|
||||
ArrowLeftIcon,
|
||||
CalendarPlusIcon,
|
||||
ClockIcon,
|
||||
ListFilterIcon,
|
||||
MailCheckIcon,
|
||||
MoreHorizontalIcon,
|
||||
TagIcon,
|
||||
Trash2Icon,
|
||||
} from "lucide-react"
|
||||
|
||||
import { Button } from "@/styles/radix-nova/ui/button"
|
||||
import { ButtonGroup } from "@/styles/radix-nova/ui/button-group"
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
@@ -15,18 +27,7 @@ import {
|
||||
DropdownMenuSubContent,
|
||||
DropdownMenuSubTrigger,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/examples/radix/ui/dropdown-menu"
|
||||
import {
|
||||
ArchiveIcon,
|
||||
ArrowLeftIcon,
|
||||
CalendarPlusIcon,
|
||||
ClockIcon,
|
||||
ListFilterIcon,
|
||||
MailCheckIcon,
|
||||
MoreHorizontalIcon,
|
||||
TagIcon,
|
||||
Trash2Icon,
|
||||
} from "lucide-react"
|
||||
} from "@/styles/radix-nova/ui/dropdown-menu"
|
||||
|
||||
export function ButtonGroupDemo() {
|
||||
const [label, setLabel] = React.useState("personal")
|
||||
|
||||
@@ -1,20 +1,21 @@
|
||||
"use client"
|
||||
|
||||
import * as React from "react"
|
||||
import { Button } from "@/examples/radix/ui/button"
|
||||
import { ButtonGroup } from "@/examples/radix/ui/button-group"
|
||||
import { AudioLinesIcon, PlusIcon } from "lucide-react"
|
||||
|
||||
import { Button } from "@/styles/radix-nova/ui/button"
|
||||
import { ButtonGroup } from "@/styles/radix-nova/ui/button-group"
|
||||
import {
|
||||
InputGroup,
|
||||
InputGroupAddon,
|
||||
InputGroupButton,
|
||||
InputGroupInput,
|
||||
} from "@/examples/radix/ui/input-group"
|
||||
} from "@/styles/radix-nova/ui/input-group"
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipTrigger,
|
||||
} from "@/examples/radix/ui/tooltip"
|
||||
import { AudioLinesIcon, PlusIcon } from "lucide-react"
|
||||
} from "@/styles/radix-nova/ui/tooltip"
|
||||
|
||||
export function ButtonGroupInputGroup() {
|
||||
const [voiceEnabled, setVoiceEnabled] = React.useState(false)
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
"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 "@/styles/radix-nova/ui/button"
|
||||
import { ButtonGroup } from "@/styles/radix-nova/ui/button-group"
|
||||
|
||||
export function ButtonGroupNested() {
|
||||
return (
|
||||
<ButtonGroup>
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
import { Button } from "@/examples/radix/ui/button"
|
||||
import { ButtonGroup } from "@/examples/radix/ui/button-group"
|
||||
import { BotIcon, ChevronDownIcon } from "lucide-react"
|
||||
|
||||
import { Button } from "@/styles/radix-nova/ui/button"
|
||||
import { ButtonGroup } from "@/styles/radix-nova/ui/button-group"
|
||||
import {
|
||||
Popover,
|
||||
PopoverContent,
|
||||
PopoverTrigger,
|
||||
} 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"
|
||||
} from "@/styles/radix-nova/ui/popover"
|
||||
import { Separator } from "@/styles/radix-nova/ui/separator"
|
||||
import { Textarea } from "@/styles/radix-nova/ui/textarea"
|
||||
|
||||
export function ButtonGroupPopover() {
|
||||
return (
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
import { PlusIcon } from "lucide-react"
|
||||
|
||||
import {
|
||||
Avatar,
|
||||
AvatarFallback,
|
||||
AvatarGroup,
|
||||
AvatarImage,
|
||||
} from "@/examples/radix/ui/avatar"
|
||||
import { Button } from "@/examples/radix/ui/button"
|
||||
} from "@/styles/radix-nova/ui/avatar"
|
||||
import { Button } from "@/styles/radix-nova/ui/button"
|
||||
import {
|
||||
Empty,
|
||||
EmptyContent,
|
||||
@@ -12,8 +14,7 @@ import {
|
||||
EmptyHeader,
|
||||
EmptyMedia,
|
||||
EmptyTitle,
|
||||
} from "@/examples/radix/ui/empty"
|
||||
import { PlusIcon } from "lucide-react"
|
||||
} from "@/styles/radix-nova/ui/empty"
|
||||
|
||||
export function EmptyAvatarGroup() {
|
||||
return (
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Checkbox } from "@/examples/radix/ui/checkbox"
|
||||
import { Field, FieldLabel } from "@/examples/radix/ui/field"
|
||||
import { Checkbox } from "@/styles/radix-nova/ui/checkbox"
|
||||
import { Field, FieldLabel } from "@/styles/radix-nova/ui/field"
|
||||
|
||||
export function FieldCheckbox() {
|
||||
return (
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Button } from "@/examples/radix/ui/button"
|
||||
import { Checkbox } from "@/examples/radix/ui/checkbox"
|
||||
import { Button } from "@/styles/radix-nova/ui/button"
|
||||
import { Checkbox } from "@/styles/radix-nova/ui/checkbox"
|
||||
import {
|
||||
Field,
|
||||
FieldDescription,
|
||||
@@ -8,8 +8,8 @@ import {
|
||||
FieldLegend,
|
||||
FieldSeparator,
|
||||
FieldSet,
|
||||
} from "@/examples/radix/ui/field"
|
||||
import { Input } from "@/examples/radix/ui/input"
|
||||
} from "@/styles/radix-nova/ui/field"
|
||||
import { Input } from "@/styles/radix-nova/ui/input"
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
@@ -17,8 +17,8 @@ import {
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "@/examples/radix/ui/select"
|
||||
import { Textarea } from "@/examples/radix/ui/textarea"
|
||||
} from "@/styles/radix-nova/ui/select"
|
||||
import { Textarea } from "@/styles/radix-nova/ui/textarea"
|
||||
|
||||
export function FieldDemo() {
|
||||
return (
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Card, CardContent } from "@/examples/radix/ui/card"
|
||||
import { Checkbox } from "@/examples/radix/ui/checkbox"
|
||||
import { Card, CardContent } from "@/styles/radix-nova/ui/card"
|
||||
import { Checkbox } from "@/styles/radix-nova/ui/checkbox"
|
||||
import {
|
||||
Field,
|
||||
FieldDescription,
|
||||
@@ -8,7 +8,7 @@ import {
|
||||
FieldLegend,
|
||||
FieldSet,
|
||||
FieldTitle,
|
||||
} from "@/examples/radix/ui/field"
|
||||
} from "@/styles/radix-nova/ui/field"
|
||||
|
||||
const options = [
|
||||
{
|
||||
|
||||
@@ -1,8 +1,13 @@
|
||||
"use client"
|
||||
|
||||
import { useState } from "react"
|
||||
import { Field, FieldDescription, FieldTitle } from "@/examples/radix/ui/field"
|
||||
import { Slider } from "@/examples/radix/ui/slider"
|
||||
|
||||
import {
|
||||
Field,
|
||||
FieldDescription,
|
||||
FieldTitle,
|
||||
} from "@/styles/radix-nova/ui/field"
|
||||
import { Slider } from "@/styles/radix-nova/ui/slider"
|
||||
|
||||
export function FieldSlider() {
|
||||
const [value, setValue] = useState([200, 800])
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { FieldSeparator } from "@/examples/radix/ui/field"
|
||||
import { FieldSeparator } from "@/styles/radix-nova/ui/field"
|
||||
|
||||
import { AppearanceSettings } from "./appearance-settings"
|
||||
import { ButtonGroupDemo } from "./button-group-demo"
|
||||
|
||||
@@ -1,19 +1,20 @@
|
||||
"use client"
|
||||
|
||||
import * as React from "react"
|
||||
import { IconInfoCircle, IconStar } from "@tabler/icons-react"
|
||||
|
||||
import {
|
||||
InputGroup,
|
||||
InputGroupAddon,
|
||||
InputGroupButton,
|
||||
InputGroupInput,
|
||||
} from "@/examples/radix/ui/input-group"
|
||||
import { Label } from "@/examples/radix/ui/label"
|
||||
} from "@/styles/radix-nova/ui/input-group"
|
||||
import { Label } from "@/styles/radix-nova/ui/label"
|
||||
import {
|
||||
Popover,
|
||||
PopoverContent,
|
||||
PopoverTrigger,
|
||||
} from "@/examples/radix/ui/popover"
|
||||
import { IconInfoCircle, IconStar } from "@tabler/icons-react"
|
||||
} from "@/styles/radix-nova/ui/popover"
|
||||
|
||||
export function InputGroupButtonExample() {
|
||||
const [isFavorite, setIsFavorite] = React.useState(false)
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
import { IconCheck, IconInfoCircle, IconPlus } from "@tabler/icons-react"
|
||||
import { ArrowUpIcon, Search } from "lucide-react"
|
||||
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/examples/radix/ui/dropdown-menu"
|
||||
} from "@/styles/radix-nova/ui/dropdown-menu"
|
||||
import {
|
||||
InputGroup,
|
||||
InputGroupAddon,
|
||||
@@ -11,15 +14,13 @@ import {
|
||||
InputGroupInput,
|
||||
InputGroupText,
|
||||
InputGroupTextarea,
|
||||
} from "@/examples/radix/ui/input-group"
|
||||
import { Separator } from "@/examples/radix/ui/separator"
|
||||
} from "@/styles/radix-nova/ui/input-group"
|
||||
import { Separator } from "@/styles/radix-nova/ui/separator"
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipTrigger,
|
||||
} from "@/examples/radix/ui/tooltip"
|
||||
import { IconCheck, IconInfoCircle, IconPlus } from "@tabler/icons-react"
|
||||
import { ArrowUpIcon, Search } from "lucide-react"
|
||||
} from "@/styles/radix-nova/ui/tooltip"
|
||||
|
||||
export function InputGroupDemo() {
|
||||
return (
|
||||
@@ -88,7 +89,7 @@ export function InputGroupDemo() {
|
||||
<InputGroupInput placeholder="@shadcn" />
|
||||
<InputGroupAddon align="inline-end">
|
||||
<div className="flex size-4 items-center justify-center rounded-full bg-primary text-foreground">
|
||||
<IconCheck className="size-3 text-white" />
|
||||
<IconCheck className="size-3 text-background" />
|
||||
</div>
|
||||
</InputGroupAddon>
|
||||
</InputGroup>
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import { Button } from "@/examples/radix/ui/button"
|
||||
import { BadgeCheckIcon, ChevronRightIcon } from "lucide-react"
|
||||
|
||||
import { Button } from "@/styles/radix-nova/ui/button"
|
||||
import {
|
||||
Item,
|
||||
ItemActions,
|
||||
@@ -6,8 +8,7 @@ import {
|
||||
ItemDescription,
|
||||
ItemMedia,
|
||||
ItemTitle,
|
||||
} from "@/examples/radix/ui/item"
|
||||
import { BadgeCheckIcon, ChevronRightIcon } from "lucide-react"
|
||||
} from "@/styles/radix-nova/ui/item"
|
||||
|
||||
export function ItemDemo() {
|
||||
return (
|
||||
|
||||
@@ -1,8 +1,24 @@
|
||||
"use client"
|
||||
|
||||
import { useMemo, useState } from "react"
|
||||
import { Avatar, AvatarFallback, AvatarImage } from "@/examples/radix/ui/avatar"
|
||||
import { Badge } from "@/examples/radix/ui/badge"
|
||||
import {
|
||||
IconApps,
|
||||
IconArrowUp,
|
||||
IconAt,
|
||||
IconBook,
|
||||
IconCircleDashedPlus,
|
||||
IconPaperclip,
|
||||
IconPlus,
|
||||
IconWorld,
|
||||
IconX,
|
||||
} from "@tabler/icons-react"
|
||||
|
||||
import {
|
||||
Avatar,
|
||||
AvatarFallback,
|
||||
AvatarImage,
|
||||
} from "@/styles/radix-nova/ui/avatar"
|
||||
import { Badge } from "@/styles/radix-nova/ui/badge"
|
||||
import {
|
||||
Command,
|
||||
CommandEmpty,
|
||||
@@ -10,7 +26,7 @@ import {
|
||||
CommandInput,
|
||||
CommandItem,
|
||||
CommandList,
|
||||
} from "@/examples/radix/ui/command"
|
||||
} from "@/styles/radix-nova/ui/command"
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuCheckboxItem,
|
||||
@@ -23,36 +39,25 @@ import {
|
||||
DropdownMenuSubContent,
|
||||
DropdownMenuSubTrigger,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/examples/radix/ui/dropdown-menu"
|
||||
import { Field, FieldLabel } from "@/examples/radix/ui/field"
|
||||
} from "@/styles/radix-nova/ui/dropdown-menu"
|
||||
import { Field, FieldLabel } from "@/styles/radix-nova/ui/field"
|
||||
import {
|
||||
InputGroup,
|
||||
InputGroupAddon,
|
||||
InputGroupButton,
|
||||
InputGroupTextarea,
|
||||
} from "@/examples/radix/ui/input-group"
|
||||
} from "@/styles/radix-nova/ui/input-group"
|
||||
import {
|
||||
Popover,
|
||||
PopoverContent,
|
||||
PopoverTrigger,
|
||||
} from "@/examples/radix/ui/popover"
|
||||
import { Switch } from "@/examples/radix/ui/switch"
|
||||
} from "@/styles/radix-nova/ui/popover"
|
||||
import { Switch } from "@/styles/radix-nova/ui/switch"
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipTrigger,
|
||||
} from "@/examples/radix/ui/tooltip"
|
||||
import {
|
||||
IconApps,
|
||||
IconArrowUp,
|
||||
IconAt,
|
||||
IconBook,
|
||||
IconCircleDashedPlus,
|
||||
IconPaperclip,
|
||||
IconPlus,
|
||||
IconWorld,
|
||||
IconX,
|
||||
} from "@tabler/icons-react"
|
||||
} from "@/styles/radix-nova/ui/tooltip"
|
||||
|
||||
const SAMPLE_DATA = {
|
||||
mentionable: [
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { Badge } from "@/examples/radix/ui/badge"
|
||||
import { Spinner } from "@/examples/radix/ui/spinner"
|
||||
import { Badge } from "@/styles/radix-nova/ui/badge"
|
||||
import { Spinner } from "@/styles/radix-nova/ui/spinner"
|
||||
|
||||
export function SpinnerBadge() {
|
||||
return (
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Button } from "@/examples/radix/ui/button"
|
||||
import { Button } from "@/styles/radix-nova/ui/button"
|
||||
import {
|
||||
Empty,
|
||||
EmptyContent,
|
||||
@@ -6,8 +6,8 @@ import {
|
||||
EmptyHeader,
|
||||
EmptyMedia,
|
||||
EmptyTitle,
|
||||
} from "@/examples/radix/ui/empty"
|
||||
import { Spinner } from "@/examples/radix/ui/spinner"
|
||||
} from "@/styles/radix-nova/ui/empty"
|
||||
import { Spinner } from "@/styles/radix-nova/ui/spinner"
|
||||
|
||||
export function SpinnerEmpty() {
|
||||
return (
|
||||
|
||||
@@ -56,7 +56,7 @@ export default function BlocksLayout({
|
||||
<a href="#blocks">Browse Blocks</a>
|
||||
</Button>
|
||||
<Button asChild variant="ghost" size="sm">
|
||||
<Link href="/docs/blocks">Add a block</Link>
|
||||
<Link href="/docs/components">View Components</Link>
|
||||
</Button>
|
||||
</PageActions>
|
||||
</PageHeader>
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import Link from "next/link"
|
||||
import { Button } from "@/examples/radix/ui/button"
|
||||
import { mdxComponents } from "@/mdx-components"
|
||||
import { IconRss } from "@tabler/icons-react"
|
||||
|
||||
import { getChangelogPages, type ChangelogPageData } from "@/lib/changelog"
|
||||
import { absoluteUrl } from "@/lib/utils"
|
||||
import { OpenInV0Cta } from "@/components/open-in-v0-cta"
|
||||
import { Button } from "@/styles/radix-nova/ui/button"
|
||||
|
||||
export const revalidate = false
|
||||
export const dynamic = "force-static"
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
"use client"
|
||||
|
||||
import * as React from "react"
|
||||
import { Button } from "@/examples/base/ui-rtl/button"
|
||||
import { ButtonGroup } from "@/examples/base/ui-rtl/button-group"
|
||||
import { IconMinus, IconPlus } from "@tabler/icons-react"
|
||||
|
||||
import { useLanguageContext } from "@/components/language-selector"
|
||||
import { Button } from "@/styles/base-nova/ui-rtl/button"
|
||||
import { ButtonGroup } from "@/styles/base-nova/ui-rtl/button-group"
|
||||
import {
|
||||
Field,
|
||||
FieldContent,
|
||||
@@ -13,13 +16,13 @@ import {
|
||||
FieldSeparator,
|
||||
FieldSet,
|
||||
FieldTitle,
|
||||
} from "@/examples/base/ui-rtl/field"
|
||||
import { Input } from "@/examples/base/ui-rtl/input"
|
||||
import { RadioGroup, RadioGroupItem } from "@/examples/base/ui-rtl/radio-group"
|
||||
import { Switch } from "@/examples/base/ui-rtl/switch"
|
||||
import { IconMinus, IconPlus } from "@tabler/icons-react"
|
||||
|
||||
import { useLanguageContext } from "@/components/language-selector"
|
||||
} from "@/styles/base-nova/ui-rtl/field"
|
||||
import { Input } from "@/styles/base-nova/ui-rtl/input"
|
||||
import {
|
||||
RadioGroup,
|
||||
RadioGroupItem,
|
||||
} from "@/styles/base-nova/ui-rtl/radio-group"
|
||||
import { Switch } from "@/styles/base-nova/ui-rtl/switch"
|
||||
|
||||
const translations = {
|
||||
ar: {
|
||||
|
||||
@@ -1,22 +1,6 @@
|
||||
"use client"
|
||||
|
||||
import * as React from "react"
|
||||
import { Button } from "@/examples/base/ui-rtl/button"
|
||||
import { ButtonGroup } from "@/examples/base/ui-rtl/button-group"
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuGroup,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuPortal,
|
||||
DropdownMenuRadioGroup,
|
||||
DropdownMenuRadioItem,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuSub,
|
||||
DropdownMenuSubContent,
|
||||
DropdownMenuSubTrigger,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/examples/base/ui-rtl/dropdown-menu"
|
||||
import {
|
||||
ArchiveIcon,
|
||||
ArrowLeftIcon,
|
||||
@@ -30,6 +14,22 @@ import {
|
||||
} from "lucide-react"
|
||||
|
||||
import { useLanguageContext } from "@/components/language-selector"
|
||||
import { Button } from "@/styles/base-nova/ui-rtl/button"
|
||||
import { ButtonGroup } from "@/styles/base-nova/ui-rtl/button-group"
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuGroup,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuPortal,
|
||||
DropdownMenuRadioGroup,
|
||||
DropdownMenuRadioItem,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuSub,
|
||||
DropdownMenuSubContent,
|
||||
DropdownMenuSubTrigger,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/styles/base-nova/ui-rtl/dropdown-menu"
|
||||
|
||||
const translations = {
|
||||
ar: {
|
||||
|
||||
@@ -1,22 +1,22 @@
|
||||
"use client"
|
||||
|
||||
import * as React from "react"
|
||||
import { Button } from "@/examples/base/ui-rtl/button"
|
||||
import { ButtonGroup } from "@/examples/base/ui-rtl/button-group"
|
||||
import { AudioLinesIcon, PlusIcon } from "lucide-react"
|
||||
|
||||
import { useLanguageContext } from "@/components/language-selector"
|
||||
import { Button } from "@/styles/base-nova/ui-rtl/button"
|
||||
import { ButtonGroup } from "@/styles/base-nova/ui-rtl/button-group"
|
||||
import {
|
||||
InputGroup,
|
||||
InputGroupAddon,
|
||||
InputGroupButton,
|
||||
InputGroupInput,
|
||||
} from "@/examples/base/ui-rtl/input-group"
|
||||
} from "@/styles/base-nova/ui-rtl/input-group"
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipTrigger,
|
||||
} from "@/examples/base/ui-rtl/tooltip"
|
||||
import { AudioLinesIcon, PlusIcon } from "lucide-react"
|
||||
|
||||
import { useLanguageContext } from "@/components/language-selector"
|
||||
} from "@/styles/base-nova/ui-rtl/tooltip"
|
||||
|
||||
const translations = {
|
||||
ar: {
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
"use client"
|
||||
|
||||
import { Button } from "@/examples/base/ui-rtl/button"
|
||||
import { ButtonGroup } from "@/examples/base/ui-rtl/button-group"
|
||||
import { ArrowLeftIcon, ArrowRightIcon } from "lucide-react"
|
||||
|
||||
import { useLanguageContext } from "@/components/language-selector"
|
||||
import { Button } from "@/styles/base-nova/ui-rtl/button"
|
||||
import { ButtonGroup } from "@/styles/base-nova/ui-rtl/button-group"
|
||||
|
||||
const translations = {
|
||||
ar: {
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
"use client"
|
||||
|
||||
import { Button } from "@/examples/base/ui-rtl/button"
|
||||
import { ButtonGroup } from "@/examples/base/ui-rtl/button-group"
|
||||
import { BotIcon, ChevronDownIcon } from "lucide-react"
|
||||
|
||||
import { useLanguageContext } from "@/components/language-selector"
|
||||
import { Button } from "@/styles/base-nova/ui-rtl/button"
|
||||
import { ButtonGroup } from "@/styles/base-nova/ui-rtl/button-group"
|
||||
import {
|
||||
Popover,
|
||||
PopoverContent,
|
||||
PopoverTrigger,
|
||||
} from "@/examples/base/ui-rtl/popover"
|
||||
import { Separator } from "@/examples/base/ui-rtl/separator"
|
||||
import { Textarea } from "@/examples/base/ui-rtl/textarea"
|
||||
import { BotIcon, ChevronDownIcon } from "lucide-react"
|
||||
|
||||
import { useLanguageContext } from "@/components/language-selector"
|
||||
} from "@/styles/base-nova/ui-rtl/popover"
|
||||
import { Separator } from "@/styles/base-nova/ui-rtl/separator"
|
||||
import { Textarea } from "@/styles/base-nova/ui-rtl/textarea"
|
||||
|
||||
const translations = {
|
||||
ar: {
|
||||
|
||||
@@ -1,12 +1,15 @@
|
||||
"use client"
|
||||
|
||||
import { PlusIcon } from "lucide-react"
|
||||
|
||||
import { useLanguageContext } from "@/components/language-selector"
|
||||
import {
|
||||
Avatar,
|
||||
AvatarFallback,
|
||||
AvatarGroup,
|
||||
AvatarImage,
|
||||
} from "@/examples/base/ui-rtl/avatar"
|
||||
import { Button } from "@/examples/base/ui-rtl/button"
|
||||
} from "@/styles/base-nova/ui-rtl/avatar"
|
||||
import { Button } from "@/styles/base-nova/ui-rtl/button"
|
||||
import {
|
||||
Empty,
|
||||
EmptyContent,
|
||||
@@ -14,10 +17,7 @@ import {
|
||||
EmptyHeader,
|
||||
EmptyMedia,
|
||||
EmptyTitle,
|
||||
} from "@/examples/base/ui-rtl/empty"
|
||||
import { PlusIcon } from "lucide-react"
|
||||
|
||||
import { useLanguageContext } from "@/components/language-selector"
|
||||
} from "@/styles/base-nova/ui-rtl/empty"
|
||||
|
||||
const translations = {
|
||||
ar: {
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
"use client"
|
||||
|
||||
import { Checkbox } from "@/examples/base/ui-rtl/checkbox"
|
||||
import { Field, FieldLabel } from "@/examples/base/ui-rtl/field"
|
||||
|
||||
import { useLanguageContext } from "@/components/language-selector"
|
||||
import { Checkbox } from "@/styles/base-nova/ui-rtl/checkbox"
|
||||
import { Field, FieldLabel } from "@/styles/base-nova/ui-rtl/field"
|
||||
|
||||
const translations = {
|
||||
ar: {
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
"use client"
|
||||
|
||||
import { Button } from "@/examples/base/ui-rtl/button"
|
||||
import { Checkbox } from "@/examples/base/ui-rtl/checkbox"
|
||||
import { useLanguageContext } from "@/components/language-selector"
|
||||
import { Button } from "@/styles/base-nova/ui-rtl/button"
|
||||
import { Checkbox } from "@/styles/base-nova/ui-rtl/checkbox"
|
||||
import {
|
||||
Field,
|
||||
FieldDescription,
|
||||
@@ -10,8 +11,8 @@ import {
|
||||
FieldLegend,
|
||||
FieldSeparator,
|
||||
FieldSet,
|
||||
} from "@/examples/base/ui-rtl/field"
|
||||
import { Input } from "@/examples/base/ui-rtl/input"
|
||||
} from "@/styles/base-nova/ui-rtl/field"
|
||||
import { Input } from "@/styles/base-nova/ui-rtl/input"
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
@@ -19,10 +20,8 @@ import {
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "@/examples/base/ui-rtl/select"
|
||||
import { Textarea } from "@/examples/base/ui-rtl/textarea"
|
||||
|
||||
import { useLanguageContext } from "@/components/language-selector"
|
||||
} from "@/styles/base-nova/ui-rtl/select"
|
||||
import { Textarea } from "@/styles/base-nova/ui-rtl/textarea"
|
||||
|
||||
const translations = {
|
||||
ar: {
|
||||
@@ -140,7 +139,7 @@ export function FieldDemo() {
|
||||
<div className="grid grid-cols-2 gap-4">
|
||||
<Field>
|
||||
<FieldLabel htmlFor="rtl-exp-month">{t.month}</FieldLabel>
|
||||
<Select defaultValue="" items={months}>
|
||||
<Select defaultValue="">
|
||||
<SelectTrigger id="rtl-exp-month">
|
||||
<SelectValue placeholder="MM" />
|
||||
</SelectTrigger>
|
||||
@@ -157,7 +156,7 @@ export function FieldDemo() {
|
||||
</Field>
|
||||
<Field>
|
||||
<FieldLabel htmlFor="rtl-exp-year">{t.year}</FieldLabel>
|
||||
<Select defaultValue="" items={years}>
|
||||
<Select defaultValue="">
|
||||
<SelectTrigger id="rtl-exp-year">
|
||||
<SelectValue placeholder="YYYY" />
|
||||
</SelectTrigger>
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
"use client"
|
||||
|
||||
import { Card, CardContent } from "@/examples/base/ui-rtl/card"
|
||||
import { Checkbox } from "@/examples/base/ui-rtl/checkbox"
|
||||
import { useLanguageContext } from "@/components/language-selector"
|
||||
import { Card, CardContent } from "@/styles/base-nova/ui-rtl/card"
|
||||
import { Checkbox } from "@/styles/base-nova/ui-rtl/checkbox"
|
||||
import {
|
||||
Field,
|
||||
FieldDescription,
|
||||
@@ -10,9 +11,7 @@ import {
|
||||
FieldLegend,
|
||||
FieldSet,
|
||||
FieldTitle,
|
||||
} from "@/examples/base/ui-rtl/field"
|
||||
|
||||
import { useLanguageContext } from "@/components/language-selector"
|
||||
} from "@/styles/base-nova/ui-rtl/field"
|
||||
|
||||
const translations = {
|
||||
ar: {
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
"use client"
|
||||
|
||||
import { useState } from "react"
|
||||
|
||||
import { useLanguageContext } from "@/components/language-selector"
|
||||
import {
|
||||
Field,
|
||||
FieldDescription,
|
||||
FieldTitle,
|
||||
} from "@/examples/base/ui-rtl/field"
|
||||
import { Slider } from "@/examples/base/ui-rtl/slider"
|
||||
|
||||
import { useLanguageContext } from "@/components/language-selector"
|
||||
} from "@/styles/base-nova/ui-rtl/field"
|
||||
import { Slider } from "@/styles/base-nova/ui-rtl/slider"
|
||||
|
||||
const translations = {
|
||||
ar: {
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
"use client"
|
||||
|
||||
import { DirectionProvider } from "@/examples/base/ui-rtl/direction"
|
||||
import { FieldSeparator } from "@/examples/base/ui-rtl/field"
|
||||
|
||||
import {
|
||||
LanguageProvider,
|
||||
LanguageSelector,
|
||||
useLanguageContext,
|
||||
} from "@/components/language-selector"
|
||||
import { DirectionProvider } from "@/styles/base-nova/ui-rtl/direction"
|
||||
import { FieldSeparator } from "@/styles/base-nova/ui-rtl/field"
|
||||
|
||||
import { AppearanceSettings } from "./appearance-settings"
|
||||
import { ButtonGroupDemo } from "./button-group-demo"
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
"use client"
|
||||
|
||||
import * as React from "react"
|
||||
import { IconInfoCircle, IconStar } from "@tabler/icons-react"
|
||||
|
||||
import { useLanguageContext } from "@/components/language-selector"
|
||||
import {
|
||||
InputGroup,
|
||||
InputGroupAddon,
|
||||
InputGroupButton,
|
||||
InputGroupInput,
|
||||
} from "@/examples/base/ui-rtl/input-group"
|
||||
import { Label } from "@/examples/base/ui-rtl/label"
|
||||
} from "@/styles/base-nova/ui-rtl/input-group"
|
||||
import { Label } from "@/styles/base-nova/ui-rtl/label"
|
||||
import {
|
||||
Popover,
|
||||
PopoverContent,
|
||||
PopoverTrigger,
|
||||
} from "@/examples/base/ui-rtl/popover"
|
||||
import { IconInfoCircle, IconStar } from "@tabler/icons-react"
|
||||
|
||||
import { useLanguageContext } from "@/components/language-selector"
|
||||
} from "@/styles/base-nova/ui-rtl/popover"
|
||||
|
||||
const translations = {
|
||||
ar: {
|
||||
|
||||
@@ -1,25 +1,5 @@
|
||||
"use client"
|
||||
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/examples/base/ui-rtl/dropdown-menu"
|
||||
import {
|
||||
InputGroup,
|
||||
InputGroupAddon,
|
||||
InputGroupButton,
|
||||
InputGroupInput,
|
||||
InputGroupText,
|
||||
InputGroupTextarea,
|
||||
} from "@/examples/base/ui-rtl/input-group"
|
||||
import { Separator } from "@/examples/base/ui-rtl/separator"
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipTrigger,
|
||||
} from "@/examples/base/ui-rtl/tooltip"
|
||||
import {
|
||||
IconCheck,
|
||||
IconChevronDown,
|
||||
@@ -29,6 +9,26 @@ import {
|
||||
import { ArrowUpIcon, Search } from "lucide-react"
|
||||
|
||||
import { useLanguageContext } from "@/components/language-selector"
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/styles/base-nova/ui-rtl/dropdown-menu"
|
||||
import {
|
||||
InputGroup,
|
||||
InputGroupAddon,
|
||||
InputGroupButton,
|
||||
InputGroupInput,
|
||||
InputGroupText,
|
||||
InputGroupTextarea,
|
||||
} from "@/styles/base-nova/ui-rtl/input-group"
|
||||
import { Separator } from "@/styles/base-nova/ui-rtl/separator"
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipTrigger,
|
||||
} from "@/styles/base-nova/ui-rtl/tooltip"
|
||||
|
||||
const translations = {
|
||||
ar: {
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
"use client"
|
||||
|
||||
import { Button } from "@/examples/base/ui-rtl/button"
|
||||
import { BadgeCheckIcon, ChevronRightIcon } from "lucide-react"
|
||||
|
||||
import { useLanguageContext } from "@/components/language-selector"
|
||||
import { Button } from "@/styles/base-nova/ui-rtl/button"
|
||||
import {
|
||||
Item,
|
||||
ItemActions,
|
||||
@@ -8,10 +11,7 @@ import {
|
||||
ItemDescription,
|
||||
ItemMedia,
|
||||
ItemTitle,
|
||||
} from "@/examples/base/ui-rtl/item"
|
||||
import { BadgeCheckIcon, ChevronRightIcon } from "lucide-react"
|
||||
|
||||
import { useLanguageContext } from "@/components/language-selector"
|
||||
} from "@/styles/base-nova/ui-rtl/item"
|
||||
|
||||
const translations = {
|
||||
ar: {
|
||||
|
||||
@@ -1,47 +1,6 @@
|
||||
"use client"
|
||||
|
||||
import { useMemo, useState } from "react"
|
||||
import {
|
||||
Avatar,
|
||||
AvatarFallback,
|
||||
AvatarImage,
|
||||
} from "@/examples/base/ui-rtl/avatar"
|
||||
import { Badge } from "@/examples/base/ui-rtl/badge"
|
||||
import {
|
||||
Command,
|
||||
CommandEmpty,
|
||||
CommandGroup,
|
||||
CommandInput,
|
||||
CommandItem,
|
||||
CommandList,
|
||||
} from "@/examples/base/ui-rtl/command"
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuCheckboxItem,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuGroup,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuLabel,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuSub,
|
||||
DropdownMenuSubContent,
|
||||
DropdownMenuSubTrigger,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/examples/base/ui-rtl/dropdown-menu"
|
||||
import { Field, FieldLabel } from "@/examples/base/ui-rtl/field"
|
||||
import {
|
||||
InputGroup,
|
||||
InputGroupAddon,
|
||||
InputGroupButton,
|
||||
InputGroupTextarea,
|
||||
} from "@/examples/base/ui-rtl/input-group"
|
||||
import { Popover, PopoverContent } from "@/examples/base/ui-rtl/popover"
|
||||
import { Switch } from "@/examples/base/ui-rtl/switch"
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipTrigger,
|
||||
} from "@/examples/base/ui-rtl/tooltip"
|
||||
import {
|
||||
IconApps,
|
||||
IconArrowUp,
|
||||
@@ -55,6 +14,47 @@ import {
|
||||
} from "@tabler/icons-react"
|
||||
|
||||
import { useLanguageContext } from "@/components/language-selector"
|
||||
import {
|
||||
Avatar,
|
||||
AvatarFallback,
|
||||
AvatarImage,
|
||||
} from "@/styles/base-nova/ui-rtl/avatar"
|
||||
import { Badge } from "@/styles/base-nova/ui-rtl/badge"
|
||||
import {
|
||||
Command,
|
||||
CommandEmpty,
|
||||
CommandGroup,
|
||||
CommandInput,
|
||||
CommandItem,
|
||||
CommandList,
|
||||
} from "@/styles/base-nova/ui-rtl/command"
|
||||
import {
|
||||
DropdownMenu,
|
||||
DropdownMenuCheckboxItem,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuGroup,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuLabel,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuSub,
|
||||
DropdownMenuSubContent,
|
||||
DropdownMenuSubTrigger,
|
||||
DropdownMenuTrigger,
|
||||
} from "@/styles/base-nova/ui-rtl/dropdown-menu"
|
||||
import { Field, FieldLabel } from "@/styles/base-nova/ui-rtl/field"
|
||||
import {
|
||||
InputGroup,
|
||||
InputGroupAddon,
|
||||
InputGroupButton,
|
||||
InputGroupTextarea,
|
||||
} from "@/styles/base-nova/ui-rtl/input-group"
|
||||
import { Popover, PopoverContent } from "@/styles/base-nova/ui-rtl/popover"
|
||||
import { Switch } from "@/styles/base-nova/ui-rtl/switch"
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipTrigger,
|
||||
} from "@/styles/base-nova/ui-rtl/tooltip"
|
||||
|
||||
const translations = {
|
||||
ar: {
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
"use client"
|
||||
|
||||
import { Badge } from "@/examples/base/ui-rtl/badge"
|
||||
import { Spinner } from "@/examples/base/ui-rtl/spinner"
|
||||
|
||||
import { useLanguageContext } from "@/components/language-selector"
|
||||
import { Badge } from "@/styles/base-nova/ui-rtl/badge"
|
||||
import { Spinner } from "@/styles/base-nova/ui-rtl/spinner"
|
||||
|
||||
const translations = {
|
||||
ar: {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
"use client"
|
||||
|
||||
import { Button } from "@/examples/base/ui-rtl/button"
|
||||
import { useLanguageContext } from "@/components/language-selector"
|
||||
import { Button } from "@/styles/base-nova/ui-rtl/button"
|
||||
import {
|
||||
Empty,
|
||||
EmptyContent,
|
||||
@@ -8,10 +9,8 @@ import {
|
||||
EmptyHeader,
|
||||
EmptyMedia,
|
||||
EmptyTitle,
|
||||
} from "@/examples/base/ui-rtl/empty"
|
||||
import { Spinner } from "@/examples/base/ui-rtl/spinner"
|
||||
|
||||
import { useLanguageContext } from "@/components/language-selector"
|
||||
} from "@/styles/base-nova/ui-rtl/empty"
|
||||
import { Spinner } from "@/styles/base-nova/ui-rtl/spinner"
|
||||
|
||||
const translations = {
|
||||
ar: {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
"use client"
|
||||
|
||||
import Script from "next/script"
|
||||
import { type RegistryItem } from "shadcn/schema"
|
||||
|
||||
import {
|
||||
Command,
|
||||
CommandDialog,
|
||||
@@ -9,9 +11,7 @@ import {
|
||||
CommandInput,
|
||||
CommandItem,
|
||||
CommandList,
|
||||
} from "@/examples/base/ui/command"
|
||||
import { type RegistryItem } from "shadcn/schema"
|
||||
|
||||
} from "@/styles/base-nova/ui/command"
|
||||
import { useActionMenu } from "@/app/(create)/hooks/use-action-menu"
|
||||
|
||||
export const CMD_K_FORWARD_TYPE = "cmd-k-forward"
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
"use client"
|
||||
|
||||
import * as React from "react"
|
||||
import { Button } from "@/examples/base/ui/button"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
import { copyToClipboardWithMeta } from "@/components/copy-button"
|
||||
import { Button } from "@/styles/base-nova/ui/button"
|
||||
import { usePresetCode } from "@/app/(create)/hooks/use-design-system"
|
||||
|
||||
export function CopyPreset({ className }: React.ComponentProps<typeof Button>) {
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
"use client"
|
||||
|
||||
import * as React from "react"
|
||||
import { type RegistryItem } from "shadcn/schema"
|
||||
|
||||
import { useIsMobile } from "@/hooks/use-mobile"
|
||||
import { getThemesForBaseColor, STYLES } from "@/registry/config"
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardFooter,
|
||||
CardHeader,
|
||||
} from "@/examples/base/ui/card"
|
||||
import { FieldGroup, FieldSeparator } from "@/examples/base/ui/field"
|
||||
import { type RegistryItem } from "shadcn/schema"
|
||||
|
||||
import { useIsMobile } from "@/hooks/use-mobile"
|
||||
import { getThemesForBaseColor, STYLES } from "@/registry/config"
|
||||
} from "@/styles/base-nova/ui/card"
|
||||
import { FieldGroup, FieldSeparator } from "@/styles/base-nova/ui/field"
|
||||
import { MenuAccentPicker } from "@/app/(create)/components/accent-picker"
|
||||
import { ActionMenu } from "@/app/(create)/components/action-menu"
|
||||
import { BaseColorPicker } from "@/app/(create)/components/base-color-picker"
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
"use client"
|
||||
|
||||
import Script from "next/script"
|
||||
import { Button } from "@/examples/base/ui/button"
|
||||
import { Redo02Icon, Undo02Icon } from "@hugeicons/core-free-icons"
|
||||
import { HugeiconsIcon } from "@hugeicons/react"
|
||||
|
||||
import { Button } from "@/styles/base-nova/ui/button"
|
||||
import { useHistory } from "@/app/(create)/hooks/use-history"
|
||||
|
||||
export const UNDO_FORWARD_TYPE = "undo-forward"
|
||||
|
||||
@@ -2,11 +2,16 @@
|
||||
|
||||
import * as React from "react"
|
||||
import Link from "next/link"
|
||||
import { ChevronRightIcon } from "lucide-react"
|
||||
import { type RegistryItem } from "shadcn/schema"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
import { type Base } from "@/registry/bases"
|
||||
import {
|
||||
Collapsible,
|
||||
CollapsibleContent,
|
||||
CollapsibleTrigger,
|
||||
} from "@/examples/base/ui/collapsible"
|
||||
} from "@/styles/base-nova/ui/collapsible"
|
||||
import {
|
||||
Sidebar,
|
||||
SidebarContent,
|
||||
@@ -15,12 +20,7 @@ import {
|
||||
SidebarMenu,
|
||||
SidebarMenuButton,
|
||||
SidebarMenuItem,
|
||||
} from "@/examples/base/ui/sidebar"
|
||||
import { ChevronRightIcon } from "lucide-react"
|
||||
import { type RegistryItem } from "shadcn/schema"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
import { type Base } from "@/registry/bases"
|
||||
} from "@/styles/base-nova/ui/sidebar"
|
||||
import { useDesignSystemSearchParams } from "@/app/(create)/lib/search-params"
|
||||
import { groupItemsByType } from "@/app/(create)/lib/utils"
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
"use client"
|
||||
|
||||
import * as React from "react"
|
||||
import { type Button } from "@/examples/base/ui/button"
|
||||
import { Menu09Icon } from "@hugeicons/core-free-icons"
|
||||
import { HugeiconsIcon } from "@hugeicons/react"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
import { type Button } from "@/styles/base-nova/ui/button"
|
||||
import {
|
||||
Picker,
|
||||
PickerContent,
|
||||
@@ -73,7 +73,7 @@ export function MainMenu({ className }: React.ComponentProps<typeof Button>) {
|
||||
</PickerItem>
|
||||
<PickerSeparator />
|
||||
<PickerItem onClick={() => setShowResetDialog(true)}>
|
||||
Reset
|
||||
Reset <PickerShortcut>⇧R</PickerShortcut>
|
||||
</PickerItem>
|
||||
</PickerGroup>
|
||||
</PickerContent>
|
||||
|
||||
@@ -104,7 +104,7 @@ export function MenuColorPicker({
|
||||
<PickerTrigger>
|
||||
<div className="flex flex-col justify-start text-left">
|
||||
<div className="text-xs text-muted-foreground">Menu</div>
|
||||
<div className="line-clamp-1 text-sm font-medium text-foreground">
|
||||
<div className="line-clamp-1 max-w-[80%] truncate text-sm font-medium text-foreground">
|
||||
{currentMenu?.label}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
|
||||
import * as React from "react"
|
||||
import Script from "next/script"
|
||||
import { Button } from "@/examples/base/ui/button"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
import { Button } from "@/styles/base-nova/ui/button"
|
||||
import { useThemeToggle } from "@/app/(create)/hooks/use-theme-toggle"
|
||||
|
||||
export const DARK_MODE_FORWARD_TYPE = "dark-mode-forward"
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
import { DARK_MODE_FORWARD_TYPE } from "@/app/(create)/components/mode-switcher"
|
||||
import { RANDOMIZE_FORWARD_TYPE } from "@/app/(create)/components/random-button"
|
||||
import { sendToIframe } from "@/app/(create)/hooks/use-iframe-sync"
|
||||
import { RESET_FORWARD_TYPE } from "@/app/(create)/hooks/use-reset"
|
||||
import {
|
||||
serializeDesignSystemSearchParams,
|
||||
useDesignSystemSearchParams,
|
||||
@@ -70,6 +71,15 @@ function handleMessage(event: MessageEvent) {
|
||||
cancelable: true,
|
||||
})
|
||||
)
|
||||
} else if (type === RESET_FORWARD_TYPE) {
|
||||
document.dispatchEvent(
|
||||
new KeyboardEvent("keydown", {
|
||||
key: "R",
|
||||
shiftKey: true,
|
||||
bubbles: true,
|
||||
cancelable: true,
|
||||
})
|
||||
)
|
||||
} else if (type === DARK_MODE_FORWARD_TYPE) {
|
||||
document.dispatchEvent(
|
||||
new KeyboardEvent("keydown", {
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
"use client"
|
||||
|
||||
import * as React from "react"
|
||||
import { Button } from "@/examples/base/ui/button"
|
||||
import { Copy01Icon, Globe02Icon, Tick02Icon } from "@hugeicons/core-free-icons"
|
||||
import { HugeiconsIcon } from "@hugeicons/react"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
import { useConfig } from "@/hooks/use-config"
|
||||
import { copyToClipboardWithMeta } from "@/components/copy-button"
|
||||
import { BASES, type BaseName } from "@/registry/config"
|
||||
import { Button } from "@/styles/base-nova/ui/button"
|
||||
import {
|
||||
Dialog,
|
||||
DialogContent,
|
||||
@@ -10,7 +17,7 @@ import {
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
DialogTrigger,
|
||||
} from "@/examples/base/ui/dialog"
|
||||
} from "@/styles/base-nova/ui/dialog"
|
||||
import {
|
||||
Field,
|
||||
FieldContent,
|
||||
@@ -20,22 +27,15 @@ import {
|
||||
FieldSeparator,
|
||||
FieldSet,
|
||||
FieldTitle,
|
||||
} from "@/examples/base/ui/field"
|
||||
import { RadioGroup, RadioGroupItem } from "@/examples/base/ui/radio-group"
|
||||
import { Switch } from "@/examples/base/ui/switch"
|
||||
} from "@/styles/base-nova/ui/field"
|
||||
import { RadioGroup, RadioGroupItem } from "@/styles/base-nova/ui/radio-group"
|
||||
import { Switch } from "@/styles/base-nova/ui/switch"
|
||||
import {
|
||||
Tabs,
|
||||
TabsContent,
|
||||
TabsList,
|
||||
TabsTrigger,
|
||||
} from "@/examples/base/ui/tabs"
|
||||
import { Copy01Icon, Globe02Icon, Tick02Icon } from "@hugeicons/core-free-icons"
|
||||
import { HugeiconsIcon } from "@hugeicons/react"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
import { useConfig } from "@/hooks/use-config"
|
||||
import { copyToClipboardWithMeta } from "@/components/copy-button"
|
||||
import { BASES, type BaseName } from "@/registry/config"
|
||||
} from "@/styles/base-nova/ui/tabs"
|
||||
import { usePresetCode } from "@/app/(create)/hooks/use-design-system"
|
||||
import {
|
||||
useDesignSystemSearchParams,
|
||||
@@ -130,7 +130,7 @@ export function ProjectForm({
|
||||
<DialogTrigger render={<Button className={cn(className)} />}>
|
||||
Create Project
|
||||
</DialogTrigger>
|
||||
<DialogContent className="dark no-scrollbar max-h-[calc(100svh-2rem)] overflow-y-auto rounded-2xl border-0 bg-neutral-800 p-6 text-foreground shadow-xl ring-1 ring-neutral-950/80 backdrop-blur-xl [--border:var(--color-neutral-700)]! sm:max-w-sm">
|
||||
<DialogContent className="dark no-scrollbar max-h-[calc(100svh-2rem)] overflow-y-auto rounded-2xl p-6 shadow-xl **:data-[slot=field-separator]:h-2 sm:max-w-sm">
|
||||
<DialogHeader>
|
||||
<DialogTitle>Create Project</DialogTitle>
|
||||
<DialogDescription>
|
||||
@@ -209,7 +209,7 @@ export function ProjectForm({
|
||||
packageManager: value as PackageManager,
|
||||
}))
|
||||
}}
|
||||
className="min-w-0 gap-0 overflow-hidden rounded-xl border-0 bg-neutral-950/20 ring-1 ring-neutral-950/80 dark:bg-neutral-900/50 dark:ring-neutral-700/50"
|
||||
className="min-w-0 gap-0 overflow-hidden rounded-xl border-0 ring-1 ring-border"
|
||||
>
|
||||
<div className="flex items-center gap-2 py-1 pr-1.5 pl-1">
|
||||
<TabsList className="bg-transparent font-mono">
|
||||
@@ -242,7 +242,7 @@ export function ProjectForm({
|
||||
{Object.entries(commands).map(([key, cmd]) => {
|
||||
return (
|
||||
<TabsContent key={key} value={key}>
|
||||
<div className="relative overflow-hidden border-t border-neutral-700/50 bg-neutral-900/50 px-3 py-3 text-neutral-100">
|
||||
<div className="relative overflow-hidden border-t bg-popover p-3">
|
||||
<div className="no-scrollbar overflow-x-auto">
|
||||
<code className="font-mono text-sm whitespace-nowrap">
|
||||
{cmd}
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
"use client"
|
||||
|
||||
import Script from "next/script"
|
||||
import { Button } from "@/examples/base/ui/button"
|
||||
import { DiceFaces05Icon } from "@hugeicons/core-free-icons"
|
||||
import { HugeiconsIcon } from "@hugeicons/react"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
import { Button } from "@/styles/base-nova/ui/button"
|
||||
import { useRandom } from "@/app/(create)/hooks/use-random"
|
||||
import { RESET_FORWARD_TYPE } from "@/app/(create)/hooks/use-reset"
|
||||
|
||||
export const RANDOMIZE_FORWARD_TYPE = "randomize-forward"
|
||||
|
||||
@@ -40,7 +41,7 @@ export function RandomizeScript() {
|
||||
dangerouslySetInnerHTML={{
|
||||
__html: `
|
||||
(function() {
|
||||
// Forward R key
|
||||
// Forward r key (shuffle) and Shift+R (reset).
|
||||
document.addEventListener('keydown', function(e) {
|
||||
if ((e.key === 'r' || e.key === 'R') && !e.metaKey && !e.ctrlKey) {
|
||||
if (
|
||||
@@ -53,8 +54,11 @@ export function RandomizeScript() {
|
||||
}
|
||||
e.preventDefault();
|
||||
if (window.parent && window.parent !== window) {
|
||||
var type = e.shiftKey
|
||||
? '${RESET_FORWARD_TYPE}'
|
||||
: '${RANDOMIZE_FORWARD_TYPE}';
|
||||
window.parent.postMessage({
|
||||
type: '${RANDOMIZE_FORWARD_TYPE}',
|
||||
type: type,
|
||||
key: e.key
|
||||
}, '*');
|
||||
}
|
||||
|
||||
@@ -9,8 +9,7 @@ import {
|
||||
AlertDialogFooter,
|
||||
AlertDialogHeader,
|
||||
AlertDialogTitle,
|
||||
} from "@/examples/base/ui/alert-dialog"
|
||||
|
||||
} from "@/styles/base-nova/ui/alert-dialog"
|
||||
import { useReset } from "@/app/(create)/hooks/use-reset"
|
||||
|
||||
export function ResetDialog() {
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
"use client"
|
||||
|
||||
import * as React from "react"
|
||||
import { Button } from "@/examples/base/ui/button"
|
||||
import { Share03Icon, Tick02Icon } from "@hugeicons/core-free-icons"
|
||||
import { HugeiconsIcon } from "@hugeicons/react"
|
||||
|
||||
import { copyToClipboardWithMeta } from "@/components/copy-button"
|
||||
import { Button } from "@/styles/base-nova/ui/button"
|
||||
import { usePresetCode } from "@/app/(create)/hooks/use-design-system"
|
||||
import { useDesignSystemSearchParams } from "@/app/(create)/lib/search-params"
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
"use client"
|
||||
|
||||
import * as React from "react"
|
||||
import { Button } from "@/examples/base/ui/button"
|
||||
import { Skeleton } from "@/examples/base/ui/skeleton"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
import { useIsMobile } from "@/hooks/use-mobile"
|
||||
import { useMounted } from "@/hooks/use-mounted"
|
||||
import { Icons } from "@/components/icons"
|
||||
import { Button } from "@/styles/base-nova/ui/button"
|
||||
import { Skeleton } from "@/styles/base-nova/ui/skeleton"
|
||||
import { useDesignSystemSearchParams } from "@/app/(create)/lib/search-params"
|
||||
|
||||
export function V0Button({ className }: { className?: string }) {
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
"use client"
|
||||
|
||||
import * as React from "react"
|
||||
import { Button } from "@/examples/base/ui/button"
|
||||
|
||||
import { Icons } from "@/components/icons"
|
||||
import { Button } from "@/styles/base-nova/ui/button"
|
||||
import {
|
||||
Dialog,
|
||||
DialogClose,
|
||||
@@ -10,9 +12,7 @@ import {
|
||||
DialogFooter,
|
||||
DialogHeader,
|
||||
DialogTitle,
|
||||
} from "@/examples/base/ui/dialog"
|
||||
|
||||
import { Icons } from "@/components/icons"
|
||||
} from "@/styles/base-nova/ui/dialog"
|
||||
|
||||
const STORAGE_KEY = "shadcn-create-welcome-dialog"
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ export default async function CreatePage() {
|
||||
return (
|
||||
<div
|
||||
data-slot="layout"
|
||||
className="group/layout relative z-10 flex h-svh flex-col overflow-hidden section-soft [--customizer-width:--spacing(56)] [--gap:--spacing(4)] md:[--gap:--spacing(6)]"
|
||||
className="group/layout relative z-10 flex h-svh flex-col overflow-hidden section-soft [--customizer-width:--spacing(48)] [--gap:--spacing(4)] md:[--gap:--spacing(6)] 2xl:[--customizer-width:--spacing(56)]"
|
||||
>
|
||||
<SiteHeader />
|
||||
<main
|
||||
|
||||
@@ -156,7 +156,7 @@ export function useRandom() {
|
||||
|
||||
React.useEffect(() => {
|
||||
const down = (e: KeyboardEvent) => {
|
||||
if ((e.key === "r" || e.key === "R") && !e.metaKey && !e.ctrlKey) {
|
||||
if (e.key === "r" && !e.shiftKey && !e.metaKey && !e.ctrlKey) {
|
||||
if (
|
||||
(e.target instanceof HTMLElement && e.target.isContentEditable) ||
|
||||
e.target instanceof HTMLInputElement ||
|
||||
|
||||
@@ -7,6 +7,7 @@ import { DEFAULT_CONFIG } from "@/registry/config"
|
||||
import { useDesignSystemSearchParams } from "@/app/(create)/lib/search-params"
|
||||
|
||||
const RESET_DIALOG_KEY = "create:reset-dialog-open"
|
||||
export const RESET_FORWARD_TYPE = "reset-forward"
|
||||
|
||||
export function useReset() {
|
||||
const [params, setParams] = useDesignSystemSearchParams()
|
||||
@@ -32,9 +33,9 @@ export function useReset() {
|
||||
menuColor: DEFAULT_CONFIG.menuColor,
|
||||
radius: DEFAULT_CONFIG.radius,
|
||||
template: DEFAULT_CONFIG.template,
|
||||
item: "preview",
|
||||
item: params.item,
|
||||
})
|
||||
}, [setParams, params.base])
|
||||
}, [setParams, params.base, params.item])
|
||||
|
||||
const handleShowResetDialogChange = React.useCallback(
|
||||
(open: boolean) => {
|
||||
@@ -48,6 +49,46 @@ export function useReset() {
|
||||
void setShowResetDialogData(false, { revalidate: false })
|
||||
}, [reset, setShowResetDialogData])
|
||||
|
||||
const showResetDialogRef = React.useRef(showResetDialog)
|
||||
React.useEffect(() => {
|
||||
showResetDialogRef.current = showResetDialog
|
||||
}, [showResetDialog])
|
||||
|
||||
const confirmResetRef = React.useRef(confirmReset)
|
||||
React.useEffect(() => {
|
||||
confirmResetRef.current = confirmReset
|
||||
}, [confirmReset])
|
||||
|
||||
React.useEffect(() => {
|
||||
const down = (e: KeyboardEvent) => {
|
||||
if (e.key === "R" && e.shiftKey && !e.metaKey && !e.ctrlKey) {
|
||||
if (
|
||||
(e.target instanceof HTMLElement && e.target.isContentEditable) ||
|
||||
e.target instanceof HTMLInputElement ||
|
||||
e.target instanceof HTMLTextAreaElement ||
|
||||
e.target instanceof HTMLSelectElement
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
e.preventDefault()
|
||||
|
||||
// If the dialog is already open, confirm the reset.
|
||||
if (showResetDialogRef.current) {
|
||||
confirmResetRef.current()
|
||||
return
|
||||
}
|
||||
|
||||
handleShowResetDialogChange(true)
|
||||
}
|
||||
}
|
||||
|
||||
document.addEventListener("keydown", down)
|
||||
return () => {
|
||||
document.removeEventListener("keydown", down)
|
||||
}
|
||||
}, [handleShowResetDialogChange])
|
||||
|
||||
return {
|
||||
reset,
|
||||
showResetDialog,
|
||||
|
||||
@@ -2,7 +2,10 @@
|
||||
|
||||
import * as React from "react"
|
||||
import { Label, Pie, PieChart, Sector } from "recharts"
|
||||
import { type PieSectorDataItem } from "recharts/types/polar/Pie"
|
||||
import type {
|
||||
PieSectorDataItem,
|
||||
PieSectorShapeProps,
|
||||
} from "recharts/types/polar/Pie"
|
||||
|
||||
import {
|
||||
Card,
|
||||
@@ -77,6 +80,26 @@ export function ChartVisitors() {
|
||||
)
|
||||
const months = React.useMemo(() => desktopData.map((item) => item.month), [])
|
||||
|
||||
const renderPieShape = React.useCallback(
|
||||
({ index, outerRadius = 0, ...props }: PieSectorShapeProps) => {
|
||||
if (index === activeIndex) {
|
||||
return (
|
||||
<g>
|
||||
<Sector {...props} outerRadius={outerRadius + 10} />
|
||||
<Sector
|
||||
{...props}
|
||||
outerRadius={outerRadius + 25}
|
||||
innerRadius={outerRadius + 12}
|
||||
/>
|
||||
</g>
|
||||
)
|
||||
}
|
||||
|
||||
return <Sector {...props} outerRadius={outerRadius} />
|
||||
},
|
||||
[activeIndex]
|
||||
)
|
||||
|
||||
return (
|
||||
<Card data-chart={id}>
|
||||
<ChartStyle id={id} config={chartConfig} />
|
||||
@@ -136,20 +159,7 @@ export function ChartVisitors() {
|
||||
nameKey="month"
|
||||
innerRadius={60}
|
||||
strokeWidth={5}
|
||||
activeIndex={activeIndex}
|
||||
activeShape={({
|
||||
outerRadius = 0,
|
||||
...props
|
||||
}: PieSectorDataItem) => (
|
||||
<g>
|
||||
<Sector {...props} outerRadius={outerRadius + 10} />
|
||||
<Sector
|
||||
{...props}
|
||||
outerRadius={outerRadius + 25}
|
||||
innerRadius={outerRadius + 12}
|
||||
/>
|
||||
</g>
|
||||
)}
|
||||
shape={renderPieShape}
|
||||
>
|
||||
<Label
|
||||
content={({ viewBox }) => {
|
||||
|
||||
@@ -86,7 +86,7 @@ export function ChartBarMixed() {
|
||||
cursor={false}
|
||||
content={<ChartTooltipContent hideLabel />}
|
||||
/>
|
||||
<Bar dataKey="visitors" layout="vertical" radius={5} />
|
||||
<Bar dataKey="visitors" radius={5} />
|
||||
</BarChart>
|
||||
</ChartContainer>
|
||||
</CardContent>
|
||||
|
||||
@@ -12,7 +12,7 @@ import {
|
||||
import { absoluteUrl } from "@/lib/utils"
|
||||
import { getStyle, legacyStyles, type Style } from "@/registry/_legacy-styles"
|
||||
|
||||
import "@/styles/legacy-themes.css"
|
||||
import "@/app/legacy-themes.css"
|
||||
|
||||
import { ComponentPreview } from "./component-preview"
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ import { TooltipProvider as BaseTooltipProvider } from "@/registry/bases/base/ui
|
||||
import { Toaster } from "@/registry/bases/radix/ui/sonner"
|
||||
import { TooltipProvider as RadixTooltipProvider } from "@/registry/bases/radix/ui/tooltip"
|
||||
|
||||
import "@/styles/globals.css"
|
||||
import "@/app/globals.css"
|
||||
|
||||
export const metadata: Metadata = {
|
||||
title: {
|
||||
|
||||
@@ -2,11 +2,6 @@
|
||||
|
||||
import * as React from "react"
|
||||
import Link from "next/link"
|
||||
import {
|
||||
Popover,
|
||||
PopoverContent,
|
||||
PopoverTrigger,
|
||||
} from "@/examples/base/ui/popover"
|
||||
import { IconAlertCircle } from "@tabler/icons-react"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
@@ -21,6 +16,11 @@ import { DirectionProvider as BaseDirectionProvider } from "@/registry/bases/bas
|
||||
import { DirectionProvider as RadixDirectionProvider } from "@/registry/bases/radix/ui/direction"
|
||||
import { Button } from "@/registry/new-york-v4/ui/button"
|
||||
import { Separator } from "@/registry/new-york-v4/ui/separator"
|
||||
import {
|
||||
Popover,
|
||||
PopoverContent,
|
||||
PopoverTrigger,
|
||||
} from "@/styles/base-nova/ui/popover"
|
||||
|
||||
export function ComponentPreviewTabs({
|
||||
className,
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
"use client"
|
||||
|
||||
import * as React from "react"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
@@ -8,9 +10,7 @@ import {
|
||||
SelectItem,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "@/examples/base/ui/select"
|
||||
|
||||
import { cn } from "@/lib/utils"
|
||||
} from "@/styles/base-nova/ui/select"
|
||||
|
||||
export type Language = "en" | "ar" | "he"
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { cn } from "@/lib/utils"
|
||||
import { Button } from "@/registry/new-york-v4/ui/button"
|
||||
import { Button } from "@/styles/base-nova/ui/button"
|
||||
|
||||
export function OpenInV0Cta({ className }: React.ComponentProps<"div">) {
|
||||
return (
|
||||
@@ -19,7 +19,7 @@ export function OpenInV0Cta({ className }: React.ComponentProps<"div">) {
|
||||
Vercel provides tools and infrastructure to deploy apps and features at
|
||||
scale.
|
||||
</div>
|
||||
<Button size="sm" className="mt-2 w-fit">
|
||||
<Button variant="outline" size="sm" className="mt-2 w-fit">
|
||||
Deploy Now
|
||||
</Button>
|
||||
<a
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import Link from "next/link"
|
||||
import { Button } from "@/examples/radix/ui/button"
|
||||
import { PlusSignIcon } from "@hugeicons/core-free-icons"
|
||||
import { HugeiconsIcon } from "@hugeicons/react"
|
||||
|
||||
@@ -14,6 +13,7 @@ import { MobileNav } from "@/components/mobile-nav"
|
||||
import { ModeSwitcher } from "@/components/mode-switcher"
|
||||
import { SiteConfig } from "@/components/site-config"
|
||||
import { Separator } from "@/registry/new-york-v4/ui/separator"
|
||||
import { Button } from "@/styles/radix-nova/ui/button"
|
||||
import { ProjectForm } from "@/app/(create)/components/project-form"
|
||||
import { V0Button } from "@/app/(create)/components/v0-button"
|
||||
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
"use client"
|
||||
|
||||
import { Label } from "@/examples/base/ui/label"
|
||||
import { THEMES } from "@/lib/themes"
|
||||
import { cn } from "@/lib/utils"
|
||||
import { useThemeConfig } from "@/components/active-theme"
|
||||
import { Label } from "@/styles/base-nova/ui/label"
|
||||
import {
|
||||
Select,
|
||||
SelectContent,
|
||||
@@ -9,11 +12,7 @@ import {
|
||||
SelectLabel,
|
||||
SelectTrigger,
|
||||
SelectValue,
|
||||
} from "@/examples/base/ui/select"
|
||||
|
||||
import { THEMES } from "@/lib/themes"
|
||||
import { cn } from "@/lib/utils"
|
||||
import { useThemeConfig } from "@/components/active-theme"
|
||||
} from "@/styles/base-nova/ui/select"
|
||||
|
||||
import { CopyCodeButton } from "./theme-customizer"
|
||||
|
||||
|
||||
@@ -74,21 +74,21 @@ Path to the CSS file that imports Tailwind CSS into your project.
|
||||
|
||||
### tailwind.baseColor
|
||||
|
||||
This is used to generate the default color palette for your components. **This cannot be changed after initialization.**
|
||||
This is used to generate the default theme tokens for your components. **This cannot be changed after initialization.**
|
||||
|
||||
```json title="components.json"
|
||||
{
|
||||
"tailwind": {
|
||||
"baseColor": "gray" | "neutral" | "slate" | "stone" | "zinc" | "mauve" | "olive" | "mist" | "taupe"
|
||||
"baseColor": "neutral" | "stone" | "zinc" | "mauve" | "olive" | "mist" | "taupe"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### tailwind.cssVariables
|
||||
|
||||
You can choose between using CSS variables or Tailwind CSS utility classes for theming.
|
||||
We use and recommend CSS variables for theming.
|
||||
|
||||
To use utility classes for theming set `tailwind.cssVariables` to `false`. For CSS variables, set `tailwind.cssVariables` to `true`.
|
||||
Set `tailwind.cssVariables` to `true` to generate semantic theme tokens like `background`, `foreground`, and `primary`. Set it to `false` to generate inline Tailwind color utilities instead.
|
||||
|
||||
```json title="components.json"
|
||||
{
|
||||
|
||||
@@ -17,6 +17,6 @@ description: Every component recreated in Figma. With customizable props, typogr
|
||||
## Paid
|
||||
|
||||
- [shadcn/ui kit](https://shadcndesign.com) by [Matt Wierzbicki](https://x.com/matsugfx) - A premium, always up-to-date UI kit for Figma - shadcn/ui compatible and optimized for smooth design-to-dev handoff.
|
||||
- [Shadcraft UI Kit](https://shadcraft.com) - The most advanced shadcn-compatible kit with instant theming via [tweakcn](https://tweakcn.com), a pro library of components and templates, and complete coverage of shadcn components and blocks.
|
||||
- [shadcncraft Design System](https://shadcncraft.com) - Production-ready shadcn/ui kit with Pro React blocks and 1:1 Figma alignment. Design and ship faster with tweakcn theming, AI-assisted workflows, and Figma to React export, built for real product UIs.
|
||||
- [shadcn/studio UI Kit](https://shadcnstudio.com/figma) - Accelerate design & development with a shadcn/ui compatible Figma kit with updated components, 550+ blocks, 10+ templates, 20+ themes, and an AI tool that converts designs into shadcn/ui code.
|
||||
- [Shadcnblocks.com](https://www.shadcnblocks.com) - A Premium Shadcn Figma UI Kit with components, 500+ pro blocks, shadcn theme variables, light/dark mode and Figma MCP ready.
|
||||
|
||||
@@ -1,46 +1,48 @@
|
||||
---
|
||||
title: Theming
|
||||
description: Using CSS Variables and color utilities for theming.
|
||||
description: Using CSS variables and theme tokens.
|
||||
---
|
||||
|
||||
You can choose between using CSS variables (recommended) or utility classes for theming.
|
||||
<Callout>
|
||||
|
||||
## CSS Variables
|
||||
Want to build your theme visually? Use [shadcn/create](/create) to preview colors, radius, fonts, and icons, then generate a preset for your project.
|
||||
|
||||
</Callout>
|
||||
|
||||
We use and recommend CSS variables for theming.
|
||||
|
||||
This gives you semantic theme tokens like `background`, `foreground`, and `primary` that components use by default. Override those tokens in your CSS to change the look of your app without rewriting component classes.
|
||||
|
||||
```tsx /bg-background/ /text-foreground/
|
||||
<div className="bg-background text-foreground" />
|
||||
```
|
||||
|
||||
To use CSS variables for theming set `tailwind.cssVariables` to `true` in your `components.json` file.
|
||||
To use CSS variables for theming, set `tailwind.cssVariables` to `true` in your `components.json` file. This is the default.
|
||||
|
||||
```json {8} title="components.json" showLineNumbers
|
||||
{
|
||||
"style": "new-york",
|
||||
"style": "base-nova",
|
||||
"rsc": true,
|
||||
"tailwind": {
|
||||
"config": "",
|
||||
"css": "app/globals.css",
|
||||
"baseColor": "neutral",
|
||||
"cssVariables": true
|
||||
},
|
||||
"aliases": {
|
||||
"components": "@/components",
|
||||
"utils": "@/lib/utils",
|
||||
"ui": "@/components/ui",
|
||||
"lib": "@/lib",
|
||||
"hooks": "@/hooks"
|
||||
},
|
||||
"iconLibrary": "lucide"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Convention
|
||||
Tailwind maps these tokens into utilities like `bg-background`, `text-foreground`, `border-border`, and `ring-ring`.
|
||||
|
||||
We use a simple `background` and `foreground` convention for colors. The `background` variable is used for the background color of the component and the `foreground` variable is used for the text color.
|
||||
Dark mode works by overriding the same tokens inside a `.dark` selector. See the [dark mode docs](/docs/dark-mode/next) for adding a theme provider and toggling the `.dark` class.
|
||||
|
||||
## Token Convention
|
||||
|
||||
We use semantic background and foreground pairs. The base token controls the surface color and the `-foreground` token controls the text and icon color that sits on that surface.
|
||||
|
||||
<Callout className="mt-4">
|
||||
|
||||
The `background` suffix is omitted when the variable is used for the background color of the component.
|
||||
The background suffix is omitted for the surface token. For example, `primary` pairs with `primary-foreground`.
|
||||
|
||||
</Callout>
|
||||
|
||||
@@ -57,11 +59,148 @@ The `background` color of the following component will be `var(--primary)` and t
|
||||
<div className="bg-primary text-primary-foreground">Hello</div>
|
||||
```
|
||||
|
||||
## List of variables
|
||||
## Theme Tokens
|
||||
|
||||
Here's the list of variables available for customization:
|
||||
These tokens live in your CSS file under `:root` and `.dark`.
|
||||
|
||||
| Token | What it controls | Used by |
|
||||
| ------------------------------------------------ | ------------------------------------------------------ | ---------------------------------------------------------------------------- |
|
||||
| `background` / `foreground` | The default app background and text color. | The page shell, page sections, and default text. |
|
||||
| `card` / `card-foreground` | Elevated surfaces and the content inside them. | `Card`, dashboard panels, settings panels. |
|
||||
| `popover` / `popover-foreground` | Floating surfaces and the content inside them. | `Popover`, `DropdownMenu`, `ContextMenu`, and other overlays. |
|
||||
| `primary` / `primary-foreground` | High-emphasis actions and brand surfaces. | Default `Button`, selected states, badges, and active accents. |
|
||||
| `secondary` / `secondary-foreground` | Lower-emphasis filled actions and supporting surfaces. | Secondary buttons, secondary badges, and supporting UI. |
|
||||
| `muted` / `muted-foreground` | Subtle surfaces and lower-emphasis content. | Descriptions, placeholders, empty states, helper text, and subdued surfaces. |
|
||||
| `accent` / `accent-foreground` | Interactive hover, focus, and active surfaces. | Ghost buttons, menu highlight states, hovered rows, and selected items. |
|
||||
| `destructive` | Destructive actions and error emphasis. | Destructive buttons, invalid states, and destructive menu items. |
|
||||
| `border` | Default borders and separators. | Cards, menus, tables, separators, and layout dividers. |
|
||||
| `input` | Form control borders and input surface treatment. | `Input`, `Textarea`, `Select`, and outline-style controls. |
|
||||
| `ring` | Focus rings and outlines. | Buttons, inputs, checkboxes, menus, and other focusable controls. |
|
||||
| `chart-1` ... `chart-5` | The default chart palette. | Charts and chart-driven dashboard blocks. |
|
||||
| `sidebar` / `sidebar-foreground` | The base sidebar surface and default sidebar text. | The `Sidebar` container and its default content. |
|
||||
| `sidebar-primary` / `sidebar-primary-foreground` | High-emphasis actions inside the sidebar. | Active items, icon tiles, badges, and sidebar CTAs. |
|
||||
| `sidebar-accent` / `sidebar-accent-foreground` | Hover and selected states inside the sidebar. | Sidebar menu hover states, open items, and interactive rows. |
|
||||
| `sidebar-border` | Sidebar-specific borders and separators. | Sidebar headers, groups, and internal dividers. |
|
||||
| `sidebar-ring` | Sidebar-specific focus rings. | Focused controls inside the sidebar. |
|
||||
| `radius` | The base corner radius scale. | Cards, inputs, buttons, popovers, and the derived `radius-*` tokens. |
|
||||
|
||||
<Callout className="mt-4">
|
||||
|
||||
The chart tokens are covered in more detail in the [Chart theming docs](/docs/components/chart#theming).
|
||||
|
||||
</Callout>
|
||||
|
||||
## Radius Scale
|
||||
|
||||
`--radius` is the base radius token for your theme.
|
||||
|
||||
We derive a small radius scale from it so components can use consistent corner sizes while still sharing a single source of truth.
|
||||
|
||||
```css title="app/globals.css" showLineNumbers
|
||||
@theme inline {
|
||||
--radius-sm: calc(var(--radius) * 0.6);
|
||||
--radius-md: calc(var(--radius) * 0.8);
|
||||
--radius-lg: var(--radius);
|
||||
--radius-xl: calc(var(--radius) * 1.4);
|
||||
--radius-2xl: calc(var(--radius) * 1.8);
|
||||
--radius-3xl: calc(var(--radius) * 2.2);
|
||||
--radius-4xl: calc(var(--radius) * 2.6);
|
||||
}
|
||||
```
|
||||
|
||||
This means:
|
||||
|
||||
- `radius-lg` is the base value.
|
||||
- Smaller radii scale down from `--radius`.
|
||||
- Larger radii scale up from `--radius`.
|
||||
- Changing `--radius` updates the entire radius scale.
|
||||
|
||||
## Adding New Tokens
|
||||
|
||||
To add a new token, define it under `:root` and `.dark`, then expose it to Tailwind with `@theme inline`.
|
||||
|
||||
```css title="app/globals.css" showLineNumbers
|
||||
:root {
|
||||
--warning: oklch(0.84 0.16 84);
|
||||
--warning-foreground: oklch(0.28 0.07 46);
|
||||
}
|
||||
|
||||
.dark {
|
||||
--warning: oklch(0.41 0.11 46);
|
||||
--warning-foreground: oklch(0.99 0.02 95);
|
||||
}
|
||||
|
||||
@theme inline {
|
||||
--color-warning: var(--warning);
|
||||
--color-warning-foreground: var(--warning-foreground);
|
||||
}
|
||||
```
|
||||
|
||||
You can now use `bg-warning` and `text-warning-foreground` in your components.
|
||||
|
||||
```tsx /bg-warning/ /text-warning-foreground/
|
||||
<div className="bg-warning text-warning-foreground" />
|
||||
```
|
||||
|
||||
## Base Colors
|
||||
|
||||
`tailwind.baseColor` controls the default token values generated for your project when you run `init` or use a preset.
|
||||
|
||||
The available base colors are: **Neutral**, **Stone**, **Zinc**, **Mauve**, **Olive**, **Mist**, and **Taupe**.
|
||||
|
||||
## Default Theme CSS
|
||||
|
||||
The following is the full default `neutral` theme scaffold. Copy it into your global CSS file and adjust the tokens as needed.
|
||||
|
||||
<CodeCollapsibleWrapper>
|
||||
|
||||
```css showLineNumbers title="app/globals.css"
|
||||
@import "tailwindcss";
|
||||
@import "shadcn/tailwind.css";
|
||||
|
||||
@custom-variant dark (&:is(.dark *));
|
||||
|
||||
@theme inline {
|
||||
--color-background: var(--background);
|
||||
--color-foreground: var(--foreground);
|
||||
--color-card: var(--card);
|
||||
--color-card-foreground: var(--card-foreground);
|
||||
--color-popover: var(--popover);
|
||||
--color-popover-foreground: var(--popover-foreground);
|
||||
--color-primary: var(--primary);
|
||||
--color-primary-foreground: var(--primary-foreground);
|
||||
--color-secondary: var(--secondary);
|
||||
--color-secondary-foreground: var(--secondary-foreground);
|
||||
--color-muted: var(--muted);
|
||||
--color-muted-foreground: var(--muted-foreground);
|
||||
--color-accent: var(--accent);
|
||||
--color-accent-foreground: var(--accent-foreground);
|
||||
--color-destructive: var(--destructive);
|
||||
--color-border: var(--border);
|
||||
--color-input: var(--input);
|
||||
--color-ring: var(--ring);
|
||||
--color-chart-1: var(--chart-1);
|
||||
--color-chart-2: var(--chart-2);
|
||||
--color-chart-3: var(--chart-3);
|
||||
--color-chart-4: var(--chart-4);
|
||||
--color-chart-5: var(--chart-5);
|
||||
--color-sidebar: var(--sidebar);
|
||||
--color-sidebar-foreground: var(--sidebar-foreground);
|
||||
--color-sidebar-primary: var(--sidebar-primary);
|
||||
--color-sidebar-primary-foreground: var(--sidebar-primary-foreground);
|
||||
--color-sidebar-accent: var(--sidebar-accent);
|
||||
--color-sidebar-accent-foreground: var(--sidebar-accent-foreground);
|
||||
--color-sidebar-border: var(--sidebar-border);
|
||||
--color-sidebar-ring: var(--sidebar-ring);
|
||||
--radius-sm: calc(var(--radius) * 0.6);
|
||||
--radius-md: calc(var(--radius) * 0.8);
|
||||
--radius-lg: var(--radius);
|
||||
--radius-xl: calc(var(--radius) * 1.4);
|
||||
--radius-2xl: calc(var(--radius) * 1.8);
|
||||
--radius-3xl: calc(var(--radius) * 2.2);
|
||||
--radius-4xl: calc(var(--radius) * 2.6);
|
||||
}
|
||||
|
||||
:root {
|
||||
--radius: 0.625rem;
|
||||
--background: oklch(1 0 0);
|
||||
@@ -79,7 +218,6 @@ Here's the list of variables available for customization:
|
||||
--accent: oklch(0.97 0 0);
|
||||
--accent-foreground: oklch(0.205 0 0);
|
||||
--destructive: oklch(0.577 0.245 27.325);
|
||||
--destructive-foreground: oklch(0.985 0 0);
|
||||
--border: oklch(0.922 0 0);
|
||||
--input: oklch(0.922 0 0);
|
||||
--ring: oklch(0.708 0 0);
|
||||
@@ -103,7 +241,7 @@ Here's the list of variables available for customization:
|
||||
--foreground: oklch(0.985 0 0);
|
||||
--card: oklch(0.205 0 0);
|
||||
--card-foreground: oklch(0.985 0 0);
|
||||
--popover: oklch(0.269 0 0);
|
||||
--popover: oklch(0.205 0 0);
|
||||
--popover-foreground: oklch(0.985 0 0);
|
||||
--primary: oklch(0.922 0 0);
|
||||
--primary-foreground: oklch(0.205 0 0);
|
||||
@@ -111,10 +249,9 @@ Here's the list of variables available for customization:
|
||||
--secondary-foreground: oklch(0.985 0 0);
|
||||
--muted: oklch(0.269 0 0);
|
||||
--muted-foreground: oklch(0.708 0 0);
|
||||
--accent: oklch(0.371 0 0);
|
||||
--accent: oklch(0.269 0 0);
|
||||
--accent-foreground: oklch(0.985 0 0);
|
||||
--destructive: oklch(0.704 0.191 22.216);
|
||||
--destructive-foreground: oklch(0.985 0 0);
|
||||
--border: oklch(1 0 0 / 10%);
|
||||
--input: oklch(1 0 0 / 15%);
|
||||
--ring: oklch(0.556 0 0);
|
||||
@@ -130,43 +267,38 @@ Here's the list of variables available for customization:
|
||||
--sidebar-accent: oklch(0.269 0 0);
|
||||
--sidebar-accent-foreground: oklch(0.985 0 0);
|
||||
--sidebar-border: oklch(1 0 0 / 10%);
|
||||
--sidebar-ring: oklch(0.439 0 0);
|
||||
--sidebar-ring: oklch(0.556 0 0);
|
||||
}
|
||||
|
||||
@layer base {
|
||||
* {
|
||||
@apply border-border outline-ring/50;
|
||||
}
|
||||
|
||||
body {
|
||||
@apply bg-background text-foreground;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Adding new colors
|
||||
</CodeCollapsibleWrapper>
|
||||
|
||||
To add new colors, you need to add them to your CSS file under the `:root` and `dark` pseudo-classes. Then, use the `@theme inline` directive to make the colors available as CSS variables.
|
||||
## Without CSS Variables
|
||||
|
||||
```css title="app/globals.css" showLineNumbers
|
||||
:root {
|
||||
--warning: oklch(0.84 0.16 84);
|
||||
--warning-foreground: oklch(0.28 0.07 46);
|
||||
}
|
||||
If you do not want to use CSS variables, the CLI can generate components with inline Tailwind color utilities instead.
|
||||
|
||||
.dark {
|
||||
--warning: oklch(0.41 0.11 46);
|
||||
--warning-foreground: oklch(0.99 0.02 95);
|
||||
}
|
||||
|
||||
@theme inline {
|
||||
--color-warning: var(--warning);
|
||||
--color-warning-foreground: var(--warning-foreground);
|
||||
}
|
||||
```bash
|
||||
npx shadcn@latest init --no-css-variables
|
||||
```
|
||||
|
||||
You can now use the `warning` utility class in your components.
|
||||
This sets `tailwind.cssVariables` to `false` in your `components.json` file.
|
||||
|
||||
```tsx /bg-warning/ /text-warning-foreground/
|
||||
<div className="bg-warning text-warning-foreground" />
|
||||
```tsx /bg-zinc-950/ /text-zinc-50/ /dark:bg-white/ /dark:text-zinc-950/
|
||||
<div className="bg-zinc-950 text-zinc-50 dark:bg-white dark:text-zinc-950" />
|
||||
```
|
||||
|
||||
## Other color formats
|
||||
<Callout className="mt-4">
|
||||
|
||||
See the [Tailwind CSS documentation](https://tailwindcss.com/docs/colors) for more information on using colors in Tailwind CSS.
|
||||
This is an installation-time choice. To switch an existing project, delete and re-install your components.
|
||||
|
||||
## Base Colors
|
||||
|
||||
The available base colors are: **Neutral**, **Stone**, **Zinc**, **Mauve**, **Olive**, **Mist**, and **Taupe**.
|
||||
|
||||
You can set the base color when initializing your project using a preset or by updating the `baseColor` field in your `components.json` file.
|
||||
</Callout>
|
||||
|
||||
@@ -5,9 +5,9 @@ base: base
|
||||
component: true
|
||||
---
|
||||
|
||||
<Callout>
|
||||
<Callout className="mt-4">
|
||||
|
||||
**Note:** We're working on upgrading to Recharts v3. In the meantime, if you'd like to start testing v3, see the code in the comment [here](https://github.com/shadcn-ui/ui/issues/7669#issuecomment-2998299159). We'll have an official release soon.
|
||||
**Updated:** The `chart` component now uses Recharts v3. If you're upgrading existing chart code, see [Updating to Recharts v3](#updating-to-recharts-v3).
|
||||
|
||||
</Callout>
|
||||
|
||||
@@ -51,6 +51,15 @@ We do not wrap Recharts. This means you're not locked into an abstraction. When
|
||||
|
||||
**The components are yours**.
|
||||
|
||||
## Updating to Recharts v3
|
||||
|
||||
If you're updating older chart code to Recharts v3:
|
||||
|
||||
- Use `var(--chart-1)` instead of `hsl(var(--chart-1))` when you reference chart tokens from your CSS variables.
|
||||
- Use `ChartTooltip.defaultIndex` for initial tooltip state only. Keep persistent active shapes in your own chart state.
|
||||
- Remove `layout` from `<Bar>` when the parent `<BarChart>` already defines it.
|
||||
- Keep a height, `min-h-*`, or `aspect-*` on `ChartContainer` so `ResponsiveContainer` can measure on first render.
|
||||
|
||||
## Installation
|
||||
|
||||
<CodeTabs>
|
||||
@@ -455,7 +464,7 @@ const chartData = [
|
||||
#### Tailwind
|
||||
|
||||
```tsx title="components/example-chart.tsx"
|
||||
<LabelList className="fill-[--color-desktop]" />
|
||||
<LabelList className="fill-(--color-desktop)" />
|
||||
```
|
||||
|
||||
## Tooltip
|
||||
|
||||
@@ -5,9 +5,9 @@ base: radix
|
||||
component: true
|
||||
---
|
||||
|
||||
<Callout>
|
||||
<Callout className="mt-4">
|
||||
|
||||
**Note:** We're working on upgrading to Recharts v3. In the meantime, if you'd like to start testing v3, see the code in the comment [here](https://github.com/shadcn-ui/ui/issues/7669#issuecomment-2998299159). We'll have an official release soon.
|
||||
**Updated:** The `chart` component now uses Recharts v3. If you're upgrading existing chart code, see [Updating to Recharts v3](#updating-to-recharts-v3).
|
||||
|
||||
</Callout>
|
||||
|
||||
@@ -51,6 +51,15 @@ We do not wrap Recharts. This means you're not locked into an abstraction. When
|
||||
|
||||
**The components are yours**.
|
||||
|
||||
## Updating to Recharts v3
|
||||
|
||||
If you're updating older chart code to Recharts v3:
|
||||
|
||||
- Use `var(--chart-1)` instead of `hsl(var(--chart-1))` when you reference chart tokens from your CSS variables.
|
||||
- Use `ChartTooltip.defaultIndex` for initial tooltip state only. Keep persistent active shapes in your own chart state.
|
||||
- Remove `layout` from `<Bar>` when the parent `<BarChart>` already defines it.
|
||||
- Keep a height, `min-h-*`, or `aspect-*` on `ChartContainer` so `ResponsiveContainer` can measure on first render.
|
||||
|
||||
## Installation
|
||||
|
||||
<CodeTabs>
|
||||
@@ -455,7 +464,7 @@ const chartData = [
|
||||
#### Tailwind
|
||||
|
||||
```tsx title="components/example-chart.tsx"
|
||||
<LabelList className="fill-[--color-desktop]" />
|
||||
<LabelList className="fill-(--color-desktop)" />
|
||||
```
|
||||
|
||||
## Tooltip
|
||||
|
||||
@@ -3,17 +3,125 @@ title: Astro
|
||||
description: Install and configure shadcn/ui for Astro.
|
||||
---
|
||||
|
||||
<Callout className="mb-6 border-emerald-600 bg-emerald-100 dark:border-emerald-400 dark:bg-emerald-900">
|
||||
Choose the setup that matches your starting point.
|
||||
|
||||
**Starting a new project?** Use [shadcn/create](/create) for a fully configured Astro app with custom themes, Base UI or Radix, and icon libraries.
|
||||
<div className="mt-6 grid gap-4 sm:grid-cols-3 sm:gap-6">
|
||||
<LinkedCard
|
||||
href="#scaffold-with-create"
|
||||
className="items-start gap-1 p-6 text-sm md:p-6"
|
||||
>
|
||||
<div className="font-medium">Use shadcn/create</div>
|
||||
<div className="leading-relaxed text-muted-foreground">
|
||||
Build your preset and generate an Astro project command.
|
||||
</div>
|
||||
</LinkedCard>
|
||||
<LinkedCard
|
||||
href="#scaffold-with-cli"
|
||||
className="items-start gap-1 p-6 text-sm md:p-6"
|
||||
>
|
||||
<div className="font-medium">Use the CLI</div>
|
||||
<div className="leading-relaxed text-muted-foreground">
|
||||
Scaffold a new Astro project directly from the terminal.
|
||||
</div>
|
||||
</LinkedCard>
|
||||
<LinkedCard
|
||||
href="#existing-astro-project"
|
||||
className="items-start gap-1 p-6 text-sm md:p-6"
|
||||
>
|
||||
<div className="font-medium">Existing Project</div>
|
||||
<div className="leading-relaxed text-muted-foreground">
|
||||
Configure shadcn/ui manually in an existing Astro project.
|
||||
</div>
|
||||
</LinkedCard>
|
||||
</div>
|
||||
|
||||
</Callout>
|
||||
<div id="scaffold-with-create" className="scroll-mt-24" />
|
||||
## Use shadcn/create
|
||||
|
||||
<Steps>
|
||||
|
||||
### Create project
|
||||
### Build Your Preset
|
||||
|
||||
Start by creating a new Astro project:
|
||||
Open [shadcn/create](/create?template=astro) and build your preset visually. Choose your style, colors, fonts, icons, and more.
|
||||
|
||||
<Button asChild size="sm">
|
||||
<Link
|
||||
href="/create?template=astro"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="mt-6 no-underline!"
|
||||
>
|
||||
Open shadcn/create
|
||||
</Link>
|
||||
</Button>
|
||||
|
||||
### Create Project
|
||||
|
||||
Click `Create Project`, choose your package manager, and copy the generated command.
|
||||
|
||||
The generated command will look similar to this:
|
||||
|
||||
```bash
|
||||
npx shadcn@latest init --preset [CODE] --template astro
|
||||
```
|
||||
|
||||
The exact command will include your selected options such as `--base`, `--monorepo`, or `--rtl`.
|
||||
|
||||
### Add Components
|
||||
|
||||
Add the `Card` component to your project:
|
||||
|
||||
```bash
|
||||
npx shadcn@latest add card
|
||||
```
|
||||
|
||||
If you created a monorepo, run the command from `apps/web` or specify the workspace from the repo root:
|
||||
|
||||
```bash
|
||||
npx shadcn@latest add card -c apps/web
|
||||
```
|
||||
|
||||
The command above will add the `Card` component to your project. You can then import it like this:
|
||||
|
||||
```astro title="src/pages/index.astro" showLineNumbers
|
||||
---
|
||||
import Layout from "@/layouts/main.astro"
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "@/components/ui/card"
|
||||
---
|
||||
|
||||
<Layout>
|
||||
<Card className="max-w-sm">
|
||||
<CardHeader>
|
||||
<CardTitle>Project Overview</CardTitle>
|
||||
<CardDescription>
|
||||
Track progress and recent activity for your Astro app.
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
Your design system is ready. Start building your next component.
|
||||
</CardContent>
|
||||
</Card>
|
||||
</Layout>
|
||||
```
|
||||
|
||||
If you created a monorepo, update `apps/web/src/pages/index.astro` and import from `@workspace/ui/components/card` instead. The monorepo layout at `apps/web/src/layouts/main.astro` already imports `@workspace/ui/globals.css` for you.
|
||||
|
||||
</Steps>
|
||||
|
||||
<div id="scaffold-with-cli" className="scroll-mt-24" />
|
||||
## Use the CLI
|
||||
|
||||
<Steps>
|
||||
|
||||
### Create Project
|
||||
|
||||
Run the `init` command to scaffold a new Astro project. Follow the prompts to configure your project: base, preset, monorepo, and more.
|
||||
|
||||
```bash
|
||||
npx shadcn@latest init -t astro
|
||||
@@ -27,6 +135,99 @@ npx shadcn@latest init -t astro --monorepo
|
||||
|
||||
### Add Components
|
||||
|
||||
Add the `Card` component to your project:
|
||||
|
||||
```bash
|
||||
npx shadcn@latest add card
|
||||
```
|
||||
|
||||
If you created a monorepo, run the command from `apps/web` or specify the workspace from the repo root:
|
||||
|
||||
```bash
|
||||
npx shadcn@latest add card -c apps/web
|
||||
```
|
||||
|
||||
The command above will add the `Card` component to your project. You can then import it like this:
|
||||
|
||||
```astro title="src/pages/index.astro" showLineNumbers
|
||||
---
|
||||
import Layout from "@/layouts/main.astro"
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "@/components/ui/card"
|
||||
---
|
||||
|
||||
<Layout>
|
||||
<Card className="max-w-sm">
|
||||
<CardHeader>
|
||||
<CardTitle>Project Overview</CardTitle>
|
||||
<CardDescription>
|
||||
Track progress and recent activity for your Astro app.
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
Your design system is ready. Start building your next component.
|
||||
</CardContent>
|
||||
</Card>
|
||||
</Layout>
|
||||
```
|
||||
|
||||
If you created a monorepo, update `apps/web/src/pages/index.astro` and import from `@workspace/ui/components/card` instead. The monorepo layout at `apps/web/src/layouts/main.astro` already imports `@workspace/ui/globals.css` for you.
|
||||
|
||||
</Steps>
|
||||
|
||||
<div id="existing-astro-project" className="scroll-mt-24" />
|
||||
## Existing Project
|
||||
|
||||
<Steps>
|
||||
|
||||
### Create Project
|
||||
|
||||
If you need a new Astro project, create one first. Otherwise, skip this step.
|
||||
|
||||
```bash
|
||||
npm create astro@latest astro-app -- --template with-tailwindcss --install --add react --git
|
||||
```
|
||||
|
||||
This command sets up Tailwind CSS and the React integration for you. If you're adding shadcn/ui to an older or custom Astro app, make sure both are configured before continuing.
|
||||
|
||||
The Tailwind starter loads your global stylesheet through `src/layouts/main.astro`. Keep that layout in place, or make sure your page imports `@/styles/global.css`.
|
||||
|
||||
### Edit tsconfig.json file
|
||||
|
||||
If your project already has the `@/*` alias configured, skip this step.
|
||||
|
||||
Add the following code to the `tsconfig.json` file to resolve paths:
|
||||
|
||||
```ts title="tsconfig.json" {4-9} showLineNumbers
|
||||
{
|
||||
"compilerOptions": {
|
||||
// ...
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@/*": [
|
||||
"./src/*"
|
||||
]
|
||||
}
|
||||
// ...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Run the CLI
|
||||
|
||||
Run the `shadcn` init command to set up your project:
|
||||
|
||||
```bash
|
||||
npx shadcn@latest init
|
||||
```
|
||||
|
||||
### Add Components
|
||||
|
||||
You can now start adding components to your project.
|
||||
|
||||
```bash
|
||||
@@ -35,26 +236,17 @@ npx shadcn@latest add button
|
||||
|
||||
The command above will add the `Button` component to your project. You can then import it like this:
|
||||
|
||||
```astro title="src/pages/index.astro" {2,16} showLineNumbers
|
||||
```astro title="src/pages/index.astro" showLineNumbers
|
||||
---
|
||||
import Layout from "@/layouts/main.astro"
|
||||
import { Button } from "@/components/ui/button"
|
||||
---
|
||||
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width" />
|
||||
<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
|
||||
<meta name="generator" content={Astro.generator} />
|
||||
<title>Astro + Tailwind CSS</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="grid place-items-center h-screen content-center">
|
||||
<Button>Button</Button>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
<Layout>
|
||||
<div class="grid h-screen place-items-center content-center">
|
||||
<Button>Button</Button>
|
||||
</div>
|
||||
</Layout>
|
||||
```
|
||||
|
||||
</Steps>
|
||||
|
||||
@@ -5,23 +5,80 @@ description: How to install dependencies and structure your app.
|
||||
|
||||
<Callout className="mb-6 border-emerald-600 bg-emerald-100 dark:border-emerald-400 dark:bg-emerald-900">
|
||||
|
||||
**Starting a new project?** Use [shadcn/create](/create) to scaffold a complete app with custom themes, components, and presets. For Next.js, Vite, Laravel, React Router, Astro, and TanStack Start.
|
||||
**Recommended for new projects:** Use [shadcn/create](/create) to build your preset visually and generate the right setup command for your framework.
|
||||
|
||||
</Callout>
|
||||
|
||||
## Quick Start
|
||||
Choose the setup that matches your starting point.
|
||||
|
||||
Run the following command to create a new project with shadcn/ui:
|
||||
<div className="mt-6 grid gap-4 sm:grid-cols-3 sm:gap-6">
|
||||
<LinkedCard
|
||||
href="#use-create"
|
||||
className="items-start gap-1 p-6 text-sm md:p-6"
|
||||
>
|
||||
<div className="font-medium">Use shadcn/create</div>
|
||||
<div className="leading-relaxed text-muted-foreground">
|
||||
Build your preset visually and generate a setup command.
|
||||
</div>
|
||||
</LinkedCard>
|
||||
<LinkedCard href="#use-cli" className="items-start gap-1 p-6 text-sm md:p-6">
|
||||
<div className="font-medium">Use the CLI</div>
|
||||
<div className="leading-relaxed text-muted-foreground">
|
||||
Scaffold a supported template directly from the terminal.
|
||||
</div>
|
||||
</LinkedCard>
|
||||
<LinkedCard
|
||||
href="#existing-project"
|
||||
className="items-start gap-1 p-6 text-sm md:p-6"
|
||||
>
|
||||
<div className="font-medium">Existing Project</div>
|
||||
<div className="leading-relaxed text-muted-foreground">
|
||||
Add shadcn/ui to an app you already created.
|
||||
</div>
|
||||
</LinkedCard>
|
||||
</div>
|
||||
|
||||
<div id="use-create" className="scroll-mt-24" />
|
||||
## Use shadcn/create
|
||||
|
||||
Build your preset visually, preview your choices, and generate a framework-specific setup command.
|
||||
|
||||
<Button asChild size="sm">
|
||||
<Link
|
||||
href="/create"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="mt-6 no-underline!"
|
||||
>
|
||||
Open shadcn/create
|
||||
</Link>
|
||||
</Button>
|
||||
|
||||
Available for Next.js, Vite, Laravel, React Router, Astro, and TanStack Start.
|
||||
|
||||
<div id="use-cli" className="scroll-mt-24" />
|
||||
## Use the CLI
|
||||
|
||||
Use the CLI to scaffold a new project directly from the terminal:
|
||||
|
||||
```bash
|
||||
npx shadcn@latest init
|
||||
npx shadcn@latest init -t [framework]
|
||||
```
|
||||
|
||||
This will guide you through the process of creating a new project with shadcn/ui with your preferred framework, icon library, and theme.
|
||||
Supported templates: `next`, `vite`, `start`, `react-router`, and `astro`.
|
||||
|
||||
## Pick Your Framework
|
||||
For Laravel, create the app first with `laravel new`, then run `npx shadcn@latest init`.
|
||||
|
||||
Start by selecting your framework of choice. Then follow the instructions to install the dependencies and structure your app. shadcn/ui is built to work with all React frameworks.
|
||||
<div id="existing-project" className="scroll-mt-24" />
|
||||
## Existing Project
|
||||
|
||||
Each framework guide includes an `Existing Project` section with the manual setup steps for that framework.
|
||||
|
||||
Pick your framework below and follow that path.
|
||||
|
||||
## Choose Your Framework
|
||||
|
||||
For Laravel, start with `laravel new` before using `shadcn/create` or `shadcn init`.
|
||||
|
||||
<div className="mt-8 grid gap-4 sm:grid-cols-2 sm:gap-6">
|
||||
<LinkedCard href="/docs/installation/next">
|
||||
|
||||
@@ -3,35 +3,88 @@ title: Laravel
|
||||
description: Install and configure shadcn/ui for Laravel.
|
||||
---
|
||||
|
||||
<Callout className="mb-6 border-emerald-600 bg-emerald-100 dark:border-emerald-400 dark:bg-emerald-900">
|
||||
|
||||
**Starting a new project?** Use [shadcn/create](/create) for a fully configured Laravel app with custom themes, Base UI or Radix, and icon libraries.
|
||||
|
||||
</Callout>
|
||||
The shadcn CLI does not scaffold a new Laravel app. Start by creating a Laravel app with the React starter kit, then choose how you want to configure shadcn/ui.
|
||||
|
||||
<Steps>
|
||||
|
||||
### Create Project
|
||||
|
||||
Start by creating a new Laravel project with Inertia and React using the Laravel installer:
|
||||
Create a new Laravel app using the Laravel installer:
|
||||
|
||||
```bash
|
||||
laravel new my-app --react
|
||||
laravel new my-app
|
||||
```
|
||||
|
||||
### Run the shadcn/ui CLI
|
||||
If you already have a Laravel app with React and Inertia configured, skip this step.
|
||||
|
||||
Run the `init` command to configure shadcn/ui in your Laravel project:
|
||||
Choose the **React** starter kit when prompted. For more information, see the official [Laravel frontend documentation](https://laravel.com/docs/12.x/frontend).
|
||||
|
||||
Then move into your project directory:
|
||||
|
||||
```bash
|
||||
npx shadcn@latest init --force
|
||||
cd my-app
|
||||
```
|
||||
|
||||
If asked to overwrite the existing components, answer `y` to continue.
|
||||
</Steps>
|
||||
|
||||
<div className="mt-10 grid gap-4 sm:grid-cols-2 sm:gap-6">
|
||||
<LinkedCard
|
||||
href="#configure-with-create"
|
||||
className="items-start gap-1 p-6 text-sm md:p-6"
|
||||
>
|
||||
<div className="font-medium">Use shadcn/create</div>
|
||||
<div className="leading-relaxed text-muted-foreground">
|
||||
Build your preset visually and generate a Laravel init command.
|
||||
</div>
|
||||
</LinkedCard>
|
||||
<LinkedCard
|
||||
href="#configure-with-cli"
|
||||
className="items-start gap-1 p-6 text-sm md:p-6"
|
||||
>
|
||||
<div className="font-medium">Use the CLI</div>
|
||||
<div className="leading-relaxed text-muted-foreground">
|
||||
Configure shadcn/ui in your Laravel app directly from the terminal.
|
||||
</div>
|
||||
</LinkedCard>
|
||||
</div>
|
||||
|
||||
<div id="configure-with-create" className="scroll-mt-24" />
|
||||
## Use shadcn/create
|
||||
|
||||
<Steps>
|
||||
|
||||
### Build Your Preset
|
||||
|
||||
Open [shadcn/create](/create?template=laravel) and build your preset visually. Choose your style, colors, fonts, icons, and more.
|
||||
|
||||
<Button asChild size="sm">
|
||||
<Link
|
||||
href="/create?template=laravel"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="mt-6 no-underline!"
|
||||
>
|
||||
Open shadcn/create
|
||||
</Link>
|
||||
</Button>
|
||||
|
||||
### Run the Command
|
||||
|
||||
Click `Create Project`, choose your package manager, and copy the generated command.
|
||||
|
||||
The generated command will look similar to this:
|
||||
|
||||
```bash
|
||||
npx shadcn@latest init --preset [CODE] --template laravel
|
||||
```
|
||||
|
||||
Run the command from the root of your Laravel app.
|
||||
|
||||
When asked to overwrite `components.json` and components, choose `Yes`.
|
||||
|
||||
### Add Components
|
||||
|
||||
You can now start adding components to your project.
|
||||
Add the `Switch` component to your project:
|
||||
|
||||
```bash
|
||||
npx shadcn@latest add switch
|
||||
@@ -39,7 +92,48 @@ npx shadcn@latest add switch
|
||||
|
||||
The command above will add the `Switch` component to `resources/js/components/ui/switch.tsx`. You can then import it like this:
|
||||
|
||||
```tsx title="resources/js/pages/index.tsx" {1,6} showLineNumbers
|
||||
```tsx title="resources/js/pages/index.tsx" showLineNumbers {1,6}
|
||||
import { Switch } from "@/components/ui/switch"
|
||||
|
||||
const MyPage = () => {
|
||||
return (
|
||||
<div>
|
||||
<Switch />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default MyPage
|
||||
```
|
||||
|
||||
</Steps>
|
||||
|
||||
<div id="configure-with-cli" className="scroll-mt-24" />
|
||||
## Use the CLI
|
||||
|
||||
<Steps>
|
||||
|
||||
### Run the CLI
|
||||
|
||||
Run the `shadcn` init command from the root of your Laravel app:
|
||||
|
||||
```bash
|
||||
npx shadcn@latest init
|
||||
```
|
||||
|
||||
When asked to overwrite `components.json` and components, choose `Yes`.
|
||||
|
||||
### Add Components
|
||||
|
||||
Add the `Switch` component to your project:
|
||||
|
||||
```bash
|
||||
npx shadcn@latest add switch
|
||||
```
|
||||
|
||||
The command above will add the `Switch` component to `resources/js/components/ui/switch.tsx`. You can then import it like this:
|
||||
|
||||
```tsx title="resources/js/pages/index.tsx" showLineNumbers {1,6}
|
||||
import { Switch } from "@/components/ui/switch"
|
||||
|
||||
const MyPage = () => {
|
||||
|
||||
@@ -3,17 +3,124 @@ title: Next.js
|
||||
description: Install and configure shadcn/ui for Next.js.
|
||||
---
|
||||
|
||||
<Callout className="mb-6 border-emerald-600 bg-emerald-100 dark:border-emerald-400 dark:bg-emerald-900">
|
||||
Choose the setup that matches your starting point.
|
||||
|
||||
**Starting a new project?** Use [shadcn/create](/create) for a fully configured Next.js app with custom themes, Base UI or Radix, and icon libraries.
|
||||
<div className="mt-6 grid gap-4 sm:grid-cols-3 sm:gap-6">
|
||||
<LinkedCard
|
||||
href="#scaffold-with-create"
|
||||
className="items-start gap-1 p-6 text-sm md:p-6"
|
||||
>
|
||||
<div className="font-medium">Use shadcn/create</div>
|
||||
<div className="leading-relaxed text-muted-foreground">
|
||||
Build your preset and generate a Next.js project command.
|
||||
</div>
|
||||
</LinkedCard>
|
||||
<LinkedCard
|
||||
href="#scaffold-with-cli"
|
||||
className="items-start gap-1 p-6 text-sm md:p-6"
|
||||
>
|
||||
<div className="font-medium">Use the CLI</div>
|
||||
<div className="leading-relaxed text-muted-foreground">
|
||||
Scaffold a new Next.js project directly from the terminal.
|
||||
</div>
|
||||
</LinkedCard>
|
||||
<LinkedCard
|
||||
href="#existing-next-project"
|
||||
className="items-start gap-1 p-6 text-sm md:p-6"
|
||||
>
|
||||
<div className="font-medium">Existing Project</div>
|
||||
<div className="leading-relaxed text-muted-foreground">
|
||||
Configure shadcn/ui manually in an existing Next.js project.
|
||||
</div>
|
||||
</LinkedCard>
|
||||
</div>
|
||||
|
||||
</Callout>
|
||||
<div id="scaffold-with-create" className="scroll-mt-24" />
|
||||
## Use shadcn/create
|
||||
|
||||
<Steps>
|
||||
|
||||
### Build Your Preset
|
||||
|
||||
Open [shadcn/create](/create?template=next) and build your preset visually. Choose your style, colors, fonts, icons, and more.
|
||||
|
||||
<Button asChild size="sm">
|
||||
<Link
|
||||
href="/create?template=next"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="mt-6 no-underline!"
|
||||
>
|
||||
Open shadcn/create
|
||||
</Link>
|
||||
</Button>
|
||||
|
||||
### Create Project
|
||||
|
||||
Click `Create Project`, choose your package manager, and copy the generated command.
|
||||
|
||||
The generated command will look similar to this:
|
||||
|
||||
```bash
|
||||
npx shadcn@latest init --preset [CODE] --template next
|
||||
```
|
||||
|
||||
The exact command will include your selected options such as `--base`, `--monorepo`, or `--rtl`.
|
||||
|
||||
### Add Components
|
||||
|
||||
Add the `Card` component to your project:
|
||||
|
||||
```bash
|
||||
npx shadcn@latest add card
|
||||
```
|
||||
|
||||
If you created a monorepo, run the command from `apps/web` or specify the workspace from the repo root:
|
||||
|
||||
```bash
|
||||
npx shadcn@latest add card -c apps/web
|
||||
```
|
||||
|
||||
The command above will add the `Card` component to your project. You can then import it like this:
|
||||
|
||||
```tsx showLineNumbers title="app/page.tsx"
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "@/components/ui/card"
|
||||
|
||||
export default function Home() {
|
||||
return (
|
||||
<Card className="max-w-sm">
|
||||
<CardHeader>
|
||||
<CardTitle>Project Overview</CardTitle>
|
||||
<CardDescription>
|
||||
Track progress and recent activity for your Next.js app.
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
Your design system is ready. Start building your next component.
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
If you created a monorepo, update `apps/web/app/page.tsx` and import from `@workspace/ui/components/card` instead.
|
||||
|
||||
</Steps>
|
||||
|
||||
<div id="scaffold-with-cli" className="scroll-mt-24" />
|
||||
## Use the CLI
|
||||
|
||||
<Steps>
|
||||
|
||||
### Create Project
|
||||
|
||||
Run the `init` command to create a new Next.js project or to set up an existing one:
|
||||
Run the `init` command to scaffold a new Next.js project. Follow the prompts to configure your project: base, preset, monorepo, and more.
|
||||
|
||||
```bash
|
||||
npx shadcn@latest init -t next
|
||||
@@ -27,6 +134,103 @@ npx shadcn@latest init -t next --monorepo
|
||||
|
||||
### Add Components
|
||||
|
||||
Add the `Card` component to your project:
|
||||
|
||||
```bash
|
||||
npx shadcn@latest add card
|
||||
```
|
||||
|
||||
If you created a monorepo, run the command from `apps/web` or specify the workspace from the repo root:
|
||||
|
||||
```bash
|
||||
npx shadcn@latest add card -c apps/web
|
||||
```
|
||||
|
||||
The command above will add the `Card` component to your project. You can then import it like this:
|
||||
|
||||
```tsx showLineNumbers title="app/page.tsx"
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "@/components/ui/card"
|
||||
|
||||
export default function Home() {
|
||||
return (
|
||||
<Card className="max-w-sm">
|
||||
<CardHeader>
|
||||
<CardTitle>Project Overview</CardTitle>
|
||||
<CardDescription>
|
||||
Track progress and recent activity for your Next.js app.
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
Your design system is ready. Start building your next component.
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
If you created a monorepo, update `apps/web/app/page.tsx` and import from `@workspace/ui/components/card` instead.
|
||||
|
||||
</Steps>
|
||||
|
||||
<div id="existing-next-project" className="scroll-mt-24" />
|
||||
## Existing Project
|
||||
|
||||
<Steps>
|
||||
|
||||
### Create Project
|
||||
|
||||
If you need a new Next.js project, create one with `create-next-app`. Otherwise, skip this step.
|
||||
|
||||
```bash
|
||||
npx create-next-app@latest
|
||||
```
|
||||
|
||||
Choose the recommended defaults so Tailwind CSS, the App Router, and the default `@/*` import alias are configured for you.
|
||||
|
||||
If you prefer a `src/` directory, use `--src-dir` or choose `Yes` when prompted:
|
||||
|
||||
```bash
|
||||
npx create-next-app@latest --src-dir
|
||||
```
|
||||
|
||||
With `--src-dir`, Next.js places your app in `src/app` and configures the `@/*` alias to point to `./src/*`.
|
||||
|
||||
### Configure Tailwind CSS and Import Aliases
|
||||
|
||||
If you created your project with the recommended `create-next-app` defaults, you can skip this step.
|
||||
|
||||
If you're adding shadcn/ui to an older or custom Next.js app, make sure Tailwind CSS is installed first. You can follow the official [Next.js installation guide](https://nextjs.org/docs/app/getting-started).
|
||||
|
||||
Then make sure your `tsconfig.json` includes the `@/*` import alias:
|
||||
|
||||
```json title="tsconfig.json" showLineNumbers
|
||||
{
|
||||
"compilerOptions": {
|
||||
"paths": {
|
||||
"@/*": ["./*"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
If you used `--src-dir`, point the alias to `./src/*` instead.
|
||||
|
||||
### Run the CLI
|
||||
|
||||
Run the `shadcn` init command to set up shadcn/ui in your project.
|
||||
|
||||
```bash
|
||||
npx shadcn@latest init
|
||||
```
|
||||
|
||||
### Add Components
|
||||
|
||||
You can now start adding components to your project.
|
||||
|
||||
```bash
|
||||
@@ -35,16 +239,18 @@ npx shadcn@latest add button
|
||||
|
||||
The command above will add the `Button` component to your project. You can then import it like this:
|
||||
|
||||
```tsx {1,6} showLineNumbers title="app/page.tsx"
|
||||
```tsx showLineNumbers title="app/page.tsx"
|
||||
import { Button } from "@/components/ui/button"
|
||||
|
||||
export default function Home() {
|
||||
return (
|
||||
<div>
|
||||
<div className="flex min-h-svh items-center justify-center">
|
||||
<Button>Click me</Button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
If you used `--src-dir`, add the component to `src/app/page.tsx` instead.
|
||||
|
||||
</Steps>
|
||||
|
||||
@@ -3,15 +3,124 @@ title: React Router
|
||||
description: Install and configure shadcn/ui for React Router.
|
||||
---
|
||||
|
||||
<Callout className="mb-6 border-emerald-600 bg-emerald-100 dark:border-emerald-400 dark:bg-emerald-900">
|
||||
Choose the setup that matches your starting point.
|
||||
|
||||
**Starting a new project?** Use [shadcn/create](/create) for a fully configured React Router app with custom themes, Base UI or Radix, and icon libraries.
|
||||
<div className="mt-6 grid gap-4 sm:grid-cols-3 sm:gap-6">
|
||||
<LinkedCard
|
||||
href="#scaffold-with-create"
|
||||
className="items-start gap-1 p-6 text-sm md:p-6"
|
||||
>
|
||||
<div className="font-medium">Use shadcn/create</div>
|
||||
<div className="leading-relaxed text-muted-foreground">
|
||||
Build your preset and generate a React Router project.
|
||||
</div>
|
||||
</LinkedCard>
|
||||
<LinkedCard
|
||||
href="#scaffold-with-cli"
|
||||
className="items-start gap-1 p-6 text-sm md:p-6"
|
||||
>
|
||||
<div className="font-medium">Use the CLI</div>
|
||||
<div className="leading-relaxed text-muted-foreground">
|
||||
Scaffold a new React Router project directly from the terminal.
|
||||
</div>
|
||||
</LinkedCard>
|
||||
<LinkedCard
|
||||
href="#existing-react-router-project"
|
||||
className="items-start gap-1 p-6 text-sm md:p-6"
|
||||
>
|
||||
<div className="font-medium">Existing Project</div>
|
||||
<div className="leading-relaxed text-muted-foreground">
|
||||
Configure shadcn/ui manually in an existing React Router project.
|
||||
</div>
|
||||
</LinkedCard>
|
||||
</div>
|
||||
|
||||
</Callout>
|
||||
<div id="scaffold-with-create" className="scroll-mt-24" />
|
||||
## Use shadcn/create
|
||||
|
||||
<Steps>
|
||||
|
||||
### Create project
|
||||
### Build Your Preset
|
||||
|
||||
Open [shadcn/create](/create?template=react-router) and build your preset visually. Choose your style, colors, fonts, icons, and more.
|
||||
|
||||
<Button asChild size="sm">
|
||||
<Link
|
||||
href="/create?template=react-router"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="mt-6 no-underline!"
|
||||
>
|
||||
Open shadcn/create
|
||||
</Link>
|
||||
</Button>
|
||||
|
||||
### Create Project
|
||||
|
||||
Click `Create Project`, choose your package manager, and copy the generated command.
|
||||
|
||||
The generated command will look similar to this:
|
||||
|
||||
```bash
|
||||
npx shadcn@latest init --preset [CODE] --template react-router
|
||||
```
|
||||
|
||||
The exact command will include your selected options such as `--base`, `--monorepo`, or `--rtl`.
|
||||
|
||||
### Add Components
|
||||
|
||||
Add the `Card` component to your project:
|
||||
|
||||
```bash
|
||||
npx shadcn@latest add card
|
||||
```
|
||||
|
||||
If you created a monorepo, run the command from `apps/web` or specify the workspace from the repo root:
|
||||
|
||||
```bash
|
||||
npx shadcn@latest add card -c apps/web
|
||||
```
|
||||
|
||||
The command above will add the `Card` component to your project. You can then import it like this:
|
||||
|
||||
```tsx showLineNumbers title="app/routes/home.tsx"
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "~/components/ui/card"
|
||||
|
||||
export default function Home() {
|
||||
return (
|
||||
<Card className="max-w-sm">
|
||||
<CardHeader>
|
||||
<CardTitle>Project Overview</CardTitle>
|
||||
<CardDescription>
|
||||
Track progress and recent activity for your React Router app.
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
Your design system is ready. Start building your next component.
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
If you created a monorepo, update `apps/web/app/routes/home.tsx` and import from `@workspace/ui/components/card` instead.
|
||||
|
||||
</Steps>
|
||||
|
||||
<div id="scaffold-with-cli" className="scroll-mt-24" />
|
||||
## Use the CLI
|
||||
|
||||
<Steps>
|
||||
|
||||
### Create Project
|
||||
|
||||
Run the `init` command to scaffold a new React Router project. Follow the prompts to configure your project: base, preset, monorepo, and more.
|
||||
|
||||
```bash
|
||||
npx shadcn@latest init -t react-router
|
||||
@@ -25,6 +134,75 @@ npx shadcn@latest init -t react-router --monorepo
|
||||
|
||||
### Add Components
|
||||
|
||||
Add the `Card` component to your project:
|
||||
|
||||
```bash
|
||||
npx shadcn@latest add card
|
||||
```
|
||||
|
||||
If you created a monorepo, run the command from `apps/web` or specify the workspace from the repo root:
|
||||
|
||||
```bash
|
||||
npx shadcn@latest add card -c apps/web
|
||||
```
|
||||
|
||||
The command above will add the `Card` component to your project. You can then import it like this:
|
||||
|
||||
```tsx showLineNumbers title="app/routes/home.tsx"
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "~/components/ui/card"
|
||||
|
||||
export default function Home() {
|
||||
return (
|
||||
<Card className="max-w-sm">
|
||||
<CardHeader>
|
||||
<CardTitle>Project Overview</CardTitle>
|
||||
<CardDescription>
|
||||
Track progress and recent activity for your React Router app.
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
Your design system is ready. Start building your next component.
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
If you created a monorepo, update `apps/web/app/routes/home.tsx` and import from `@workspace/ui/components/card` instead.
|
||||
|
||||
</Steps>
|
||||
|
||||
<div id="existing-react-router-project" className="scroll-mt-24" />
|
||||
## Existing Project
|
||||
|
||||
<Steps>
|
||||
|
||||
### Create Project
|
||||
|
||||
If you need a new React Router project, create one first. Otherwise, skip this step.
|
||||
|
||||
```bash
|
||||
npm create react-router@latest
|
||||
```
|
||||
|
||||
`create-react-router` already configures Tailwind CSS and the default `~/*` import alias for you. If you're adding shadcn/ui to an older or custom React Router app, make sure both are configured before continuing.
|
||||
|
||||
### Run the CLI
|
||||
|
||||
Run the `shadcn` init command to set up shadcn/ui in your project.
|
||||
|
||||
```bash
|
||||
npx shadcn@latest init
|
||||
```
|
||||
|
||||
### Add Components
|
||||
|
||||
You can now start adding components to your project.
|
||||
|
||||
```bash
|
||||
@@ -34,16 +212,7 @@ npx shadcn@latest add button
|
||||
The command above will add the `Button` component to your project. You can then import it like this:
|
||||
|
||||
```tsx showLineNumbers title="app/routes/home.tsx"
|
||||
import { Button } from "@/components/ui/button"
|
||||
|
||||
import type { Route } from "./+types/home"
|
||||
|
||||
export function meta({}: Route.MetaArgs) {
|
||||
return [
|
||||
{ title: "New React Router App" },
|
||||
{ name: "description", content: "Welcome to React Router!" },
|
||||
]
|
||||
}
|
||||
import { Button } from "~/components/ui/button"
|
||||
|
||||
export default function Home() {
|
||||
return (
|
||||
|
||||
@@ -3,17 +3,130 @@ title: TanStack Start
|
||||
description: Install and configure shadcn/ui for TanStack Start.
|
||||
---
|
||||
|
||||
<Callout className="mb-6 border-emerald-600 bg-emerald-100 dark:border-emerald-400 dark:bg-emerald-900">
|
||||
Choose the setup that matches your starting point.
|
||||
|
||||
**Starting a new project?** Use [shadcn/create](/create) for a fully configured TanStack Start app with custom themes, Base UI or Radix, and icon libraries.
|
||||
<div className="mt-6 grid gap-4 sm:grid-cols-3 sm:gap-6">
|
||||
<LinkedCard
|
||||
href="#scaffold-with-create"
|
||||
className="items-start gap-1 p-6 text-sm md:p-6"
|
||||
>
|
||||
<div className="font-medium">Use shadcn/create</div>
|
||||
<div className="leading-relaxed text-muted-foreground">
|
||||
Build your preset and generate a TanStack project command.
|
||||
</div>
|
||||
</LinkedCard>
|
||||
<LinkedCard
|
||||
href="#scaffold-with-cli"
|
||||
className="items-start gap-1 p-6 text-sm md:p-6"
|
||||
>
|
||||
<div className="font-medium">Use the CLI</div>
|
||||
<div className="leading-relaxed text-muted-foreground">
|
||||
Scaffold a new TanStack project from the terminal.
|
||||
</div>
|
||||
</LinkedCard>
|
||||
<LinkedCard
|
||||
href="#existing-start-project"
|
||||
className="items-start gap-1 p-6 text-sm md:p-6"
|
||||
>
|
||||
<div className="font-medium">Existing Project</div>
|
||||
<div className="leading-relaxed text-muted-foreground">
|
||||
Configure shadcn/ui manually in an existing TanStack project.
|
||||
</div>
|
||||
</LinkedCard>
|
||||
</div>
|
||||
|
||||
</Callout>
|
||||
<div id="scaffold-with-create" className="scroll-mt-24" />
|
||||
## Use shadcn/create
|
||||
|
||||
<Steps>
|
||||
|
||||
### Create project
|
||||
### Build Your Preset
|
||||
|
||||
Run the following command to create a new TanStack Start project with shadcn/ui:
|
||||
Open [shadcn/create](/create?template=start) and build your preset visually. Choose your style, colors, fonts, icons, and more.
|
||||
|
||||
<Button asChild size="sm">
|
||||
<Link
|
||||
href="/create?template=start"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="mt-6 no-underline!"
|
||||
>
|
||||
Open shadcn/create
|
||||
</Link>
|
||||
</Button>
|
||||
|
||||
### Create Project
|
||||
|
||||
Click `Create Project`, choose your package manager, and copy the generated command.
|
||||
|
||||
The generated command will look similar to this:
|
||||
|
||||
```bash
|
||||
npx shadcn@latest init --preset [CODE] --template start
|
||||
```
|
||||
|
||||
The exact command will include your selected options such as `--base`, `--monorepo`, or `--rtl`.
|
||||
|
||||
### Add Components
|
||||
|
||||
Add the `Card` component to your project:
|
||||
|
||||
```bash
|
||||
npx shadcn@latest add card
|
||||
```
|
||||
|
||||
If you created a monorepo, run the command from `apps/web` or specify the workspace from the repo root:
|
||||
|
||||
```bash
|
||||
npx shadcn@latest add card -c apps/web
|
||||
```
|
||||
|
||||
The command above will add the `Card` component to your project. You can then import it like this:
|
||||
|
||||
```tsx showLineNumbers title="src/routes/index.tsx"
|
||||
import { createFileRoute } from "@tanstack/react-router"
|
||||
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "@/components/ui/card"
|
||||
|
||||
export const Route = createFileRoute("/")({
|
||||
component: App,
|
||||
})
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<Card className="max-w-sm">
|
||||
<CardHeader>
|
||||
<CardTitle>Project Overview</CardTitle>
|
||||
<CardDescription>
|
||||
Track progress and recent activity for your TanStack Start app.
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
Your design system is ready. Start building your next component.
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
If you created a monorepo, update `apps/web/src/routes/index.tsx` and import from `@workspace/ui/components/card` instead.
|
||||
|
||||
</Steps>
|
||||
|
||||
<div id="scaffold-with-cli" className="scroll-mt-24" />
|
||||
## Use the CLI
|
||||
|
||||
<Steps>
|
||||
|
||||
### Create Project
|
||||
|
||||
Run the `init` command to scaffold a new TanStack Start project. Follow the prompts to configure your project: base, preset, monorepo, and more.
|
||||
|
||||
```bash
|
||||
npx shadcn@latest init -t start
|
||||
@@ -27,6 +140,89 @@ npx shadcn@latest init -t start --monorepo
|
||||
|
||||
### Add Components
|
||||
|
||||
Add the `Card` component to your project:
|
||||
|
||||
```bash
|
||||
npx shadcn@latest add card
|
||||
```
|
||||
|
||||
If you created a monorepo, run the command from `apps/web` or specify the workspace from the repo root:
|
||||
|
||||
```bash
|
||||
npx shadcn@latest add card -c apps/web
|
||||
```
|
||||
|
||||
The command above will add the `Card` component to your project. You can then import it like this:
|
||||
|
||||
```tsx showLineNumbers title="src/routes/index.tsx"
|
||||
import { createFileRoute } from "@tanstack/react-router"
|
||||
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "@/components/ui/card"
|
||||
|
||||
export const Route = createFileRoute("/")({
|
||||
component: App,
|
||||
})
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<Card className="max-w-sm">
|
||||
<CardHeader>
|
||||
<CardTitle>Project Overview</CardTitle>
|
||||
<CardDescription>
|
||||
Track progress and recent activity for your TanStack Start app.
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
Your design system is ready. Start building your next component.
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
```
|
||||
|
||||
If you created a monorepo, update `apps/web/src/routes/index.tsx` and import from `@workspace/ui/components/card` instead.
|
||||
|
||||
</Steps>
|
||||
|
||||
<div id="existing-start-project" className="scroll-mt-24" />
|
||||
## Existing Project
|
||||
|
||||
<Steps>
|
||||
|
||||
### Create Project
|
||||
|
||||
If you need a new TanStack Start project, create one first. Otherwise, skip this step.
|
||||
|
||||
```bash
|
||||
npx @tanstack/cli@latest create
|
||||
```
|
||||
|
||||
Choose TanStack Start, the React framework, and the recommended defaults so Tailwind CSS and the `@/*` import alias are configured for you.
|
||||
|
||||
<Callout className="mt-6">
|
||||
|
||||
Do not add the `shadcn` add-on when prompted. The `shadcn` CLI will configure shadcn/ui later in this guide.
|
||||
|
||||
</Callout>
|
||||
|
||||
The TanStack CLI already configures Tailwind CSS and the default `@/*` import alias for you. If you're adding shadcn/ui to an older or custom TanStack Start app, make sure both are configured before continuing.
|
||||
|
||||
### Run the CLI
|
||||
|
||||
Run the `shadcn` init command to set up shadcn/ui in your project.
|
||||
|
||||
```bash
|
||||
npx shadcn@latest init
|
||||
```
|
||||
|
||||
### Add Components
|
||||
|
||||
You can now start adding components to your project.
|
||||
|
||||
```bash
|
||||
@@ -35,12 +231,18 @@ npx shadcn@latest add button
|
||||
|
||||
The command above will add the `Button` component to your project. You can then import it like this:
|
||||
|
||||
```tsx title="app/routes/index.tsx" showLineNumbers {1,6}
|
||||
```tsx showLineNumbers title="src/routes/index.tsx"
|
||||
import { createFileRoute } from "@tanstack/react-router"
|
||||
|
||||
import { Button } from "@/components/ui/button"
|
||||
|
||||
export const Route = createFileRoute("/")({
|
||||
component: App,
|
||||
})
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<div>
|
||||
<div className="flex min-h-svh items-center justify-center p-6">
|
||||
<Button>Click me</Button>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -3,17 +3,126 @@ title: Vite
|
||||
description: Install and configure shadcn/ui for Vite.
|
||||
---
|
||||
|
||||
<Callout className="mb-6 border-emerald-600 bg-emerald-100 dark:border-emerald-400 dark:bg-emerald-900">
|
||||
Choose the setup that matches your starting point.
|
||||
|
||||
**Starting fresh?** Use [shadcn/create](/create) to configure a Vite project with custom themes, Base UI or Radix, and icon libraries.
|
||||
<div className="mt-6 grid gap-4 sm:grid-cols-3 sm:gap-6">
|
||||
<LinkedCard
|
||||
href="#scaffold-with-create"
|
||||
className="items-start gap-1 p-6 text-sm md:p-6"
|
||||
>
|
||||
<div className="font-medium">Use shadcn/create</div>
|
||||
<div className="leading-relaxed text-muted-foreground">
|
||||
Build your preset and generate a Vite project command.
|
||||
</div>
|
||||
</LinkedCard>
|
||||
<LinkedCard
|
||||
href="#scaffold-with-cli"
|
||||
className="items-start gap-1 p-6 text-sm md:p-6"
|
||||
>
|
||||
<div className="font-medium">Use the CLI</div>
|
||||
<div className="leading-relaxed text-muted-foreground">
|
||||
Scaffold a new Vite project directly from the terminal.
|
||||
</div>
|
||||
</LinkedCard>
|
||||
<LinkedCard
|
||||
href="#existing-vite-project"
|
||||
className="items-start gap-1 p-6 text-sm md:p-6"
|
||||
>
|
||||
<div className="font-medium">Existing Project</div>
|
||||
<div className="leading-relaxed text-muted-foreground">
|
||||
Configure shadcn/ui manually in an existing Vite project.
|
||||
</div>
|
||||
</LinkedCard>
|
||||
</div>
|
||||
|
||||
</Callout>
|
||||
<div id="scaffold-with-create" className="scroll-mt-24" />
|
||||
## Use shadcn/create
|
||||
|
||||
<Steps>
|
||||
|
||||
### Build Your Preset
|
||||
|
||||
Open [shadcn/create](/create?template=vite) and build your preset visually. Choose your style, colors, fonts, icons, and more.
|
||||
|
||||
<Button asChild size="sm">
|
||||
<Link
|
||||
href="/create?template=vite"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="mt-6 no-underline!"
|
||||
>
|
||||
Open shadcn/create
|
||||
</Link>
|
||||
</Button>
|
||||
|
||||
### Create Project
|
||||
|
||||
Click `Create Project`, choose your package manager, and copy the generated command.
|
||||
|
||||
The generated command will look similar to this:
|
||||
|
||||
```bash
|
||||
npx shadcn@latest init --preset [CODE] --template vite
|
||||
```
|
||||
|
||||
The exact command will include your selected options such as `--base`, `--monorepo`, or `--rtl`.
|
||||
|
||||
### Add Components
|
||||
|
||||
Add the `Card` component to your project:
|
||||
|
||||
```bash
|
||||
npx shadcn@latest add card
|
||||
```
|
||||
|
||||
If you created a monorepo, run the command from `apps/web` or specify the workspace from the repo root:
|
||||
|
||||
```bash
|
||||
npx shadcn@latest add card -c apps/web
|
||||
```
|
||||
|
||||
The command above will add the `Card` component to your project. You can then import it like this:
|
||||
|
||||
```tsx showLineNumbers title="src/App.tsx"
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "@/components/ui/card"
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<Card className="max-w-sm">
|
||||
<CardHeader>
|
||||
<CardTitle>Project Overview</CardTitle>
|
||||
<CardDescription>
|
||||
Track progress and recent activity for your Vite app.
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
Your design system is ready. Start building your next component.
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
export default App
|
||||
```
|
||||
|
||||
If you created a monorepo, update `apps/web/src/App.tsx` and import from `@workspace/ui/components/card` instead.
|
||||
|
||||
</Steps>
|
||||
|
||||
<div id="scaffold-with-cli" className="scroll-mt-24" />
|
||||
## Use the CLI
|
||||
|
||||
<Steps>
|
||||
|
||||
### Create Project
|
||||
|
||||
Run the `init` command to create a new Vite project or to set up an existing one:
|
||||
Run the `init` command to scaffold a new Vite project. Follow the prompts to configure your project: base, preset, monorepo, and more.
|
||||
|
||||
```bash
|
||||
npx shadcn@latest init -t vite
|
||||
@@ -27,6 +136,159 @@ npx shadcn@latest init -t vite --monorepo
|
||||
|
||||
### Add Components
|
||||
|
||||
Add the `Card` component to your project:
|
||||
|
||||
```bash
|
||||
npx shadcn@latest add card
|
||||
```
|
||||
|
||||
If you created a monorepo, run the command from `apps/web` or specify the workspace from the repo root:
|
||||
|
||||
```bash
|
||||
npx shadcn@latest add card -c apps/web
|
||||
```
|
||||
|
||||
The command above will add the `Card` component to your project. You can then import it like this:
|
||||
|
||||
```tsx showLineNumbers title="src/App.tsx"
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "@/components/ui/card"
|
||||
|
||||
function App() {
|
||||
return (
|
||||
<Card className="max-w-sm">
|
||||
<CardHeader>
|
||||
<CardTitle>Project Overview</CardTitle>
|
||||
<CardDescription>
|
||||
Track progress and recent activity for your Vite app.
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
Your design system is ready. Start building your next component.
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
export default App
|
||||
```
|
||||
|
||||
If you created a monorepo, update `apps/web/src/App.tsx` and import from `@workspace/ui/components/card` instead.
|
||||
|
||||
</Steps>
|
||||
|
||||
<div id="existing-vite-project" className="scroll-mt-24" />
|
||||
## Existing Project
|
||||
|
||||
<Steps>
|
||||
|
||||
### Create Project
|
||||
|
||||
If you need a new Vite project, create one first and select the **React + TypeScript** template. Otherwise, skip this step.
|
||||
|
||||
```bash
|
||||
npm create vite@latest
|
||||
```
|
||||
|
||||
### Add Tailwind CSS
|
||||
|
||||
If your project already has Tailwind CSS configured, skip this step.
|
||||
|
||||
```bash
|
||||
npm install tailwindcss @tailwindcss/vite
|
||||
```
|
||||
|
||||
Replace everything in `src/index.css` with the following:
|
||||
|
||||
```css title="src/index.css"
|
||||
@import "tailwindcss";
|
||||
```
|
||||
|
||||
### Edit tsconfig.json file
|
||||
|
||||
If your project already has the `@/*` alias configured, skip this step.
|
||||
|
||||
Vite splits TypeScript configuration across multiple files. Add the `baseUrl` and `paths` properties to the `compilerOptions` section of `tsconfig.json` and `tsconfig.app.json`:
|
||||
|
||||
```ts title="tsconfig.json" {11-16} showLineNumbers
|
||||
{
|
||||
"files": [],
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.app.json"
|
||||
},
|
||||
{
|
||||
"path": "./tsconfig.node.json"
|
||||
}
|
||||
],
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@/*": ["./src/*"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Edit tsconfig.app.json file
|
||||
|
||||
Add the same alias to `tsconfig.app.json` so your editor can resolve imports:
|
||||
|
||||
```ts title="tsconfig.app.json" {4-9} showLineNumbers
|
||||
{
|
||||
"compilerOptions": {
|
||||
// ...
|
||||
"baseUrl": ".",
|
||||
"paths": {
|
||||
"@/*": [
|
||||
"./src/*"
|
||||
]
|
||||
}
|
||||
// ...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Update vite.config.ts
|
||||
|
||||
Install `@types/node` and update `vite.config.ts` so Vite can resolve the `@` alias:
|
||||
|
||||
```bash
|
||||
npm install -D @types/node
|
||||
```
|
||||
|
||||
```typescript title="vite.config.ts" showLineNumbers {1,2,8-13}
|
||||
import path from "path"
|
||||
import tailwindcss from "@tailwindcss/vite"
|
||||
import react from "@vitejs/plugin-react"
|
||||
import { defineConfig } from "vite"
|
||||
|
||||
// https://vite.dev/config/
|
||||
export default defineConfig({
|
||||
plugins: [react(), tailwindcss()],
|
||||
resolve: {
|
||||
alias: {
|
||||
"@": path.resolve(__dirname, "./src"),
|
||||
},
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
### Run the CLI
|
||||
|
||||
Run the `shadcn` init command to set up shadcn/ui in your project:
|
||||
|
||||
```bash
|
||||
npx shadcn@latest init
|
||||
```
|
||||
|
||||
### Add Components
|
||||
|
||||
You can now start adding components to your project.
|
||||
|
||||
```bash
|
||||
@@ -35,16 +297,18 @@ npx shadcn@latest add button
|
||||
|
||||
The command above will add the `Button` component to your project. You can then import it like this:
|
||||
|
||||
```tsx {1,6} showLineNumbers title="src/App.tsx"
|
||||
```tsx showLineNumbers title="src/App.tsx"
|
||||
import { Button } from "@/components/ui/button"
|
||||
|
||||
export default function App() {
|
||||
function App() {
|
||||
return (
|
||||
<div>
|
||||
<div className="flex min-h-svh flex-col items-center justify-center">
|
||||
<Button>Click me</Button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
export default App
|
||||
```
|
||||
|
||||
</Steps>
|
||||
|
||||
@@ -7,17 +7,11 @@ This directory contains demo components for the component documentation.
|
||||
```
|
||||
examples
|
||||
├── base
|
||||
│ ├── ui # Auto-generated by build-registry.mts
|
||||
│ ├── lib # Auto-generated by build-registry.mts
|
||||
│ ├── hooks # Auto-generated by build-registry.mts
|
||||
│ ├── button-demo.tsx
|
||||
│ └── ...
|
||||
├── radix
|
||||
│ ├── ui # Auto-generated by build-registry.mts
|
||||
│ ├── lib # Auto-generated by build-registry.mts
|
||||
│ ├── hooks # Auto-generated by build-registry.mts
|
||||
│ └── ...
|
||||
└── __index__.tsx # Auto-generated by build-registry.mts
|
||||
└── __index__.tsx # Auto-generated by registry:build
|
||||
```
|
||||
|
||||
## Adding a New Example
|
||||
@@ -26,17 +20,17 @@ examples
|
||||
|
||||
```tsx
|
||||
// examples/base/button-loading.tsx
|
||||
import { Button } from "@/examples/base/ui/button"
|
||||
import { Button } from "@/styles/base-nova/ui/button"
|
||||
|
||||
export function ButtonLoading() {
|
||||
return <Button disabled>Loading...</Button>
|
||||
}
|
||||
```
|
||||
|
||||
2. Run the examples build to regenerate the index:
|
||||
2. Run the registry build to regenerate the index:
|
||||
|
||||
```bash
|
||||
pnpm examples:build
|
||||
pnpm --filter=v4 registry:build
|
||||
```
|
||||
|
||||
3. Use the example in documentation by referencing its name (filename without `.tsx`):
|
||||
@@ -47,7 +41,7 @@ pnpm examples:build
|
||||
|
||||
## Notes
|
||||
|
||||
- The `ui`, `lib`, and `hooks` directories are auto-generated during `pnpm registry:build`. Do not edit files in these directories directly.
|
||||
- Example files should be placed directly in `examples/base` or `examples/radix`, not in subdirectories.
|
||||
- Base examples should import from `@/styles/base-nova/*`. Radix examples should import from `@/styles/radix-nova/*`.
|
||||
- Both named exports and default exports are supported.
|
||||
- After adding or removing examples, run `pnpm examples:build` to update the index.
|
||||
- After adding or removing examples, run `pnpm --filter=v4 registry:build` to update the index.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// @ts-nocheck
|
||||
// This file is autogenerated by scripts/build-examples-index.mts
|
||||
// This file is autogenerated by scripts/build-registry.mts
|
||||
// Do not edit this file directly.
|
||||
import * as React from "react"
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import {
|
||||
AccordionContent,
|
||||
AccordionItem,
|
||||
AccordionTrigger,
|
||||
} from "@/examples/base/ui/accordion"
|
||||
} from "@/styles/base-nova/ui/accordion"
|
||||
|
||||
const items = [
|
||||
{
|
||||
|
||||
@@ -3,7 +3,7 @@ import {
|
||||
AccordionContent,
|
||||
AccordionItem,
|
||||
AccordionTrigger,
|
||||
} from "@/examples/base/ui/accordion"
|
||||
} from "@/styles/base-nova/ui/accordion"
|
||||
|
||||
const items = [
|
||||
{
|
||||
|
||||
@@ -3,14 +3,14 @@ import {
|
||||
AccordionContent,
|
||||
AccordionItem,
|
||||
AccordionTrigger,
|
||||
} from "@/examples/base/ui/accordion"
|
||||
} from "@/styles/base-nova/ui/accordion"
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardDescription,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "@/examples/base/ui/card"
|
||||
} from "@/styles/base-nova/ui/card"
|
||||
|
||||
const items = [
|
||||
{
|
||||
|
||||
@@ -3,7 +3,7 @@ import {
|
||||
AccordionContent,
|
||||
AccordionItem,
|
||||
AccordionTrigger,
|
||||
} from "@/examples/base/ui/accordion"
|
||||
} from "@/styles/base-nova/ui/accordion"
|
||||
|
||||
export default function AccordionDemo() {
|
||||
return (
|
||||
|
||||
@@ -3,7 +3,7 @@ import {
|
||||
AccordionContent,
|
||||
AccordionItem,
|
||||
AccordionTrigger,
|
||||
} from "@/examples/base/ui/accordion"
|
||||
} from "@/styles/base-nova/ui/accordion"
|
||||
|
||||
export default function AccordionDisabled() {
|
||||
return (
|
||||
|
||||
@@ -3,7 +3,7 @@ import {
|
||||
AccordionContent,
|
||||
AccordionItem,
|
||||
AccordionTrigger,
|
||||
} from "@/examples/base/ui/accordion"
|
||||
} from "@/styles/base-nova/ui/accordion"
|
||||
|
||||
const items = [
|
||||
{
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
"use client"
|
||||
|
||||
import * as React from "react"
|
||||
import {
|
||||
Accordion,
|
||||
AccordionContent,
|
||||
AccordionItem,
|
||||
AccordionTrigger,
|
||||
} from "@/examples/base/ui-rtl/accordion"
|
||||
|
||||
import {
|
||||
useTranslation,
|
||||
type Translations,
|
||||
} from "@/components/language-selector"
|
||||
import {
|
||||
Accordion,
|
||||
AccordionContent,
|
||||
AccordionItem,
|
||||
AccordionTrigger,
|
||||
} from "@/styles/base-nova/ui-rtl/accordion"
|
||||
|
||||
const translations: Translations = {
|
||||
en: {
|
||||
|
||||
@@ -3,8 +3,8 @@ import {
|
||||
AlertAction,
|
||||
AlertDescription,
|
||||
AlertTitle,
|
||||
} from "@/examples/base/ui/alert"
|
||||
import { Button } from "@/examples/base/ui/button"
|
||||
} from "@/styles/base-nova/ui/alert"
|
||||
import { Button } from "@/styles/base-nova/ui/button"
|
||||
|
||||
export default function AlertActionExample() {
|
||||
return (
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
import { Alert, AlertDescription, AlertTitle } from "@/examples/base/ui/alert"
|
||||
import { CheckCircle2Icon } from "lucide-react"
|
||||
|
||||
import {
|
||||
Alert,
|
||||
AlertDescription,
|
||||
AlertTitle,
|
||||
} from "@/styles/base-nova/ui/alert"
|
||||
|
||||
export default function AlertBasic() {
|
||||
return (
|
||||
<Alert className="max-w-md">
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
import { Alert, AlertDescription, AlertTitle } from "@/examples/base/ui/alert"
|
||||
import { AlertTriangleIcon } from "lucide-react"
|
||||
|
||||
import {
|
||||
Alert,
|
||||
AlertDescription,
|
||||
AlertTitle,
|
||||
} from "@/styles/base-nova/ui/alert"
|
||||
|
||||
export default function AlertColors() {
|
||||
return (
|
||||
<Alert className="max-w-md border-amber-200 bg-amber-50 text-amber-900 dark:border-amber-900 dark:bg-amber-950 dark:text-amber-50">
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
import { Alert, AlertDescription, AlertTitle } from "@/examples/base/ui/alert"
|
||||
import { CheckCircle2Icon, InfoIcon } from "lucide-react"
|
||||
|
||||
import {
|
||||
Alert,
|
||||
AlertDescription,
|
||||
AlertTitle,
|
||||
} from "@/styles/base-nova/ui/alert"
|
||||
|
||||
export default function AlertDemo() {
|
||||
return (
|
||||
<div className="grid w-full max-w-md items-start gap-4">
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
import { Alert, AlertDescription, AlertTitle } from "@/examples/base/ui/alert"
|
||||
import { AlertCircleIcon } from "lucide-react"
|
||||
|
||||
import {
|
||||
Alert,
|
||||
AlertDescription,
|
||||
AlertTitle,
|
||||
} from "@/styles/base-nova/ui/alert"
|
||||
|
||||
export default function AlertDestructive() {
|
||||
return (
|
||||
<Alert variant="destructive" className="max-w-md">
|
||||
|
||||
@@ -8,8 +8,8 @@ import {
|
||||
AlertDialogHeader,
|
||||
AlertDialogTitle,
|
||||
AlertDialogTrigger,
|
||||
} from "@/examples/base/ui/alert-dialog"
|
||||
import { Button } from "@/examples/base/ui/button"
|
||||
} from "@/styles/base-nova/ui/alert-dialog"
|
||||
import { Button } from "@/styles/base-nova/ui/button"
|
||||
|
||||
export function AlertDialogBasic() {
|
||||
return (
|
||||
|
||||
@@ -8,8 +8,8 @@ import {
|
||||
AlertDialogHeader,
|
||||
AlertDialogTitle,
|
||||
AlertDialogTrigger,
|
||||
} from "@/examples/base/ui/alert-dialog"
|
||||
import { Button } from "@/examples/base/ui/button"
|
||||
} from "@/styles/base-nova/ui/alert-dialog"
|
||||
import { Button } from "@/styles/base-nova/ui/button"
|
||||
|
||||
export default function AlertDialogDemo() {
|
||||
return (
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { Trash2Icon } from "lucide-react"
|
||||
|
||||
import {
|
||||
AlertDialog,
|
||||
AlertDialogAction,
|
||||
@@ -9,9 +11,8 @@ import {
|
||||
AlertDialogMedia,
|
||||
AlertDialogTitle,
|
||||
AlertDialogTrigger,
|
||||
} from "@/examples/base/ui/alert-dialog"
|
||||
import { Button } from "@/examples/base/ui/button"
|
||||
import { Trash2Icon } from "lucide-react"
|
||||
} from "@/styles/base-nova/ui/alert-dialog"
|
||||
import { Button } from "@/styles/base-nova/ui/button"
|
||||
|
||||
export function AlertDialogDestructive() {
|
||||
return (
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { CircleFadingPlusIcon } from "lucide-react"
|
||||
|
||||
import {
|
||||
AlertDialog,
|
||||
AlertDialogAction,
|
||||
@@ -9,9 +11,8 @@ import {
|
||||
AlertDialogMedia,
|
||||
AlertDialogTitle,
|
||||
AlertDialogTrigger,
|
||||
} from "@/examples/base/ui/alert-dialog"
|
||||
import { Button } from "@/examples/base/ui/button"
|
||||
import { CircleFadingPlusIcon } from "lucide-react"
|
||||
} from "@/styles/base-nova/ui/alert-dialog"
|
||||
import { Button } from "@/styles/base-nova/ui/button"
|
||||
|
||||
export function AlertDialogWithMedia() {
|
||||
return (
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
"use client"
|
||||
|
||||
import { BluetoothIcon } from "lucide-react"
|
||||
|
||||
import {
|
||||
useTranslation,
|
||||
type Translations,
|
||||
} from "@/components/language-selector"
|
||||
import {
|
||||
AlertDialog,
|
||||
AlertDialogAction,
|
||||
@@ -11,14 +17,8 @@ import {
|
||||
AlertDialogMedia,
|
||||
AlertDialogTitle,
|
||||
AlertDialogTrigger,
|
||||
} from "@/examples/base/ui-rtl/alert-dialog"
|
||||
import { Button } from "@/examples/base/ui-rtl/button"
|
||||
import { BluetoothIcon } from "lucide-react"
|
||||
|
||||
import {
|
||||
useTranslation,
|
||||
type Translations,
|
||||
} from "@/components/language-selector"
|
||||
} from "@/styles/base-nova/ui-rtl/alert-dialog"
|
||||
import { Button } from "@/styles/base-nova/ui-rtl/button"
|
||||
|
||||
const translations: Translations = {
|
||||
en: {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { BluetoothIcon } from "lucide-react"
|
||||
|
||||
import {
|
||||
AlertDialog,
|
||||
AlertDialogAction,
|
||||
@@ -9,9 +11,8 @@ import {
|
||||
AlertDialogMedia,
|
||||
AlertDialogTitle,
|
||||
AlertDialogTrigger,
|
||||
} from "@/examples/base/ui/alert-dialog"
|
||||
import { Button } from "@/examples/base/ui/button"
|
||||
import { BluetoothIcon } from "lucide-react"
|
||||
} from "@/styles/base-nova/ui/alert-dialog"
|
||||
import { Button } from "@/styles/base-nova/ui/button"
|
||||
|
||||
export function AlertDialogSmallWithMedia() {
|
||||
return (
|
||||
|
||||
@@ -8,8 +8,8 @@ import {
|
||||
AlertDialogHeader,
|
||||
AlertDialogTitle,
|
||||
AlertDialogTrigger,
|
||||
} from "@/examples/base/ui/alert-dialog"
|
||||
import { Button } from "@/examples/base/ui/button"
|
||||
} from "@/styles/base-nova/ui/alert-dialog"
|
||||
import { Button } from "@/styles/base-nova/ui/button"
|
||||
|
||||
export function AlertDialogSmall() {
|
||||
return (
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
"use client"
|
||||
|
||||
import * as React from "react"
|
||||
import {
|
||||
Alert,
|
||||
AlertDescription,
|
||||
AlertTitle,
|
||||
} from "@/examples/base/ui-rtl/alert"
|
||||
import { CheckCircle2Icon, InfoIcon } from "lucide-react"
|
||||
|
||||
import {
|
||||
useTranslation,
|
||||
type Translations,
|
||||
} from "@/components/language-selector"
|
||||
import {
|
||||
Alert,
|
||||
AlertDescription,
|
||||
AlertTitle,
|
||||
} from "@/styles/base-nova/ui-rtl/alert"
|
||||
|
||||
const translations: Translations = {
|
||||
en: {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user