mirror of
https://github.com/shadcn-ui/ui.git
synced 2026-06-22 04:05:48 +00:00
Compare commits
17 Commits
@shadcn/ui
...
shadcn-ui@
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d3cc7a3a6f | ||
|
|
96f300ea74 | ||
|
|
a243262748 | ||
|
|
b5d43688b9 | ||
|
|
3819f07d9d | ||
|
|
81ee0de71c | ||
|
|
4444c28b9f | ||
|
|
3899b1cc10 | ||
|
|
49dbba624f | ||
|
|
309267b73c | ||
|
|
d6933321dc | ||
|
|
272c7c0980 | ||
|
|
29a333721a | ||
|
|
a86af454cc | ||
|
|
33e72a6796 | ||
|
|
3961f15dc6 | ||
|
|
faf05aa086 |
4
.github/workflows/prerelease-comment.yml
vendored
4
.github/workflows/prerelease-comment.yml
vendored
@@ -28,7 +28,7 @@ jobs:
|
|||||||
|
|
||||||
for (const artifact of allArtifacts.data.artifacts) {
|
for (const artifact of allArtifacts.data.artifacts) {
|
||||||
// Extract the PR number and package version from the artifact name
|
// Extract the PR number and package version from the artifact name
|
||||||
const match = /^npm-package-@shadcn-ui@(.*?)-pr-(\d+)/.exec(artifact.name);
|
const match = /^npm-package-shadcn-ui@(.*?)-pr-(\d+)/.exec(artifact.name);
|
||||||
|
|
||||||
if (match) {
|
if (match) {
|
||||||
require("fs").appendFileSync(
|
require("fs").appendFileSync(
|
||||||
@@ -49,7 +49,7 @@ jobs:
|
|||||||
A new prerelease is available for testing:
|
A new prerelease is available for testing:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
pnpm @shadcn/ui@${{ env.BETA_PACKAGE_VERSION }}
|
npx shadcn-ui@${{ env.BETA_PACKAGE_VERSION }}
|
||||||
```
|
```
|
||||||
|
|
||||||
- name: "Remove the autorelease label once published"
|
- name: "Remove the autorelease label once published"
|
||||||
|
|||||||
2
.github/workflows/prerelease.yml
vendored
2
.github/workflows/prerelease.yml
vendored
@@ -54,5 +54,5 @@ jobs:
|
|||||||
- name: Upload packaged artifact
|
- name: Upload packaged artifact
|
||||||
uses: actions/upload-artifact@v2
|
uses: actions/upload-artifact@v2
|
||||||
with:
|
with:
|
||||||
name: npm-package-@shadcn-ui@${{ steps.package-version.outputs.current-version }}-pr-${{ github.event.number }} # encode the PR number into the artifact name
|
name: npm-package-shadcn-ui@${{ steps.package-version.outputs.current-version }}-pr-${{ github.event.number }} # encode the PR number into the artifact name
|
||||||
path: packages/cli/dist/index.js
|
path: packages/cli/dist/index.js
|
||||||
|
|||||||
4
.github/workflows/release.yml
vendored
4
.github/workflows/release.yml
vendored
@@ -30,8 +30,8 @@ jobs:
|
|||||||
- name: Install NPM Dependencies
|
- name: Install NPM Dependencies
|
||||||
run: pnpm install
|
run: pnpm install
|
||||||
|
|
||||||
- name: Check for errors
|
# - name: Check for errors
|
||||||
run: pnpm check
|
# run: pnpm check
|
||||||
|
|
||||||
- name: Build the package
|
- name: Build the package
|
||||||
run: pnpm build:cli
|
run: pnpm build:cli
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { Inter as FontSans } from "@next/font/google"
|
import { Inter as FontSans } from "next/font/google"
|
||||||
|
|
||||||
import "@/styles/globals.css"
|
import "@/styles/globals.css"
|
||||||
import { cn } from "@/lib/utils"
|
import { cn } from "@/lib/utils"
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import { siteConfig } from "@/config/site"
|
|||||||
import { cn } from "@/lib/utils"
|
import { cn } from "@/lib/utils"
|
||||||
import { AppleMusicDemo } from "@/components/apple-music-demo"
|
import { AppleMusicDemo } from "@/components/apple-music-demo"
|
||||||
import { CopyButton } from "@/components/copy-button"
|
import { CopyButton } from "@/components/copy-button"
|
||||||
|
import { Icons } from "@/components/icons"
|
||||||
import { PromoVideo } from "@/components/promo-video"
|
import { PromoVideo } from "@/components/promo-video"
|
||||||
import { buttonVariants } from "@/components/ui/button"
|
import { buttonVariants } from "@/components/ui/button"
|
||||||
|
|
||||||
@@ -30,7 +31,7 @@ export default function IndexPage() {
|
|||||||
</div>
|
</div>
|
||||||
<div className="flex flex-col space-y-4 sm:flex-row sm:space-y-0 sm:space-x-4 md:flex-row">
|
<div className="flex flex-col space-y-4 sm:flex-row sm:space-y-0 sm:space-x-4 md:flex-row">
|
||||||
<Link href="/docs" className={buttonVariants({ size: "lg" })}>
|
<Link href="/docs" className={buttonVariants({ size: "lg" })}>
|
||||||
Documentation
|
Get Started
|
||||||
</Link>
|
</Link>
|
||||||
<Link
|
<Link
|
||||||
target="_blank"
|
target="_blank"
|
||||||
@@ -38,20 +39,12 @@ export default function IndexPage() {
|
|||||||
href={siteConfig.links.github}
|
href={siteConfig.links.github}
|
||||||
className={cn(
|
className={cn(
|
||||||
buttonVariants({ variant: "outline", size: "lg" }),
|
buttonVariants({ variant: "outline", size: "lg" }),
|
||||||
"md:hidden"
|
"pl-6"
|
||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
|
<Icons.gitHub className="mr-2 h-4 w-4" />
|
||||||
GitHub
|
GitHub
|
||||||
</Link>
|
</Link>
|
||||||
<pre className="hidden h-11 items-center justify-between space-x-2 overflow-x-auto rounded-lg border border-slate-100 bg-slate-100 pr-2 pl-6 dark:border-slate-700 dark:bg-black md:flex">
|
|
||||||
<code className="font-mono text-sm font-semibold text-slate-900 dark:text-slate-50">
|
|
||||||
npx create-next-app -e https://github.com/shadcn/next-template
|
|
||||||
</code>
|
|
||||||
<CopyButton
|
|
||||||
value="npx create-next-app -e https://github.com/shadcn/next-template"
|
|
||||||
className="border-none text-slate-900 hover:bg-transparent dark:text-slate-50"
|
|
||||||
/>
|
|
||||||
</pre>
|
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<p className="text-sm text-slate-500 dark:text-slate-400">
|
<p className="text-sm text-slate-500 dark:text-slate-400">
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
import {
|
import {
|
||||||
JetBrains_Mono as FontMono,
|
JetBrains_Mono as FontMono,
|
||||||
Inter as FontSans,
|
Inter as FontSans,
|
||||||
} from "@next/font/google"
|
} from "next/font/google"
|
||||||
|
|
||||||
const fontSans = FontSans({
|
const fontSans = FontSans({
|
||||||
subsets: ["latin"],
|
subsets: ["latin"],
|
||||||
|
|||||||
@@ -1,23 +1,8 @@
|
|||||||
"use client"
|
|
||||||
|
|
||||||
import * as React from "react"
|
import * as React from "react"
|
||||||
import Link from "next/link"
|
import Link from "next/link"
|
||||||
import { allDocs } from "contentlayer/generated"
|
|
||||||
|
|
||||||
import { siteConfig } from "@/config/site"
|
import { siteConfig } from "@/config/site"
|
||||||
import { cn } from "@/lib/utils"
|
|
||||||
import { Icons } from "@/components/icons"
|
import { Icons } from "@/components/icons"
|
||||||
import { buttonVariants } from "@/components/ui/button"
|
|
||||||
import {
|
|
||||||
NavigationMenu,
|
|
||||||
NavigationMenuContent,
|
|
||||||
NavigationMenuItem,
|
|
||||||
NavigationMenuLink,
|
|
||||||
NavigationMenuList,
|
|
||||||
NavigationMenuTrigger,
|
|
||||||
navigationMenuTriggerStyle,
|
|
||||||
} from "@/components/ui/navigation-menu"
|
|
||||||
import { Separator } from "@/components/ui/separator"
|
|
||||||
|
|
||||||
export function MainNav() {
|
export function MainNav() {
|
||||||
return (
|
return (
|
||||||
@@ -28,114 +13,12 @@ export function MainNav() {
|
|||||||
{siteConfig.name}
|
{siteConfig.name}
|
||||||
</span>
|
</span>
|
||||||
</Link>
|
</Link>
|
||||||
<NavigationMenu>
|
<nav className="flex items-center space-x-6 text-sm font-medium">
|
||||||
<NavigationMenuList>
|
<Link href="/docs">Documentation</Link>
|
||||||
<NavigationMenuItem>
|
<Link href="/docs/primitives/accordion">Components</Link>
|
||||||
<NavigationMenuTrigger className="h-9">
|
<Link href="/figma">Figma</Link>
|
||||||
Getting started
|
<Link href={siteConfig.links.github}>GitHub</Link>
|
||||||
</NavigationMenuTrigger>
|
</nav>
|
||||||
<NavigationMenuContent>
|
|
||||||
<ul className="grid gap-3 p-6 md:w-[400px] lg:w-[500px] lg:grid-cols-[.75fr_1fr]">
|
|
||||||
<li className="row-span-3">
|
|
||||||
<Link href="/" passHref legacyBehavior>
|
|
||||||
<NavigationMenuLink
|
|
||||||
className="flex h-full w-full select-none
|
|
||||||
flex-col justify-end space-y-2 rounded-md bg-gradient-to-b from-rose-500 to-indigo-700 p-6 no-underline outline-none focus:shadow-md"
|
|
||||||
>
|
|
||||||
<div className="text-lg font-medium text-white">
|
|
||||||
{siteConfig.name}
|
|
||||||
</div>
|
|
||||||
<p className="text-sm leading-snug text-white/90">
|
|
||||||
{siteConfig.description}
|
|
||||||
</p>
|
|
||||||
</NavigationMenuLink>
|
|
||||||
</Link>
|
|
||||||
</li>
|
|
||||||
<ListItem href="/docs" title="Introduction">
|
|
||||||
Re-usable components built using Radix UI and Tailwind CSS.
|
|
||||||
</ListItem>
|
|
||||||
<ListItem href="/docs/installation" title="Installation">
|
|
||||||
How to install dependencies and structure your app.
|
|
||||||
</ListItem>
|
|
||||||
<ListItem href="/docs/primitives/typography" title="Typography">
|
|
||||||
Styles for headings, paragraphs, lists...etc
|
|
||||||
</ListItem>
|
|
||||||
</ul>
|
|
||||||
</NavigationMenuContent>
|
|
||||||
</NavigationMenuItem>
|
|
||||||
<NavigationMenuItem>
|
|
||||||
<NavigationMenuTrigger className="h-9">
|
|
||||||
Components
|
|
||||||
</NavigationMenuTrigger>
|
|
||||||
<NavigationMenuContent>
|
|
||||||
<ul className="grid w-[600px] grid-cols-2 gap-3 p-4">
|
|
||||||
{allDocs
|
|
||||||
.filter((doc) => doc.featured)
|
|
||||||
.map((doc) => (
|
|
||||||
<ListItem key={doc._id} title={doc.title} href={doc.slug}>
|
|
||||||
{doc.description}
|
|
||||||
</ListItem>
|
|
||||||
))}
|
|
||||||
</ul>
|
|
||||||
<div className="p-4 pt-0">
|
|
||||||
<Separator className="mb-4" />
|
|
||||||
<Link href="/docs/primitives/accordion" passHref legacyBehavior>
|
|
||||||
<NavigationMenuLink
|
|
||||||
className={cn(
|
|
||||||
buttonVariants({ variant: "outline" }),
|
|
||||||
"w-full dark:hover:bg-slate-700"
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
Browse components
|
|
||||||
</NavigationMenuLink>
|
|
||||||
</Link>
|
|
||||||
</div>
|
|
||||||
</NavigationMenuContent>
|
|
||||||
</NavigationMenuItem>
|
|
||||||
<NavigationMenuItem className="hidden lg:flex">
|
|
||||||
<Link href="/figma" legacyBehavior passHref>
|
|
||||||
<NavigationMenuLink
|
|
||||||
className={cn(navigationMenuTriggerStyle(), "h-9")}
|
|
||||||
>
|
|
||||||
Figma
|
|
||||||
</NavigationMenuLink>
|
|
||||||
</Link>
|
|
||||||
</NavigationMenuItem>
|
|
||||||
<NavigationMenuItem className="hidden lg:flex">
|
|
||||||
<Link href={siteConfig.links.github} legacyBehavior passHref>
|
|
||||||
<NavigationMenuLink
|
|
||||||
className={cn(navigationMenuTriggerStyle(), "h-9")}
|
|
||||||
>
|
|
||||||
GitHub
|
|
||||||
</NavigationMenuLink>
|
|
||||||
</Link>
|
|
||||||
</NavigationMenuItem>
|
|
||||||
</NavigationMenuList>
|
|
||||||
</NavigationMenu>
|
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const ListItem = React.forwardRef<
|
|
||||||
React.ElementRef<typeof Link>,
|
|
||||||
React.ComponentPropsWithoutRef<typeof Link>
|
|
||||||
>(({ className, title, children, href, ...props }, ref) => {
|
|
||||||
return (
|
|
||||||
<li>
|
|
||||||
<Link href={href} passHref legacyBehavior {...props}>
|
|
||||||
<NavigationMenuLink
|
|
||||||
className={cn(
|
|
||||||
"block select-none space-y-1 rounded-md p-3 leading-none no-underline outline-none transition-colors hover:bg-slate-100 focus:bg-slate-100 dark:hover:bg-slate-700 dark:focus:bg-slate-700",
|
|
||||||
className
|
|
||||||
)}
|
|
||||||
>
|
|
||||||
<div className="text-sm font-medium leading-none">{title}</div>
|
|
||||||
<p className="line-clamp-2 text-sm leading-snug text-slate-500 dark:text-slate-400">
|
|
||||||
{children}
|
|
||||||
</p>
|
|
||||||
</NavigationMenuLink>
|
|
||||||
</Link>
|
|
||||||
</li>
|
|
||||||
)
|
|
||||||
})
|
|
||||||
ListItem.displayName = "ListItem"
|
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { VariantProps, cva } from "class-variance-authority"
|
|||||||
import { cn } from "@/lib/utils"
|
import { cn } from "@/lib/utils"
|
||||||
|
|
||||||
const buttonVariants = cva(
|
const buttonVariants = cva(
|
||||||
"active:scale-95 inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-slate-400 focus:ring-offset-2 dark:hover:bg-slate-800 dark:hover:text-slate-100 disabled:opacity-50 dark:focus:ring-slate-400 disabled:pointer-events-none dark:focus:ring-offset-slate-900 data-[state=open]:bg-slate-100 dark:data-[state=open]:bg-slate-800",
|
"inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-slate-400 focus:ring-offset-2 dark:hover:bg-slate-800 dark:hover:text-slate-100 disabled:opacity-50 dark:focus:ring-slate-400 disabled:pointer-events-none dark:focus:ring-offset-slate-900 data-[state=open]:bg-slate-100 dark:data-[state=open]:bg-slate-800",
|
||||||
{
|
{
|
||||||
variants: {
|
variants: {
|
||||||
variant: {
|
variant: {
|
||||||
|
|||||||
189
apps/www/components/ui/use-toast.ts
Normal file
189
apps/www/components/ui/use-toast.ts
Normal file
@@ -0,0 +1,189 @@
|
|||||||
|
// Inspired by react-hot-toast library
|
||||||
|
import * as React from "react"
|
||||||
|
|
||||||
|
import { ToastActionElement, type ToastProps } from "@/components/ui/toast"
|
||||||
|
|
||||||
|
const TOAST_LIMIT = 1
|
||||||
|
const TOAST_REMOVE_DELAY = 1000
|
||||||
|
|
||||||
|
type ToasterToast = ToastProps & {
|
||||||
|
id: string
|
||||||
|
title?: React.ReactNode
|
||||||
|
description?: React.ReactNode
|
||||||
|
action?: ToastActionElement
|
||||||
|
}
|
||||||
|
|
||||||
|
const actionTypes = {
|
||||||
|
ADD_TOAST: "ADD_TOAST",
|
||||||
|
UPDATE_TOAST: "UPDATE_TOAST",
|
||||||
|
DISMISS_TOAST: "DISMISS_TOAST",
|
||||||
|
REMOVE_TOAST: "REMOVE_TOAST",
|
||||||
|
} as const
|
||||||
|
|
||||||
|
let count = 0
|
||||||
|
|
||||||
|
function genId() {
|
||||||
|
count = (count + 1) % Number.MAX_VALUE
|
||||||
|
return count.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
type ActionType = typeof actionTypes
|
||||||
|
|
||||||
|
type Action =
|
||||||
|
| {
|
||||||
|
type: ActionType["ADD_TOAST"]
|
||||||
|
toast: ToasterToast
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
type: ActionType["UPDATE_TOAST"]
|
||||||
|
toast: Partial<ToasterToast>
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
type: ActionType["DISMISS_TOAST"]
|
||||||
|
toastId?: ToasterToast["id"]
|
||||||
|
}
|
||||||
|
| {
|
||||||
|
type: ActionType["REMOVE_TOAST"]
|
||||||
|
toastId?: ToasterToast["id"]
|
||||||
|
}
|
||||||
|
|
||||||
|
interface State {
|
||||||
|
toasts: ToasterToast[]
|
||||||
|
}
|
||||||
|
|
||||||
|
const toastTimeouts = new Map<string, ReturnType<typeof setTimeout>>()
|
||||||
|
|
||||||
|
const addToRemoveQueue = (toastId: string) => {
|
||||||
|
if (toastTimeouts.has(toastId)) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
const timeout = setTimeout(() => {
|
||||||
|
toastTimeouts.delete(toastId)
|
||||||
|
dispatch({
|
||||||
|
type: "REMOVE_TOAST",
|
||||||
|
toastId: toastId,
|
||||||
|
})
|
||||||
|
}, TOAST_REMOVE_DELAY)
|
||||||
|
|
||||||
|
toastTimeouts.set(toastId, timeout)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const reducer = (state: State, action: Action): State => {
|
||||||
|
switch (action.type) {
|
||||||
|
case "ADD_TOAST":
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
toasts: [action.toast, ...state.toasts].slice(0, TOAST_LIMIT),
|
||||||
|
}
|
||||||
|
|
||||||
|
case "UPDATE_TOAST":
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
toasts: state.toasts.map((t) =>
|
||||||
|
t.id === action.toast.id ? { ...t, ...action.toast } : t
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
case "DISMISS_TOAST": {
|
||||||
|
const { toastId } = action
|
||||||
|
|
||||||
|
// ! Side effects ! - This could be extracted into a dismissToast() action,
|
||||||
|
// but I'll keep it here for simplicity
|
||||||
|
if (toastId) {
|
||||||
|
addToRemoveQueue(toastId)
|
||||||
|
} else {
|
||||||
|
state.toasts.forEach((toast) => {
|
||||||
|
addToRemoveQueue(toast.id)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
toasts: state.toasts.map((t) =>
|
||||||
|
t.id === toastId || toastId === undefined
|
||||||
|
? {
|
||||||
|
...t,
|
||||||
|
open: false,
|
||||||
|
}
|
||||||
|
: t
|
||||||
|
),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case "REMOVE_TOAST":
|
||||||
|
if (action.toastId === undefined) {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
toasts: [],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
toasts: state.toasts.filter((t) => t.id !== action.toastId),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const listeners: Array<(state: State) => void> = []
|
||||||
|
|
||||||
|
let memoryState: State = { toasts: [] }
|
||||||
|
|
||||||
|
function dispatch(action: Action) {
|
||||||
|
memoryState = reducer(memoryState, action)
|
||||||
|
listeners.forEach((listener) => {
|
||||||
|
listener(memoryState)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Toast extends Omit<ToasterToast, "id"> {}
|
||||||
|
|
||||||
|
function toast({ ...props }: Toast) {
|
||||||
|
const id = genId()
|
||||||
|
|
||||||
|
const update = (props: ToasterToast) =>
|
||||||
|
dispatch({
|
||||||
|
type: "UPDATE_TOAST",
|
||||||
|
toast: { ...props, id },
|
||||||
|
})
|
||||||
|
const dismiss = () => dispatch({ type: "DISMISS_TOAST", toastId: id })
|
||||||
|
|
||||||
|
dispatch({
|
||||||
|
type: "ADD_TOAST",
|
||||||
|
toast: {
|
||||||
|
...props,
|
||||||
|
id,
|
||||||
|
open: true,
|
||||||
|
onOpenChange: (open) => {
|
||||||
|
if (!open) dismiss()
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: id,
|
||||||
|
dismiss,
|
||||||
|
update,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function useToast() {
|
||||||
|
const [state, setState] = React.useState<State>(memoryState)
|
||||||
|
|
||||||
|
React.useEffect(() => {
|
||||||
|
listeners.push(setState)
|
||||||
|
return () => {
|
||||||
|
const index = listeners.indexOf(setState)
|
||||||
|
if (index > -1) {
|
||||||
|
listeners.splice(index, 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, [state])
|
||||||
|
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
toast,
|
||||||
|
dismiss: (toastId?: string) => dispatch({ type: "DISMISS_TOAST", toastId }),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export { useToast, toast }
|
||||||
@@ -1,295 +1,179 @@
|
|||||||
export const components = [
|
export const components = [
|
||||||
{
|
{
|
||||||
|
component: "accordion",
|
||||||
name: "Accordion",
|
name: "Accordion",
|
||||||
dependencies: ["@radix-ui/react-accordion"],
|
dependencies: ["@radix-ui/react-accordion"],
|
||||||
files: [
|
files: ["components/ui/accordion.tsx"],
|
||||||
{
|
|
||||||
name: "accordion.tsx",
|
|
||||||
dir: "components/ui",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
component: "alert-dialog",
|
||||||
name: "Alert Dialog",
|
name: "Alert Dialog",
|
||||||
dependencies: ["@radix-ui/react-alert-dialog"],
|
dependencies: ["@radix-ui/react-alert-dialog"],
|
||||||
files: [
|
files: ["components/ui/alert-dialog.tsx"],
|
||||||
{
|
|
||||||
name: "alert-dialog.tsx",
|
|
||||||
dir: "components/ui",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
component: "aspect-ratio",
|
||||||
name: "Aspect Ratio",
|
name: "Aspect Ratio",
|
||||||
dependencies: ["@radix-ui/react-aspect-ratio"],
|
dependencies: ["@radix-ui/react-aspect-ratio"],
|
||||||
files: [
|
files: ["components/ui/aspect-ratio.tsx"],
|
||||||
{
|
|
||||||
name: "aspect-ratio.tsx",
|
|
||||||
dir: "components/ui",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
component: "avatar",
|
||||||
name: "Avatar",
|
name: "Avatar",
|
||||||
dependencies: ["@radix-ui/react-avatar"],
|
dependencies: ["@radix-ui/react-avatar"],
|
||||||
files: [
|
files: ["components/ui/avatar.tsx"],
|
||||||
{
|
|
||||||
name: "avatar.tsx",
|
|
||||||
dir: "components/ui",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
component: "button",
|
||||||
name: "Button",
|
name: "Button",
|
||||||
files: [
|
files: ["components/ui/button.tsx"],
|
||||||
{
|
|
||||||
name: "button.tsx",
|
|
||||||
dir: "components/ui",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
component: "checkbox",
|
||||||
name: "Checkbox",
|
name: "Checkbox",
|
||||||
dependencies: ["@radix-ui/react-checkbox"],
|
dependencies: ["@radix-ui/react-checkbox"],
|
||||||
files: [
|
files: ["components/ui/checkbox.tsx"],
|
||||||
{
|
|
||||||
name: "checkbox.tsx",
|
|
||||||
dir: "components/ui",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
component: "collapsible",
|
||||||
name: "Collapsible",
|
name: "Collapsible",
|
||||||
dependencies: ["@radix-ui/react-collapsible"],
|
dependencies: ["@radix-ui/react-collapsible"],
|
||||||
files: [
|
files: ["components/ui/collapsible.tsx"],
|
||||||
{
|
|
||||||
name: "collapsible.tsx",
|
|
||||||
dir: "components/ui",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
component: "command",
|
||||||
name: "Command",
|
name: "Command",
|
||||||
dependencies: ["cmdk"],
|
dependencies: ["cmdk"],
|
||||||
files: [
|
files: ["components/ui/command.tsx"],
|
||||||
{
|
|
||||||
name: "command.tsx",
|
|
||||||
dir: "components/ui",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
component: "context-menu",
|
||||||
name: "Context Menu",
|
name: "Context Menu",
|
||||||
dependencies: ["@radix-ui/react-context-menu"],
|
dependencies: ["@radix-ui/react-context-menu"],
|
||||||
files: [
|
files: ["components/ui/context-menu.tsx"],
|
||||||
{
|
|
||||||
name: "context-menu.tsx",
|
|
||||||
dir: "components/ui",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
component: "dialog",
|
||||||
name: "Dialog",
|
name: "Dialog",
|
||||||
dependencies: ["@radix-ui/react-dialog"],
|
dependencies: ["@radix-ui/react-dialog"],
|
||||||
files: [
|
files: ["components/ui/dialog.tsx"],
|
||||||
{
|
|
||||||
name: "dialog.tsx",
|
|
||||||
dir: "components/ui",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
component: "dropdown-menu",
|
||||||
name: "Dropdown Menu",
|
name: "Dropdown Menu",
|
||||||
dependencies: ["@radix-ui/react-dropdown-menu"],
|
dependencies: ["@radix-ui/react-dropdown-menu"],
|
||||||
files: [
|
files: ["components/ui/dropdown-menu.tsx"],
|
||||||
{
|
|
||||||
name: "dropdown-menu.tsx",
|
|
||||||
dir: "components/ui",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
component: "hover-card",
|
||||||
name: "Hover Card",
|
name: "Hover Card",
|
||||||
dependencies: ["@radix-ui/react-hover-card"],
|
dependencies: ["@radix-ui/react-hover-card"],
|
||||||
files: [
|
files: ["components/ui/hover-card.tsx"],
|
||||||
{
|
|
||||||
name: "hover-card.tsx",
|
|
||||||
dir: "components/ui",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
{ name: "Input", files: [{ name: "input.tsx", dir: "components/ui" }] },
|
|
||||||
{
|
{
|
||||||
|
component: "input",
|
||||||
|
name: "Input",
|
||||||
|
files: ["components/ui/input.tsx"],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
component: "label",
|
||||||
name: "Label",
|
name: "Label",
|
||||||
dependencies: ["@radix-ui/react-label"],
|
dependencies: ["@radix-ui/react-label"],
|
||||||
files: [
|
files: ["components/ui/label.tsx"],
|
||||||
{
|
|
||||||
name: "label.tsx",
|
|
||||||
dir: "components/ui",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
component: "menubar",
|
||||||
name: "Menubar",
|
name: "Menubar",
|
||||||
dependencies: ["@radix-ui/react-menubar"],
|
dependencies: ["@radix-ui/react-menubar"],
|
||||||
files: [
|
files: ["components/ui/menubar.tsx"],
|
||||||
{
|
|
||||||
name: "menubar.tsx",
|
|
||||||
dir: "components/ui",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
component: "navigation-menu",
|
||||||
name: "Navigation Menu",
|
name: "Navigation Menu",
|
||||||
dependencies: ["@radix-ui/react-navigation-menu"],
|
dependencies: ["@radix-ui/react-navigation-menu"],
|
||||||
files: [
|
files: ["components/ui/navigation-menu.tsx"],
|
||||||
{
|
|
||||||
name: "navigation-menu.tsx",
|
|
||||||
dir: "components/ui",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
component: "popover",
|
||||||
name: "Popover",
|
name: "Popover",
|
||||||
dependencies: ["@radix-ui/react-popover"],
|
dependencies: ["@radix-ui/react-popover"],
|
||||||
files: [
|
files: ["components/ui/popover.tsx"],
|
||||||
{
|
|
||||||
name: "popover.tsx",
|
|
||||||
dir: "components/ui",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
component: "progress",
|
||||||
name: "Progress",
|
name: "Progress",
|
||||||
dependencies: ["@radix-ui/react-progress"],
|
dependencies: ["@radix-ui/react-progress"],
|
||||||
files: [
|
files: ["components/ui/progress.tsx"],
|
||||||
{
|
|
||||||
name: "progress.tsx",
|
|
||||||
dir: "components/ui",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
component: "radio-group",
|
||||||
name: "Radio Group",
|
name: "Radio Group",
|
||||||
dependencies: ["@radix-ui/react-radio-group"],
|
dependencies: ["@radix-ui/react-radio-group"],
|
||||||
files: [
|
files: ["components/ui/radio-group.tsx"],
|
||||||
{
|
|
||||||
name: "radio-group.tsx",
|
|
||||||
dir: "components/ui",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
component: "scroll-area",
|
||||||
name: "Scroll-area",
|
name: "Scroll-area",
|
||||||
dependencies: ["@radix-ui/react-scroll-area"],
|
dependencies: ["@radix-ui/react-scroll-area"],
|
||||||
files: [
|
files: ["components/ui/scroll-area.tsx"],
|
||||||
{
|
|
||||||
name: "scroll-area.tsx",
|
|
||||||
dir: "components/ui",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
component: "select",
|
||||||
name: "Select",
|
name: "Select",
|
||||||
dependencies: ["@radix-ui/react-select"],
|
dependencies: ["@radix-ui/react-select"],
|
||||||
files: [
|
files: ["components/ui/select.tsx"],
|
||||||
{
|
|
||||||
name: "select.tsx",
|
|
||||||
dir: "components/ui",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
component: "separator",
|
||||||
name: "Separator",
|
name: "Separator",
|
||||||
dependencies: ["@radix-ui/react-separator"],
|
dependencies: ["@radix-ui/react-separator"],
|
||||||
files: [
|
files: ["components/ui/separator.tsx"],
|
||||||
{
|
|
||||||
name: "separator.tsx",
|
|
||||||
dir: "components/ui",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
component: "sheet",
|
||||||
name: "Sheet",
|
name: "Sheet",
|
||||||
dependencies: ["@radix-ui/react-dialog"],
|
dependencies: ["@radix-ui/react-dialog"],
|
||||||
files: [
|
files: ["components/ui/sheet.tsx"],
|
||||||
{
|
|
||||||
name: "sheet.tsx",
|
|
||||||
dir: "components/ui",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
component: "slider",
|
||||||
name: "Slider",
|
name: "Slider",
|
||||||
dependencies: ["@radix-ui/react-slider"],
|
dependencies: ["@radix-ui/react-slider"],
|
||||||
files: [
|
files: ["components/ui/slider.tsx"],
|
||||||
{
|
|
||||||
name: "slider.tsx",
|
|
||||||
dir: "components/ui",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
component: "switch",
|
||||||
name: "Switch",
|
name: "Switch",
|
||||||
dependencies: ["@radix-ui/react-switch"],
|
dependencies: ["@radix-ui/react-switch"],
|
||||||
files: [
|
files: ["components/ui/switch.tsx"],
|
||||||
{
|
|
||||||
name: "switch.tsx",
|
|
||||||
dir: "components/ui",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
component: "tabs",
|
||||||
name: "Tabs",
|
name: "Tabs",
|
||||||
dependencies: ["@radix-ui/react-tabs"],
|
dependencies: ["@radix-ui/react-tabs"],
|
||||||
files: [
|
files: ["components/ui/tabs.tsx"],
|
||||||
{
|
|
||||||
name: "tabs.tsx",
|
|
||||||
dir: "components/ui",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
component: "textarea",
|
||||||
name: "Textarea",
|
name: "Textarea",
|
||||||
files: [
|
files: ["components/ui/textarea.tsx"],
|
||||||
{
|
|
||||||
name: "textarea.tsx",
|
|
||||||
dir: "components/ui",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
component: "toast",
|
||||||
name: "Toast",
|
name: "Toast",
|
||||||
dependencies: ["@radix-ui/react-toast"],
|
dependencies: ["@radix-ui/react-toast"],
|
||||||
files: [
|
files: ["components/ui/toast.tsx", "components/ui/use-toast.ts"],
|
||||||
{
|
|
||||||
name: "toast.tsx",
|
|
||||||
dir: "components/ui",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "use-toast.ts",
|
|
||||||
dir: "hooks",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
component: "toggle",
|
||||||
name: "Toggle",
|
name: "Toggle",
|
||||||
dependencies: ["@radix-ui/react-toggle"],
|
dependencies: ["@radix-ui/react-toggle"],
|
||||||
files: [
|
files: ["components/ui/toggle.tsx"],
|
||||||
{
|
|
||||||
name: "toggle.tsx",
|
|
||||||
dir: "components/ui",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
component: "tooltip",
|
||||||
name: "Tooltip",
|
name: "Tooltip",
|
||||||
dependencies: ["@radix-ui/react-tooltip"],
|
dependencies: ["@radix-ui/react-tooltip"],
|
||||||
files: [
|
files: ["components/ui/tooltip.tsx"],
|
||||||
{
|
|
||||||
name: "tooltip.tsx",
|
|
||||||
dir: "components/ui",
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ I did. But I'm not really a designer. Most of what you see here, I learned by lo
|
|||||||
|
|
||||||
### Is it ready for production?
|
### Is it ready for production?
|
||||||
|
|
||||||
Almost. I'm using it in production, but I'm still adding components and fixing bugs. See the roadmap on [GitHub](https://github.com/shadcn/ui).
|
Yes. You can use it in your production apps.
|
||||||
|
|
||||||
### How do I customize the colors?
|
### How do I customize the colors?
|
||||||
|
|
||||||
|
|||||||
@@ -33,7 +33,11 @@ This is the `<Collapsible />` primitive. You can place it in a file at `componen
|
|||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
import { Collapsible } from "@/components/ui/collapsible"
|
import {
|
||||||
|
Collapsible,
|
||||||
|
CollapsibleContent,
|
||||||
|
CollapsibleTrigger,
|
||||||
|
} from "@/components/ui/collapsible"
|
||||||
```
|
```
|
||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
title: Dialog
|
title: Dialog
|
||||||
description: A modal dialog that interrupts the user with important content and expects a response.
|
description: A window overlaid on either the primary window or another dialog window, rendering the content underneath inert.
|
||||||
featured: true
|
featured: true
|
||||||
component: true
|
component: true
|
||||||
radix:
|
radix:
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
title: Scroll-area
|
title: Scroll-area
|
||||||
description: Visually or semantically separates content.
|
description: Augments native scroll functionality for custom, cross-browser styling.
|
||||||
component: true
|
component: true
|
||||||
radix:
|
radix:
|
||||||
link: https://www.radix-ui.com/docs/primitives/components/scroll-area
|
link: https://www.radix-ui.com/docs/primitives/components/scroll-area
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ import {
|
|||||||
SheetHeader,
|
SheetHeader,
|
||||||
SheetTitle,
|
SheetTitle,
|
||||||
SheetTrigger,
|
SheetTrigger,
|
||||||
} from "@/components/ui/dialog"
|
} from "@/components/ui/sheet"
|
||||||
```
|
```
|
||||||
|
|
||||||
```tsx
|
```tsx
|
||||||
|
|||||||
1
apps/www/next-env.d.ts
vendored
1
apps/www/next-env.d.ts
vendored
@@ -1,5 +1,6 @@
|
|||||||
/// <reference types="next" />
|
/// <reference types="next" />
|
||||||
/// <reference types="next/image-types/global" />
|
/// <reference types="next/image-types/global" />
|
||||||
|
/// <reference types="next/navigation-types/compat/navigation" />
|
||||||
|
|
||||||
// NOTE: This file should not be edited
|
// NOTE: This file should not be edited
|
||||||
// see https://nextjs.org/docs/basic-features/typescript for more information.
|
// see https://nextjs.org/docs/basic-features/typescript for more information.
|
||||||
|
|||||||
@@ -14,7 +14,6 @@
|
|||||||
"format:check": "prettier --check \"**/*.{ts,tsx,mdx}\" --cache"
|
"format:check": "prettier --check \"**/*.{ts,tsx,mdx}\" --cache"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@next/font": "^13.1.6",
|
|
||||||
"@radix-ui/react-accessible-icon": "^1.0.1",
|
"@radix-ui/react-accessible-icon": "^1.0.1",
|
||||||
"@radix-ui/react-accordion": "^1.1.0",
|
"@radix-ui/react-accordion": "^1.1.0",
|
||||||
"@radix-ui/react-alert-dialog": "^1.0.2",
|
"@radix-ui/react-alert-dialog": "^1.0.2",
|
||||||
@@ -50,7 +49,7 @@
|
|||||||
"cmdk": "^0.1.21",
|
"cmdk": "^0.1.21",
|
||||||
"contentlayer": "^0.3.0",
|
"contentlayer": "^0.3.0",
|
||||||
"lucide-react": "0.105.0-alpha.4",
|
"lucide-react": "0.105.0-alpha.4",
|
||||||
"next": "^13.1.6",
|
"next": "13.2.4",
|
||||||
"next-contentlayer": "^0.3.0",
|
"next-contentlayer": "^0.3.0",
|
||||||
"next-themes": "^0.2.1",
|
"next-themes": "^0.2.1",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
@@ -77,7 +76,6 @@
|
|||||||
"shiki": "^0.12.1",
|
"shiki": "^0.12.1",
|
||||||
"tailwindcss": "^3.1.7",
|
"tailwindcss": "^3.1.7",
|
||||||
"typescript": "^4.5.3",
|
"typescript": "^4.5.3",
|
||||||
"unist": "^8.0.11",
|
|
||||||
"unist-builder": "^3.0.0",
|
"unist-builder": "^3.0.0",
|
||||||
"unist-util-visit": "^4.1.1"
|
"unist-util-visit": "^4.1.1"
|
||||||
},
|
},
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -6,13 +6,11 @@ import { components } from "../config/components"
|
|||||||
const payload = components
|
const payload = components
|
||||||
.map((component) => {
|
.map((component) => {
|
||||||
const files = component.files?.map((file) => {
|
const files = component.files?.map((file) => {
|
||||||
const content = fs.readFileSync(
|
const content = fs.readFileSync(path.join(process.cwd(), file), "utf8")
|
||||||
path.join(process.cwd(), file.dir, file.name),
|
|
||||||
"utf8"
|
|
||||||
)
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...file,
|
name: basename(file),
|
||||||
|
dir: dirname(file),
|
||||||
content,
|
content,
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -16,10 +16,11 @@
|
|||||||
],
|
],
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "turbo run build",
|
"build": "turbo run build",
|
||||||
"build:cli": "turbo --filter=@shadcn/ui build",
|
"build:cli": "turbo --filter=shadcn-ui build",
|
||||||
|
"build:components": "pnpm --filter=www build:components",
|
||||||
"dev": "turbo run dev --parallel",
|
"dev": "turbo run dev --parallel",
|
||||||
"dev:cli": "turbo --filter=@shadcn/ui dev",
|
"dev:cli": "turbo --filter=shadcn-ui dev",
|
||||||
"start:cli": "pnpm --filter=@shadcn/ui start:dev",
|
"start:cli": "pnpm --filter=shadcn-ui start:dev",
|
||||||
"lint": "turbo run lint",
|
"lint": "turbo run lint",
|
||||||
"preview": "turbo run preview",
|
"preview": "turbo run preview",
|
||||||
"typecheck": "turbo run typecheck",
|
"typecheck": "turbo run typecheck",
|
||||||
|
|||||||
@@ -1,5 +1,15 @@
|
|||||||
# @shadcn/ui
|
# @shadcn/ui
|
||||||
|
|
||||||
|
## 0.1.0
|
||||||
|
|
||||||
|
### Minor Changes
|
||||||
|
|
||||||
|
- [#178](https://github.com/shadcn/ui/pull/178) [`96f300e`](https://github.com/shadcn/ui/commit/96f300ea7471de9de9d433114d010d8fef2c8bae) Thanks [@shadcn](https://github.com/shadcn)! - add init command
|
||||||
|
|
||||||
|
### Patch Changes
|
||||||
|
|
||||||
|
- [#175](https://github.com/shadcn/ui/pull/175) [`b5d4368`](https://github.com/shadcn/ui/commit/b5d43688b975eb66b95b71af0396d07f94dde247) Thanks [@shadcn](https://github.com/shadcn)! - rename package to shadcn-ui
|
||||||
|
|
||||||
## 0.0.4
|
## 0.0.4
|
||||||
|
|
||||||
### Patch Changes
|
### Patch Changes
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
# @shadcn/ui
|
# shadcn-ui
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
```
|
```
|
||||||
npx @shadcn/ui
|
npx shadcn-ui add
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@shadcn/ui",
|
"name": "shadcn-ui",
|
||||||
"version": "0.0.4",
|
"version": "0.1.0",
|
||||||
"description": "Add @shadcn/ui components to your app.",
|
"description": "Add components to your apps.",
|
||||||
"publishConfig": {
|
"publishConfig": {
|
||||||
"access": "public"
|
"access": "public"
|
||||||
},
|
},
|
||||||
@@ -15,6 +15,9 @@
|
|||||||
"url": "https://github.com/shadcn/ui.git",
|
"url": "https://github.com/shadcn/ui.git",
|
||||||
"directory": "packages/cli"
|
"directory": "packages/cli"
|
||||||
},
|
},
|
||||||
|
"files": [
|
||||||
|
"dist"
|
||||||
|
],
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"components",
|
"components",
|
||||||
"ui",
|
"ui",
|
||||||
@@ -24,15 +27,13 @@
|
|||||||
],
|
],
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"exports": "./dist/index.js",
|
"exports": "./dist/index.js",
|
||||||
"bin": {
|
"bin": "./dist/index.js",
|
||||||
"@shadcn/ui": "./dist/index.js"
|
|
||||||
},
|
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "tsup --watch",
|
"dev": "tsup --watch",
|
||||||
"build": "tsup",
|
"build": "tsup",
|
||||||
"typecheck": "tsc --noEmit",
|
"typecheck": "tsc --noEmit",
|
||||||
"clean": "rimraf dist && rimraf components",
|
"clean": "rimraf dist && rimraf components",
|
||||||
"start:dev": "cross-env COMPONENTS_BASE_URL=http://localhost:3000 node dist/index.js",
|
"start:dev": "cross-env COMPONENTS_BASE_URL=http://localhost:3001 node dist/index.js",
|
||||||
"start": "node dist/index.js",
|
"start": "node dist/index.js",
|
||||||
"format:write": "prettier --write \"**/*.{ts,tsx,mdx}\" --cache",
|
"format:write": "prettier --write \"**/*.{ts,tsx,mdx}\" --cache",
|
||||||
"format:check": "prettier --check \"**/*.{ts,tsx,mdx}\" --cache",
|
"format:check": "prettier --check \"**/*.{ts,tsx,mdx}\" --cache",
|
||||||
@@ -57,6 +58,6 @@
|
|||||||
"rimraf": "^4.1.3",
|
"rimraf": "^4.1.3",
|
||||||
"tsup": "^6.6.3",
|
"tsup": "^6.6.3",
|
||||||
"type-fest": "^3.6.1",
|
"type-fest": "^3.6.1",
|
||||||
"typescript": "^4.9.5"
|
"typescript": "^4.5.5"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,27 +9,123 @@ import prompts from "prompts"
|
|||||||
import { Component, getAvailableComponents } from "./utils/get-components"
|
import { Component, getAvailableComponents } from "./utils/get-components"
|
||||||
import { getPackageInfo } from "./utils/get-package-info"
|
import { getPackageInfo } from "./utils/get-package-info"
|
||||||
import { getPackageManager } from "./utils/get-package-manager"
|
import { getPackageManager } from "./utils/get-package-manager"
|
||||||
|
import { getProjectInfo } from "./utils/get-project-info"
|
||||||
import { logger } from "./utils/logger"
|
import { logger } from "./utils/logger"
|
||||||
|
import { STYLES, TAILWIND_CONFIG, UTILS } from "./utils/templates"
|
||||||
|
|
||||||
process.on("SIGINT", () => process.exit(0))
|
process.on("SIGINT", () => process.exit(0))
|
||||||
process.on("SIGTERM", () => process.exit(0))
|
process.on("SIGTERM", () => process.exit(0))
|
||||||
|
|
||||||
|
const PROJECT_DEPENDENCIES = [
|
||||||
|
"tailwindcss-animate",
|
||||||
|
"class-variance-authority",
|
||||||
|
"clsx",
|
||||||
|
"tailwind-merge",
|
||||||
|
"lucide-react",
|
||||||
|
]
|
||||||
|
|
||||||
async function main() {
|
async function main() {
|
||||||
const packageInfo = await getPackageInfo()
|
const packageInfo = await getPackageInfo()
|
||||||
|
const projectInfo = await getProjectInfo()
|
||||||
|
const packageManager = getPackageManager()
|
||||||
|
|
||||||
const program = new Command()
|
const program = new Command()
|
||||||
.name("@shadcn/ui")
|
.name("shadcn-ui")
|
||||||
.description("Add @shadcn/ui components to your project")
|
.description("Add shadcn-ui components to your project")
|
||||||
.version(
|
.version(
|
||||||
packageInfo.version || "1.0.0",
|
packageInfo.version || "1.0.0",
|
||||||
"-v, --version",
|
"-v, --version",
|
||||||
"display the version number"
|
"display the version number"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
program
|
||||||
|
.command("init")
|
||||||
|
.description("Configure your Next.js project.")
|
||||||
|
.option("-y, --yes", "Skip confirmation prompt.")
|
||||||
|
.action(async (options) => {
|
||||||
|
logger.warn(
|
||||||
|
"Running the following command will overwrite existing files."
|
||||||
|
)
|
||||||
|
logger.warn(
|
||||||
|
"Make sure you have committed your changes before proceeding."
|
||||||
|
)
|
||||||
|
logger.warn("")
|
||||||
|
logger.warn(
|
||||||
|
"This command assumes a Next.js project with TypeScript and Tailwind CSS."
|
||||||
|
)
|
||||||
|
logger.warn(
|
||||||
|
"If you don't have these, follow the manual steps at https://ui.shadcn.com/docs/installation."
|
||||||
|
)
|
||||||
|
logger.warn("")
|
||||||
|
|
||||||
|
if (!options.yes) {
|
||||||
|
const { proceed } = await prompts({
|
||||||
|
type: "confirm",
|
||||||
|
name: "proceed",
|
||||||
|
message:
|
||||||
|
"Running this command will install dependencies and overwrite files. Proceed?",
|
||||||
|
initial: true,
|
||||||
|
})
|
||||||
|
|
||||||
|
if (!proceed) {
|
||||||
|
process.exit(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Install dependencies.
|
||||||
|
const dependenciesSpinner = ora(`Installing dependencies...`).start()
|
||||||
|
await execa(packageManager, [
|
||||||
|
packageManager === "npm" ? "install" : "add",
|
||||||
|
...PROJECT_DEPENDENCIES,
|
||||||
|
])
|
||||||
|
dependenciesSpinner.succeed()
|
||||||
|
|
||||||
|
// Ensure styles directory exists.
|
||||||
|
if (!projectInfo?.appDir) {
|
||||||
|
const stylesDir = projectInfo?.srcDir ? "./src/styles" : "./styles"
|
||||||
|
if (!existsSync(path.resolve(stylesDir))) {
|
||||||
|
await fs.mkdir(path.resolve(stylesDir), { recursive: true })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update styles.css
|
||||||
|
let stylesDestination = projectInfo?.srcDir
|
||||||
|
? "./src/styles/globals.css"
|
||||||
|
: "./styles/globals.css"
|
||||||
|
if (projectInfo?.appDir) {
|
||||||
|
stylesDestination = projectInfo?.srcDir
|
||||||
|
? "./src/app/globals.css"
|
||||||
|
: "./app/globals.css"
|
||||||
|
}
|
||||||
|
const stylesSpinner = ora(`Adding styles with CSS variables...`).start()
|
||||||
|
await fs.writeFile(stylesDestination, STYLES, "utf8")
|
||||||
|
stylesSpinner.succeed()
|
||||||
|
|
||||||
|
// Ensure lib directory exists.
|
||||||
|
const libDir = projectInfo?.srcDir ? "./src/lib" : "./lib"
|
||||||
|
if (!existsSync(path.resolve(libDir))) {
|
||||||
|
await fs.mkdir(path.resolve(libDir), { recursive: true })
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create lib/utils.ts
|
||||||
|
const utilsDestination = projectInfo?.srcDir
|
||||||
|
? "./src/lib/utils.ts"
|
||||||
|
: "./lib/utils.ts"
|
||||||
|
const utilsSpinner = ora(`Adding utils...`).start()
|
||||||
|
await fs.writeFile(utilsDestination, UTILS, "utf8")
|
||||||
|
utilsSpinner.succeed()
|
||||||
|
|
||||||
|
const tailwindDestination = "./tailwind.config.js"
|
||||||
|
const tailwindSpinner = ora(`Updating tailwind.config.js...`).start()
|
||||||
|
await fs.writeFile(tailwindDestination, TAILWIND_CONFIG, "utf8")
|
||||||
|
tailwindSpinner.succeed()
|
||||||
|
})
|
||||||
|
|
||||||
program
|
program
|
||||||
.command("add")
|
.command("add")
|
||||||
.description("add components to your project")
|
.description("add components to your project")
|
||||||
.action(async () => {
|
.argument("[components...]", "name of components")
|
||||||
|
.action(async (components: string[]) => {
|
||||||
logger.warn(
|
logger.warn(
|
||||||
"Running the following command will overwrite existing files."
|
"Running the following command will overwrite existing files."
|
||||||
)
|
)
|
||||||
@@ -38,8 +134,26 @@ async function main() {
|
|||||||
)
|
)
|
||||||
logger.warn("")
|
logger.warn("")
|
||||||
|
|
||||||
const { components, dir } = await promptForAddOptions()
|
const availableComponents = await getAvailableComponents()
|
||||||
if (!components?.length) {
|
|
||||||
|
if (!availableComponents?.length) {
|
||||||
|
logger.error(
|
||||||
|
"An error occurred while fetching components. Please try again."
|
||||||
|
)
|
||||||
|
process.exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
let selectedComponents = availableComponents.filter((component) =>
|
||||||
|
components.includes(component.component)
|
||||||
|
)
|
||||||
|
|
||||||
|
if (!selectedComponents?.length) {
|
||||||
|
selectedComponents = await promptForComponents(availableComponents)
|
||||||
|
}
|
||||||
|
|
||||||
|
const dir = await promptForDestinationDir()
|
||||||
|
|
||||||
|
if (!selectedComponents?.length) {
|
||||||
logger.warn("No components selected. Nothing to install.")
|
logger.warn("No components selected. Nothing to install.")
|
||||||
process.exit(0)
|
process.exit(0)
|
||||||
}
|
}
|
||||||
@@ -52,14 +166,19 @@ async function main() {
|
|||||||
spinner.succeed()
|
spinner.succeed()
|
||||||
}
|
}
|
||||||
|
|
||||||
const packageManager = getPackageManager()
|
logger.success(
|
||||||
|
`Installing ${selectedComponents.length} component(s) and dependencies...`
|
||||||
logger.success(`Installing components...`)
|
)
|
||||||
for (const component of components) {
|
for (const component of selectedComponents) {
|
||||||
const componentSpinner = ora(`${component.name}...`).start()
|
const componentSpinner = ora(`${component.name}...`).start()
|
||||||
|
|
||||||
// Write the files.
|
// Write the files.
|
||||||
for (const file of component.files) {
|
for (const file of component.files) {
|
||||||
|
// Replace alias with the project's alias.
|
||||||
|
if (projectInfo?.alias) {
|
||||||
|
file.content = file.content.replace(/@\//g, projectInfo.alias)
|
||||||
|
}
|
||||||
|
|
||||||
const filePath = path.resolve(dir, file.name)
|
const filePath = path.resolve(dir, file.name)
|
||||||
await fs.writeFile(filePath, file.content)
|
await fs.writeFile(filePath, file.content)
|
||||||
}
|
}
|
||||||
@@ -79,34 +198,24 @@ async function main() {
|
|||||||
program.parse()
|
program.parse()
|
||||||
}
|
}
|
||||||
|
|
||||||
type AddOptions = {
|
async function promptForComponents(components: Component[]) {
|
||||||
components: Component[]
|
const { components: selectedComponents } = await prompts({
|
||||||
dir: string
|
type: "autocompleteMultiselect",
|
||||||
|
name: "components",
|
||||||
|
message: "Which component(s) would you like to add?",
|
||||||
|
hint: "Space to select. A to select all. I to invert selection.",
|
||||||
|
instructions: false,
|
||||||
|
choices: components.map((component) => ({
|
||||||
|
title: component.name,
|
||||||
|
value: component,
|
||||||
|
})),
|
||||||
|
})
|
||||||
|
|
||||||
|
return selectedComponents
|
||||||
}
|
}
|
||||||
|
|
||||||
async function promptForAddOptions() {
|
async function promptForDestinationDir() {
|
||||||
const availableComponents = await getAvailableComponents()
|
const { dir } = await prompts([
|
||||||
|
|
||||||
if (!availableComponents?.length) {
|
|
||||||
logger.error(
|
|
||||||
"An error occurred while fetching components. Please try again."
|
|
||||||
)
|
|
||||||
process.exit(0)
|
|
||||||
}
|
|
||||||
|
|
||||||
const options = await prompts([
|
|
||||||
{
|
|
||||||
type: "multiselect",
|
|
||||||
name: "components",
|
|
||||||
message: "Which component(s) would you like to add?",
|
|
||||||
hint: "Space to select. A to select all. I to invert selection.",
|
|
||||||
instructions: false,
|
|
||||||
|
|
||||||
choices: availableComponents.map((component) => ({
|
|
||||||
title: component.name,
|
|
||||||
value: component,
|
|
||||||
})),
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
type: "text",
|
type: "text",
|
||||||
name: "dir",
|
name: "dir",
|
||||||
@@ -115,7 +224,7 @@ async function promptForAddOptions() {
|
|||||||
},
|
},
|
||||||
])
|
])
|
||||||
|
|
||||||
return options as AddOptions
|
return dir
|
||||||
}
|
}
|
||||||
|
|
||||||
main()
|
main()
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import * as z from "zod"
|
|||||||
const baseUrl = process.env.COMPONENTS_BASE_URL ?? "https://ui.shadcn.com"
|
const baseUrl = process.env.COMPONENTS_BASE_URL ?? "https://ui.shadcn.com"
|
||||||
|
|
||||||
const componentSchema = z.object({
|
const componentSchema = z.object({
|
||||||
|
component: z.string(),
|
||||||
name: z.string(),
|
name: z.string(),
|
||||||
dependencies: z.array(z.string()).optional(),
|
dependencies: z.array(z.string()).optional(),
|
||||||
files: z.array(
|
files: z.array(
|
||||||
|
|||||||
44
packages/cli/src/utils/get-project-info.ts
Normal file
44
packages/cli/src/utils/get-project-info.ts
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
import { existsSync } from "fs"
|
||||||
|
import path from "path"
|
||||||
|
import fs from "fs-extra"
|
||||||
|
|
||||||
|
export async function getProjectInfo() {
|
||||||
|
const info = {
|
||||||
|
tsconfig: null,
|
||||||
|
alias: null,
|
||||||
|
srcDir: false,
|
||||||
|
appDir: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const tsconfig = await getTsConfig()
|
||||||
|
const paths = tsconfig?.compilerOptions?.paths
|
||||||
|
const alias = paths ? Object.keys(paths)[0].replace("*", "") : null
|
||||||
|
|
||||||
|
return {
|
||||||
|
tsconfig,
|
||||||
|
alias,
|
||||||
|
srcDir: existsSync(path.resolve("./src")),
|
||||||
|
appDir:
|
||||||
|
existsSync(path.resolve("./app")) ||
|
||||||
|
existsSync(path.resolve("./src/app")),
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
return info
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getTsConfig() {
|
||||||
|
try {
|
||||||
|
const tsconfigPath = path.join("tsconfig.json")
|
||||||
|
const tsconfig = await fs.readJSON(tsconfigPath)
|
||||||
|
|
||||||
|
if (!tsconfig) {
|
||||||
|
throw new Error("tsconfig.json is missing")
|
||||||
|
}
|
||||||
|
|
||||||
|
return tsconfig
|
||||||
|
} catch (error) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
165
packages/cli/src/utils/templates.ts
Normal file
165
packages/cli/src/utils/templates.ts
Normal file
@@ -0,0 +1,165 @@
|
|||||||
|
export const STYLES = `@tailwind base;
|
||||||
|
@tailwind components;
|
||||||
|
@tailwind utilities;
|
||||||
|
|
||||||
|
@layer base {
|
||||||
|
:root {
|
||||||
|
--background: 0 0% 100%;
|
||||||
|
--foreground: 222.2 47.4% 11.2%;
|
||||||
|
|
||||||
|
--muted: 210 40% 96.1%;
|
||||||
|
--muted-foreground: 215.4 16.3% 46.9%;
|
||||||
|
|
||||||
|
--popover: 0 0% 100%;
|
||||||
|
--popover-foreground: 222.2 47.4% 11.2%;
|
||||||
|
|
||||||
|
--card: 0 0% 100%;
|
||||||
|
--card-foreground: 222.2 47.4% 11.2%;
|
||||||
|
|
||||||
|
--border: 214.3 31.8% 91.4%;
|
||||||
|
--input: 214.3 31.8% 91.4%;
|
||||||
|
|
||||||
|
--primary: 222.2 47.4% 11.2%;
|
||||||
|
--primary-foreground: 210 40% 98%;
|
||||||
|
|
||||||
|
--secondary: 210 40% 96.1%;
|
||||||
|
--secondary-foreground: 222.2 47.4% 11.2%;
|
||||||
|
|
||||||
|
--accent: 210 40% 96.1%;
|
||||||
|
--accent-foreground: 222.2 47.4% 11.2%;
|
||||||
|
|
||||||
|
--destructive: 0 100% 50%;
|
||||||
|
--destructive-foreground: 210 40% 98%;
|
||||||
|
|
||||||
|
--ring: 215 20.2% 65.1%;
|
||||||
|
|
||||||
|
--radius: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark {
|
||||||
|
--background: 224 71% 4%;
|
||||||
|
--foreground: 213 31% 91%;
|
||||||
|
|
||||||
|
--muted: 223 47% 11%;
|
||||||
|
--muted-foreground: 215.4 16.3% 56.9%;
|
||||||
|
|
||||||
|
--popover: 224 71% 4%;
|
||||||
|
--popover-foreground: 215 20.2% 65.1%;
|
||||||
|
|
||||||
|
--card: 0 0% 100%;
|
||||||
|
--card-foreground: 222.2 47.4% 11.2%;
|
||||||
|
|
||||||
|
--border: 216 34% 17%;
|
||||||
|
--input: 216 34% 17%;
|
||||||
|
|
||||||
|
--primary: 210 40% 98%;
|
||||||
|
--primary-foreground: 222.2 47.4% 1.2%;
|
||||||
|
|
||||||
|
--secondary: 222.2 47.4% 11.2%;
|
||||||
|
--secondary-foreground: 210 40% 98%;
|
||||||
|
|
||||||
|
--accent: 216 34% 17%;
|
||||||
|
--accent-foreground: 210 40% 98%;
|
||||||
|
|
||||||
|
--destructive: 0 63% 31%;
|
||||||
|
--destructive-foreground: 210 40% 98%;
|
||||||
|
|
||||||
|
--ring: 216 34% 17%;
|
||||||
|
|
||||||
|
--radius: 0.5rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@layer base {
|
||||||
|
* {
|
||||||
|
@apply border-border;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
@apply bg-background text-foreground;
|
||||||
|
font-feature-settings: "rlig" 1, "calt" 1;
|
||||||
|
}
|
||||||
|
}`
|
||||||
|
|
||||||
|
export const UTILS = `import { ClassValue, clsx } from "clsx"
|
||||||
|
import { twMerge } from "tailwind-merge"
|
||||||
|
|
||||||
|
export function cn(...inputs: ClassValue[]) {
|
||||||
|
return twMerge(clsx(inputs))
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
export const TAILWIND_CONFIG = `/** @type {import('tailwindcss').Config} */
|
||||||
|
module.exports = {
|
||||||
|
darkMode: ["class"],
|
||||||
|
content: [
|
||||||
|
'./pages/**/*.{ts,tsx}',
|
||||||
|
'./components/**/*.{ts,tsx}',
|
||||||
|
'./app/**/*.{ts,tsx}',
|
||||||
|
],
|
||||||
|
theme: {
|
||||||
|
container: {
|
||||||
|
center: true,
|
||||||
|
padding: "2rem",
|
||||||
|
screens: {
|
||||||
|
"2xl": "1400px",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
extend: {
|
||||||
|
colors: {
|
||||||
|
border: "hsl(var(--border))",
|
||||||
|
input: "hsl(var(--input))",
|
||||||
|
ring: "hsl(var(--ring))",
|
||||||
|
background: "hsl(var(--background))",
|
||||||
|
foreground: "hsl(var(--foreground))",
|
||||||
|
primary: {
|
||||||
|
DEFAULT: "hsl(var(--primary))",
|
||||||
|
foreground: "hsl(var(--primary-foreground))",
|
||||||
|
},
|
||||||
|
secondary: {
|
||||||
|
DEFAULT: "hsl(var(--secondary))",
|
||||||
|
foreground: "hsl(var(--secondary-foreground))",
|
||||||
|
},
|
||||||
|
destructive: {
|
||||||
|
DEFAULT: "hsl(var(--destructive))",
|
||||||
|
foreground: "hsl(var(--destructive-foreground))",
|
||||||
|
},
|
||||||
|
muted: {
|
||||||
|
DEFAULT: "hsl(var(--muted))",
|
||||||
|
foreground: "hsl(var(--muted-foreground))",
|
||||||
|
},
|
||||||
|
accent: {
|
||||||
|
DEFAULT: "hsl(var(--accent))",
|
||||||
|
foreground: "hsl(var(--accent-foreground))",
|
||||||
|
},
|
||||||
|
popover: {
|
||||||
|
DEFAULT: "hsl(var(--popover))",
|
||||||
|
foreground: "hsl(var(--popover-foreground))",
|
||||||
|
},
|
||||||
|
card: {
|
||||||
|
DEFAULT: "hsl(var(--card))",
|
||||||
|
foreground: "hsl(var(--card-foreground))",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
borderRadius: {
|
||||||
|
lg: "var(--radius)",
|
||||||
|
md: "calc(var(--radius) - 2px)",
|
||||||
|
sm: "calc(var(--radius) - 4px)",
|
||||||
|
},
|
||||||
|
keyframes: {
|
||||||
|
"accordion-down": {
|
||||||
|
from: { height: 0 },
|
||||||
|
to: { height: "var(--radix-accordion-content-height)" },
|
||||||
|
},
|
||||||
|
"accordion-up": {
|
||||||
|
from: { height: "var(--radix-accordion-content-height)" },
|
||||||
|
to: { height: 0 },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
animation: {
|
||||||
|
"accordion-down": "accordion-down 0.2s ease-out",
|
||||||
|
"accordion-up": "accordion-up 0.2s ease-out",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
plugins: [require("tailwindcss-animate")],
|
||||||
|
}`
|
||||||
4903
pnpm-lock.yaml
generated
4903
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -50,7 +50,7 @@ const AccordionContent = React.forwardRef<
|
|||||||
<AccordionPrimitive.Content
|
<AccordionPrimitive.Content
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn(
|
className={cn(
|
||||||
"overflow-hidden text-sm transition-all data-[state=open]:animate-accordion-down data-[state=closed]:animate-accordion-up",
|
"data-[state=open]:animate-accordion-down data-[state=closed]:animate-accordion-up overflow-hidden text-sm transition-all",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ const AlertDialogOverlay = React.forwardRef<
|
|||||||
>(({ className, children, ...props }, ref) => (
|
>(({ className, children, ...props }, ref) => (
|
||||||
<AlertDialogPrimitive.Overlay
|
<AlertDialogPrimitive.Overlay
|
||||||
className={cn(
|
className={cn(
|
||||||
"fixed inset-0 z-50 bg-black/50 backdrop-blur-sm transition-opacity animate-in fade-in",
|
"animate-in fade-in fixed inset-0 z-50 bg-black/50 backdrop-blur-sm transition-opacity",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
@@ -46,7 +46,7 @@ const AlertDialogContent = React.forwardRef<
|
|||||||
<AlertDialogPrimitive.Content
|
<AlertDialogPrimitive.Content
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn(
|
className={cn(
|
||||||
"fixed z-50 grid w-full max-w-lg scale-100 gap-4 bg-white p-6 opacity-100 animate-in fade-in-90 slide-in-from-bottom-10 sm:rounded-lg sm:zoom-in-90 sm:slide-in-from-bottom-0 md:w-full",
|
"animate-in fade-in-90 slide-in-from-bottom-10 sm:zoom-in-90 sm:slide-in-from-bottom-0 fixed z-50 grid w-full max-w-lg scale-100 gap-4 bg-white p-6 opacity-100 sm:rounded-lg md:w-full",
|
||||||
"dark:bg-slate-900",
|
"dark:bg-slate-900",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import { VariantProps, cva } from "class-variance-authority"
|
|||||||
import { cn } from "@/lib/utils"
|
import { cn } from "@/lib/utils"
|
||||||
|
|
||||||
const buttonVariants = cva(
|
const buttonVariants = cva(
|
||||||
"active:scale-95 inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-slate-400 focus:ring-offset-2 dark:hover:bg-slate-800 dark:hover:text-slate-100 disabled:opacity-50 dark:focus:ring-slate-400 disabled:pointer-events-none dark:focus:ring-offset-slate-900 data-[state=open]:bg-slate-100 dark:data-[state=open]:bg-slate-800",
|
"inline-flex items-center justify-center rounded-md text-sm font-medium transition-colors focus:outline-none focus:ring-2 focus:ring-slate-400 focus:ring-offset-2 dark:hover:bg-slate-800 dark:hover:text-slate-100 disabled:opacity-50 dark:focus:ring-slate-400 disabled:pointer-events-none dark:focus:ring-offset-slate-900 data-[state=open]:bg-slate-100 dark:data-[state=open]:bg-slate-800",
|
||||||
{
|
{
|
||||||
variants: {
|
variants: {
|
||||||
variant: {
|
variant: {
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
|
|
||||||
import * as React from "react"
|
import * as React from "react"
|
||||||
import { DialogProps } from "@radix-ui/react-dialog"
|
import { DialogProps } from "@radix-ui/react-dialog"
|
||||||
import { Command as CommandPrimitive, useCommandState } from "cmdk"
|
import { Command as CommandPrimitive } from "cmdk"
|
||||||
import { ChevronsUpDown, Search } from "lucide-react"
|
import { Search } from "lucide-react"
|
||||||
|
|
||||||
import { cn } from "@/lib/utils"
|
import { cn } from "@/lib/utils"
|
||||||
import { Dialog, DialogContent } from "@/components/ui/dialog"
|
import { Dialog, DialogContent } from "@/components/ui/dialog"
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ const ContextMenuSubContent = React.forwardRef<
|
|||||||
<ContextMenuPrimitive.SubContent
|
<ContextMenuPrimitive.SubContent
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn(
|
className={cn(
|
||||||
"z-50 min-w-[8rem] overflow-hidden rounded-md border border-slate-100 bg-white p-1 shadow-md animate-in slide-in-from-left-1 dark:border-slate-700 dark:bg-slate-800",
|
"animate-in slide-in-from-left-1 z-50 min-w-[8rem] overflow-hidden rounded-md border border-slate-100 bg-white p-1 shadow-md dark:border-slate-700 dark:bg-slate-800",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
@@ -62,7 +62,7 @@ const ContextMenuContent = React.forwardRef<
|
|||||||
<ContextMenuPrimitive.Content
|
<ContextMenuPrimitive.Content
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn(
|
className={cn(
|
||||||
"z-50 min-w-[8rem] overflow-hidden rounded-md border border-slate-100 bg-white p-1 text-slate-700 shadow-md animate-in fade-in-80 dark:border-slate-800 dark:bg-slate-800 dark:text-slate-400",
|
"animate-in fade-in-80 z-50 min-w-[8rem] overflow-hidden rounded-md border border-slate-100 bg-white p-1 text-slate-700 shadow-md dark:border-slate-800 dark:bg-slate-800 dark:text-slate-400",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ const DialogOverlay = React.forwardRef<
|
|||||||
>(({ className, children, ...props }, ref) => (
|
>(({ className, children, ...props }, ref) => (
|
||||||
<DialogPrimitive.Overlay
|
<DialogPrimitive.Overlay
|
||||||
className={cn(
|
className={cn(
|
||||||
"fixed inset-0 z-50 bg-black/50 backdrop-blur-sm transition-all duration-100 data-[state=closed]:animate-out data-[state=open]:fade-in data-[state=closed]:fade-out",
|
"data-[state=closed]:animate-out data-[state=open]:fade-in data-[state=closed]:fade-out fixed inset-0 z-50 bg-black/50 backdrop-blur-sm transition-all duration-100",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
@@ -47,7 +47,7 @@ const DialogContent = React.forwardRef<
|
|||||||
<DialogPrimitive.Content
|
<DialogPrimitive.Content
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn(
|
className={cn(
|
||||||
"fixed z-50 grid w-full gap-4 rounded-b-lg bg-white p-6 animate-in data-[state=open]:fade-in-90 data-[state=open]:slide-in-from-bottom-10 sm:max-w-lg sm:rounded-lg sm:zoom-in-90 data-[state=open]:sm:slide-in-from-bottom-0",
|
"animate-in data-[state=open]:fade-in-90 data-[state=open]:slide-in-from-bottom-10 sm:zoom-in-90 data-[state=open]:sm:slide-in-from-bottom-0 fixed z-50 grid w-full gap-4 rounded-b-lg bg-white p-6 sm:max-w-lg sm:rounded-lg",
|
||||||
"dark:bg-slate-900",
|
"dark:bg-slate-900",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ const DropdownMenuSubContent = React.forwardRef<
|
|||||||
<DropdownMenuPrimitive.SubContent
|
<DropdownMenuPrimitive.SubContent
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn(
|
className={cn(
|
||||||
"z-50 min-w-[8rem] overflow-hidden rounded-md border border-slate-100 bg-white p-1 text-slate-700 shadow-md animate-in slide-in-from-left-1 dark:border-slate-800 dark:bg-slate-800 dark:text-slate-400",
|
"animate-in slide-in-from-left-1 z-50 min-w-[8rem] overflow-hidden rounded-md border border-slate-100 bg-white p-1 text-slate-700 shadow-md dark:border-slate-800 dark:bg-slate-800 dark:text-slate-400",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
@@ -65,7 +65,7 @@ const DropdownMenuContent = React.forwardRef<
|
|||||||
ref={ref}
|
ref={ref}
|
||||||
sideOffset={sideOffset}
|
sideOffset={sideOffset}
|
||||||
className={cn(
|
className={cn(
|
||||||
"z-50 min-w-[8rem] overflow-hidden rounded-md border border-slate-100 bg-white p-1 text-slate-700 shadow-md animate-in data-[side=right]:slide-in-from-left-2 data-[side=left]:slide-in-from-right-2 data-[side=bottom]:slide-in-from-top-2 data-[side=top]:slide-in-from-bottom-2 dark:border-slate-800 dark:bg-slate-800 dark:text-slate-400",
|
"animate-in data-[side=right]:slide-in-from-left-2 data-[side=left]:slide-in-from-right-2 data-[side=bottom]:slide-in-from-top-2 data-[side=top]:slide-in-from-bottom-2 z-50 min-w-[8rem] overflow-hidden rounded-md border border-slate-100 bg-white p-1 text-slate-700 shadow-md dark:border-slate-800 dark:bg-slate-800 dark:text-slate-400",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ const HoverCardContent = React.forwardRef<
|
|||||||
align={align}
|
align={align}
|
||||||
sideOffset={sideOffset}
|
sideOffset={sideOffset}
|
||||||
className={cn(
|
className={cn(
|
||||||
"z-50 w-64 rounded-md border border-slate-100 bg-white p-4 shadow-md outline-none animate-in zoom-in-90 dark:border-slate-800 dark:bg-slate-800",
|
"animate-in zoom-in-90 z-50 w-64 rounded-md border border-slate-100 bg-white p-4 shadow-md outline-none dark:border-slate-800 dark:bg-slate-800",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ const MenubarSubContent = React.forwardRef<
|
|||||||
<MenubarPrimitive.SubContent
|
<MenubarPrimitive.SubContent
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn(
|
className={cn(
|
||||||
"z-50 min-w-[8rem] overflow-hidden rounded-md border border-slate-100 bg-white p-1 shadow-md animate-in slide-in-from-left-1 dark:border-slate-700 dark:bg-slate-800",
|
"animate-in slide-in-from-left-1 z-50 min-w-[8rem] overflow-hidden rounded-md border border-slate-100 bg-white p-1 shadow-md dark:border-slate-700 dark:bg-slate-800",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
@@ -97,7 +97,7 @@ const MenubarContent = React.forwardRef<
|
|||||||
alignOffset={alignOffset}
|
alignOffset={alignOffset}
|
||||||
sideOffset={sideOffset}
|
sideOffset={sideOffset}
|
||||||
className={cn(
|
className={cn(
|
||||||
"z-50 min-w-[12rem] overflow-hidden rounded-md border border-slate-100 bg-white p-1 text-slate-700 shadow-md animate-in slide-in-from-top-1 dark:border-slate-800 dark:bg-slate-800 dark:text-slate-400",
|
"animate-in slide-in-from-top-1 z-50 min-w-[12rem] overflow-hidden rounded-md border border-slate-100 bg-white p-1 text-slate-700 shadow-md dark:border-slate-800 dark:bg-slate-800 dark:text-slate-400",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ const NavigationMenuContent = React.forwardRef<
|
|||||||
<NavigationMenuPrimitive.Content
|
<NavigationMenuPrimitive.Content
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn(
|
className={cn(
|
||||||
"top-0 left-0 w-full data-[motion^=from-]:animate-in data-[motion^=to-]:animate-out data-[motion^=from-]:fade-in data-[motion^=to-]:fade-out data-[motion=to-start]:slide-out-to-left-52 data-[motion=to-end]:slide-out-to-right-52 data-[motion=from-start]:slide-in-from-left-52 data-[motion=from-end]:slide-in-from-right-52 md:absolute md:w-auto ",
|
"data-[motion^=from-]:animate-in data-[motion^=to-]:animate-out data-[motion^=from-]:fade-in data-[motion^=to-]:fade-out data-[motion=to-start]:slide-out-to-left-52 data-[motion=to-end]:slide-out-to-right-52 data-[motion=from-start]:slide-in-from-left-52 data-[motion=from-end]:slide-in-from-right-52 top-0 left-0 w-full md:absolute md:w-auto ",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
@@ -86,7 +86,7 @@ const NavigationMenuViewport = React.forwardRef<
|
|||||||
<div className={cn("absolute left-0 top-full flex justify-center")}>
|
<div className={cn("absolute left-0 top-full flex justify-center")}>
|
||||||
<NavigationMenuPrimitive.Viewport
|
<NavigationMenuPrimitive.Viewport
|
||||||
className={cn(
|
className={cn(
|
||||||
"origin-top-center relative mt-1.5 h-[var(--radix-navigation-menu-viewport-height)] w-full overflow-hidden rounded-md border border-slate-200 bg-white shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=open]:zoom-in-90 data-[state=closed]:zoom-out-95 dark:border-slate-700 dark:bg-slate-800 md:w-[var(--radix-navigation-menu-viewport-width)]",
|
"origin-top-center data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=open]:zoom-in-90 data-[state=closed]:zoom-out-95 relative mt-1.5 h-[var(--radix-navigation-menu-viewport-height)] w-full overflow-hidden rounded-md border border-slate-200 bg-white shadow-lg dark:border-slate-700 dark:bg-slate-800 md:w-[var(--radix-navigation-menu-viewport-width)]",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
ref={ref}
|
ref={ref}
|
||||||
@@ -104,7 +104,7 @@ const NavigationMenuIndicator = React.forwardRef<
|
|||||||
<NavigationMenuPrimitive.Indicator
|
<NavigationMenuPrimitive.Indicator
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn(
|
className={cn(
|
||||||
"top-full z-[1] flex h-1.5 items-end justify-center overflow-hidden data-[state=visible]:animate-in data-[state=hidden]:animate-out data-[state=visible]:fade-in data-[state=hidden]:fade-out",
|
"data-[state=visible]:animate-in data-[state=hidden]:animate-out data-[state=visible]:fade-in data-[state=hidden]:fade-out top-full z-[1] flex h-1.5 items-end justify-center overflow-hidden",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ const PopoverContent = React.forwardRef<
|
|||||||
align={align}
|
align={align}
|
||||||
sideOffset={sideOffset}
|
sideOffset={sideOffset}
|
||||||
className={cn(
|
className={cn(
|
||||||
"z-50 w-72 rounded-md border border-slate-100 bg-white p-4 shadow-md outline-none animate-in data-[side=bottom]:slide-in-from-top-2 data-[side=top]:slide-in-from-bottom-2 data-[side=right]:slide-in-from-left-2 data-[side=left]:slide-in-from-right-2 dark:border-slate-800 dark:bg-slate-800",
|
"animate-in data-[side=bottom]:slide-in-from-top-2 data-[side=top]:slide-in-from-bottom-2 data-[side=right]:slide-in-from-left-2 data-[side=left]:slide-in-from-right-2 z-50 w-72 rounded-md border border-slate-100 bg-white p-4 shadow-md outline-none dark:border-slate-800 dark:bg-slate-800",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ const SelectContent = React.forwardRef<
|
|||||||
<SelectPrimitive.Content
|
<SelectPrimitive.Content
|
||||||
ref={ref}
|
ref={ref}
|
||||||
className={cn(
|
className={cn(
|
||||||
"relative z-50 min-w-[8rem] overflow-hidden rounded-md border border-slate-100 bg-white text-slate-700 shadow-md animate-in fade-in-80 dark:border-slate-800 dark:bg-slate-800 dark:text-slate-400",
|
"animate-in fade-in-80 relative z-50 min-w-[8rem] overflow-hidden rounded-md border border-slate-100 bg-white text-slate-700 shadow-md dark:border-slate-800 dark:bg-slate-800 dark:text-slate-400",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ const SheetOverlay = React.forwardRef<
|
|||||||
>(({ className, children, ...props }, ref) => (
|
>(({ className, children, ...props }, ref) => (
|
||||||
<SheetPrimitive.Overlay
|
<SheetPrimitive.Overlay
|
||||||
className={cn(
|
className={cn(
|
||||||
"fixed inset-0 z-50 bg-black/50 backdrop-blur-sm transition-all duration-100 data-[state=closed]:animate-out data-[state=open]:fade-in data-[state=closed]:fade-out",
|
"data-[state=closed]:animate-out data-[state=open]:fade-in data-[state=closed]:fade-out fixed inset-0 z-50 bg-black/50 backdrop-blur-sm transition-all duration-100",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ const TooltipContent = React.forwardRef<
|
|||||||
ref={ref}
|
ref={ref}
|
||||||
sideOffset={sideOffset}
|
sideOffset={sideOffset}
|
||||||
className={cn(
|
className={cn(
|
||||||
"z-50 overflow-hidden rounded-md border border-slate-100 bg-white px-3 py-1.5 text-sm text-slate-700 shadow-md animate-in fade-in-50 data-[side=bottom]:slide-in-from-top-1 data-[side=top]:slide-in-from-bottom-1 data-[side=left]:slide-in-from-right-1 data-[side=right]:slide-in-from-left-1 dark:border-slate-800 dark:bg-slate-800 dark:text-slate-400",
|
"animate-in fade-in-50 data-[side=bottom]:slide-in-from-top-1 data-[side=top]:slide-in-from-bottom-1 data-[side=left]:slide-in-from-right-1 data-[side=right]:slide-in-from-left-1 z-50 overflow-hidden rounded-md border border-slate-100 bg-white px-3 py-1.5 text-sm text-slate-700 shadow-md dark:border-slate-800 dark:bg-slate-800 dark:text-slate-400",
|
||||||
className
|
className
|
||||||
)}
|
)}
|
||||||
{...props}
|
{...props}
|
||||||
|
|||||||
@@ -14,10 +14,10 @@ export default function App({ Component, pageProps }: AppProps) {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<style jsx global>{`
|
<style jsx global>{`
|
||||||
:root {
|
:root {
|
||||||
--font-sans: ${fontSans.style.fontFamily};
|
--font-sans: ${fontSans.style.fontFamily};
|
||||||
}
|
}
|
||||||
}`}</style>
|
`}</style>
|
||||||
<ThemeProvider attribute="class" defaultTheme="system" enableSystem>
|
<ThemeProvider attribute="class" defaultTheme="system" enableSystem>
|
||||||
<Component {...pageProps} />
|
<Component {...pageProps} />
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
|
|||||||
Reference in New Issue
Block a user