├── .nvmrc
├── apps
└── www
│ ├── pages
│ ├── .gitkeep
│ └── api
│ │ ├── .gitkeep
│ │ └── components.ts
│ ├── __registry__
│ ├── .gitkeep
│ ├── .autogenerated
│ └── README.md
│ ├── .gitignore
│ ├── postcss.config.cjs
│ ├── public
│ ├── og.png
│ ├── favicon.ico
│ ├── og-unused.jpg
│ ├── avatars
│ │ ├── 01.png
│ │ ├── 02.png
│ │ ├── 03.png
│ │ ├── 04.png
│ │ └── 05.png
│ ├── favicon-16x16.png
│ ├── favicon-32x32.png
│ ├── images
│ │ ├── style.jpg
│ │ └── style-with-theming.jpg
│ ├── registry
│ │ ├── styles
│ │ │ ├── index.json
│ │ │ └── default
│ │ │ │ ├── aspect-ratio.json
│ │ │ │ ├── skeleton.json
│ │ │ │ ├── collapsible.json
│ │ │ │ ├── textarea.json
│ │ │ │ ├── label.json
│ │ │ │ ├── progress.json
│ │ │ │ ├── spinner.json
│ │ │ │ ├── status-dot.json
│ │ │ │ ├── kbd.json
│ │ │ │ ├── sonner.json
│ │ │ │ ├── loading-dots.json
│ │ │ │ ├── checkbox.json
│ │ │ │ ├── show-more.json
│ │ │ │ ├── hover-card.json
│ │ │ │ └── popover.json
│ │ └── themes
│ │ │ └── neutral.json
│ ├── apple-touch-icon.png
│ ├── examples
│ │ ├── cards-dark.png
│ │ ├── forms-dark.png
│ │ ├── mail-dark.png
│ │ ├── mail-light.png
│ │ ├── music-dark.png
│ │ ├── tasks-dark.png
│ │ ├── cards-light.png
│ │ ├── forms-light.png
│ │ ├── music-light.png
│ │ ├── tasks-light.png
│ │ ├── dashboard-dark.png
│ │ ├── dashboard-light.png
│ │ ├── playground-dark.png
│ │ ├── playground-light.png
│ │ ├── authentication-dark.png
│ │ └── authentication-light.png
│ ├── android-chrome-192x192.png
│ ├── android-chrome-512x512.png
│ ├── site.webmanifest
│ └── schema.json
│ ├── assets
│ └── fonts
│ │ ├── Inter-Bold.ttf
│ │ └── Inter-Regular.ttf
│ ├── registry
│ ├── default
│ │ ├── example
│ │ │ ├── grid-cell-span.tsx
│ │ │ ├── kbd-small.tsx
│ │ │ ├── spinner-demo.tsx
│ │ │ ├── kbd-combination.tsx
│ │ │ ├── spinner-size.tsx
│ │ │ ├── gauge-arc-priority.tsx
│ │ │ ├── theme-switcher-demo.tsx
│ │ │ ├── snippet-demo.tsx
│ │ │ ├── text-responsive.tsx
│ │ │ ├── textarea-demo.tsx
│ │ │ ├── snippet-multi-line.tsx
│ │ │ ├── snippet-inverted.tsx
│ │ │ ├── snippet-no-prompt.tsx
│ │ │ ├── textarea-disabled.tsx
│ │ │ ├── text-color.tsx
│ │ │ ├── text-polymorphic.tsx
│ │ │ ├── kbd-demo.tsx
│ │ │ ├── text-monospace.tsx
│ │ │ ├── text-truncate.tsx
│ │ │ ├── button-with-icon.tsx
│ │ │ ├── toggle-disabled.tsx
│ │ │ ├── snippet-callback.tsx
│ │ │ ├── text-modifiers.tsx
│ │ │ ├── show-more-demo.tsx
│ │ │ ├── tooltip-demo.tsx
│ │ │ ├── tooltip-other.tsx
│ │ │ ├── loading-dots-with-text.tsx
│ │ │ ├── tooltip-box-align.tsx
│ │ │ ├── tooltip-components.tsx
│ │ │ ├── tooltip-custom-type.tsx
│ │ │ ├── tooltip-no-delay.tsx
│ │ │ ├── switch-full-width.tsx
│ │ │ ├── tooltip-custom-content.tsx
│ │ │ ├── avatar-demo.tsx
│ │ │ ├── text-align.tsx
│ │ │ ├── loading-dots-demo.tsx
│ │ │ ├── toggle-size.tsx
│ │ │ ├── switch-demo.tsx
│ │ │ ├── stack-demo.tsx
│ │ │ ├── textarea-with-button.tsx
│ │ │ ├── input-with-label.tsx
│ │ │ ├── switch-icon.tsx
│ │ │ ├── gauge-color-scale.tsx
│ │ │ ├── input-with-button.tsx
│ │ │ ├── switch-disabled.tsx
│ │ │ ├── textarea-with-label.tsx
│ │ │ ├── label-demo.tsx
│ │ │ ├── gauge-demo.tsx
│ │ │ ├── note-demo.tsx
│ │ │ ├── skeleton-demo.tsx
│ │ │ ├── skeleton-card.tsx
│ │ │ ├── calendar-demo.tsx
│ │ │ ├── gauge-custom-secondary-color.tsx
│ │ │ ├── status-dot-demo.tsx
│ │ │ ├── progress-demo.tsx
│ │ │ ├── snippet-variants.tsx
│ │ │ ├── status-dot-label.tsx
│ │ │ ├── grid-debug.tsx
│ │ │ ├── grid-demo.tsx
│ │ │ ├── input-with-text.tsx
│ │ │ ├── alert-demo.tsx
│ │ │ ├── stack-responsive.tsx
│ │ │ ├── button-demo.tsx
│ │ │ ├── checkbox-disabled.tsx
│ │ │ ├── toast-simple.tsx
│ │ │ ├── badge-sizes.tsx
│ │ │ ├── checkbox-demo.tsx
│ │ │ ├── aspect-ratio-demo.tsx
│ │ │ ├── menu-link-items.tsx
│ │ │ ├── alert-destructive.tsx
│ │ │ ├── textarea-with-text.tsx
│ │ │ ├── text-clamp.tsx
│ │ │ ├── input-disabled.tsx
│ │ │ ├── sonner-demo.tsx
│ │ │ ├── toast-with-title.tsx
│ │ │ ├── button-loading.tsx
│ │ │ ├── button-types.tsx
│ │ │ ├── button-disabled.tsx
│ │ │ ├── note-disabled.tsx
│ │ │ ├── gauge-label.tsx
│ │ │ ├── stack-padding.tsx
│ │ │ ├── input-demo.tsx
│ │ │ ├── text-demo.tsx
│ │ │ ├── note-action.tsx
│ │ │ ├── button-rounded.tsx
│ │ │ ├── toast-with-action.tsx
│ │ │ ├── toggle-demo.tsx
│ │ │ ├── scroll-area-demo.tsx
│ │ │ ├── menu-disabled-items.tsx
│ │ │ ├── checkbox-with-text.tsx
│ │ │ ├── toast-demo.tsx
│ │ │ ├── toast-destructive.tsx
│ │ │ ├── button-prefix.tsx
│ │ │ ├── note-cyan.tsx
│ │ │ ├── note-error.tsx
│ │ │ ├── menu-demo.tsx
│ │ │ ├── menu-prefix.tsx
│ │ │ ├── note-success.tsx
│ │ │ ├── note-violet.tsx
│ │ │ ├── note-warning.tsx
│ │ │ ├── menu-custom-trigger.tsx
│ │ │ ├── tabs-demo.tsx
│ │ │ ├── radio-group-demo.tsx
│ │ │ ├── tabs-disable-specific-tabs.tsx
│ │ │ ├── resizable-vertical.tsx
│ │ │ ├── resizable-handle.tsx
│ │ │ ├── collapse-demo.tsx
│ │ │ ├── note-secondary.tsx
│ │ │ ├── tabs-controlled.tsx
│ │ │ ├── select-demo.tsx
│ │ │ ├── switch-sizes.tsx
│ │ │ ├── menu-radio-group.tsx
│ │ │ ├── pagination-demo.tsx
│ │ │ ├── text-variants.tsx
│ │ │ ├── mode-toggle.tsx
│ │ │ ├── input-prefix-suffix.tsx
│ │ │ ├── date-picker-demo.tsx
│ │ │ ├── resizable-demo.tsx
│ │ │ ├── resizable-demo-with-handle.tsx
│ │ │ ├── menu-position.tsx
│ │ │ ├── button-shapes.tsx
│ │ │ ├── hover-card-demo.tsx
│ │ │ ├── collapsible-demo.tsx
│ │ │ └── menu-checkboxes.tsx
│ │ └── ui
│ │ │ ├── aspect-ratio.tsx
│ │ │ ├── skeleton.tsx
│ │ │ ├── collapsible.tsx
│ │ │ ├── label.tsx
│ │ │ ├── textarea.tsx
│ │ │ ├── progress.tsx
│ │ │ ├── toaster.tsx
│ │ │ ├── sonner.tsx
│ │ │ ├── status-dot.tsx
│ │ │ ├── spinner.tsx
│ │ │ ├── loading-dots.tsx
│ │ │ ├── kbd.tsx
│ │ │ ├── checkbox.tsx
│ │ │ ├── show-more.tsx
│ │ │ ├── hover-card.tsx
│ │ │ ├── popover.tsx
│ │ │ ├── tooltip.tsx
│ │ │ └── avatar.tsx
│ ├── .eslintrc.json
│ ├── styles.ts
│ └── schema.ts
│ ├── .prettierignore
│ ├── lib
│ ├── validations
│ │ ├── log.ts
│ │ └── og.ts
│ ├── fonts.ts
│ ├── utils.ts
│ └── events.ts
│ ├── components
│ ├── analytics.tsx
│ ├── announcement.tsx
│ ├── providers.tsx
│ ├── promo-video.tsx
│ ├── style-wrapper.tsx
│ ├── component-card.tsx
│ ├── callout.tsx
│ ├── framework-docs.tsx
│ ├── component-source.tsx
│ ├── tailwind-indicator.tsx
│ ├── theme-switcher.tsx
│ ├── theme-wrapper.tsx
│ ├── padding-box.tsx
│ ├── site-footer.tsx
│ ├── drawer.tsx
│ └── theme-component.tsx
│ ├── .env.example
│ ├── hooks
│ ├── use-mounted.ts
│ ├── use-lock-body.ts
│ ├── use-config.ts
│ ├── use-media-query.tsx
│ └── use-mutation-observer.ts
│ ├── next-env.d.ts
│ ├── tailwind.config.cjs
│ ├── content
│ └── docs
│ │ ├── changelog.mdx
│ │ ├── index.mdx
│ │ ├── about.mdx
│ │ └── components
│ │ ├── grid.mdx
│ │ ├── theme-switcher.mdx
│ │ ├── status-dot.mdx
│ │ ├── kbd.mdx
│ │ ├── skeleton.mdx
│ │ ├── label.mdx
│ │ ├── progress.mdx
│ │ ├── switch.mdx
│ │ ├── show-more.mdx
│ │ ├── avatar.mdx
│ │ ├── card.mdx
│ │ ├── popover.mdx
│ │ ├── snippet.mdx
│ │ ├── aspect-ratio.mdx
│ │ ├── gauge.mdx
│ │ ├── textarea.mdx
│ │ ├── toggle.mdx
│ │ ├── hover-card.mdx
│ │ └── checkbox.mdx
│ ├── tsconfig.scripts.json
│ ├── config
│ └── site.ts
│ ├── types
│ ├── nav.ts
│ └── unist.ts
│ ├── app
│ ├── docs
│ │ └── layout.tsx
│ └── examples
│ │ └── authentication
│ │ └── components
│ │ └── user-auth-form.tsx
│ ├── tsconfig.json
│ └── next.config.mjs
├── packages
└── cli
│ ├── .prettierignore
│ ├── .gitignore
│ ├── tsup.config.ts
│ ├── src
│ ├── utils
│ │ ├── get-package-info.ts
│ │ ├── handle-error.ts
│ │ ├── resolve-import.ts
│ │ ├── logger.ts
│ │ ├── get-package-manager.ts
│ │ ├── transformers
│ │ │ ├── transform-rsc.ts
│ │ │ └── transform-import.ts
│ │ └── registry
│ │ │ └── schema.ts
│ └── index.ts
│ ├── tsconfig.json
│ └── README.md
├── .npmrc
├── .commitlintrc.json
├── .prettierignore
├── pnpm-workspace.yaml
├── postcss.config.cjs
├── .editorconfig
├── vitest.config.ts
├── .vscode
└── settings.json
├── README.md
├── .kodiak.toml
├── .gitignore
├── tsconfig.json
├── .eslintrc.json
├── prettier.config.cjs
├── LICENSE.md
├── scripts
└── sync-templates.sh
└── turbo.json
/.nvmrc:
--------------------------------------------------------------------------------
1 | v18.17.0
2 |
--------------------------------------------------------------------------------
/apps/www/pages/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/apps/www/pages/api/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/apps/www/__registry__/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/packages/cli/.prettierignore:
--------------------------------------------------------------------------------
1 | test
--------------------------------------------------------------------------------
/.npmrc:
--------------------------------------------------------------------------------
1 | auto-install-peers=true
2 |
--------------------------------------------------------------------------------
/apps/www/.gitignore:
--------------------------------------------------------------------------------
1 | .vscode
2 | .env
--------------------------------------------------------------------------------
/packages/cli/.gitignore:
--------------------------------------------------------------------------------
1 | components
2 | dist
3 | .turbo
--------------------------------------------------------------------------------
/.commitlintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": ["@commitlint/config-conventional"]
3 | }
4 |
--------------------------------------------------------------------------------
/apps/www/postcss.config.cjs:
--------------------------------------------------------------------------------
1 | module.exports = require("../../postcss.config.cjs")
2 |
--------------------------------------------------------------------------------
/apps/www/public/og.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imMatheus/vercel-ui/HEAD/apps/www/public/og.png
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | dist
2 | node_modules
3 | .next
4 | build
5 | .contentlayer
6 | apps/www/pages/api/registry.json
--------------------------------------------------------------------------------
/apps/www/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imMatheus/vercel-ui/HEAD/apps/www/public/favicon.ico
--------------------------------------------------------------------------------
/apps/www/public/og-unused.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imMatheus/vercel-ui/HEAD/apps/www/public/og-unused.jpg
--------------------------------------------------------------------------------
/apps/www/__registry__/.autogenerated:
--------------------------------------------------------------------------------
1 | // The content of this directory is autogenerated by the registry server.
2 |
--------------------------------------------------------------------------------
/apps/www/public/avatars/01.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imMatheus/vercel-ui/HEAD/apps/www/public/avatars/01.png
--------------------------------------------------------------------------------
/apps/www/public/avatars/02.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imMatheus/vercel-ui/HEAD/apps/www/public/avatars/02.png
--------------------------------------------------------------------------------
/apps/www/public/avatars/03.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imMatheus/vercel-ui/HEAD/apps/www/public/avatars/03.png
--------------------------------------------------------------------------------
/apps/www/public/avatars/04.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imMatheus/vercel-ui/HEAD/apps/www/public/avatars/04.png
--------------------------------------------------------------------------------
/apps/www/public/avatars/05.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imMatheus/vercel-ui/HEAD/apps/www/public/avatars/05.png
--------------------------------------------------------------------------------
/pnpm-workspace.yaml:
--------------------------------------------------------------------------------
1 | packages:
2 | - "apps/*"
3 | - "packages/*"
4 | - "templates/*"
5 | - "!**/test/**"
6 |
--------------------------------------------------------------------------------
/apps/www/public/favicon-16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imMatheus/vercel-ui/HEAD/apps/www/public/favicon-16x16.png
--------------------------------------------------------------------------------
/apps/www/public/favicon-32x32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imMatheus/vercel-ui/HEAD/apps/www/public/favicon-32x32.png
--------------------------------------------------------------------------------
/apps/www/public/images/style.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imMatheus/vercel-ui/HEAD/apps/www/public/images/style.jpg
--------------------------------------------------------------------------------
/apps/www/public/registry/styles/index.json:
--------------------------------------------------------------------------------
1 | [
2 | {
3 | "name": "default",
4 | "label": "Default"
5 | }
6 | ]
--------------------------------------------------------------------------------
/apps/www/assets/fonts/Inter-Bold.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imMatheus/vercel-ui/HEAD/apps/www/assets/fonts/Inter-Bold.ttf
--------------------------------------------------------------------------------
/apps/www/public/apple-touch-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imMatheus/vercel-ui/HEAD/apps/www/public/apple-touch-icon.png
--------------------------------------------------------------------------------
/postcss.config.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | tailwindcss: {},
4 | autoprefixer: {},
5 | },
6 | }
7 |
--------------------------------------------------------------------------------
/apps/www/assets/fonts/Inter-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imMatheus/vercel-ui/HEAD/apps/www/assets/fonts/Inter-Regular.ttf
--------------------------------------------------------------------------------
/apps/www/public/examples/cards-dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imMatheus/vercel-ui/HEAD/apps/www/public/examples/cards-dark.png
--------------------------------------------------------------------------------
/apps/www/public/examples/forms-dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imMatheus/vercel-ui/HEAD/apps/www/public/examples/forms-dark.png
--------------------------------------------------------------------------------
/apps/www/public/examples/mail-dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imMatheus/vercel-ui/HEAD/apps/www/public/examples/mail-dark.png
--------------------------------------------------------------------------------
/apps/www/public/examples/mail-light.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imMatheus/vercel-ui/HEAD/apps/www/public/examples/mail-light.png
--------------------------------------------------------------------------------
/apps/www/public/examples/music-dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imMatheus/vercel-ui/HEAD/apps/www/public/examples/music-dark.png
--------------------------------------------------------------------------------
/apps/www/public/examples/tasks-dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imMatheus/vercel-ui/HEAD/apps/www/public/examples/tasks-dark.png
--------------------------------------------------------------------------------
/apps/www/registry/default/example/grid-cell-span.tsx:
--------------------------------------------------------------------------------
1 | export default function GridCellSpan() {
2 | return
grid
3 | }
4 |
--------------------------------------------------------------------------------
/apps/www/public/examples/cards-light.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imMatheus/vercel-ui/HEAD/apps/www/public/examples/cards-light.png
--------------------------------------------------------------------------------
/apps/www/public/examples/forms-light.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imMatheus/vercel-ui/HEAD/apps/www/public/examples/forms-light.png
--------------------------------------------------------------------------------
/apps/www/public/examples/music-light.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imMatheus/vercel-ui/HEAD/apps/www/public/examples/music-light.png
--------------------------------------------------------------------------------
/apps/www/public/examples/tasks-light.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imMatheus/vercel-ui/HEAD/apps/www/public/examples/tasks-light.png
--------------------------------------------------------------------------------
/apps/www/public/android-chrome-192x192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imMatheus/vercel-ui/HEAD/apps/www/public/android-chrome-192x192.png
--------------------------------------------------------------------------------
/apps/www/public/android-chrome-512x512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imMatheus/vercel-ui/HEAD/apps/www/public/android-chrome-512x512.png
--------------------------------------------------------------------------------
/apps/www/public/examples/dashboard-dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imMatheus/vercel-ui/HEAD/apps/www/public/examples/dashboard-dark.png
--------------------------------------------------------------------------------
/apps/www/public/examples/dashboard-light.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imMatheus/vercel-ui/HEAD/apps/www/public/examples/dashboard-light.png
--------------------------------------------------------------------------------
/apps/www/public/examples/playground-dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imMatheus/vercel-ui/HEAD/apps/www/public/examples/playground-dark.png
--------------------------------------------------------------------------------
/apps/www/public/examples/playground-light.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imMatheus/vercel-ui/HEAD/apps/www/public/examples/playground-light.png
--------------------------------------------------------------------------------
/apps/www/public/images/style-with-theming.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imMatheus/vercel-ui/HEAD/apps/www/public/images/style-with-theming.jpg
--------------------------------------------------------------------------------
/apps/www/public/examples/authentication-dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imMatheus/vercel-ui/HEAD/apps/www/public/examples/authentication-dark.png
--------------------------------------------------------------------------------
/apps/www/public/examples/authentication-light.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/imMatheus/vercel-ui/HEAD/apps/www/public/examples/authentication-light.png
--------------------------------------------------------------------------------
/apps/www/.prettierignore:
--------------------------------------------------------------------------------
1 | dist
2 | node_modules
3 | .next
4 | build
5 | .contentlayer
6 | __registry__/index.tsx
7 | app/examples/mail/components/mail.tsx
8 |
--------------------------------------------------------------------------------
/apps/www/__registry__/README.md:
--------------------------------------------------------------------------------
1 | > Files inside this directory is autogenerated by `./scripts/build-registry.ts`. **Do not edit them manually.** - shadcn
2 |
--------------------------------------------------------------------------------
/apps/www/registry/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json.schemastore.org/eslintrc",
3 | "rules": {
4 | "react/no-unescaped-entities": "off"
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/apps/www/lib/validations/log.ts:
--------------------------------------------------------------------------------
1 | import { z } from "zod"
2 |
3 | export const logSchema = z.object({
4 | event: z.enum(["copy_primitive"]),
5 | data: z.record(z.string()),
6 | })
7 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/kbd-small.tsx:
--------------------------------------------------------------------------------
1 | import { Kbd } from "@/registry/default/ui/kbd"
2 |
3 | export default function KbdSmallDemo() {
4 | return /
5 | }
6 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/spinner-demo.tsx:
--------------------------------------------------------------------------------
1 | import { Spinner } from "@/registry/default/ui/spinner"
2 |
3 | export default function SpinnerDemo() {
4 | return
5 | }
6 |
--------------------------------------------------------------------------------
/apps/www/registry/styles.ts:
--------------------------------------------------------------------------------
1 | export const styles = [
2 | {
3 | name: "default",
4 | label: "Default",
5 | },
6 | ] as const
7 |
8 | export type Style = (typeof styles)[number]
9 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/kbd-combination.tsx:
--------------------------------------------------------------------------------
1 | import { Kbd } from "@/registry/default/ui/kbd"
2 |
3 | export default function KbdCombination() {
4 | return
5 | }
6 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/spinner-size.tsx:
--------------------------------------------------------------------------------
1 | import { Spinner } from "@/registry/default/ui/spinner"
2 |
3 | export default function SpinnerSize() {
4 | return
5 | }
6 |
--------------------------------------------------------------------------------
/apps/www/components/analytics.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import { Analytics as VercelAnalytics } from "@vercel/analytics/react"
4 |
5 | export function Analytics() {
6 | return
7 | }
8 |
--------------------------------------------------------------------------------
/apps/www/lib/validations/og.ts:
--------------------------------------------------------------------------------
1 | import { z } from "zod"
2 |
3 | export const ogImageSchema = z.object({
4 | heading: z.string(),
5 | type: z.string(),
6 | mode: z.enum(["light", "dark"]).default("dark"),
7 | })
8 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/gauge-arc-priority.tsx:
--------------------------------------------------------------------------------
1 | import { Gauge } from "@/registry/default/ui/gauge"
2 |
3 | export default function GaugeArcPriority() {
4 | return
5 | }
6 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/theme-switcher-demo.tsx:
--------------------------------------------------------------------------------
1 | import { ThemeSwitcher } from "@/registry/default/ui/theme-switcher"
2 |
3 | export default function ThemeSwitcherDemo() {
4 | return
5 | }
6 |
--------------------------------------------------------------------------------
/apps/www/registry/default/ui/aspect-ratio.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as AspectRatioPrimitive from "@radix-ui/react-aspect-ratio"
4 |
5 | const AspectRatio = AspectRatioPrimitive.Root
6 |
7 | export { AspectRatio }
8 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # editorconfig.org
2 | root = true
3 |
4 | [*]
5 | charset = utf-8
6 | end_of_line = lf
7 | indent_size = 2
8 | indent_style = space
9 | insert_final_newline = true
10 | trim_trailing_whitespace = true
11 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/snippet-demo.tsx:
--------------------------------------------------------------------------------
1 | import { Snippet } from "@/registry/default/ui/snippet"
2 |
3 | export default function SnippetDemo() {
4 | return
5 | }
6 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/text-responsive.tsx:
--------------------------------------------------------------------------------
1 | import { Text } from "../ui/text"
2 |
3 | export default function TextResponsive() {
4 | return The Evil Rabbit jumps.
5 | }
6 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/textarea-demo.tsx:
--------------------------------------------------------------------------------
1 | import { Textarea } from "@/registry/default/ui/textarea"
2 |
3 | export default function TextareaDemo() {
4 | return
5 | }
6 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/snippet-multi-line.tsx:
--------------------------------------------------------------------------------
1 | import { Snippet } from "@/registry/default/ui/snippet"
2 |
3 | export default function SnippetMultiLine() {
4 | return
5 | }
6 |
--------------------------------------------------------------------------------
/apps/www/.env.example:
--------------------------------------------------------------------------------
1 | # -----------------------------------------------------------------------------
2 | # App
3 | # -----------------------------------------------------------------------------
4 | NEXT_PUBLIC_APP_URL=http://localhost:3001
5 |
--------------------------------------------------------------------------------
/vitest.config.ts:
--------------------------------------------------------------------------------
1 | import tsconfigPaths from "vite-tsconfig-paths"
2 | import { defineConfig } from "vitest/config"
3 |
4 | export default defineConfig({
5 | test: {
6 | // ...
7 | },
8 | plugins: [tsconfigPaths()],
9 | })
10 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/snippet-inverted.tsx:
--------------------------------------------------------------------------------
1 | import { Snippet } from "@/registry/default/ui/snippet"
2 |
3 | export default function SnippetInverted() {
4 | return
5 | }
6 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/snippet-no-prompt.tsx:
--------------------------------------------------------------------------------
1 | import { Snippet } from "@/registry/default/ui/snippet"
2 |
3 | export default function SnippetNoPrompt() {
4 | return
5 | }
6 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/textarea-disabled.tsx:
--------------------------------------------------------------------------------
1 | import { Textarea } from "@/registry/default/ui/textarea"
2 |
3 | export default function TextareaDisabled() {
4 | return
5 | }
6 |
--------------------------------------------------------------------------------
/apps/www/components/announcement.tsx:
--------------------------------------------------------------------------------
1 | import { Badge } from "@/registry/default/ui/badge"
2 |
3 | export function Announcement() {
4 | return (
5 |
6 | Just Released In Alpha 🎉
7 |
8 | )
9 | }
10 |
--------------------------------------------------------------------------------
/apps/www/hooks/use-mounted.ts:
--------------------------------------------------------------------------------
1 | import * as React from "react"
2 |
3 | export function useMounted() {
4 | const [mounted, setMounted] = React.useState(false)
5 |
6 | React.useEffect(() => {
7 | setMounted(true)
8 | }, [])
9 |
10 | return mounted
11 | }
12 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/text-color.tsx:
--------------------------------------------------------------------------------
1 | import { Text } from "@/registry/default/ui/text"
2 |
3 | export default function TextColor() {
4 | return (
5 |
6 | The Evil Rabbit jumps.
7 |
8 | )
9 | }
10 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/text-polymorphic.tsx:
--------------------------------------------------------------------------------
1 | import { Text } from "@/registry/default/ui/text"
2 |
3 | export default function TextPolymorphic() {
4 | return (
5 |
6 | {``} semantically, {`
`} visually.
7 |
8 | )
9 | }
10 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/kbd-demo.tsx:
--------------------------------------------------------------------------------
1 | import { Kbd } from "@/registry/default/ui/kbd"
2 |
3 | export default function KbdDemo() {
4 | return (
5 | <>
6 |
7 |
8 |
9 |
10 | >
11 | )
12 | }
13 |
--------------------------------------------------------------------------------
/packages/cli/tsup.config.ts:
--------------------------------------------------------------------------------
1 | import { defineConfig } from "tsup"
2 |
3 | export default defineConfig({
4 | clean: true,
5 | dts: true,
6 | entry: ["src/index.ts"],
7 | format: ["esm"],
8 | sourcemap: true,
9 | minify: true,
10 | target: "esnext",
11 | outDir: "dist",
12 | })
13 |
--------------------------------------------------------------------------------
/apps/www/next-env.d.ts:
--------------------------------------------------------------------------------
1 | ///
2 | ///
3 | ///
4 |
5 | // NOTE: This file should not be edited
6 | // see https://nextjs.org/docs/basic-features/typescript for more information.
7 |
--------------------------------------------------------------------------------
/apps/www/tailwind.config.cjs:
--------------------------------------------------------------------------------
1 | const baseConfig = require("../../tailwind.config.cjs")
2 |
3 | /** @type {import('tailwindcss').Config} */
4 | module.exports = {
5 | ...baseConfig,
6 | content: [
7 | ...baseConfig.content,
8 | "content/**/*.mdx",
9 | "registry/**/*.{ts,tsx}",
10 | ],
11 | }
12 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "eslint.workingDirectories": [
3 | { "pattern": "apps/*/" },
4 | { "pattern": "packages/*/" }
5 | ],
6 | "tailwindCSS.experimental.classRegex": [
7 | ["cva\\(([^)]*)\\)", "[\"'`]([^\"'`]*).*?[\"'`]"],
8 | ["cn\\(([^)]*)\\)", "[\"'`]([^\"'`]*).*?[\"'`]"]
9 | ]
10 | }
11 |
--------------------------------------------------------------------------------
/packages/cli/src/utils/get-package-info.ts:
--------------------------------------------------------------------------------
1 | import path from "path"
2 | import fs from "fs-extra"
3 | import { type PackageJson } from "type-fest"
4 |
5 | export function getPackageInfo() {
6 | const packageJsonPath = path.join("package.json")
7 |
8 | return fs.readJSONSync(packageJsonPath) as PackageJson
9 | }
10 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/text-monospace.tsx:
--------------------------------------------------------------------------------
1 | import { Text } from "@/registry/default/ui/text"
2 |
3 | export default function TextMonospace() {
4 | return (
5 |
6 | This is a sans-serif font.
7 |
8 | This is a monospace font.
9 |
10 | )
11 | }
12 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/text-truncate.tsx:
--------------------------------------------------------------------------------
1 | import { Text } from "@/registry/default/ui/text"
2 |
3 | export default function TextTruncate() {
4 | return (
5 |
6 |
7 | The Evil Rabbit jumps.
8 |
9 |
10 | )
11 | }
12 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/button-with-icon.tsx:
--------------------------------------------------------------------------------
1 | import { Mail } from "lucide-react"
2 |
3 | import { Button } from "@/registry/default/ui/button"
4 |
5 | export default function ButtonWithIcon() {
6 | return (
7 |
8 | Login with Email
9 |
10 | )
11 | }
12 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/toggle-disabled.tsx:
--------------------------------------------------------------------------------
1 | import { Toggle } from "@/registry/default/ui/toggle"
2 |
3 | export default function ToggleDemo() {
4 | return (
5 |
6 |
7 |
8 |
9 | )
10 | }
11 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/snippet-callback.tsx:
--------------------------------------------------------------------------------
1 | import { Snippet } from "@/registry/default/ui/snippet"
2 |
3 | export default function SnippetCallback() {
4 | return (
5 | alert("You copied the text!")}
7 | text="npm init next-app"
8 | width="300px"
9 | />
10 | )
11 | }
12 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/text-modifiers.tsx:
--------------------------------------------------------------------------------
1 | import { Text } from "@/registry/default/ui/text"
2 |
3 | export default function TextModifiers() {
4 | return (
5 |
6 | The Evil Rabbit jumps
7 | over the quick brown fox Lawful Meerkat .
8 |
9 | )
10 | }
11 |
--------------------------------------------------------------------------------
/apps/www/content/docs/changelog.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Changelog
3 | description: Latest updates and announcements.
4 | toc: false
5 | ---
6 |
7 |
8 |
9 | Project gets its first sortof working use case, with many components still needing fixing, but its good enought for trying :)
10 |
11 |
12 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/show-more-demo.tsx:
--------------------------------------------------------------------------------
1 | import { useState } from "react"
2 |
3 | import { ShowMore } from "@/registry/default/ui/show-more"
4 |
5 | export default function ShowMoreDemo() {
6 | const [expanded, setExpanded] = useState(false)
7 |
8 | return setExpanded(!expanded)} />
9 | }
10 |
--------------------------------------------------------------------------------
/packages/cli/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json.schemastore.org/tsconfig",
3 | "extends": "../../tsconfig.json",
4 | "compilerOptions": {
5 | "isolatedModules": false,
6 | "baseUrl": ".",
7 | "paths": {
8 | "@/*": ["./*"]
9 | }
10 | },
11 | "include": ["src/**/*.ts"],
12 | "exclude": ["node_modules"]
13 | }
14 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/tooltip-demo.tsx:
--------------------------------------------------------------------------------
1 | import { Button } from "@/registry/default/ui/button"
2 | import { Tooltip } from "@/registry/default/ui/tooltip"
3 |
4 | export default function TooltipDemo() {
5 | return (
6 |
7 | Hover
8 |
9 | )
10 | }
11 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/tooltip-other.tsx:
--------------------------------------------------------------------------------
1 | import { Button } from "@/registry/default/ui/button"
2 | import { Tooltip } from "@/registry/default/ui/tooltip"
3 |
4 | export default function TooltipBoxAlignDemo() {
5 | return (
6 |
7 | Box
8 |
9 | )
10 | }
11 |
--------------------------------------------------------------------------------
/apps/www/registry/default/ui/skeleton.tsx:
--------------------------------------------------------------------------------
1 | import { cn } from "@/lib/utils"
2 |
3 | function Skeleton({
4 | className,
5 | ...props
6 | }: React.HTMLAttributes) {
7 | return (
8 |
12 | )
13 | }
14 |
15 | export { Skeleton }
16 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/loading-dots-with-text.tsx:
--------------------------------------------------------------------------------
1 | import { LoadingDots } from "@/registry/default/ui/loading-dots"
2 | import { Text } from "@/registry/default/ui/text"
3 |
4 | export default function LoadingDotsWithText() {
5 | return (
6 |
7 | Loading
8 |
9 | )
10 | }
11 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/tooltip-box-align.tsx:
--------------------------------------------------------------------------------
1 | import { Button } from "@/registry/default/ui/button"
2 | import { Tooltip } from "@/registry/default/ui/tooltip"
3 |
4 | export default function TooltipBoxAlignDemo() {
5 | return (
6 |
7 | Box
8 |
9 | )
10 | }
11 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/tooltip-components.tsx:
--------------------------------------------------------------------------------
1 | import { Button } from "@/registry/default/ui/button"
2 | import { Tooltip } from "@/registry/default/ui/tooltip"
3 |
4 | export default function TooltipBoxAlignDemo() {
5 | return (
6 |
7 | Box
8 |
9 | )
10 | }
11 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/tooltip-custom-type.tsx:
--------------------------------------------------------------------------------
1 | import { Button } from "@/registry/default/ui/button"
2 | import { Tooltip } from "@/registry/default/ui/tooltip"
3 |
4 | export default function TooltipBoxAlignDemo() {
5 | return (
6 |
7 | Box
8 |
9 | )
10 | }
11 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/tooltip-no-delay.tsx:
--------------------------------------------------------------------------------
1 | import { Button } from "@/registry/default/ui/button"
2 | import { Tooltip } from "@/registry/default/ui/tooltip"
3 |
4 | export default function TooltipNoDelayDemo() {
5 | return (
6 |
7 | No delay
8 |
9 | )
10 | }
11 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/switch-full-width.tsx:
--------------------------------------------------------------------------------
1 | import { Switch, SwitchControl } from "@/registry/default/ui/switch"
2 |
3 | export default function SwitchFullWidth() {
4 | return (
5 |
6 |
7 |
8 |
9 | )
10 | }
11 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/tooltip-custom-content.tsx:
--------------------------------------------------------------------------------
1 | import { Button } from "@/registry/default/ui/button"
2 | import { Tooltip } from "@/registry/default/ui/tooltip"
3 |
4 | export default function TooltipBoxAlignDemo() {
5 | return (
6 |
7 | Box
8 |
9 | )
10 | }
11 |
--------------------------------------------------------------------------------
/apps/www/components/providers.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import { ThemeProvider as NextThemesProvider } from "next-themes"
5 | import { ThemeProviderProps } from "next-themes/dist/types"
6 |
7 | export function ThemeProvider({ children, ...props }: ThemeProviderProps) {
8 | return {children}
9 | }
10 |
--------------------------------------------------------------------------------
/apps/www/pages/api/components.ts:
--------------------------------------------------------------------------------
1 | import { NextApiRequest, NextApiResponse } from "next"
2 |
3 | import components from "./components.json"
4 |
5 | export default async function handler(
6 | req: NextApiRequest,
7 | res: NextApiResponse
8 | ) {
9 | if (req.method !== "GET") {
10 | return res.status(405).end()
11 | }
12 |
13 | return res.status(200).json(components)
14 | }
15 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/avatar-demo.tsx:
--------------------------------------------------------------------------------
1 | import {
2 | Avatar,
3 | AvatarFallback,
4 | AvatarImage,
5 | } from "@/registry/default/ui/avatar"
6 |
7 | export default function AvatarDemo() {
8 | return (
9 |
10 |
11 | CN
12 |
13 | )
14 | }
15 |
--------------------------------------------------------------------------------
/apps/www/tsconfig.scripts.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json.schemastore.org/tsconfig",
3 | "extends": "./tsconfig.json",
4 | "compilerOptions": {
5 | "target": "es6",
6 | "module": "commonjs",
7 | "esModuleInterop": true,
8 | "isolatedModules": false
9 | },
10 | "include": [".contentlayer/generated", "scripts/**/*.ts"],
11 | "exclude": ["node_modules"]
12 | }
13 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/text-align.tsx:
--------------------------------------------------------------------------------
1 | import { Text } from "@/registry/default/ui/text"
2 |
3 | export default function TextAlign() {
4 | return (
5 |
6 | The Evil Rabbit jumps.
7 |
8 | The Evil Rabbit jumps.
9 |
10 | The Evil Rabbit jumps.
11 |
12 | )
13 | }
14 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/loading-dots-demo.tsx:
--------------------------------------------------------------------------------
1 | import { LoadingDots } from "@/registry/default/ui/loading-dots"
2 | import { Stack } from "@/registry/default/ui/stack"
3 |
4 | export default function LoadingDotsDemo() {
5 | return (
6 |
7 |
8 |
9 |
10 | )
11 | }
12 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/toggle-size.tsx:
--------------------------------------------------------------------------------
1 | import { Toggle } from "@/registry/default/ui/toggle"
2 |
3 | export default function ToggleDemo() {
4 | return (
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | )
14 | }
15 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/switch-demo.tsx:
--------------------------------------------------------------------------------
1 | import { Switch, SwitchControl } from "@/registry/default/ui/switch"
2 |
3 | export default function SwitchDemo() {
4 | return (
5 |
6 |
7 |
8 |
9 |
10 |
11 | )
12 | }
13 |
--------------------------------------------------------------------------------
/apps/www/registry/default/ui/collapsible.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as CollapsiblePrimitive from "@radix-ui/react-collapsible"
4 |
5 | const Collapsible = CollapsiblePrimitive.Root
6 |
7 | const CollapsibleTrigger = CollapsiblePrimitive.CollapsibleTrigger
8 |
9 | const CollapsibleContent = CollapsiblePrimitive.CollapsibleContent
10 |
11 | export { Collapsible, CollapsibleTrigger, CollapsibleContent }
12 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/stack-demo.tsx:
--------------------------------------------------------------------------------
1 | import { Stack } from "@/registry/default/ui/stack"
2 |
3 | export default function Component(): JSX.Element {
4 | return (
5 |
6 |
7 |
8 |
9 |
10 | )
11 | }
12 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/textarea-with-button.tsx:
--------------------------------------------------------------------------------
1 | import { Button } from "@/registry/default/ui/button"
2 | import { Textarea } from "@/registry/default/ui/textarea"
3 |
4 | export default function TextareaWithButton() {
5 | return (
6 |
7 |
8 | Send message
9 |
10 | )
11 | }
12 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/input-with-label.tsx:
--------------------------------------------------------------------------------
1 | import type { JSX } from "react"
2 |
3 | import { Input } from "@/registry/default/ui/input"
4 | import { Stack } from "@/registry/default/ui/stack"
5 |
6 | export default function Component(): JSX.Element {
7 | return (
8 |
9 |
10 |
11 | )
12 | }
13 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/switch-icon.tsx:
--------------------------------------------------------------------------------
1 | import { Switch, SwitchControl } from "@/registry/default/ui/switch"
2 |
3 | export default function SwitchIcon() {
4 | return (
5 |
6 |
7 |
8 |
9 |
10 |
11 | )
12 | }
13 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/gauge-color-scale.tsx:
--------------------------------------------------------------------------------
1 | import { Gauge } from "@/registry/default/ui/gauge"
2 | import { Stack } from "@/registry/default/ui/stack"
3 |
4 | export default function GaugeColorScale() {
5 | return (
6 |
7 |
8 |
9 |
10 |
11 | )
12 | }
13 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/input-with-button.tsx:
--------------------------------------------------------------------------------
1 | import { Button } from "@/registry/default/ui/button"
2 | import { Input } from "@/registry/default/ui/input"
3 |
4 | export default function InputWithButton() {
5 | return (
6 |
7 |
8 | Subscribe
9 |
10 | )
11 | }
12 |
--------------------------------------------------------------------------------
/apps/www/config/site.ts:
--------------------------------------------------------------------------------
1 | export const siteConfig = {
2 | name: "vercel/ui",
3 | url: "https://vercel-ui-phi.vercel.app",
4 | ogImage: "https://vercel-ui-phi.vercel.app/og.png",
5 | description: "Component system based on Vercel's Geist system",
6 | links: {
7 | twitter: "https://twitter.com/whosmatu",
8 | github: "https://github.com/immatheus/vercel-ui",
9 | },
10 | }
11 |
12 | export type SiteConfig = typeof siteConfig
13 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/switch-disabled.tsx:
--------------------------------------------------------------------------------
1 | import { Switch, SwitchControl } from "@/registry/default/ui/switch"
2 |
3 | export default function SwitchDisabled() {
4 | return (
5 |
6 |
7 |
8 |
9 |
10 |
11 | )
12 | }
13 |
--------------------------------------------------------------------------------
/apps/www/hooks/use-lock-body.ts:
--------------------------------------------------------------------------------
1 | import * as React from "react"
2 |
3 | // @see https://usehooks.com/useLockBodyScroll.
4 | export function useLockBody() {
5 | React.useLayoutEffect((): (() => void) => {
6 | const originalStyle: string = window.getComputedStyle(
7 | document.body
8 | ).overflow
9 | document.body.style.overflow = "hidden"
10 | return () => (document.body.style.overflow = originalStyle)
11 | }, [])
12 | }
13 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/textarea-with-label.tsx:
--------------------------------------------------------------------------------
1 | import { Label } from "@/registry/default/ui/label"
2 | import { Textarea } from "@/registry/default/ui/textarea"
3 |
4 | export default function TextareaWithLabel() {
5 | return (
6 |
7 | Your message
8 |
9 |
10 | )
11 | }
12 |
--------------------------------------------------------------------------------
/packages/cli/src/utils/handle-error.ts:
--------------------------------------------------------------------------------
1 | import { logger } from "@/src/utils/logger"
2 |
3 | export function handleError(error: unknown) {
4 | if (typeof error === "string") {
5 | logger.error(error)
6 | process.exit(1)
7 | }
8 |
9 | if (error instanceof Error) {
10 | logger.error(error.message)
11 | process.exit(1)
12 | }
13 |
14 | logger.error("Something went wrong. Please try again.")
15 | process.exit(1)
16 | }
17 |
--------------------------------------------------------------------------------
/packages/cli/src/utils/resolve-import.ts:
--------------------------------------------------------------------------------
1 | import { createMatchPath, type ConfigLoaderSuccessResult } from "tsconfig-paths"
2 |
3 | export async function resolveImport(
4 | importPath: string,
5 | config: Pick
6 | ) {
7 | return createMatchPath(config.absoluteBaseUrl, config.paths)(
8 | importPath,
9 | undefined,
10 | () => true,
11 | [".ts", ".tsx"]
12 | )
13 | }
14 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/label-demo.tsx:
--------------------------------------------------------------------------------
1 | import { Checkbox } from "@/registry/default/ui/checkbox"
2 | import { Label } from "@/registry/default/ui/label"
3 |
4 | export default function LabelDemo() {
5 | return (
6 |
7 |
8 |
9 | Accept terms and conditions
10 |
11 |
12 | )
13 | }
14 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # vercel/ui
2 |
3 | Accessible and customizable components designed by [vercel](https://vercel.com) that you can copy and paste into your apps. Free. Open Source. **Use this to build your own component library**.
4 |
5 | > [!NOTE]
6 | > This is a NOT affiliated with Vercel or Shadcn in any way and is only a fork of Shadcn I made for fun and learning.
7 |
8 | This repo was a fork of the Shadcn repo, so a lot of cred to him and the other contributors.
9 |
--------------------------------------------------------------------------------
/.kodiak.toml:
--------------------------------------------------------------------------------
1 | # .kodiak.toml
2 | version = 1
3 |
4 | [merge]
5 | automerge_label = "automerge"
6 | require_automerge_label = true
7 | method = "squash"
8 | delete_branch_on_merge = true
9 | optimistic_updates = false
10 | prioritize_ready_to_merge = true
11 | notify_on_conflict = true
12 |
13 | [merge.message]
14 | title = "pull_request_title"
15 | body = "pull_request_body"
16 | include_pr_number = true
17 | body_type = "markdown"
18 | strip_html_comments = true
19 |
--------------------------------------------------------------------------------
/apps/www/public/registry/styles/default/aspect-ratio.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "aspect-ratio",
3 | "dependencies": [
4 | "@radix-ui/react-aspect-ratio"
5 | ],
6 | "files": [
7 | {
8 | "name": "aspect-ratio.tsx",
9 | "content": "\"use client\"\n\nimport * as AspectRatioPrimitive from \"@radix-ui/react-aspect-ratio\"\n\nconst AspectRatio = AspectRatioPrimitive.Root\n\nexport { AspectRatio }\n"
10 | }
11 | ],
12 | "type": "components:ui"
13 | }
--------------------------------------------------------------------------------
/apps/www/registry/default/example/gauge-demo.tsx:
--------------------------------------------------------------------------------
1 | import { Gauge } from "@/registry/default/ui/gauge"
2 | import { Stack } from "@/registry/default/ui/stack"
3 |
4 | export default function GaugeDemo() {
5 | return (
6 |
7 |
8 |
9 |
10 |
11 |
12 | )
13 | }
14 |
--------------------------------------------------------------------------------
/apps/www/public/site.webmanifest:
--------------------------------------------------------------------------------
1 | {
2 | "name": "",
3 | "short_name": "",
4 | "icons": [
5 | {
6 | "src": "/android-chrome-192x192.png",
7 | "sizes": "192x192",
8 | "type": "image/png"
9 | },
10 | {
11 | "src": "/android-chrome-512x512.png",
12 | "sizes": "512x512",
13 | "type": "image/png"
14 | }
15 | ],
16 | "theme_color": "#ffffff",
17 | "background_color": "#ffffff",
18 | "display": "standalone"
19 | }
20 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/note-demo.tsx:
--------------------------------------------------------------------------------
1 | import { Note } from "@/registry/default/ui/note"
2 | import { Stack } from "@/registry/default/ui/stack"
3 |
4 | export default function NoteDemo() {
5 | return (
6 |
7 | A small note.
8 | A default note.
9 | A large note.
10 |
11 | )
12 | }
13 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/skeleton-demo.tsx:
--------------------------------------------------------------------------------
1 | import { Skeleton } from "@/registry/default/ui/skeleton"
2 |
3 | export default function SkeletonDemo() {
4 | return (
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | )
13 | }
14 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/skeleton-card.tsx:
--------------------------------------------------------------------------------
1 | import { Skeleton } from "@/registry/default/ui/skeleton"
2 |
3 | export default function SkeletonCard() {
4 | return (
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | )
13 | }
14 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/calendar-demo.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 |
5 | import { Calendar } from "@/registry/default/ui/calendar"
6 |
7 | export default function CalendarDemo() {
8 | const [date, setDate] = React.useState(new Date())
9 |
10 | return (
11 |
17 | )
18 | }
19 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/gauge-custom-secondary-color.tsx:
--------------------------------------------------------------------------------
1 | import { Gauge } from "@/registry/default/ui/gauge"
2 |
3 | export default function GaugeCustomSecondaryColor() {
4 | return (
5 |
6 |
14 |
15 | )
16 | }
17 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/status-dot-demo.tsx:
--------------------------------------------------------------------------------
1 | import { Stack } from "@/registry/default/ui/stack"
2 | import { StatusDot } from "@/registry/default/ui/status-dot"
3 |
4 | export default function StatusDotDemo() {
5 | return (
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | )
14 | }
15 |
--------------------------------------------------------------------------------
/apps/www/types/nav.ts:
--------------------------------------------------------------------------------
1 | import { Icons } from "@/components/icons"
2 |
3 | export interface NavItem {
4 | title: string
5 | href?: string
6 | disabled?: boolean
7 | external?: boolean
8 | icon?: keyof typeof Icons
9 | label?: string
10 | }
11 |
12 | export interface NavItemWithChildren extends NavItem {
13 | items: NavItemWithChildren[]
14 | }
15 |
16 | export interface MainNavItem extends NavItem {}
17 |
18 | export interface SidebarNavItem extends NavItemWithChildren {}
19 |
--------------------------------------------------------------------------------
/packages/cli/src/utils/logger.ts:
--------------------------------------------------------------------------------
1 | import chalk from "chalk"
2 |
3 | export const logger = {
4 | error(...args: unknown[]) {
5 | console.log(chalk.red(...args))
6 | },
7 | warn(...args: unknown[]) {
8 | console.log(chalk.yellow(...args))
9 | },
10 | info(...args: unknown[]) {
11 | console.log(chalk.cyan(...args))
12 | },
13 | success(...args: unknown[]) {
14 | console.log(chalk.green(...args))
15 | },
16 | break() {
17 | console.log("")
18 | },
19 | }
20 |
--------------------------------------------------------------------------------
/apps/www/public/registry/styles/default/skeleton.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "skeleton",
3 | "files": [
4 | {
5 | "name": "skeleton.tsx",
6 | "content": "import { cn } from \"@/lib/utils\"\n\nfunction Skeleton({\n className,\n ...props\n}: React.HTMLAttributes) {\n return (\n
\n )\n}\n\nexport { Skeleton }\n"
7 | }
8 | ],
9 | "type": "components:ui"
10 | }
--------------------------------------------------------------------------------
/packages/cli/src/utils/get-package-manager.ts:
--------------------------------------------------------------------------------
1 | import { detect } from "@antfu/ni"
2 |
3 | export async function getPackageManager(
4 | targetDir: string
5 | ): Promise<"yarn" | "pnpm" | "bun" | "npm"> {
6 | const packageManager = await detect({ programmatic: true, cwd: targetDir })
7 |
8 | if (packageManager === "yarn@berry") return "yarn"
9 | if (packageManager === "pnpm@6") return "pnpm"
10 | if (packageManager === "bun") return "bun"
11 |
12 | return packageManager ?? "npm"
13 | }
14 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/progress-demo.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 |
5 | import { Progress } from "@/registry/default/ui/progress"
6 |
7 | export default function ProgressDemo() {
8 | const [progress, setProgress] = React.useState(13)
9 |
10 | React.useEffect(() => {
11 | const timer = setTimeout(() => setProgress(66), 500)
12 | return () => clearTimeout(timer)
13 | }, [])
14 |
15 | return
16 | }
17 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/snippet-variants.tsx:
--------------------------------------------------------------------------------
1 | import { Snippet } from "@/registry/default/ui/snippet"
2 | import { Stack } from "@/registry/default/ui/stack"
3 |
4 | export default function SnippetVariants() {
5 | return (
6 |
7 |
8 |
9 |
10 |
11 | )
12 | }
13 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/status-dot-label.tsx:
--------------------------------------------------------------------------------
1 | import { Stack } from "@/registry/default/ui/stack"
2 | import { StatusDot } from "@/registry/default/ui/status-dot"
3 |
4 | export default function Component() {
5 | return (
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 | )
14 | }
15 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/grid-debug.tsx:
--------------------------------------------------------------------------------
1 | import { Grid, GridCell, GridSystem } from "@/registry/default/ui/grid"
2 |
3 | export default function GridDebug() {
4 | return (
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | )
16 | }
17 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/grid-demo.tsx:
--------------------------------------------------------------------------------
1 | import { Grid, GridCell, GridSystem } from "@/registry/default/ui/grid"
2 |
3 | export default function GridDemo() {
4 | return (
5 |
6 |
7 | 1
8 | 2
9 | 3
10 | 4
11 | 5
12 | 6
13 |
14 |
15 | )
16 | }
17 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/input-with-text.tsx:
--------------------------------------------------------------------------------
1 | import { Input } from "@/registry/default/ui/input"
2 | import { Label } from "@/registry/default/ui/label"
3 |
4 | export default function InputWithText() {
5 | return (
6 |
7 |
Email
8 |
9 |
Enter your email address.
10 |
11 | )
12 | }
13 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/alert-demo.tsx:
--------------------------------------------------------------------------------
1 | import { Terminal } from "lucide-react"
2 |
3 | import {
4 | Alert,
5 | AlertDescription,
6 | AlertTitle,
7 | } from "@/registry/default/ui/alert"
8 |
9 | export default function AlertDemo() {
10 | return (
11 |
12 |
13 | Heads up!
14 |
15 | You can add components to your app using the cli.
16 |
17 |
18 | )
19 | }
20 |
--------------------------------------------------------------------------------
/apps/www/hooks/use-config.ts:
--------------------------------------------------------------------------------
1 | import { useAtom } from "jotai"
2 | import { atomWithStorage } from "jotai/utils"
3 |
4 | import { Style } from "@/registry/styles"
5 | import { Theme } from "@/registry/themes"
6 |
7 | type Config = {
8 | style: Style["name"]
9 | theme: Theme["name"]
10 | radius: number
11 | }
12 |
13 | const configAtom = atomWithStorage("config", {
14 | style: "default",
15 | theme: "zinc",
16 | radius: 0.5,
17 | })
18 |
19 | export function useConfig() {
20 | return useAtom(configAtom)
21 | }
22 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/stack-responsive.tsx:
--------------------------------------------------------------------------------
1 | import { Stack } from "@/registry/default/ui/stack"
2 |
3 | export default function Component(): JSX.Element {
4 | return (
5 |
9 |
10 |
11 |
12 |
13 | )
14 | }
15 |
--------------------------------------------------------------------------------
/apps/www/lib/fonts.ts:
--------------------------------------------------------------------------------
1 | // import { JetBrains_Mono as FontMono, Inter as FontSans } from "next/font/google"
2 | import { JetBrains_Mono as FontMono } from "next/font/google"
3 | // import { GeistMono } from "geist/font/mono"
4 | import { GeistSans } from "geist/font/sans"
5 |
6 | // export const fontSans = FontSans({
7 | // subsets: ["latin"],
8 | // variable: "--font-sans",
9 | // })
10 | export const fontSans = GeistSans
11 |
12 | export const fontMono = FontMono({
13 | subsets: ["latin"],
14 | variable: "--font-mono",
15 | })
16 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/button-demo.tsx:
--------------------------------------------------------------------------------
1 | import { Button } from "@/registry/default/ui/button"
2 | import { Stack } from "@/registry/default/ui/stack"
3 |
4 | export default function ButtonDemo() {
5 | return (
6 |
12 | Upload
13 | Upload
14 | Upload
15 |
16 | )
17 | }
18 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/checkbox-disabled.tsx:
--------------------------------------------------------------------------------
1 | import { Checkbox } from "@/registry/default/ui/checkbox"
2 |
3 | export default function CheckboxDisabled() {
4 | return (
5 |
6 |
7 |
11 | Accept terms and conditions
12 |
13 |
14 | )
15 | }
16 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/toast-simple.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import { Button } from "@/registry/default/ui/button"
4 | import { useToast } from "@/registry/default/ui/use-toast"
5 |
6 | export default function ToastSimple() {
7 | const { toast } = useToast()
8 |
9 | return (
10 | {
13 | toast({
14 | description: "Your message has been sent.",
15 | })
16 | }}
17 | >
18 | Show Toast
19 |
20 | )
21 | }
22 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/badge-sizes.tsx:
--------------------------------------------------------------------------------
1 | import { Badge } from "@/registry/default/ui/badge"
2 | import { Stack } from "@/registry/default/ui/stack"
3 |
4 | export default function BadgeDestructive() {
5 | return (
6 |
7 |
8 | Small
9 |
10 |
11 | Medium
12 |
13 |
14 | Large
15 |
16 |
17 | )
18 | }
19 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/checkbox-demo.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import { Checkbox } from "@/registry/default/ui/checkbox"
4 |
5 | export default function CheckboxDemo() {
6 | return (
7 |
8 |
9 |
13 | Accept terms and conditions
14 |
15 |
16 | )
17 | }
18 |
--------------------------------------------------------------------------------
/apps/www/components/promo-video.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import { AspectRatio } from "@/registry/default/ui/aspect-ratio"
4 |
5 | export function PromoVideo() {
6 | return (
7 |
11 |
12 |
16 |
17 |
18 | )
19 | }
20 |
--------------------------------------------------------------------------------
/packages/cli/src/utils/transformers/transform-rsc.ts:
--------------------------------------------------------------------------------
1 | import { Transformer } from "@/src/utils/transformers"
2 | import { SyntaxKind } from "ts-morph"
3 |
4 | export const transformRsc: Transformer = async ({ sourceFile, config }) => {
5 | if (config.rsc) {
6 | return sourceFile
7 | }
8 |
9 | // Remove "use client" from the top of the file.
10 | const first = sourceFile.getFirstChildByKind(SyntaxKind.ExpressionStatement)
11 | if (first?.getText() === `"use client"`) {
12 | first.remove()
13 | }
14 |
15 | return sourceFile
16 | }
17 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/aspect-ratio-demo.tsx:
--------------------------------------------------------------------------------
1 | import Image from "next/image"
2 |
3 | import { AspectRatio } from "@/registry/default/ui/aspect-ratio"
4 |
5 | export default function AspectRatioDemo() {
6 | return (
7 |
8 |
14 |
15 | )
16 | }
17 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/menu-link-items.tsx:
--------------------------------------------------------------------------------
1 | import {
2 | Menu,
3 | MenuButton,
4 | MenuContainer,
5 | MenuLink,
6 | } from "@/registry/default/ui/menu"
7 |
8 | export default function MenuLinksDemo() {
9 | return (
10 |
11 | Actions
12 |
13 | One
14 | Two
15 | Three
16 |
17 |
18 | )
19 | }
20 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/alert-destructive.tsx:
--------------------------------------------------------------------------------
1 | import { AlertCircle } from "lucide-react"
2 |
3 | import {
4 | Alert,
5 | AlertDescription,
6 | AlertTitle,
7 | } from "@/registry/default/ui/alert"
8 |
9 | export default function AlertDestructive() {
10 | return (
11 |
12 |
13 | Error
14 |
15 | Your session has expired. Please log in again.
16 |
17 |
18 | )
19 | }
20 |
--------------------------------------------------------------------------------
/apps/www/registry/schema.ts:
--------------------------------------------------------------------------------
1 | import { z } from "zod"
2 |
3 | export const registrySchema = z.array(
4 | z.object({
5 | name: z.string(),
6 | dependencies: z.array(z.string()).optional(),
7 | devDependencies: z.array(z.string()).optional(),
8 | registryDependencies: z.array(z.string()).optional(),
9 | files: z.array(z.string()),
10 | type: z.enum([
11 | "components:ui",
12 | "components:component",
13 | "components:example",
14 | ]),
15 | })
16 | )
17 |
18 | export type Registry = z.infer
19 |
--------------------------------------------------------------------------------
/apps/www/components/style-wrapper.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 |
5 | import { useConfig } from "@/hooks/use-config"
6 | import { Style } from "@/registry/styles"
7 |
8 | interface StyleWrapperProps extends React.HTMLAttributes {
9 | styleName?: Style["name"]
10 | }
11 |
12 | export function StyleWrapper({ styleName, children }: StyleWrapperProps) {
13 | const [config] = useConfig()
14 |
15 | if (!styleName || config.style === styleName) {
16 | return <>{children}>
17 | }
18 |
19 | return null
20 | }
21 |
--------------------------------------------------------------------------------
/apps/www/hooks/use-media-query.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react"
2 |
3 | export function useMediaQuery(query: string) {
4 | const [value, setValue] = React.useState(false)
5 |
6 | React.useEffect(() => {
7 | function onChange(event: MediaQueryListEvent) {
8 | setValue(event.matches)
9 | }
10 |
11 | const result = matchMedia(query)
12 | result.addEventListener("change", onChange)
13 | setValue(result.matches)
14 |
15 | return () => result.removeEventListener("change", onChange)
16 | }, [query])
17 |
18 | return value
19 | }
20 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
2 |
3 | # dependencies
4 | node_modules
5 | .pnp
6 | .pnp.js
7 |
8 | # testing
9 | coverage
10 |
11 | # next.js
12 | .next/
13 | out/
14 | build
15 |
16 | # misc
17 | .DS_Store
18 | *.pem
19 |
20 | # debug
21 | npm-debug.log*
22 | yarn-debug.log*
23 | yarn-error.log*
24 | .pnpm-debug.log*
25 |
26 | # local env files
27 | .env.local
28 | .env.development.local
29 | .env.test.local
30 | .env.production.local
31 |
32 | # turbo
33 | .turbo
34 |
35 | .contentlayer
36 | tsconfig.tsbuildinfo
--------------------------------------------------------------------------------
/apps/www/registry/default/example/textarea-with-text.tsx:
--------------------------------------------------------------------------------
1 | import { Label } from "@/registry/default/ui/label"
2 | import { Textarea } from "@/registry/default/ui/textarea"
3 |
4 | export default function TextareaWithText() {
5 | return (
6 |
7 |
Your Message
8 |
9 |
10 | Your message will be copied to the support team.
11 |
12 |
13 | )
14 | }
15 |
--------------------------------------------------------------------------------
/apps/www/components/component-card.tsx:
--------------------------------------------------------------------------------
1 | import React from "react"
2 |
3 | import { cn } from "@/lib/utils"
4 | import { AspectRatio } from "@/registry/default/ui/aspect-ratio"
5 |
6 | export function ComponentCard({
7 | className,
8 | ...props
9 | }: React.HTMLAttributes) {
10 | return (
11 |
12 |
19 |
20 | )
21 | }
22 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/text-clamp.tsx:
--------------------------------------------------------------------------------
1 | import { Text } from "@/registry/default/ui/text"
2 |
3 | export default function TextClamp() {
4 | return (
5 |
6 |
7 | The Evil Rabbit jumps. The Evil Rabbit jumps. The Evil Rabbit jumps. The
8 | Evil Rabbit jumps. The Evil Rabbit jumps. The Evil Rabbit jumps. The
9 | Evil Rabbit jumps. The Evil Rabbit jumps. The Evil Rabbit jumps. The
10 | Evil Rabbit jumps. The Evil Rabbit jumps.
11 |
12 |
13 | )
14 | }
15 |
--------------------------------------------------------------------------------
/apps/www/components/callout.tsx:
--------------------------------------------------------------------------------
1 | import {
2 | Alert,
3 | AlertDescription,
4 | AlertTitle,
5 | } from "@/registry/default/ui/alert"
6 |
7 | interface CalloutProps {
8 | icon?: string
9 | title?: string
10 | children?: React.ReactNode
11 | }
12 |
13 | export function Callout({ title, children, icon, ...props }: CalloutProps) {
14 | return (
15 |
16 | {icon && {icon} }
17 | {title && {title} }
18 | {children}
19 |
20 | )
21 | }
22 |
--------------------------------------------------------------------------------
/apps/www/lib/utils.ts:
--------------------------------------------------------------------------------
1 | import * as React from "react"
2 | import { clsx, type ClassValue } from "clsx"
3 | import { twMerge } from "tailwind-merge"
4 |
5 | export function cn(...inputs: ClassValue[]) {
6 | return twMerge(clsx(inputs))
7 | }
8 |
9 | export function formatDate(input: string | number): string {
10 | const date = new Date(input)
11 | return date.toLocaleDateString("en-US", {
12 | month: "long",
13 | day: "numeric",
14 | year: "numeric",
15 | })
16 | }
17 |
18 | export function absoluteUrl(path: string) {
19 | return `${process.env.NEXT_PUBLIC_APP_URL}${path}`
20 | }
21 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/input-disabled.tsx:
--------------------------------------------------------------------------------
1 | import type { JSX } from "react"
2 |
3 | import { Input } from "@/registry/default/ui/input"
4 | import { Stack } from "@/registry/default/ui/stack"
5 |
6 | export default function Component(): JSX.Element {
7 | return (
8 |
9 |
14 |
15 |
16 | )
17 | }
18 |
--------------------------------------------------------------------------------
/apps/www/hooks/use-mutation-observer.ts:
--------------------------------------------------------------------------------
1 | import * as React from "react"
2 |
3 | export const useMutationObserver = (
4 | ref: React.MutableRefObject,
5 | callback: MutationCallback,
6 | options = {
7 | attributes: true,
8 | characterData: true,
9 | childList: true,
10 | subtree: true,
11 | }
12 | ) => {
13 | React.useEffect(() => {
14 | if (ref.current) {
15 | const observer = new MutationObserver(callback)
16 | observer.observe(ref.current, options)
17 | return () => observer.disconnect()
18 | }
19 | }, [ref, callback, options])
20 | }
21 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/sonner-demo.tsx:
--------------------------------------------------------------------------------
1 | import { toast } from "sonner"
2 |
3 | import { Button } from "@/registry/default/ui/button"
4 |
5 | export default function SonnerDemo() {
6 | return (
7 |
10 | toast("Event has been created", {
11 | description: "Sunday, December 03, 2023 at 9:00 AM",
12 | action: {
13 | label: "Undo",
14 | onClick: () => console.log("Undo"),
15 | },
16 | })
17 | }
18 | >
19 | Show Toast
20 |
21 | )
22 | }
23 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/toast-with-title.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import { Button } from "@/registry/default/ui/button"
4 | import { useToast } from "@/registry/default/ui/use-toast"
5 |
6 | export default function ToastWithTitle() {
7 | const { toast } = useToast()
8 |
9 | return (
10 | {
13 | toast({
14 | title: "Uh oh! Something went wrong.",
15 | description: "There was a problem with your request.",
16 | })
17 | }}
18 | >
19 | Show Toast
20 |
21 | )
22 | }
23 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/button-loading.tsx:
--------------------------------------------------------------------------------
1 | import { Button } from "@/registry/default/ui/button"
2 | import { Stack } from "@/registry/default/ui/stack"
3 |
4 | export default function ButtonLoading() {
5 | return (
6 |
12 |
13 | Upload
14 |
15 | Upload
16 |
17 | Upload
18 |
19 |
20 | )
21 | }
22 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/button-types.tsx:
--------------------------------------------------------------------------------
1 | import { Button } from "@/registry/default/ui/button"
2 | import { Stack } from "@/registry/default/ui/stack"
3 |
4 | export default function ButtonTypes() {
5 | return (
6 |
12 | Upload
13 | Upload
14 | Upload
15 | Upload
16 |
17 | )
18 | }
19 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json.schemastore.org/tsconfig",
3 | "display": "Default",
4 | "compilerOptions": {
5 | "composite": false,
6 | "declaration": true,
7 | "declarationMap": true,
8 | "esModuleInterop": true,
9 | "forceConsistentCasingInFileNames": true,
10 | "inlineSources": false,
11 | "isolatedModules": true,
12 | "moduleResolution": "node",
13 | "noUnusedLocals": false,
14 | "noUnusedParameters": false,
15 | "preserveWatchOutput": true,
16 | "skipLibCheck": true,
17 | "strict": true
18 | },
19 | "exclude": ["node_modules"]
20 | }
21 |
--------------------------------------------------------------------------------
/apps/www/components/framework-docs.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import { allDocs } from "contentlayer/generated"
5 |
6 | import { Mdx } from "./mdx-components"
7 |
8 | interface FrameworkDocsProps extends React.HTMLAttributes {
9 | data: string
10 | }
11 |
12 | export function FrameworkDocs({ ...props }: FrameworkDocsProps) {
13 | const frameworkDoc = allDocs.find(
14 | (doc) => doc.slug === `/docs/installation/${props.data}`
15 | )
16 |
17 | if (!frameworkDoc) {
18 | return null
19 | }
20 |
21 | return
22 | }
23 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/button-disabled.tsx:
--------------------------------------------------------------------------------
1 | import { Button } from "@/registry/default/ui/button"
2 | import { Stack } from "@/registry/default/ui/stack"
3 |
4 | export default function ButtonDisabled() {
5 | return (
6 |
12 |
13 | Upload
14 |
15 | Upload
16 |
17 | Upload
18 |
19 |
20 | )
21 | }
22 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/note-disabled.tsx:
--------------------------------------------------------------------------------
1 | import { Button } from "@/registry/default/ui/button"
2 | import { Note } from "@/registry/default/ui/note"
3 | import { Stack } from "@/registry/default/ui/stack"
4 |
5 | export default function NoteDisabled() {
6 | return (
7 |
8 |
11 | Upgrade
12 |
13 | }
14 | disabled
15 | fill
16 | type="warning"
17 | >
18 | This note details a warning.
19 |
20 |
21 | )
22 | }
23 |
--------------------------------------------------------------------------------
/apps/www/public/registry/styles/default/collapsible.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "collapsible",
3 | "dependencies": [
4 | "@radix-ui/react-collapsible"
5 | ],
6 | "files": [
7 | {
8 | "name": "collapsible.tsx",
9 | "content": "\"use client\"\n\nimport * as CollapsiblePrimitive from \"@radix-ui/react-collapsible\"\n\nconst Collapsible = CollapsiblePrimitive.Root\n\nconst CollapsibleTrigger = CollapsiblePrimitive.CollapsibleTrigger\n\nconst CollapsibleContent = CollapsiblePrimitive.CollapsibleContent\n\nexport { Collapsible, CollapsibleTrigger, CollapsibleContent }\n"
10 | }
11 | ],
12 | "type": "components:ui"
13 | }
--------------------------------------------------------------------------------
/apps/www/content/docs/index.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Introduction
3 | description: Inspired by ShadcnUI and Vercel, this is a collection of re-usable components that you can copy and paste into your apps.
4 | ---
5 |
6 |
7 |
8 | This is **NOT** in any way affiliated with **Vercel** or **ShadcnUI**. This is a solo project made for fun.
9 |
10 |
11 | This project is currently in alpha so please note that some components are not fully implemented and can change without further notice. If you encounter any issues, please reach out on Github or Twitter/X
12 |
13 |
14 |
--------------------------------------------------------------------------------
/apps/www/components/component-source.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 |
5 | import { cn } from "@/lib/utils"
6 | import { CodeBlockWrapper } from "@/components/code-block-wrapper"
7 |
8 | interface ComponentSourceProps extends React.HTMLAttributes {
9 | src: string
10 | }
11 |
12 | export function ComponentSource({
13 | children,
14 | className,
15 | ...props
16 | }: ComponentSourceProps) {
17 | return (
18 |
22 | {children}
23 |
24 | )
25 | }
26 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/gauge-label.tsx:
--------------------------------------------------------------------------------
1 | import { Gauge } from "@/registry/default/ui/gauge"
2 | import { Stack } from "@/registry/default/ui/stack"
3 |
4 | export default function GaugeLabel() {
5 | return (
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | )
16 | }
17 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/stack-padding.tsx:
--------------------------------------------------------------------------------
1 | import { Stack } from "@/registry/default/ui/stack"
2 |
3 | export default function Component(): JSX.Element {
4 | return (
5 |
6 |
9 |
12 |
15 |
16 | )
17 | }
18 |
--------------------------------------------------------------------------------
/apps/www/components/tailwind-indicator.tsx:
--------------------------------------------------------------------------------
1 | export function TailwindIndicator() {
2 | if (process.env.NODE_ENV === "production") return null
3 |
4 | return (
5 |
6 |
xs
7 |
sm
8 |
md
9 |
lg
10 |
xl
11 |
2xl
12 |
13 | )
14 | }
15 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/input-demo.tsx:
--------------------------------------------------------------------------------
1 | import type { JSX } from "react"
2 |
3 | import { Input } from "@/registry/default/ui/input"
4 | import { Stack } from "@/registry/default/ui/stack"
5 |
6 | export default function Component(): JSX.Element {
7 | return (
8 |
14 |
15 |
16 |
17 |
18 | )
19 | }
20 |
--------------------------------------------------------------------------------
/apps/www/content/docs/about.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: About
3 | description: Powered by amazing open source projects.
4 | ---
5 |
6 | ## About
7 |
8 | [ui.shadcn.com](https://ui.shadcn.com) is a project by [shadcn](https://shadcn.com).
9 |
10 | ## Credits
11 |
12 | - [Radix UI](https://radix-ui.com) - For the primitives.
13 | - [Vercel](https://vercel.com) - Where I host all my projects.
14 | - [Shu Ding](https://shud.in) - The typography style is adapted from his work on Nextra.
15 | - [Cal](https://cal.com) - Where I copied the styles for the first component: the `Button`.
16 | - [cmdk](https://cmdk.paco.me) - For the ` ` component.
17 |
18 | ## License
19 |
20 | MIT © [shadcn](https://shadcn.com)
21 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/text-demo.tsx:
--------------------------------------------------------------------------------
1 | import { Stack } from "@/registry/default/ui/stack"
2 | import { Text } from "@/registry/default/ui/text"
3 |
4 | export default function TextDemo() {
5 | return (
6 |
7 | The Evil Rabbit jumps.
8 | The Evil Rabbit jumps.
9 | The Evil Rabbit jumps.
10 | The Evil Rabbit jumps.
11 | The Evil Rabbit jumps.
12 | The Evil Rabbit jumps.
13 | The Evil Rabbit jumps.
14 | The Evil Rabbit jumps.
15 |
16 | )
17 | }
18 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/note-action.tsx:
--------------------------------------------------------------------------------
1 | import { Button } from "@/registry/default/ui/button"
2 | import { Note } from "@/registry/default/ui/note"
3 | import { Stack } from "@/registry/default/ui/stack"
4 |
5 | export default function NoteAction() {
6 | return (
7 |
8 | Upgrade}>
9 | This note details some information.
10 |
11 | Upgrade}>
12 | This note details a large amount information that could potentially wrap
13 | into two or more lines, forcing the height of the Note to be larger.
14 |
15 |
16 | )
17 | }
18 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/button-rounded.tsx:
--------------------------------------------------------------------------------
1 | import { Button } from "@/registry/default/ui/button"
2 | import { Stack } from "@/registry/default/ui/stack"
3 |
4 | export default function ButtonRounded() {
5 | return (
6 |
12 |
13 | Upload
14 |
15 |
16 | Upload
17 |
18 |
19 | Upload
20 |
21 |
22 | )
23 | }
24 |
--------------------------------------------------------------------------------
/apps/www/lib/events.ts:
--------------------------------------------------------------------------------
1 | import va from "@vercel/analytics"
2 | import { z } from "zod"
3 |
4 | const eventSchema = z.object({
5 | name: z.enum([
6 | "copy_npm_command",
7 | "copy_usage_import_code",
8 | "copy_usage_code",
9 | "copy_primitive_code",
10 | "copy_theme_code",
11 | ]),
12 | // declare type AllowedPropertyValues = string | number | boolean | null
13 | properties: z
14 | .record(z.union([z.string(), z.number(), z.boolean(), z.null()]))
15 | .optional(),
16 | })
17 |
18 | export type Event = z.infer
19 |
20 | export function trackEvent(input: Event): void {
21 | const event = eventSchema.parse(input)
22 | if (event) {
23 | va.track(event.name, event.properties)
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/apps/www/types/unist.ts:
--------------------------------------------------------------------------------
1 | import { Node } from "unist-builder"
2 |
3 | export interface UnistNode extends Node {
4 | type: string
5 | name?: string
6 | tagName?: string
7 | value?: string
8 | properties?: {
9 | __rawString__?: string
10 | __className__?: string
11 | __event__?: string
12 | [key: string]: unknown
13 | } & NpmCommands
14 | attributes?: {
15 | name: string
16 | value: unknown
17 | type?: string
18 | }[]
19 | children?: UnistNode[]
20 | }
21 |
22 | export interface UnistTree extends Node {
23 | children: UnistNode[]
24 | }
25 |
26 | export interface NpmCommands {
27 | __npmCommand__?: string
28 | __yarnCommand__?: string
29 | __pnpmCommand__?: string
30 | __bunCommand__?: string
31 | }
32 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/toast-with-action.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import { Button } from "@/registry/default/ui/button"
4 | import { ToastAction } from "@/registry/default/ui/toast"
5 | import { useToast } from "@/registry/default/ui/use-toast"
6 |
7 | export default function ToastWithAction() {
8 | const { toast } = useToast()
9 |
10 | return (
11 | {
14 | toast({
15 | title: "Uh oh! Something went wrong.",
16 | description: "There was a problem with your request.",
17 | action: Try again ,
18 | })
19 | }}
20 | >
21 | Show Toast
22 |
23 | )
24 | }
25 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/toggle-demo.tsx:
--------------------------------------------------------------------------------
1 | import { useState } from "react"
2 |
3 | import { Toggle } from "@/registry/default/ui/toggle"
4 |
5 | export default function ToggleDemo() {
6 | const [checked, setChecked] = useState(false)
7 | const [checked2, setChecked2] = useState(true)
8 |
9 | return (
10 |
11 |
12 | setChecked(!checked)}
15 | />
16 |
17 |
18 | setChecked2(!checked2)}
21 | />
22 |
23 |
24 | )
25 | }
26 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/scroll-area-demo.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react"
2 |
3 | import { ScrollArea } from "@/registry/default/ui/scroll-area"
4 |
5 | const tags = Array.from({ length: 50 }).map(
6 | (_, i, a) => `v1.2.0-beta.${a.length - i}`
7 | )
8 |
9 | export default function ScrollAreaDemo() {
10 | return (
11 |
12 |
13 |
Tags
14 | {tags.map((tag) => (
15 | <>
16 |
17 | {tag}
18 |
19 | >
20 | ))}
21 |
22 |
23 | )
24 | }
25 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/menu-disabled-items.tsx:
--------------------------------------------------------------------------------
1 | import {
2 | Menu,
3 | MenuButton,
4 | MenuContainer,
5 | MenuItem,
6 | } from "@/registry/default/ui/menu"
7 |
8 | export default function DropdownMenuDemo() {
9 | return (
10 |
11 | Actions
12 |
13 | undefined}>One
14 | undefined}>
15 | Two
16 |
17 | undefined}>
18 | Three
19 |
20 | undefined} type="error">
21 | Delete
22 |
23 |
24 |
25 | )
26 | }
27 |
--------------------------------------------------------------------------------
/apps/www/components/theme-switcher.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import { useSelectedLayoutSegment } from "next/navigation"
5 |
6 | import { useConfig } from "@/hooks/use-config"
7 |
8 | export function ThemeSwitcher() {
9 | const [config] = useConfig()
10 | const segment = useSelectedLayoutSegment()
11 |
12 | React.useEffect(() => {
13 | document.body.classList.forEach((className) => {
14 | if (className.match(/^theme.*/)) {
15 | document.body.classList.remove(className)
16 | }
17 | })
18 |
19 | const theme = segment === "themes" ? config.theme : null
20 | if (theme) {
21 | return document.body.classList.add(`theme-${theme}`)
22 | }
23 | }, [segment, config])
24 |
25 | return null
26 | }
27 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/checkbox-with-text.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import { Checkbox } from "@/registry/default/ui/checkbox"
4 |
5 | export default function CheckboxWithText() {
6 | return (
7 |
8 |
9 |
10 |
14 | Accept terms and conditions
15 |
16 |
17 | You agree to our Terms of Service and Privacy Policy.
18 |
19 |
20 |
21 | )
22 | }
23 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/toast-demo.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import { Button } from "@/registry/default/ui/button"
4 | import { ToastAction } from "@/registry/default/ui/toast"
5 | import { useToast } from "@/registry/default/ui/use-toast"
6 |
7 | export default function ToastDemo() {
8 | const { toast } = useToast()
9 |
10 | return (
11 | {
14 | toast({
15 | title: "Scheduled: Catch up ",
16 | description: "Friday, February 10, 2023 at 5:57 PM",
17 | action: (
18 | Undo
19 | ),
20 | })
21 | }}
22 | >
23 | Add to calendar
24 |
25 | )
26 | }
27 |
--------------------------------------------------------------------------------
/.eslintrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json.schemastore.org/eslintrc",
3 | "root": true,
4 | "extends": [
5 | "next/core-web-vitals",
6 | "turbo",
7 | "prettier",
8 | "plugin:tailwindcss/recommended"
9 | ],
10 | "plugins": ["tailwindcss"],
11 | "rules": {
12 | "@next/next/no-html-link-for-pages": "off",
13 | "tailwindcss/no-custom-classname": "off",
14 | "tailwindcss/classnames-order": "off"
15 | },
16 | "settings": {
17 | "tailwindcss": {
18 | "callees": ["cn", "cva"],
19 | "config": "tailwind.config.cjs"
20 | },
21 | "next": {
22 | "rootDir": ["apps/*/"]
23 | }
24 | },
25 | "overrides": [
26 | {
27 | "files": ["*.ts", "*.tsx"],
28 | "parser": "@typescript-eslint/parser"
29 | }
30 | ]
31 | }
32 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/toast-destructive.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import { Button } from "@/registry/default/ui/button"
4 | import { ToastAction } from "@/registry/default/ui/toast"
5 | import { useToast } from "@/registry/default/ui/use-toast"
6 |
7 | export default function ToastDestructive() {
8 | const { toast } = useToast()
9 |
10 | return (
11 | {
14 | toast({
15 | variant: "destructive",
16 | title: "Uh oh! Something went wrong.",
17 | description: "There was a problem with your request.",
18 | action: Try again ,
19 | })
20 | }}
21 | >
22 | Show Toast
23 |
24 | )
25 | }
26 |
--------------------------------------------------------------------------------
/apps/www/components/theme-wrapper.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import { cn } from "@/lib/utils"
4 | import { useConfig } from "@/hooks/use-config"
5 |
6 | interface ThemeWrapperProps extends React.ComponentProps<"div"> {
7 | defaultTheme?: string
8 | }
9 |
10 | export function ThemeWrapper({
11 | defaultTheme,
12 | children,
13 | className,
14 | }: ThemeWrapperProps) {
15 | const [config] = useConfig()
16 |
17 | return (
18 |
30 | {children}
31 |
32 | )
33 | }
34 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/button-prefix.tsx:
--------------------------------------------------------------------------------
1 | import { ArrowLeft, ArrowRight } from "lucide-react"
2 |
3 | import { Button } from "@/registry/default/ui/button"
4 | import { Stack } from "@/registry/default/ui/stack"
5 |
6 | export default function ButtonPrefix() {
7 | return (
8 |
14 | }>Upload
15 | }>Upload
16 | }
18 | suffix={ }
19 | >
20 | Upload
21 |
22 |
23 | )
24 | }
25 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/note-cyan.tsx:
--------------------------------------------------------------------------------
1 | import { Button } from "@/registry/default/ui/button"
2 | import { Note } from "@/registry/default/ui/note"
3 | import { Stack } from "@/registry/default/ui/stack"
4 |
5 | export default function NoteCyan() {
6 | return (
7 |
8 | This note details some success information.
9 | Upgrade} type="cyan">
10 | This note details some success information.
11 |
12 |
13 | This filled note details some success information.
14 |
15 | Upgrade} fill type="cyan">
16 | This filled note details some success information.
17 |
18 |
19 | )
20 | }
21 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/note-error.tsx:
--------------------------------------------------------------------------------
1 | import { Button } from "@/registry/default/ui/button"
2 | import { Note } from "@/registry/default/ui/note"
3 | import { Stack } from "@/registry/default/ui/stack"
4 |
5 | export default function NoteDemo() {
6 | return (
7 |
8 | This note details some error information.
9 | Upgrade} type="error">
10 | This note details some error information.
11 |
12 |
13 | This filled note details some error information.
14 |
15 | Upgrade} fill type="error">
16 | This filled note details some error information.
17 |
18 |
19 | )
20 | }
21 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/menu-demo.tsx:
--------------------------------------------------------------------------------
1 | import { Cloud, Plus, Users } from "lucide-react"
2 |
3 | import { Button } from "@/registry/default/ui/button"
4 | import {
5 | DropdownMenuShortcut,
6 | Menu,
7 | MenuButton,
8 | MenuContainer,
9 | MenuItem,
10 | } from "@/registry/default/ui/menu"
11 |
12 | export default function DropdownMenuDemo() {
13 | return (
14 |
15 | Actions
16 |
17 | alert("one")}>One
18 | alert("one")}>Two
19 | alert("one")}>Three
20 | alert("one")} type="error">
21 | Delete
22 |
23 |
24 |
25 | )
26 | }
27 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/menu-prefix.tsx:
--------------------------------------------------------------------------------
1 | import { Cloud, Plus, Users } from "lucide-react"
2 |
3 | import { Button } from "@/registry/default/ui/button"
4 | import {
5 | DropdownMenuShortcut,
6 | Menu,
7 | MenuButton,
8 | MenuContainer,
9 | MenuItem,
10 | } from "@/registry/default/ui/menu"
11 |
12 | export default function MenuPrefixDemo() {
13 | return (
14 |
15 | prefix
16 |
17 | alert("one")}>One
18 | alert("one")}>Two
19 | alert("one")}>Three
20 | alert("one")} type="error">
21 | Delete
22 |
23 |
24 |
25 | )
26 | }
27 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/note-success.tsx:
--------------------------------------------------------------------------------
1 | import { Button } from "@/registry/default/ui/button"
2 | import { Note } from "@/registry/default/ui/note"
3 | import { Stack } from "@/registry/default/ui/stack"
4 |
5 | export default function NoteDemo() {
6 | return (
7 |
8 | This note details some success information.
9 | Upgrade} type="success">
10 | This note details some success information.
11 |
12 |
13 | This filled note details some success information.
14 |
15 | Upgrade} fill type="success">
16 | This filled note details some success information.
17 |
18 |
19 | )
20 | }
21 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/note-violet.tsx:
--------------------------------------------------------------------------------
1 | import { Button } from "@/registry/default/ui/button"
2 | import { Note } from "@/registry/default/ui/note"
3 | import { Stack } from "@/registry/default/ui/stack"
4 |
5 | export default function NoteViolet() {
6 | return (
7 |
8 | This note details some warning information.
9 | Upgrade} type="violet">
10 | This note details some warning information.
11 |
12 |
13 | This filled note details some warning information.
14 |
15 | Upgrade} fill type="violet">
16 | This filled note details some warning information.
17 |
18 |
19 | )
20 | }
21 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/note-warning.tsx:
--------------------------------------------------------------------------------
1 | import { Button } from "@/registry/default/ui/button"
2 | import { Note } from "@/registry/default/ui/note"
3 | import { Stack } from "@/registry/default/ui/stack"
4 |
5 | export default function NoteWarning() {
6 | return (
7 |
8 | This note details some warning information.
9 | Upgrade} type="warning">
10 | This note details some warning information.
11 |
12 |
13 | This filled note details some warning information.
14 |
15 | Upgrade} fill type="warning">
16 | This filled note details some warning information.
17 |
18 |
19 | )
20 | }
21 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/menu-custom-trigger.tsx:
--------------------------------------------------------------------------------
1 | import { Cloud, Plus, Users } from "lucide-react"
2 |
3 | import { Button } from "@/registry/default/ui/button"
4 | import {
5 | DropdownMenuShortcut,
6 | Menu,
7 | MenuButton,
8 | MenuContainer,
9 | MenuItem,
10 | } from "@/registry/default/ui/menu"
11 |
12 | export default function DropdownMenuDemo() {
13 | return (
14 |
15 | custom trigger
16 |
17 | alert("one")}>One
18 | alert("one")}>Two
19 | alert("one")}>Three
20 | alert("one")} type="error">
21 | Delete
22 |
23 |
24 |
25 | )
26 | }
27 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/tabs-demo.tsx:
--------------------------------------------------------------------------------
1 | import {
2 | Tabs,
3 | TabsContent,
4 | TabsList,
5 | TabsTrigger,
6 | } from "@/registry/default/ui/tabs"
7 |
8 | // TODO fix some of the left over cases
9 | export default function TabsDemo() {
10 | return (
11 |
12 |
13 | Apple
14 | Orange
15 | Mango
16 |
17 |
18 | Apple
19 |
20 |
21 | Orange
22 |
23 |
24 | Mango
25 |
26 |
27 | )
28 | }
29 |
--------------------------------------------------------------------------------
/apps/www/registry/default/ui/label.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import * as LabelPrimitive from "@radix-ui/react-label"
5 | import { cva, type VariantProps } from "class-variance-authority"
6 |
7 | import { cn } from "@/lib/utils"
8 |
9 | const labelVariants = cva(
10 | "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
11 | )
12 |
13 | const Label = React.forwardRef<
14 | React.ElementRef,
15 | React.ComponentPropsWithoutRef &
16 | VariantProps
17 | >(({ className, ...props }, ref) => (
18 |
23 | ))
24 | Label.displayName = LabelPrimitive.Root.displayName
25 |
26 | export { Label }
27 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/radio-group-demo.tsx:
--------------------------------------------------------------------------------
1 | import { Label } from "@/registry/default/ui/label"
2 | import { RadioGroup, RadioGroupItem } from "@/registry/default/ui/radio-group"
3 |
4 | export default function RadioGroupDemo() {
5 | return (
6 |
7 |
8 |
9 | Default
10 |
11 |
12 |
13 | Comfortable
14 |
15 |
16 |
17 | Compact
18 |
19 |
20 | )
21 | }
22 |
--------------------------------------------------------------------------------
/packages/cli/src/index.ts:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | import { add } from "@/src/commands/add"
3 | import { diff } from "@/src/commands/diff"
4 | import { init } from "@/src/commands/init"
5 | import { Command } from "commander"
6 |
7 | import { getPackageInfo } from "./utils/get-package-info"
8 |
9 | process.on("SIGINT", () => process.exit(0))
10 | process.on("SIGTERM", () => process.exit(0))
11 |
12 | async function main() {
13 | const packageInfo = await getPackageInfo()
14 |
15 | const program = new Command()
16 | .name("shadcn-ui")
17 | .description("add components and dependencies to your project")
18 | .version(
19 | packageInfo.version || "1.0.0",
20 | "-v, --version",
21 | "display the version number"
22 | )
23 |
24 | program.addCommand(init).addCommand(add).addCommand(diff)
25 |
26 | program.parse()
27 | }
28 |
29 | main()
30 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/tabs-disable-specific-tabs.tsx:
--------------------------------------------------------------------------------
1 | import {
2 | Tabs,
3 | TabsContent,
4 | TabsList,
5 | TabsTrigger,
6 | } from "@/registry/default/ui/tabs"
7 |
8 | export default function TabsDisableSpecificTabs() {
9 | return (
10 |
11 |
12 | Apple
13 | Orange
14 |
15 | Mango
16 |
17 |
18 |
19 | Apple
20 |
21 |
22 | Orange
23 |
24 |
25 | Mango
26 |
27 |
28 | )
29 | }
30 |
--------------------------------------------------------------------------------
/apps/www/components/padding-box.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react"
2 |
3 | interface PaddingBoxProps {
4 | title?: string
5 | description?: string
6 | children: React.ReactNode
7 | }
8 |
9 | export function PaddingBox({ title, description, children }: PaddingBoxProps) {
10 | const hasLabel = !!title || !!description
11 |
12 | return (
13 |
14 | {hasLabel && (
15 |
16 | {title && (
17 |
{title}
18 | )}
19 | {description && (
20 |
21 | {description}
22 |
23 | )}
24 |
25 | )}
26 | {children}
27 |
28 | )
29 | }
30 |
--------------------------------------------------------------------------------
/apps/www/app/docs/layout.tsx:
--------------------------------------------------------------------------------
1 | import { docsConfig } from "@/config/docs"
2 | import { DocsSidebarNav } from "@/components/sidebar-nav"
3 | import { ScrollArea } from "@/registry/default/ui/scroll-area"
4 |
5 | interface DocsLayoutProps {
6 | children: React.ReactNode
7 | }
8 |
9 | export default function DocsLayout({ children }: DocsLayoutProps) {
10 | return (
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 | {children}
20 |
21 | )
22 | }
23 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/resizable-vertical.tsx:
--------------------------------------------------------------------------------
1 | import {
2 | ResizableHandle,
3 | ResizablePanel,
4 | ResizablePanelGroup,
5 | } from "@/registry/default/ui/resizable"
6 |
7 | export default function ResizableDemo() {
8 | return (
9 |
13 |
14 |
15 | Header
16 |
17 |
18 |
19 |
20 |
21 | Content
22 |
23 |
24 |
25 | )
26 | }
27 |
--------------------------------------------------------------------------------
/apps/www/registry/default/ui/textarea.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react"
2 |
3 | import { cn } from "@/lib/utils"
4 |
5 | export interface TextareaProps
6 | extends React.TextareaHTMLAttributes {}
7 |
8 | const Textarea = React.forwardRef(
9 | ({ className, ...props }, ref) => {
10 | return (
11 |
19 | )
20 | }
21 | )
22 | Textarea.displayName = "Textarea"
23 |
24 | export { Textarea }
25 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/resizable-handle.tsx:
--------------------------------------------------------------------------------
1 | import {
2 | ResizableHandle,
3 | ResizablePanel,
4 | ResizablePanelGroup,
5 | } from "@/registry/default/ui/resizable"
6 |
7 | export default function ResizableDemo() {
8 | return (
9 |
13 |
14 |
15 | Sidebar
16 |
17 |
18 |
19 |
20 |
21 | Content
22 |
23 |
24 |
25 | )
26 | }
27 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/collapse-demo.tsx:
--------------------------------------------------------------------------------
1 | import { Collapse, CollapseGroup } from "@/registry/default/ui/collapse"
2 |
3 | export default function CollapseDemo() {
4 | return (
5 |
6 |
7 | {/* TODO add the text component */}
8 |
9 | Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do
10 | eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad
11 | minim veniam, quis nostrud exercitation ullamco laboris nisi ut
12 | aliquip ex ea commodo consequat.
13 |
14 |
15 |
16 |
17 | Duis aute irure dolor in reprehenderit in voluptate velit esse cillum
18 | dolore eu fugiat nulla pariatur.
19 |
20 |
21 |
22 | )
23 | }
24 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/note-secondary.tsx:
--------------------------------------------------------------------------------
1 | import { Button } from "@/registry/default/ui/button"
2 | import { Note } from "@/registry/default/ui/note"
3 | import { Stack } from "@/registry/default/ui/stack"
4 |
5 | export default function NoteDemo() {
6 | return (
7 |
8 |
9 | This note details some secondary information.
10 |
11 | Upgrade} type="secondary">
12 | This note details some secondary information.
13 |
14 |
15 | This filled note details some secondary information.
16 |
17 | Upgrade}
19 | fill
20 | type="secondary"
21 | >
22 | This filled note details some secondary information.
23 |
24 |
25 | )
26 | }
27 |
--------------------------------------------------------------------------------
/apps/www/registry/default/ui/progress.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import * as ProgressPrimitive from "@radix-ui/react-progress"
5 |
6 | import { cn } from "@/lib/utils"
7 |
8 | const Progress = React.forwardRef<
9 | React.ElementRef,
10 | React.ComponentPropsWithoutRef
11 | >(({ className, value, ...props }, ref) => (
12 |
20 |
24 |
25 | ))
26 | Progress.displayName = ProgressPrimitive.Root.displayName
27 |
28 | export { Progress }
29 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/tabs-controlled.tsx:
--------------------------------------------------------------------------------
1 | import { useState } from "react"
2 |
3 | import {
4 | Tabs,
5 | TabsContent,
6 | TabsList,
7 | TabsTrigger,
8 | } from "@/registry/default/ui/tabs"
9 |
10 | export default function TabsControlled() {
11 | const [selected, setSelected] = useState("apple")
12 |
13 | return (
14 |
15 |
16 | Apple
17 | Orange
18 | Mango
19 |
20 |
21 | Apple
22 |
23 |
24 | Orange
25 |
26 |
27 | Mango
28 |
29 |
30 | )
31 | }
32 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/select-demo.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react"
2 |
3 | import {
4 | Select,
5 | SelectContent,
6 | SelectGroup,
7 | SelectItem,
8 | SelectLabel,
9 | SelectTrigger,
10 | SelectValue,
11 | } from "@/registry/default/ui/select"
12 |
13 | export default function SelectDemo() {
14 | return (
15 |
16 |
17 |
18 |
19 |
20 |
21 | Fruits
22 | Apple
23 | Banana
24 | Blueberry
25 | Grapes
26 | Pineapple
27 |
28 |
29 |
30 | )
31 | }
32 |
--------------------------------------------------------------------------------
/apps/www/registry/default/ui/toaster.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import {
4 | Toast,
5 | ToastClose,
6 | ToastDescription,
7 | ToastProvider,
8 | ToastTitle,
9 | ToastViewport,
10 | } from "@/registry/default/ui/toast"
11 | import { useToast } from "@/registry/default/ui/use-toast"
12 |
13 | export function Toaster() {
14 | const { toasts } = useToast()
15 |
16 | return (
17 |
18 | {toasts.map(function ({ id, title, description, action, ...props }) {
19 | return (
20 |
21 |
22 | {title && {title} }
23 | {description && (
24 | {description}
25 | )}
26 |
27 | {action}
28 |
29 |
30 | )
31 | })}
32 |
33 |
34 | )
35 | }
36 |
--------------------------------------------------------------------------------
/apps/www/public/registry/styles/default/textarea.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "textarea",
3 | "files": [
4 | {
5 | "name": "textarea.tsx",
6 | "content": "import * as React from \"react\"\n\nimport { cn } from \"@/lib/utils\"\n\nexport interface TextareaProps\n extends React.TextareaHTMLAttributes {}\n\nconst Textarea = React.forwardRef(\n ({ className, ...props }, ref) => {\n return (\n \n )\n }\n)\nTextarea.displayName = \"Textarea\"\n\nexport { Textarea }\n"
7 | }
8 | ],
9 | "type": "components:ui"
10 | }
--------------------------------------------------------------------------------
/apps/www/public/registry/styles/default/label.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "label",
3 | "dependencies": [
4 | "@radix-ui/react-label"
5 | ],
6 | "files": [
7 | {
8 | "name": "label.tsx",
9 | "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as LabelPrimitive from \"@radix-ui/react-label\"\nimport { cva, type VariantProps } from \"class-variance-authority\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst labelVariants = cva(\n \"text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70\"\n)\n\nconst Label = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef &\n VariantProps\n>(({ className, ...props }, ref) => (\n \n))\nLabel.displayName = LabelPrimitive.Root.displayName\n\nexport { Label }\n"
10 | }
11 | ],
12 | "type": "components:ui"
13 | }
--------------------------------------------------------------------------------
/apps/www/registry/default/example/switch-sizes.tsx:
--------------------------------------------------------------------------------
1 | import { Switch, SwitchControl } from "@/registry/default/ui/switch"
2 |
3 | export default function SwitchSizes() {
4 | return (
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 | )
26 | }
27 |
--------------------------------------------------------------------------------
/apps/www/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://json.schemastore.org/tsconfig",
3 | "extends": "../../tsconfig.json",
4 | "compilerOptions": {
5 | "target": "es5",
6 | "lib": ["dom", "dom.iterable", "esnext"],
7 | "allowJs": true,
8 | "skipLibCheck": true,
9 | "strict": true,
10 | "forceConsistentCasingInFileNames": true,
11 | "noEmit": true,
12 | "incremental": true,
13 | "esModuleInterop": true,
14 | "module": "esnext",
15 | "resolveJsonModule": true,
16 | "isolatedModules": true,
17 | "jsx": "preserve",
18 | "baseUrl": ".",
19 | "paths": {
20 | "@/*": ["./*"],
21 | "contentlayer/generated": ["./.contentlayer/generated"]
22 | },
23 | "plugins": [
24 | {
25 | "name": "next"
26 | }
27 | ]
28 | },
29 | "include": [
30 | "next-env.d.ts",
31 | "**/*.ts",
32 | "**/*.tsx",
33 | ".next/types/**/*.ts",
34 | ".contentlayer/generated"
35 | ],
36 | "exclude": ["node_modules", "./scripts/build-registry.ts"]
37 | }
38 |
--------------------------------------------------------------------------------
/apps/www/registry/default/ui/sonner.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import { useTheme } from "next-themes"
4 | import { Toaster as Sonner } from "sonner"
5 |
6 | type ToasterProps = React.ComponentProps
7 |
8 | const Toaster = ({ ...props }: ToasterProps) => {
9 | const { theme = "system" } = useTheme()
10 |
11 | return (
12 |
28 | )
29 | }
30 |
31 | export { Toaster }
32 |
--------------------------------------------------------------------------------
/prettier.config.cjs:
--------------------------------------------------------------------------------
1 | /** @type {import('prettier').Config} */
2 | module.exports = {
3 | endOfLine: "lf",
4 | semi: false,
5 | singleQuote: false,
6 | tabWidth: 2,
7 | trailingComma: "es5",
8 | importOrder: [
9 | "^(react/(.*)$)|^(react$)",
10 | "^(next/(.*)$)|^(next$)",
11 | "",
12 | "",
13 | "^types$",
14 | "^@/types/(.*)$",
15 | "^@/config/(.*)$",
16 | "^@/lib/(.*)$",
17 | "^@/hooks/(.*)$",
18 | "^@/components/ui/(.*)$",
19 | "^@/components/(.*)$",
20 | "^@/registry/(.*)$",
21 | "^@/styles/(.*)$",
22 | "^@/app/(.*)$",
23 | "",
24 | "^[./]",
25 | ],
26 | importOrderSeparation: false,
27 | importOrderSortSpecifiers: true,
28 | importOrderBuiltinModulesToTop: true,
29 | importOrderParserPlugins: ["typescript", "jsx", "decorators-legacy"],
30 | importOrderMergeDuplicateImports: true,
31 | importOrderCombineTypeAndValueImports: true,
32 | plugins: [
33 | "@ianvs/prettier-plugin-sort-imports",
34 | "prettier-plugin-tailwindcss",
35 | ],
36 | }
37 |
--------------------------------------------------------------------------------
/packages/cli/README.md:
--------------------------------------------------------------------------------
1 | # shadcn-ui
2 |
3 | A CLI for adding components to your project.
4 |
5 | ## Usage
6 |
7 | Use the `init` command to initialize dependencies for a new project.
8 |
9 | The `init` command installs dependencies, adds the `cn` util, configures `tailwind.config.js`, and CSS variables for the project.
10 |
11 | ```bash
12 | npx shadcn-ui init
13 | ```
14 |
15 | ## add
16 |
17 | Use the `add` command to add components to your project.
18 |
19 | The `add` command adds a component to your project and installs all required dependencies.
20 |
21 | ```bash
22 | npx shadcn-ui add [component]
23 | ```
24 |
25 | ### Example
26 |
27 | ```bash
28 | npx shadcn-ui add modal
29 | ```
30 |
31 | You can also run the command without any arguments to view a list of all available components:
32 |
33 | ```bash
34 | npx shadcn-ui add
35 | ```
36 |
37 | ## Documentation
38 |
39 | Visit https://ui.shadcn.com/docs/cli to view the documentation.
40 |
41 | ## License
42 |
43 | Licensed under the [MIT license](https://github.com/shadcn/ui/blob/main/LICENSE.md).
44 |
--------------------------------------------------------------------------------
/apps/www/registry/default/ui/status-dot.tsx:
--------------------------------------------------------------------------------
1 | import * as React from "react"
2 |
3 | import { cn } from "@/lib/utils"
4 |
5 | type State = "QUEUED" | "BUILDING" | "ERROR" | "READY" | "CANCELED"
6 |
7 | const labels: Record = {
8 | QUEUED: "Queued",
9 | BUILDING: "Building",
10 | ERROR: "Error",
11 | READY: "Ready",
12 | CANCELED: "Canceled",
13 | }
14 |
15 | const colors: Record = {
16 | QUEUED: "bg-accents-2",
17 | BUILDING: "bg-orange-500", // TODO change out these colors to real colors
18 | ERROR: "bg-red-800",
19 | READY: "bg-teal-600",
20 | CANCELED: "bg-accents-2",
21 | }
22 |
23 | interface StatusDotProps {
24 | state: State
25 | label?: boolean
26 | }
27 |
28 | const StatusDot: React.FC = ({ state, label }) => {
29 | return (
30 |
31 |
32 | {label &&
{labels[state]}
}
33 |
34 | )
35 | }
36 |
37 | export { StatusDot }
38 |
--------------------------------------------------------------------------------
/apps/www/components/site-footer.tsx:
--------------------------------------------------------------------------------
1 | import { siteConfig } from "@/config/site"
2 |
3 | export function SiteFooter() {
4 | return (
5 |
30 | )
31 | }
32 |
--------------------------------------------------------------------------------
/apps/www/registry/default/ui/spinner.tsx:
--------------------------------------------------------------------------------
1 | import React from "react"
2 |
3 | type SpinnerProps = { size?: number }
4 |
5 | const Spinner = ({ size }: SpinnerProps) => {
6 | return (
7 |
15 |
16 | {Array(12)
17 | .fill(null)
18 | .map((_, i) => (
19 |
27 | ))}
28 |
29 |
30 | )
31 | }
32 |
33 | export { Spinner }
34 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/menu-radio-group.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 |
5 | import { Button } from "@/registry/default/ui/button"
6 | import {
7 | DropdownMenuLabel,
8 | DropdownMenuRadioGroup,
9 | DropdownMenuRadioItem,
10 | Menu,
11 | MenuButton,
12 | MenuContainer,
13 | } from "@/registry/default/ui/menu"
14 |
15 | export default function DropdownMenuRadioGroupDemo() {
16 | const [position, setPosition] = React.useState("bottom")
17 |
18 | return (
19 |
20 | Open
21 |
22 | Panel Position
23 |
24 | Top
25 | Bottom
26 | Right
27 |
28 |
29 |
30 | )
31 | }
32 |
--------------------------------------------------------------------------------
/apps/www/public/registry/styles/default/progress.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "progress",
3 | "dependencies": [
4 | "@radix-ui/react-progress"
5 | ],
6 | "files": [
7 | {
8 | "name": "progress.tsx",
9 | "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as ProgressPrimitive from \"@radix-ui/react-progress\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst Progress = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, value, ...props }, ref) => (\n \n \n \n))\nProgress.displayName = ProgressPrimitive.Root.displayName\n\nexport { Progress }\n"
10 | }
11 | ],
12 | "type": "components:ui"
13 | }
--------------------------------------------------------------------------------
/apps/www/components/drawer.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import { forwardRef } from "react"
4 | import { Drawer as DrawerPrimitive } from "vaul"
5 |
6 | import { cn } from "@/lib/utils"
7 |
8 | const DrawerTrigger = DrawerPrimitive.Trigger
9 |
10 | const DrawerContent = forwardRef<
11 | React.ElementRef,
12 | React.ComponentPropsWithoutRef
13 | >(({ className, children, ...props }, ref) => (
14 |
15 |
16 |
24 |
25 | {children}
26 |
27 |
28 | ))
29 | DrawerContent.displayName = "DrawerContent"
30 |
31 | export { DrawerTrigger, DrawerContent }
32 |
--------------------------------------------------------------------------------
/apps/www/content/docs/components/grid.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Grid
3 | description: Grid stuff
4 | component: true
5 | ---
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | CLI
16 | Manual
17 |
18 |
19 |
20 | ```bash
21 | npx shadcn-ui@latest add grid
22 | ```
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 | Copy and paste the following code into your project.
31 |
32 |
33 |
34 | Update the import paths to match your project setup.
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/apps/www/content/docs/components/theme-switcher.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Theme Switcher
3 | description: Component that allows users to switch between light and dark themes.
4 | component: true
5 | ---
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | {/* CLI */}
16 | Manual
17 |
18 |
19 |
20 | ```bash
21 | npx shadcn-ui@latest add theme-switcher
22 | ```
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 | Install the following dependencies:
31 |
32 | ```bash
33 | npm install next-themes
34 | ```
35 |
36 | Copy and paste the following code into your project.
37 |
38 |
39 |
40 | Update the import paths to match your project setup.
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/apps/www/registry/default/ui/loading-dots.tsx:
--------------------------------------------------------------------------------
1 | import React from "react"
2 |
3 | interface LoadingDotsProps {
4 | size?: number
5 | children?: React.ReactNode
6 | }
7 |
8 | const LoadingDots: React.FC = ({ size = 2, children }) => {
9 | return (
10 |
17 | {children && {children} }
18 |
19 |
20 |
21 |
22 | )
23 | }
24 |
25 | export { LoadingDots }
26 |
--------------------------------------------------------------------------------
/apps/www/content/docs/components/status-dot.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Status dot
3 | description: Display an indicator of deployment status.
4 | component: true
5 | ---
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | {/* CLI */}
17 | Manual
18 |
19 |
20 |
21 | {/* TODO change all of theese to be own command */}
22 |
23 | ```bash
24 | npx shadcn-ui@latest add status-dot
25 | ```
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 | Copy and paste the following code into your project.
34 |
35 |
36 |
37 | Update the import paths to match your project setup.
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
--------------------------------------------------------------------------------
/apps/www/content/docs/components/kbd.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Keyboard input
3 | description: Display keyboard input that triggers an action.
4 | component: true
5 | ---
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | {/* CLI */}
16 | Manual
17 |
18 |
19 |
20 | ```bash
21 | npx shadcn-ui@latest add kbd
22 | ```
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 | Copy and paste the following code into your project.
31 |
32 |
33 |
34 | Update the import paths to match your project setup.
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2024 imMatheus
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/apps/www/public/registry/styles/default/spinner.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "spinner",
3 | "files": [
4 | {
5 | "name": "spinner.tsx",
6 | "content": "import React from \"react\"\n\ntype SpinnerProps = { size?: number }\n\nconst Spinner = ({ size }: SpinnerProps) => {\n return (\n \n
\n {Array(12)\n .fill(null)\n .map((_, i) => (\n
\n ))}\n
\n
\n )\n}\n\nexport { Spinner }\n"
7 | }
8 | ],
9 | "type": "components:ui"
10 | }
--------------------------------------------------------------------------------
/apps/www/content/docs/components/skeleton.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Skeleton
3 | description: Use to show a placeholder while content is loading.
4 | component: true
5 | ---
6 |
7 |
8 |
9 | ## Installation
10 |
11 |
12 |
13 |
14 | {/* CLI */}
15 | Manual
16 |
17 |
18 |
19 | ```bash
20 | npx shadcn-ui@latest add skeleton
21 | ```
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | Copy and paste the following code into your project.
30 |
31 |
32 |
33 | Update the import paths to match your project setup.
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 | ## Usage
42 |
43 | ```tsx
44 | import { Skeleton } from "@/components/ui/skeleton"
45 | ```
46 |
47 | ```tsx
48 |
49 | ```
50 |
51 | ## Examples
52 |
53 | ### Card
54 |
55 |
56 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/pagination-demo.tsx:
--------------------------------------------------------------------------------
1 | import {
2 | Pagination,
3 | PaginationContent,
4 | PaginationEllipsis,
5 | PaginationItem,
6 | PaginationLink,
7 | PaginationNext,
8 | PaginationPrevious,
9 | } from "@/registry/default/ui/pagination"
10 |
11 | export default function PaginationDemo() {
12 | return (
13 |
14 |
15 |
16 |
17 |
18 |
19 | 1
20 |
21 |
22 |
23 | 2
24 |
25 |
26 |
27 | 3
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 | )
38 | }
39 |
--------------------------------------------------------------------------------
/apps/www/public/registry/styles/default/status-dot.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "status-dot",
3 | "dependencies": [],
4 | "files": [
5 | {
6 | "name": "status-dot.tsx",
7 | "content": "import * as React from \"react\"\n\nimport { cn } from \"@/lib/utils\"\n\ntype State = \"QUEUED\" | \"BUILDING\" | \"ERROR\" | \"READY\" | \"CANCELED\"\n\nconst labels: Record = {\n QUEUED: \"Queued\",\n BUILDING: \"Building\",\n ERROR: \"Error\",\n READY: \"Ready\",\n CANCELED: \"Canceled\",\n}\n\nconst colors: Record = {\n QUEUED: \"bg-accents-2\",\n BUILDING: \"bg-orange-500\", // TODO change out these colors to real colors\n ERROR: \"bg-red-800\",\n READY: \"bg-teal-600\",\n CANCELED: \"bg-accents-2\",\n}\n\ninterface StatusDotProps {\n state: State\n label?: boolean\n}\n\nconst StatusDot: React.FC = ({ state, label }) => {\n return (\n \n
\n {label &&
{labels[state]}
}\n
\n )\n}\n\nexport { StatusDot }\n"
8 | }
9 | ],
10 | "type": "components:ui"
11 | }
--------------------------------------------------------------------------------
/apps/www/registry/default/example/text-variants.tsx:
--------------------------------------------------------------------------------
1 | import { Stack } from "@/registry/default/ui/stack"
2 | import { Text } from "@/registry/default/ui/text"
3 |
4 | export default function TextVariants() {
5 | return (
6 |
7 | {(
8 | [
9 | "heading-72",
10 | "heading-64",
11 | "heading-56",
12 | "heading-48",
13 | "heading-40",
14 | "heading-32",
15 | "heading-24",
16 | "heading-20",
17 | "heading-16",
18 | "button-16",
19 | "button-14",
20 | "button-12",
21 | "label-20",
22 | "label-18",
23 | "label-16",
24 | "label-14",
25 | "label-13",
26 | "label-12",
27 | "copy-24",
28 | "copy-20",
29 | "copy-18",
30 | "copy-16",
31 | "copy-14",
32 | "copy-13",
33 | ] as const
34 | ).map((variant) => {
35 | return (
36 |
37 | {variant.replace("-", " ")}
38 |
39 | )
40 | })}
41 |
42 | )
43 | }
44 |
--------------------------------------------------------------------------------
/apps/www/public/registry/styles/default/kbd.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "kbd",
3 | "files": [
4 | {
5 | "name": "kbd.tsx",
6 | "content": "import React from \"react\"\nimport { cva } from \"class-variance-authority\"\n\nconst kbdVariants = cva(\n \"text-gray-1000 text-sm bg-background-100 text-center space-x-1 inline-block rounded ml-1 shadow-border\",\n {\n variants: {\n size: {\n small: \"min-w-5 px-1\",\n medium: \"min-w-6 min-h-6 px-1.5\",\n },\n },\n defaultVariants: {\n size: \"medium\",\n },\n }\n)\n\ninterface KbdProps {\n meta?: boolean\n shift?: boolean\n alt?: boolean\n ctrl?: boolean\n small?: boolean\n children?: React.ReactNode\n}\n\n// TODO fix the font so that this looks good\nconst Kbd: React.FC = ({\n meta,\n shift,\n alt,\n ctrl,\n small,\n children,\n}) => {\n return (\n \n {meta && ⌘ }\n {shift && ⇧ }\n {alt && ⌥ }\n {ctrl && ⌃ }\n\n {children && {children} }\n \n )\n}\n\nexport { Kbd }\n"
7 | }
8 | ],
9 | "type": "components:ui"
10 | }
--------------------------------------------------------------------------------
/apps/www/registry/default/ui/kbd.tsx:
--------------------------------------------------------------------------------
1 | import React from "react"
2 | import { cva } from "class-variance-authority"
3 |
4 | const kbdVariants = cva(
5 | "text-gray-1000 text-sm bg-background-100 text-center space-x-1 inline-block rounded ml-1 shadow-border",
6 | {
7 | variants: {
8 | size: {
9 | small: "min-w-5 px-1",
10 | medium: "min-w-6 min-h-6 px-1.5",
11 | },
12 | },
13 | defaultVariants: {
14 | size: "medium",
15 | },
16 | }
17 | )
18 |
19 | interface KbdProps {
20 | meta?: boolean
21 | shift?: boolean
22 | alt?: boolean
23 | ctrl?: boolean
24 | small?: boolean
25 | children?: React.ReactNode
26 | }
27 |
28 | // TODO fix the font so that this looks good
29 | const Kbd: React.FC = ({
30 | meta,
31 | shift,
32 | alt,
33 | ctrl,
34 | small,
35 | children,
36 | }) => {
37 | return (
38 |
39 | {meta && ⌘ }
40 | {shift && ⇧ }
41 | {alt && ⌥ }
42 | {ctrl && ⌃ }
43 |
44 | {children && {children} }
45 |
46 | )
47 | }
48 |
49 | export { Kbd }
50 |
--------------------------------------------------------------------------------
/scripts/sync-templates.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | set -e # bail on errors
4 | GLOB=$1
5 | IS_CI="${CI:-false}"
6 | BASE=$(pwd)
7 | COMMIT_MESSAGE=$(git log -1 --pretty=%B)
8 |
9 | for folder in $GLOB; do
10 | [ -d "$folder" ] || continue
11 | cd $BASE
12 |
13 | if [ -n "$(git status --porcelain)" ]; then
14 | git add .
15 | git commit -m "chore: update template"
16 | git push origin main
17 | fi
18 |
19 | NAME=${folder##*/}
20 | CLONE_DIR="__${NAME}__clone__"
21 |
22 | # sync to read-only clones
23 | # clone, delete files in the clone, and copy (new) files over
24 | # this handles file deletions, additions, and changes seamlessly
25 | # note: redirect output to dev/null to avoid any possibility of leaking token
26 | git clone --quiet --depth 1 git@github.com:shadcn/${NAME}.git $CLONE_DIR > /dev/null
27 | cd $CLONE_DIR
28 | find . | grep -v ".git" | grep -v "^\.*$" | xargs rm -rf # delete all files (to handle deletions in monorepo)
29 | cp -r $BASE/$folder/. .
30 |
31 | if [ -n "$(git status --porcelain)" ]; then
32 | git add .
33 | git commit -m "$COMMIT_MESSAGE"
34 | git push origin main
35 | fi
36 |
37 | cd $BASE
38 | rm -rf $CLONE_DIR
39 | done
40 |
--------------------------------------------------------------------------------
/apps/www/public/registry/styles/default/sonner.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "sonner",
3 | "dependencies": [
4 | "sonner",
5 | "next-themes"
6 | ],
7 | "files": [
8 | {
9 | "name": "sonner.tsx",
10 | "content": "\"use client\"\n\nimport { useTheme } from \"next-themes\"\nimport { Toaster as Sonner } from \"sonner\"\n\ntype ToasterProps = React.ComponentProps\n\nconst Toaster = ({ ...props }: ToasterProps) => {\n const { theme = \"system\" } = useTheme()\n\n return (\n \n )\n}\n\nexport { Toaster }\n"
11 | }
12 | ],
13 | "type": "components:ui"
14 | }
--------------------------------------------------------------------------------
/apps/www/registry/default/ui/checkbox.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import * as CheckboxPrimitive from "@radix-ui/react-checkbox"
5 | import { Check } from "lucide-react"
6 |
7 | import { cn } from "@/lib/utils"
8 |
9 | const Checkbox = React.forwardRef<
10 | React.ElementRef,
11 | React.ComponentPropsWithoutRef
12 | >(({ className, ...props }, ref) => (
13 |
21 |
24 |
25 |
26 |
27 | ))
28 | Checkbox.displayName = CheckboxPrimitive.Root.displayName
29 |
30 | export { Checkbox }
31 |
--------------------------------------------------------------------------------
/apps/www/public/registry/styles/default/loading-dots.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "loading-dots",
3 | "files": [
4 | {
5 | "name": "loading-dots.tsx",
6 | "content": "import React from \"react\"\n\ninterface LoadingDotsProps {\n size?: number\n children?: React.ReactNode\n}\n\nconst LoadingDots: React.FC = ({ size = 2, children }) => {\n return (\n \n {children && {children} }\n \n \n \n \n )\n}\n\nexport { LoadingDots }\n"
7 | }
8 | ],
9 | "type": "components:ui"
10 | }
--------------------------------------------------------------------------------
/turbo.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://turbo.build/schema.json",
3 | "globalEnv": ["NODE_ENV"],
4 | "pipeline": {
5 | "build": {
6 | "dependsOn": ["^build"],
7 | "env": [
8 | "NEXT_PUBLIC_APP_URL",
9 | "UPSTASH_REDIS_REST_URL",
10 | "UPSTASH_REDIS_REST_TOKEN",
11 | "COMPONENTS_REGISTRY_URL",
12 | "npm_config_user_agent",
13 | "https_proxy"
14 | ],
15 | "outputs": ["dist/**", ".next/**"]
16 | },
17 | "preview": {
18 | "env": ["NEXT_PUBLIC_APP_URL"],
19 | "outputs": ["dist/**", ".next/**"]
20 | },
21 | "start": {
22 | "dependsOn": ["^build"]
23 | },
24 | "lint": {
25 | "cache": false,
26 | "outputs": []
27 | },
28 | "lint:fix": {
29 | "cache": false,
30 | "outputs": []
31 | },
32 | "format:check": {
33 | "cache": false,
34 | "outputs": []
35 | },
36 | "format:write": {
37 | "cache": false,
38 | "outputs": []
39 | },
40 | "typecheck": {},
41 | "dev": {
42 | "cache": false
43 | },
44 | "check": {
45 | "cache": false
46 | },
47 | "test": {
48 | "cache": false,
49 | "outputs": []
50 | }
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/mode-toggle.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import { Moon, Sun } from "lucide-react"
5 | import { useTheme } from "next-themes"
6 |
7 | import { Button } from "@/registry/default/ui/button"
8 | import {
9 | Menu,
10 | MenuButton,
11 | MenuContainer,
12 | MenuItem,
13 | } from "@/registry/default/ui/menu"
14 |
15 | export default function ModeToggle() {
16 | const { setTheme } = useTheme()
17 |
18 | return (
19 |
20 |
21 |
22 |
23 |
24 | Toggle theme
25 |
26 |
27 |
28 | setTheme("light")}>Light
29 | setTheme("dark")}>Dark
30 | setTheme("system")}>System
31 |
32 |
33 | )
34 | }
35 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/input-prefix-suffix.tsx:
--------------------------------------------------------------------------------
1 | import { ArrowUpCircle } from "lucide-react"
2 |
3 | import { Input } from "@/registry/default/ui/input"
4 | import { Stack } from "@/registry/default/ui/stack"
5 |
6 | export default function Component(): JSX.Element {
7 | return (
8 |
9 | }
13 | />
14 |
15 | }
19 | />
20 |
21 |
27 |
28 | }
32 | prefixStyling={false}
33 | suffix={ }
34 | suffixStyling={false}
35 | />
36 |
37 | }
42 | suffixStyling={false}
43 | />
44 |
45 | )
46 | }
47 |
--------------------------------------------------------------------------------
/apps/www/app/examples/authentication/components/user-auth-form.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 |
5 | import { cn } from "@/lib/utils"
6 | import { Icons } from "@/components/icons"
7 |
8 | interface UserAuthFormProps extends React.HTMLAttributes {}
9 |
10 | export function UserAuthForm({ className, ...props }: UserAuthFormProps) {
11 | const [isLoading, setIsLoading] = React.useState(false)
12 |
13 | async function onSubmit(event: React.SyntheticEvent) {
14 | event.preventDefault()
15 | setIsLoading(true)
16 |
17 | setTimeout(() => {
18 | setIsLoading(false)
19 | }, 3000)
20 | }
21 |
22 | return (
23 |
24 |
27 |
28 |
29 |
30 |
31 |
32 |
33 | Or continue with
34 |
35 |
36 |
37 |
38 | )
39 | }
40 |
--------------------------------------------------------------------------------
/apps/www/public/schema.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "http://json-schema.org/draft-07/schema#",
3 | "type": "object",
4 | "properties": {
5 | "style": {
6 | "type": "string",
7 | "enum": ["default"]
8 | },
9 | "tailwind": {
10 | "type": "object",
11 | "properties": {
12 | "config": {
13 | "type": "string"
14 | },
15 | "css": {
16 | "type": "string"
17 | },
18 | "baseColor": {
19 | "type": "string"
20 | },
21 | "cssVariables": {
22 | "type": "boolean"
23 | },
24 | "prefix": {
25 | "type": "string"
26 | }
27 | },
28 | "required": ["config", "css", "baseColor", "cssVariables"]
29 | },
30 | "rsc": {
31 | "type": "boolean"
32 | },
33 | "tsx": {
34 | "type": "boolean"
35 | },
36 | "aliases": {
37 | "type": "object",
38 | "properties": {
39 | "utils": {
40 | "type": "string"
41 | },
42 | "components": {
43 | "type": "string"
44 | },
45 | "ui": {
46 | "type": "string"
47 | }
48 | },
49 | "required": ["utils", "components"]
50 | }
51 | },
52 | "required": ["style", "tailwind", "rsc", "aliases"]
53 | }
54 |
--------------------------------------------------------------------------------
/apps/www/content/docs/components/label.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Label
3 | description: Renders an accessible label associated with controls.
4 | component: true
5 | links:
6 | doc: https://www.radix-ui.com/docs/primitives/components/label
7 | api: https://www.radix-ui.com/docs/primitives/components/label#api-reference
8 | ---
9 |
10 |
11 |
12 | ## Installation
13 |
14 |
15 |
16 |
17 | {/* CLI */}
18 | Manual
19 |
20 |
21 |
22 | ```bash
23 | npx shadcn-ui@latest add label
24 | ```
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 | Install the following dependencies:
33 |
34 | ```bash
35 | npm install @radix-ui/react-label
36 | ```
37 |
38 | Copy and paste the following code into your project.
39 |
40 |
41 |
42 | Update the import paths to match your project setup.
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 | ## Usage
51 |
52 | ```tsx
53 | import { Label } from "@/components/ui/label"
54 | ```
55 |
56 | ```tsx
57 | Your email address
58 | ```
59 |
--------------------------------------------------------------------------------
/apps/www/registry/default/ui/show-more.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import { ChevronDownIcon } from "lucide-react"
5 |
6 | import { cn } from "@/lib/utils"
7 | import { Button } from "@/registry/default/ui/button"
8 |
9 | interface ShowMoreProps {
10 | expanded: boolean
11 | onClick: () => void
12 | }
13 |
14 | const ShowMore = ({ expanded, onClick }: ShowMoreProps) => {
15 | return (
16 |
17 |
18 |
19 |
25 |
26 | {expanded ? "Show less" : "Show more"}
27 |
33 |
34 |
35 |
36 |
37 |
38 | )
39 | }
40 |
41 | export { ShowMore }
42 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/date-picker-demo.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import { format } from "date-fns"
5 | import { Calendar as CalendarIcon } from "lucide-react"
6 |
7 | import { cn } from "@/lib/utils"
8 | import { Button } from "@/registry/default/ui/button"
9 | import { Calendar } from "@/registry/default/ui/calendar"
10 | import {
11 | Popover,
12 | PopoverContent,
13 | PopoverTrigger,
14 | } from "@/registry/default/ui/popover"
15 |
16 | export default function DatePickerDemo() {
17 | const [date, setDate] = React.useState()
18 |
19 | return (
20 |
21 |
22 |
29 |
30 | {date ? format(date, "PPP") : Pick a date }
31 |
32 |
33 |
34 |
40 |
41 |
42 | )
43 | }
44 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/resizable-demo.tsx:
--------------------------------------------------------------------------------
1 | import {
2 | ResizableHandle,
3 | ResizablePanel,
4 | ResizablePanelGroup,
5 | } from "@/registry/default/ui/resizable"
6 |
7 | export default function ResizableDemo() {
8 | return (
9 |
13 |
14 |
15 | One
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | Two
24 |
25 |
26 |
27 |
28 |
29 | Three
30 |
31 |
32 |
33 |
34 |
35 | )
36 | }
37 |
--------------------------------------------------------------------------------
/apps/www/registry/default/ui/hover-card.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import * as HoverCardPrimitive from "@radix-ui/react-hover-card"
5 |
6 | import { cn } from "@/lib/utils"
7 |
8 | const HoverCard = HoverCardPrimitive.Root
9 |
10 | const HoverCardTrigger = HoverCardPrimitive.Trigger
11 |
12 | const HoverCardContent = React.forwardRef<
13 | React.ElementRef,
14 | React.ComponentPropsWithoutRef
15 | >(({ className, align = "center", sideOffset = 4, ...props }, ref) => (
16 |
26 | ))
27 | HoverCardContent.displayName = HoverCardPrimitive.Content.displayName
28 |
29 | export { HoverCard, HoverCardTrigger, HoverCardContent }
30 |
--------------------------------------------------------------------------------
/apps/www/content/docs/components/progress.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Progress
3 | description: Displays an indicator showing the completion progress of a task, typically displayed as a progress bar.
4 | component: true
5 | links:
6 | doc: https://www.radix-ui.com/docs/primitives/components/progress
7 | api: https://www.radix-ui.com/docs/primitives/components/progress#api-reference
8 | ---
9 |
10 |
11 |
12 | ## Installation
13 |
14 |
15 |
16 |
17 | {/* CLI */}
18 | Manual
19 |
20 |
21 |
22 | ```bash
23 | npx shadcn-ui@latest add progress
24 | ```
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 | Install the following dependencies:
33 |
34 | ```bash
35 | npm install @radix-ui/react-progress
36 | ```
37 |
38 | Copy and paste the following code into your project.
39 |
40 |
41 |
42 | Update the import paths to match your project setup.
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 | ## Usage
51 |
52 | ```tsx
53 | import { Progress } from "@/components/ui/progress"
54 | ```
55 |
56 | ```tsx
57 |
58 | ```
59 |
--------------------------------------------------------------------------------
/apps/www/public/registry/styles/default/checkbox.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "checkbox",
3 | "dependencies": [
4 | "@radix-ui/react-checkbox"
5 | ],
6 | "files": [
7 | {
8 | "name": "checkbox.tsx",
9 | "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as CheckboxPrimitive from \"@radix-ui/react-checkbox\"\nimport { Check } from \"lucide-react\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst Checkbox = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, ...props }, ref) => (\n \n \n \n \n \n))\nCheckbox.displayName = CheckboxPrimitive.Root.displayName\n\nexport { Checkbox }\n"
10 | }
11 | ],
12 | "type": "components:ui"
13 | }
--------------------------------------------------------------------------------
/apps/www/registry/default/example/resizable-demo-with-handle.tsx:
--------------------------------------------------------------------------------
1 | import {
2 | ResizableHandle,
3 | ResizablePanel,
4 | ResizablePanelGroup,
5 | } from "@/registry/default/ui/resizable"
6 |
7 | export default function ResizableDemo() {
8 | return (
9 |
13 |
14 |
15 | One
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | Two
24 |
25 |
26 |
27 |
28 |
29 | Three
30 |
31 |
32 |
33 |
34 |
35 | )
36 | }
37 |
--------------------------------------------------------------------------------
/apps/www/content/docs/components/switch.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Switch
3 | description: Choose between a set of options.
4 | component: true
5 | ---
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | {/* CLI */}
17 | Manual
18 |
19 |
20 |
21 | ```bash
22 | npx shadcn-ui@latest add switch
23 | ```
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 | Copy and paste the following code into your project.
32 |
33 |
34 |
35 | Update the import paths to match your project setup.
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 | {/* TODO fix switch */}
58 |
59 |
60 |
61 |
62 |
--------------------------------------------------------------------------------
/apps/www/content/docs/components/show-more.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Show more
3 | description: Displays a card with header, content, and footer.
4 | component: true
5 | ---
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | {/* CLI */}
16 | Manual
17 |
18 |
19 |
20 | ```bash
21 | npx shadcn-ui@latest add show-more
22 | ```
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 | Copy and paste the following code into your project.
31 |
32 |
33 |
34 | Update the import paths to match your project setup.
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 | ## Usage
43 |
44 | ```tsx
45 | import { ShowMore } from "@/components/ui/show-more"
46 | ```
47 |
48 | ```tsx
49 | import { useState } from "react"
50 |
51 | import { ShowMore } from "@/registry/default/ui/show-more"
52 |
53 | export default function ShowMoreDemo() {
54 | const [expanded, setExpanded] = useState(false)
55 |
56 | return setExpanded(!expanded)} />
57 | }
58 | ```
59 |
60 |
61 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/menu-position.tsx:
--------------------------------------------------------------------------------
1 | import {
2 | Menu,
3 | MenuButton,
4 | MenuContainer,
5 | MenuItem,
6 | } from "@/registry/default/ui/menu"
7 | import { Stack } from "@/registry/default/ui/stack"
8 |
9 | export default function MenuPositionDemo() {
10 | return (
11 |
12 |
13 | Left Start
14 |
15 | One
16 | Two
17 |
18 |
19 |
20 | Top Start
21 |
22 | One
23 | Two
24 |
25 |
26 |
27 | Bottom Start
28 |
29 | One
30 | Two
31 |
32 |
33 |
34 | Right Start
35 |
36 | One
37 | Two
38 |
39 |
40 |
41 | )
42 | }
43 |
--------------------------------------------------------------------------------
/apps/www/registry/default/ui/popover.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import * as PopoverPrimitive from "@radix-ui/react-popover"
5 |
6 | import { cn } from "@/lib/utils"
7 |
8 | const Popover = PopoverPrimitive.Root
9 |
10 | const PopoverTrigger = PopoverPrimitive.Trigger
11 |
12 | const PopoverContent = React.forwardRef<
13 | React.ElementRef,
14 | React.ComponentPropsWithoutRef
15 | >(({ className, align = "center", sideOffset = 4, ...props }, ref) => (
16 |
17 |
27 |
28 | ))
29 | PopoverContent.displayName = PopoverPrimitive.Content.displayName
30 |
31 | export { Popover, PopoverTrigger, PopoverContent }
32 |
--------------------------------------------------------------------------------
/packages/cli/src/utils/registry/schema.ts:
--------------------------------------------------------------------------------
1 | import { z } from "zod"
2 |
3 | // TODO: Extract this to a shared package.
4 | export const registryItemSchema = z.object({
5 | name: z.string(),
6 | dependencies: z.array(z.string()).optional(),
7 | devDependencies: z.array(z.string()).optional(),
8 | registryDependencies: z.array(z.string()).optional(),
9 | files: z.array(z.string()),
10 | type: z.enum(["components:ui", "components:component", "components:example"]),
11 | })
12 |
13 | export const registryIndexSchema = z.array(registryItemSchema)
14 |
15 | export const registryItemWithContentSchema = registryItemSchema.extend({
16 | files: z.array(
17 | z.object({
18 | name: z.string(),
19 | content: z.string(),
20 | })
21 | ),
22 | })
23 |
24 | export const registryWithContentSchema = z.array(registryItemWithContentSchema)
25 |
26 | export const stylesSchema = z.array(
27 | z.object({
28 | name: z.string(),
29 | label: z.string(),
30 | })
31 | )
32 |
33 | export const registryBaseColorSchema = z.object({
34 | inlineColors: z.object({
35 | light: z.record(z.string(), z.string()),
36 | dark: z.record(z.string(), z.string()),
37 | }),
38 | cssVars: z.object({
39 | light: z.record(z.string(), z.string()),
40 | dark: z.record(z.string(), z.string()),
41 | }),
42 | inlineColorsTemplate: z.string(),
43 | cssVarsTemplate: z.string(),
44 | })
45 |
--------------------------------------------------------------------------------
/apps/www/content/docs/components/avatar.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Avatar
3 | description: An image element with a fallback for representing the user.
4 | component: true
5 | links:
6 | doc: https://www.radix-ui.com/docs/primitives/components/avatar
7 | api: https://www.radix-ui.com/docs/primitives/components/avatar#api-reference
8 | ---
9 |
10 |
11 |
12 | ## Installation
13 |
14 |
15 |
16 |
17 | {/* CLI */}
18 | Manual
19 |
20 |
21 |
22 | ```bash
23 | npx shadcn-ui@latest add avatar
24 | ```
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 | Install the following dependencies:
33 |
34 | ```bash
35 | npm install @radix-ui/react-avatar
36 | ```
37 |
38 | Copy and paste the following code into your project.
39 |
40 |
41 |
42 | Update the import paths to match your project setup.
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 | ## Usage
51 |
52 | ```tsx
53 | import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"
54 | ```
55 |
56 | ```tsx
57 |
58 |
59 | CN
60 |
61 | ```
62 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/button-shapes.tsx:
--------------------------------------------------------------------------------
1 | import { ArrowUp } from "lucide-react"
2 |
3 | import { Button } from "@/registry/default/ui/button"
4 | import { Stack } from "@/registry/default/ui/stack"
5 |
6 | export default function ButtonShapes() {
7 | const Arrow = () =>
8 |
9 | return (
10 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 | )
42 | }
43 |
--------------------------------------------------------------------------------
/packages/cli/src/utils/transformers/transform-import.ts:
--------------------------------------------------------------------------------
1 | import { Transformer } from "@/src/utils/transformers"
2 |
3 | export const transformImport: Transformer = async ({ sourceFile, config }) => {
4 | const importDeclarations = sourceFile.getImportDeclarations()
5 |
6 | for (const importDeclaration of importDeclarations) {
7 | const moduleSpecifier = importDeclaration.getModuleSpecifierValue()
8 |
9 | // Replace @/registry/[style] with the components alias.
10 | if (moduleSpecifier.startsWith("@/registry/")) {
11 | if (config.aliases.ui) {
12 | importDeclaration.setModuleSpecifier(
13 | moduleSpecifier.replace(/^@\/registry\/[^/]+\/ui/, config.aliases.ui)
14 | )
15 | } else {
16 | importDeclaration.setModuleSpecifier(
17 | moduleSpecifier.replace(
18 | /^@\/registry\/[^/]+/,
19 | config.aliases.components
20 | )
21 | )
22 | }
23 | }
24 |
25 | // Replace `import { cn } from "@/lib/utils"`
26 | if (moduleSpecifier == "@/lib/utils") {
27 | const namedImports = importDeclaration.getNamedImports()
28 | const cnImport = namedImports.find((i) => i.getName() === "cn")
29 | if (cnImport) {
30 | importDeclaration.setModuleSpecifier(
31 | moduleSpecifier.replace(/^@\/lib\/utils/, config.aliases.utils)
32 | )
33 | }
34 | }
35 | }
36 |
37 | return sourceFile
38 | }
39 |
--------------------------------------------------------------------------------
/apps/www/content/docs/components/card.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Card
3 | description: Displays a card with header, content, and footer.
4 | component: true
5 | ---
6 |
7 |
8 |
9 | ## Installation
10 |
11 |
12 |
13 |
14 | {/* CLI */}
15 | Manual
16 |
17 |
18 |
19 | ```bash
20 | npx shadcn-ui@latest add card
21 | ```
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | Copy and paste the following code into your project.
30 |
31 |
32 |
33 | Update the import paths to match your project setup.
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 | ## Usage
42 |
43 | ```tsx
44 | import {
45 | Card,
46 | CardContent,
47 | CardDescription,
48 | CardFooter,
49 | CardHeader,
50 | CardTitle,
51 | } from "@/components/ui/card"
52 | ```
53 |
54 | ```tsx
55 |
56 |
57 | Card Title
58 | Card Description
59 |
60 |
61 | Card Content
62 |
63 |
64 | Card Footer
65 |
66 |
67 | ```
68 |
69 | ## Examples
70 |
71 |
72 |
--------------------------------------------------------------------------------
/apps/www/public/registry/styles/default/show-more.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "show-more",
3 | "dependencies": [],
4 | "registryDependencies": [
5 | "button"
6 | ],
7 | "files": [
8 | {
9 | "name": "show-more.tsx",
10 | "content": "\"use client\"\n\nimport * as React from \"react\"\nimport { ChevronDownIcon } from \"lucide-react\"\n\nimport { cn } from \"@/lib/utils\"\nimport { Button } from \"@/registry/default/ui/button\"\n\ninterface ShowMoreProps {\n expanded: boolean\n onClick: () => void\n}\n\nconst ShowMore = ({ expanded, onClick }: ShowMoreProps) => {\n return (\n \n
\n
\n
\n \n {expanded ? \"Show less\" : \"Show more\"} \n \n
\n \n
\n
\n
\n )\n}\n\nexport { ShowMore }\n"
11 | }
12 | ],
13 | "type": "components:ui"
14 | }
--------------------------------------------------------------------------------
/apps/www/content/docs/components/popover.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Popover
3 | description: Displays rich content in a portal, triggered by a button.
4 | component: true
5 | links:
6 | doc: https://www.radix-ui.com/docs/primitives/components/popover
7 | api: https://www.radix-ui.com/docs/primitives/components/popover#api-reference
8 | ---
9 |
10 |
11 |
12 | ## Installation
13 |
14 |
15 |
16 |
17 | {/* CLI */}
18 | Manual
19 |
20 |
21 |
22 | ```bash
23 | npx shadcn-ui@latest add popover
24 | ```
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 | Install the following dependencies:
33 |
34 | ```bash
35 | npm install @radix-ui/react-popover
36 | ```
37 |
38 | Copy and paste the following code into your project.
39 |
40 |
41 |
42 | Update the import paths to match your project setup.
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 | ## Usage
51 |
52 | ```tsx
53 | import {
54 | Popover,
55 | PopoverContent,
56 | PopoverTrigger,
57 | } from "@/components/ui/popover"
58 | ```
59 |
60 | ```tsx
61 |
62 | Open
63 | Place content for the popover here.
64 |
65 | ```
66 |
--------------------------------------------------------------------------------
/apps/www/public/registry/styles/default/hover-card.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "hover-card",
3 | "dependencies": [
4 | "@radix-ui/react-hover-card"
5 | ],
6 | "files": [
7 | {
8 | "name": "hover-card.tsx",
9 | "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as HoverCardPrimitive from \"@radix-ui/react-hover-card\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst HoverCard = HoverCardPrimitive.Root\n\nconst HoverCardTrigger = HoverCardPrimitive.Trigger\n\nconst HoverCardContent = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, align = \"center\", sideOffset = 4, ...props }, ref) => (\n \n))\nHoverCardContent.displayName = HoverCardPrimitive.Content.displayName\n\nexport { HoverCard, HoverCardTrigger, HoverCardContent }\n"
10 | }
11 | ],
12 | "type": "components:ui"
13 | }
--------------------------------------------------------------------------------
/apps/www/content/docs/components/snippet.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Snippet
3 | description: Display a snippet of copyable code for the command line.
4 | component: true
5 | ---
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | {/* CLI */}
17 | Manual
18 |
19 |
20 |
21 | ```bash
22 | npx shadcn-ui@latest add snippet
23 | ```
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 | Copy and paste the following code into your project.
32 |
33 |
34 |
35 | Update the import paths to match your project setup.
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/hover-card-demo.tsx:
--------------------------------------------------------------------------------
1 | import { CalendarDays } from "lucide-react"
2 |
3 | import {
4 | Avatar,
5 | AvatarFallback,
6 | AvatarImage,
7 | } from "@/registry/default/ui/avatar"
8 | import { Button } from "@/registry/default/ui/button"
9 | import {
10 | HoverCard,
11 | HoverCardContent,
12 | HoverCardTrigger,
13 | } from "@/registry/default/ui/hover-card"
14 |
15 | export default function HoverCardDemo() {
16 | return (
17 |
18 |
19 | @nextjs
20 |
21 |
22 |
23 |
24 |
25 | VC
26 |
27 |
28 |
@nextjs
29 |
30 | The React Framework – created and maintained by @vercel.
31 |
32 |
33 | {" "}
34 |
35 | Joined December 2021
36 |
37 |
38 |
39 |
40 |
41 |
42 | )
43 | }
44 |
--------------------------------------------------------------------------------
/apps/www/content/docs/components/aspect-ratio.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Aspect Ratio
3 | description: Displays content within a desired ratio.
4 | component: true
5 | links:
6 | doc: https://www.radix-ui.com/docs/primitives/components/aspect-ratio
7 | api: https://www.radix-ui.com/docs/primitives/components/aspect-ratio#api-reference
8 | ---
9 |
10 |
11 |
12 | ## Installation
13 |
14 |
15 |
16 |
17 | {/* CLI */}
18 | Manual
19 |
20 |
21 |
22 | ```bash
23 | npx shadcn-ui@latest add aspect-ratio
24 | ```
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 | Install the following dependencies:
33 |
34 | ```bash
35 | npm install @radix-ui/react-aspect-ratio
36 | ```
37 |
38 | Copy and paste the following code into your project.
39 |
40 |
41 |
42 | Update the import paths to match your project setup.
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 | ## Usage
51 |
52 | ```tsx
53 | import Image from "next/image"
54 |
55 | import { AspectRatio } from "@/components/ui/aspect-ratio"
56 | ```
57 |
58 | ```tsx
59 |
64 | ```
65 |
--------------------------------------------------------------------------------
/apps/www/content/docs/components/gauge.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Gauge
3 | description: A circular visual for conveying a percentage.
4 | component: true
5 | ---
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | {/* CLI */}
17 | Manual
18 |
19 |
20 |
21 | ```bash
22 | npx shadcn-ui@latest add gauge
23 | ```
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 | Copy and paste the following code into your project.
32 |
33 |
34 |
35 | Update the import paths to match your project setup.
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/apps/www/public/registry/styles/default/popover.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "popover",
3 | "dependencies": [
4 | "@radix-ui/react-popover"
5 | ],
6 | "files": [
7 | {
8 | "name": "popover.tsx",
9 | "content": "\"use client\"\n\nimport * as React from \"react\"\nimport * as PopoverPrimitive from \"@radix-ui/react-popover\"\n\nimport { cn } from \"@/lib/utils\"\n\nconst Popover = PopoverPrimitive.Root\n\nconst PopoverTrigger = PopoverPrimitive.Trigger\n\nconst PopoverContent = React.forwardRef<\n React.ElementRef,\n React.ComponentPropsWithoutRef\n>(({ className, align = \"center\", sideOffset = 4, ...props }, ref) => (\n \n \n \n))\nPopoverContent.displayName = PopoverPrimitive.Content.displayName\n\nexport { Popover, PopoverTrigger, PopoverContent }\n"
10 | }
11 | ],
12 | "type": "components:ui"
13 | }
--------------------------------------------------------------------------------
/apps/www/content/docs/components/textarea.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Textarea
3 | description: Displays a form textarea or a component that looks like a textarea.
4 | component: true
5 | ---
6 |
7 |
8 |
9 | ## Installation
10 |
11 |
12 |
13 |
14 | {/* CLI */}
15 | Manual
16 |
17 |
18 |
19 | ```bash
20 | npx shadcn-ui@latest add textarea
21 | ```
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | Copy and paste the following code into your project.
30 |
31 |
32 |
33 | Update the import paths to match your project setup.
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 | ## Usage
42 |
43 | ```tsx
44 | import { Textarea } from "@/components/ui/textarea"
45 | ```
46 |
47 | ```tsx
48 |
49 | ```
50 |
51 | ## Examples
52 |
53 | ### Default
54 |
55 |
56 |
57 | ### Disabled
58 |
59 |
60 |
61 | ### With Label
62 |
63 |
64 |
65 | ### With Text
66 |
67 |
68 |
69 | ### With Button
70 |
71 |
72 |
73 | ### Form
74 |
75 |
76 |
--------------------------------------------------------------------------------
/apps/www/content/docs/components/toggle.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Toggle
3 | description: Displays a boolean value.
4 | component: true
5 | links:
6 | doc: https://www.radix-ui.com/docs/primitives/components/switch
7 | api: https://www.radix-ui.com/docs/primitives/components/switch#api-reference
8 | ---
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | {/* CLI */}
19 | Manual
20 |
21 |
22 |
23 | ```bash
24 | npx shadcn-ui@latest add toggle
25 | ```
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 | Install the following dependencies:
34 |
35 | ```bash
36 | npm install @radix-ui/react-switch
37 | ```
38 |
39 | Copy and paste the following code into your project.
40 |
41 |
42 |
43 | Update the import paths to match your project setup.
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 | ## Usage
52 |
53 | ```tsx
54 | import { Toggle } from "@/components/ui/toggle"
55 | ```
56 |
57 | ```tsx
58 |
59 | ```
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
--------------------------------------------------------------------------------
/apps/www/content/docs/components/hover-card.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Hover Card
3 | description: For sighted users to preview content available behind a link.
4 | component: true
5 | links:
6 | doc: https://www.radix-ui.com/docs/primitives/components/hover-card
7 | api: https://www.radix-ui.com/docs/primitives/components/hover-card#api-reference
8 | ---
9 |
10 |
11 |
12 | ## Installation
13 |
14 |
15 |
16 |
17 | {/* CLI */}
18 | Manual
19 |
20 |
21 |
22 | ```bash
23 | npx shadcn-ui@latest add hover-card
24 | ```
25 |
26 |
27 |
28 |
29 |
30 | Install the following dependencies:
31 |
32 | ```bash
33 | npm install @radix-ui/react-hover-card
34 | ```
35 |
36 |
37 |
38 | Copy and paste the following code into your project.
39 |
40 |
41 |
42 | Update the import paths to match your project setup.
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 | ## Usage
51 |
52 | ```tsx
53 | import {
54 | HoverCard,
55 | HoverCardContent,
56 | HoverCardTrigger,
57 | } from "@/components/ui/hover-card"
58 | ```
59 |
60 | ```tsx
61 |
62 | Hover
63 |
64 | The React Framework – created and maintained by @vercel.
65 |
66 |
67 | ```
68 |
--------------------------------------------------------------------------------
/apps/www/components/theme-component.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import { Index } from "@/__registry__"
5 |
6 | import { cn } from "@/lib/utils"
7 | import { useConfig } from "@/hooks/use-config"
8 | import { Icons } from "@/components/icons"
9 |
10 | interface ThemeComponentProps extends React.HTMLAttributes {
11 | name: string
12 | extractClassname?: boolean
13 | extractedClassNames?: string
14 | align?: "center" | "start" | "end"
15 | }
16 |
17 | export function ThemeComponent({ name, ...props }: ThemeComponentProps) {
18 | const [config] = useConfig()
19 |
20 | const Preview = React.useMemo(() => {
21 | const Component = Index[config.style][name]?.component
22 |
23 | if (!Component) {
24 | return (
25 |
26 | Component{" "}
27 |
28 | {name}
29 | {" "}
30 | not found in registry.
31 |
32 | )
33 | }
34 |
35 | return
36 | }, [name, config.style])
37 |
38 | return (
39 |
40 |
43 |
44 | Loading...
45 |
46 | }
47 | >
48 | {Preview}
49 |
50 |
51 | )
52 | }
53 |
--------------------------------------------------------------------------------
/apps/www/next.config.mjs:
--------------------------------------------------------------------------------
1 | import { createContentlayerPlugin } from "next-contentlayer"
2 |
3 | /** @type {import('next').NextConfig} */
4 | const nextConfig = {
5 | reactStrictMode: true,
6 | swcMinify: true,
7 | images: {
8 | remotePatterns: [
9 | {
10 | protocol: "https",
11 | hostname: "avatars.githubusercontent.com",
12 | },
13 | {
14 | protocol: "https",
15 | hostname: "images.unsplash.com",
16 | },
17 | ],
18 | },
19 | redirects() {
20 | return [
21 | {
22 | source: "/components",
23 | destination: "/docs/components/button",
24 | permanent: true,
25 | },
26 | {
27 | source: "/docs/components",
28 | destination: "/docs/components/button",
29 | permanent: true,
30 | },
31 | {
32 | source: "/examples",
33 | destination: "/examples/mail",
34 | permanent: false,
35 | },
36 | {
37 | source: "/docs/primitives/:path*",
38 | destination: "/docs/components/:path*",
39 | permanent: true,
40 | },
41 | {
42 | source: "/docs/forms",
43 | destination: "/docs/components/form",
44 | permanent: false,
45 | },
46 | {
47 | source: "/docs/forms/react-hook-form",
48 | destination: "/docs/components/form",
49 | permanent: false,
50 | },
51 | ]
52 | },
53 | }
54 |
55 | const withContentlayer = createContentlayerPlugin({
56 | // Additional Contentlayer config options
57 | })
58 |
59 | export default withContentlayer(nextConfig)
60 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/collapsible-demo.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import { ChevronsUpDown, Plus, X } from "lucide-react"
5 |
6 | import { Button } from "@/registry/default/ui/button"
7 | import {
8 | Collapsible,
9 | CollapsibleContent,
10 | CollapsibleTrigger,
11 | } from "@/registry/default/ui/collapsible"
12 |
13 | export default function CollapsibleDemo() {
14 | const [isOpen, setIsOpen] = React.useState(false)
15 |
16 | return (
17 |
22 |
23 |
24 | @peduarte starred 3 repositories
25 |
26 |
27 |
28 |
29 | Toggle
30 |
31 |
32 |
33 |
34 | @radix-ui/primitives
35 |
36 |
37 |
38 | @radix-ui/colors
39 |
40 |
41 | @stitches/react
42 |
43 |
44 |
45 | )
46 | }
47 |
--------------------------------------------------------------------------------
/apps/www/public/registry/themes/neutral.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "neutral",
3 | "label": "Neutral",
4 | "cssVars": {
5 | "light": {
6 | "background": "0 0% 100%",
7 | "foreground": "0 0% 3.9%",
8 | "card": "0 0% 100%",
9 | "card-foreground": "0 0% 3.9%",
10 | "popover": "0 0% 100%",
11 | "popover-foreground": "0 0% 3.9%",
12 | "primary": "0 0% 9%",
13 | "primary-foreground": "0 0% 98%",
14 | "secondary": "0 0% 96.1%",
15 | "secondary-foreground": "0 0% 9%",
16 | "muted": "0 0% 96.1%",
17 | "muted-foreground": "0 0% 45.1%",
18 | "accent": "0 0% 96.1%",
19 | "accent-foreground": "0 0% 9%",
20 | "destructive": "0 84.2% 60.2%",
21 | "destructive-foreground": "0 0% 98%",
22 | "border": "0 0% 89.8%",
23 | "input": "0 0% 89.8%",
24 | "ring": "0 0% 3.9%"
25 | },
26 | "dark": {
27 | "background": "0 0% 3.9%",
28 | "foreground": "0 0% 98%",
29 | "card": "0 0% 3.9%",
30 | "card-foreground": "0 0% 98%",
31 | "popover": "0 0% 3.9%",
32 | "popover-foreground": "0 0% 98%",
33 | "primary": "0 0% 98%",
34 | "primary-foreground": "0 0% 9%",
35 | "secondary": "0 0% 14.9%",
36 | "secondary-foreground": "0 0% 98%",
37 | "muted": "0 0% 14.9%",
38 | "muted-foreground": "0 0% 63.9%",
39 | "accent": "0 0% 14.9%",
40 | "accent-foreground": "0 0% 98%",
41 | "destructive": "0 62.8% 30.6%",
42 | "destructive-foreground": "0 0% 98%",
43 | "border": "0 0% 14.9%",
44 | "input": "0 0% 14.9%",
45 | "ring": "0 0% 83.1%"
46 | }
47 | }
48 | }
--------------------------------------------------------------------------------
/apps/www/registry/default/ui/tooltip.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import * as TooltipPrimitive from "@radix-ui/react-tooltip"
5 |
6 | import { cn } from "@/lib/utils"
7 |
8 | const Tooltip = React.forwardRef<
9 | React.ElementRef,
10 | React.ComponentPropsWithoutRef & {
11 | text: string | React.ReactNode
12 | }
13 | >(({ className, sideOffset = 5, text, children, ...props }, ref) => (
14 |
15 |
16 | {children}
17 |
18 |
27 | {text}
28 |
29 |
30 |
31 |
32 |
33 | ))
34 | Tooltip.displayName = TooltipPrimitive.Content.displayName
35 |
36 | export { Tooltip }
37 |
--------------------------------------------------------------------------------
/apps/www/registry/default/example/menu-checkboxes.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import { DropdownMenuCheckboxItemProps } from "@radix-ui/react-dropdown-menu"
5 |
6 | import { Button } from "@/registry/default/ui/button"
7 | import {
8 | DropdownMenuCheckboxItem,
9 | DropdownMenuLabel,
10 | Menu,
11 | MenuButton,
12 | MenuContainer,
13 | } from "@/registry/default/ui/menu"
14 |
15 | type Checked = DropdownMenuCheckboxItemProps["checked"]
16 |
17 | export default function DropdownMenuCheckboxes() {
18 | const [showStatusBar, setShowStatusBar] = React.useState(true)
19 | const [showActivityBar, setShowActivityBar] = React.useState(false)
20 | const [showPanel, setShowPanel] = React.useState(false)
21 |
22 | return (
23 |
24 | Open
25 |
26 | Appearance
27 |
31 | Status Bar
32 |
33 |
38 | Activity Bar
39 |
40 |
44 | Panel
45 |
46 |
47 |
48 | )
49 | }
50 |
--------------------------------------------------------------------------------
/apps/www/content/docs/components/checkbox.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Checkbox
3 | description: A control that allows the user to toggle between checked and not checked.
4 | component: true
5 | links:
6 | doc: https://www.radix-ui.com/docs/primitives/components/checkbox
7 | api: https://www.radix-ui.com/docs/primitives/components/checkbox#api-reference
8 | ---
9 |
10 |
11 |
12 | ## Installation
13 |
14 |
15 |
16 |
17 | {/* CLI */}
18 | Manual
19 |
20 |
21 |
22 | ```bash
23 | npx shadcn-ui@latest add checkbox
24 | ```
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 | Install the following dependencies:
33 |
34 | ```bash
35 | npm install @radix-ui/react-checkbox
36 | ```
37 |
38 | Copy and paste the following code into your project.
39 |
40 |
41 |
42 | Update the import paths to match your project setup.
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 | ## Usage
51 |
52 | ```tsx
53 | import { Checkbox } from "@/components/ui/checkbox"
54 | ```
55 |
56 | ```tsx
57 |
58 | ```
59 |
60 | ## Examples
61 |
62 | ### With text
63 |
64 |
65 |
66 | ### Disabled
67 |
68 |
69 |
70 | ### Form
71 |
72 |
73 |
74 |
75 |
--------------------------------------------------------------------------------
/apps/www/registry/default/ui/avatar.tsx:
--------------------------------------------------------------------------------
1 | "use client"
2 |
3 | import * as React from "react"
4 | import * as AvatarPrimitive from "@radix-ui/react-avatar"
5 |
6 | import { cn } from "@/lib/utils"
7 |
8 | const Avatar = React.forwardRef<
9 | React.ElementRef,
10 | React.ComponentPropsWithoutRef
11 | >(({ className, ...props }, ref) => (
12 |
20 | ))
21 | Avatar.displayName = AvatarPrimitive.Root.displayName
22 |
23 | const AvatarImage = React.forwardRef<
24 | React.ElementRef,
25 | React.ComponentPropsWithoutRef
26 | >(({ className, ...props }, ref) => (
27 |
32 | ))
33 | AvatarImage.displayName = AvatarPrimitive.Image.displayName
34 |
35 | const AvatarFallback = React.forwardRef<
36 | React.ElementRef,
37 | React.ComponentPropsWithoutRef
38 | >(({ className, ...props }, ref) => (
39 |
47 | ))
48 | AvatarFallback.displayName = AvatarPrimitive.Fallback.displayName
49 |
50 | export { Avatar, AvatarImage, AvatarFallback }
51 |
--------------------------------------------------------------------------------