# 9UI Documentation Beautiful, customizable components built with Base UI and Tailwind CSS. This is a curated set of components that you can customize to fit your style. You won't install it through npm - instead, you simply select the components you need and add them directly to your project. ## Getting Started ### Astro Setting up dark mode in your Astro project. **Create script to handle theme.** ```astro {5-28} title="src/pages/index.astro" --- import '../styles/global.css'; --- {/* content */} ``` **Create theme utilies.** Create a utility to handle theme management. ```ts title="src/utils/theme.ts" export type Theme = "light" | "dark" | "system" export function getTheme(): Theme { if (typeof localStorage !== "undefined" && localStorage.getItem("theme")) { return localStorage.getItem("theme") as Theme } return "system" } export function setTheme(theme: Theme) { const isDark = theme === "dark" || (theme === "system" && window.matchMedia("(prefers-color-scheme: dark)").matches) document.documentElement.classList[isDark ? "add" : "remove"]("dark") } ``` **Add theme toggle component.** ```tsx title="src/components/theme-toggle.tsx" import * as React from "react" import { MoonIcon, SunIcon } from "lucide-react" import { getTheme, setTheme, type Theme } from "../utils/theme" import { Button } from "./ui/button" export function ThemeToggle() { const [theme, setCurrentTheme] = React.useState(() => getTheme()) const toggleTheme = () => { const newTheme = theme === "dark" ? "light" : "dark" setTheme(newTheme) setCurrentTheme(newTheme) } return ( ) } ``` **Use the theme toggle in your app** You can now use the theme toggle component anywhere in your app. ```astro title="src/components/Header.astro" --- import { ThemeToggle } from "./theme-toggle" ---
``` --- ### Changelog Latest Updates ## 09/08/2025 - Added [`multiple select example`](/docs/components/select#multiple) - Added [`LLMs`](/docs/getting-started/llms) documentation page with AI-friendly formats - Added search functionality with command dialog (⌘K) - Added manual installation documentation - Updated Base UI to latest version (1.0.0-beta.2) - Fixed registry build to support shadcn monorepo setup ## 22/07/2025 - Added [`Navigation Menu`](/docs/components/navigation-menu) component - Added [`Number Field`](/docs/components/number-field) component - Added [`Pagination`](/docs/components/pagination) component - Added [`Toast`](/docs/components/toast) component ## 30/06/2025 - New version! 🎉 - Compatible with Tailwind 4 and React 19 ## 02/05/2025 - Added [`Checkbox Group`](/docs/components/checkbox-group) component - Added [`Meter`](/docs/components/meter) component ## 21/03/2025 - Added [`Toolbar`](/docs/components/toolbar) component - Added [`useRender`](https://base-ui.com/react/utils/use-render) hook to button component that overrides the default rendered element ## 23/02/2025 - Added examples for compose components [`Combobox`](/docs/components/combobox) and [`Date Picker`](/docs/components/date-picker) ## 18/02/2025 - Added [`Chart`](/docs/components/chart) component ## 08/02/2025 - Initial components release ## 31/12/2024 - Project started 🎉 --- ### Dark Mode Setting up dark mode in your project. [Next.js](/docs/getting-started/dark-mode/next) [Vite](/docs/getting-started/dark-mode/vite) [Remix](/docs/getting-started/dark-mode/remix) [Astro](/docs/getting-started/dark-mode/astro) --- ### Installation Get started with 9ui by installing dependencies and setting up your project. ### Quick Setup **Set up your project with 9ui configuration** Start by initializing your project with 9ui's custom configuration. This approach builds upon the [shadcn installation guide](https://ui.shadcn.com/docs/installation) but uses 9ui-specific settings. #### Danger Alert **Don't use the standard command. Instead, use our custom configuration below to ensure proper 9ui theme setup.** ```bash title="Terminal" npx shadcn@latest init https://9ui.dev/r/init.json ``` This command automatically installs the required dependencies, applies the 9ui theme configuration, and updates your `globals.css` file with the necessary styling. **Add the root wrapper to your layout** Add the `root` class to your app layout to ensure proper styling isolation and theme application. ```tsx {2} title="layout.tsx"
{children}
``` **Start using 9ui components** Your project is now ready! You can start installing and using 9ui components in your application. ### Manual Setup **Install required dependencies** Install the core dependencies needed for 9ui components to function properly. ```bash title="Terminal" npm install tw-animate-css @base-ui-components/react tailwind-merge clsx lucide-react class-variance-authority ``` **Set up utility functions** Create a utilities file that provides essential helper functions for component styling and class management. ```ts title="src/lib/utils.ts" import { clsx, type ClassValue } from "clsx" import { twMerge } from "tailwind-merge" export function cn(...inputs: ClassValue[]) { return twMerge(clsx(inputs)) } ``` **Configure your global styles** Add the 9ui theme configuration and styling to your global CSS file. This includes color variables, custom properties, and base styles. ```css title="globals.css" @import "tailwindcss"; @import "tw-animate-css"; @custom-variant dark (&:is(.dark *)); @theme inline { --font-sans: "Inter", ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; --font-mono: "Geist Mono", "ui-monospace", "SFMono-Regular", "Menlo", "Monaco", "Consolas", '"Liberation Mono"', '"Courier New"', "monospace"; --radius-sm: calc(var(--radius) - 4px); --radius-md: calc(var(--radius) - 2px); --radius-lg: var(--radius); --radius-xl: calc(var(--radius) + 2px); --color-background: var(--background); --color-foreground: var(--foreground); --color-card: var(--card); --color-card-foreground: var(--card-foreground); --color-popover: var(--popover); --color-popover-foreground: var(--popover-foreground); --color-primary: var(--primary); --color-primary-foreground: var(--primary-foreground); --color-secondary: var(--secondary); --color-secondary-foreground: var(--secondary-foreground); --color-muted: var(--muted); --color-muted-foreground: var(--muted-foreground); --color-accent: var(--accent); --color-accent-foreground: var(--accent-foreground); --color-destructive: var(--destructive); --color-destructive-foreground: var(--destructive-foreground); --color-danger: var(--danger); --color-danger-foreground: var(--danger-foreground); --color-danger-border: var(--danger-border); --color-warning: var(--warning); --color-warning-foreground: var(--warning-foreground); --color-warning-border: var(--warning-border); --color-info: var(--info); --color-info-foreground: var(--info-foreground); --color-info-border: var(--info-border); --color-success: var(--success); --color-success-foreground: var(--success-foreground); --color-success-border: var(--success-border); --color-border: var(--border); --color-input: var(--input); --color-ring: var(--ring); --color-chart-1: var(--chart-1); --color-chart-2: var(--chart-2); --color-chart-3: var(--chart-3); --color-chart-4: var(--chart-4); --color-chart-5: var(--chart-5); } :root { --radius: 0.5rem; --background: oklch(0.985 0 0); --foreground: oklch(0.141 0.005 285.823); --card: oklch(0.976 0.0005 143.188); --card-foreground: oklch(0.141 0.005 285.823); --popover: oklch(0.976 0.0005 143.188); --popover-foreground: oklch(0.141 0.005 285.823); --primary: oklch(0.141 0.005 285.823); --primary-foreground: oklch(0.985 0 0); --secondary: oklch(0.92 0.004 286.32); --secondary-foreground: oklch(0.37 0.013 285.805); --muted: oklch(0.944 0.0025 286.348); --muted-foreground: oklch(0.442 0.017 285.786); --accent: oklch(0.944 0.0025 286.348); --accent-foreground: oklch(0.141 0.005 285.823); --destructive: oklch(0.541 0.229 27.422); --destructive-foreground: oklch(0.985 0 0); --danger: oklch(0.9664 0.016568 16.2788); --danger-foreground: oklch(0.5799 0.23795071614349592 29.233885192342644); --danger-border: oklch(0.9332 0.0338 16.63); --warning: oklch(0.9904 0.0167 96.37); --warning-foreground: oklch(0.6692 0.1602 56.73); --warning-border: oklch(0.9448 0.0787 96.97); --info: oklch(0.9746 0.0129 244.25); --info-foreground: oklch(0.5626 0.1821 255.12); --info-border: oklch(0.9275 0.0322 265.82); --success: oklch(0.9797 0.023 158.94); --success-foreground: oklch(0.5507 0.1654 146.61); --success-border: oklch(0.9413 0.0781 158.88); --border: oklch(0.871 0.006 286.286); --input: oklch(0.967 0.001 286.375); --ring: oklch(0.752 0 0); --chart-1: oklch(0.585 0.23 261.348); --chart-2: oklch(0.675 0.207 149.396); --chart-3: oklch(0.527 0.277 302.123); --chart-4: oklch(0.676 0.218 44.36); --chart-5: oklch(0.541 0.229 27.422); } .dark { --background: oklch(0.141 0.005 285.823); --foreground: oklch(0.985 0 0); --card: oklch(0.176 0.0055 285.854); --card-foreground: oklch(0.985 0 0); --popover: oklch(0.176 0.0055 285.854); --popover-foreground: oklch(0.985 0 0); --primary: oklch(0.985 0 0); --primary-foreground: oklch(0.141 0.005 285.823); --secondary: oklch(0.21 0.006 285.885); --secondary-foreground: oklch(0.629 0.0155 286.003); --muted: oklch(0.242 0.006 285.959); --muted-foreground: oklch(0.552 0.016 285.938); --accent: oklch(0.242 0.006 285.959); --accent-foreground: oklch(0.985 0 0); --destructive: oklch(0.396 0.141 25.723); --destructive-foreground: oklch(0.985 0 0); --danger: oklch(0.1995 0.0639 23.01); --danger-foreground: oklch(0.7987 0.1158 17.83); --danger-border: oklch(0.2696 0.1029 25.45); --warning: oklch(0.2277 0.0509 113.29); --warning-foreground: oklch(0.8642 0.1416 92.19); --warning-border: oklch(0.2912 0.0635 109.77); --info: oklch(0.156 0.045 250.71); --info-foreground: oklch(0.6751 0.1529 258.33); --info-border: oklch(0.2622 0.0525 266.51); --success: oklch(0.2093 0.0487 158.25); --success-foreground: oklch(0.8622 0.169434 157.7642); --success-border: oklch(0.3161 0.0826 152.3); --border: oklch(0.322 0.0095 285.919); --input: oklch(0.21 0.006 285.885); --ring: oklch(0.542 0 0); --chart-1: oklch(0.585 0.23 261.348); --chart-2: oklch(0.577 0.174 149.642); --chart-3: oklch(0.593 0.277 303.111); --chart-4: oklch(0.676 0.218 44.36); --chart-5: oklch(0.577 0.245 27.325); } @layer base { * { border-color: var(--border); outline-color: var(--ring) 50%; scrollbar-width: thin; scrollbar-color: var(--border) transparent; } html { scroll-behavior: smooth; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; -webkit-tap-highlight-color: transparent; } html[data-base-ui-scroll-locked] { scroll-behavior: auto; } body { background-color: var(--background); color: var(--foreground); overscroll-behavior: none; } .root { isolation: isolate; min-height: 100vh; } ::-webkit-scrollbar { width: 4px; } ::-webkit-scrollbar-track { background: transparent; } ::-webkit-scrollbar-thumb { background: var(--border); border-radius: 4px; } } ``` **Set up import aliases** Configure TypeScript path mapping to enable clean `@/*` imports throughout your project. ```json title="tsconfig.json" { "compilerOptions": { "baseUrl": ".", "paths": { "@/*": ["./*"] } } } ``` **Add the root wrapper to your layout** Wrap your application content with the `root` class to ensure proper styling isolation and theme application. ```tsx {2} title="layout.tsx"
{children}
``` **Configure components.json (optional)** Optionally create a `components.json` file to enable shadcn CLI component installation with the correct paths and settings. ```json title="components.json" { "$schema": "https://ui.shadcn.com/schema.json", "rsc": false, "tsx": true, "tailwind": { "config": "", "css": "src/styles/globals.css", "baseColor": "neutral", "cssVariables": true, "prefix": "" }, "aliases": { "components": "@/components", "utils": "@/lib/utils", "ui": "@/components/ui", "lib": "@/lib", "hooks": "@/hooks" }, "iconLibrary": "lucide" } ``` **Start using 9ui components** Your project is now fully configured! You can start installing and using 9ui components in your application. ## Icon Libraries 9ui components use [`lucide-react`](https://lucide.dev/) as the default icon library, which provides a comprehensive set of beautiful, consistent icons. ### Alternative Icon Libraries For additional icon options, consider these popular alternatives: - **[Monicon](https://monicon-docs.vercel.app/)** - Access over 200,000 icons from various popular libraries in a unified interface - **[pqoqubbw/icons](https://icons.pqoqubbw.dev/)** - A curated collection of animated icons for enhanced user interactions These libraries can be used alongside or instead of lucide-react depending on your project's specific needs. --- ### Introduction Beautiful, customizable components built with Base UI and Tailwind CSS This isn’t a standard component library. It’s a curated set of components that you can customize to fit your style. You won’t install it through npm. Instead, you simply select the components you need and add them directly to your project. Once included, each component is fully adaptable, letting you fine-tune it to meet your exact requirements. ## Why Base UI? [Base UI](https://base-ui.com) offers unstyled, headless components with built-in accessibility. This makes it perfect for 9ui, allowing us to integrate Tailwind CSS without forcing any default design. It’s a clean foundation that stays lightweight, letting you adapt every detail to fit your exact needs. ## Is it production ready? It’s built on Base UI, which is in alpha, so there may be changes in the future. However, I'm actively testing and refining it. If you’re comfortable with an early-stage library and ready to adapt as it matures, you can use it in production. Just ensure you perform your own checks and stay updated with any changes. You can follow the development and updates of Base UI [here](https://base-ui.com/react/overview/releases). ## Why it's called 9ui? The number **"9"** looks like the letter **"g"**. If you read **"9"** as **"g"**, it becomes **"gui"**, which stands for **"Graphical User Interface"**. ## Thank you First of all, I would like to thank [shadcn](https://ui.shadcn.com) for the inspiration. I am grateful to everyone who uses 9ui, provides feedback, and helps me improve it. Thank you! ## FAQ Yes. It is free and open source. You can use it in your projects without any costs. I would love to see your projects using it. Yes. It is a design system that allows you to create beautiful and customizable components. You can use it with all the frameworks that support React. Such as Next.js, Remix, Astro, Gatsby, etc. --- ### LLMs AI-friendly documentation for 9ui This page provides AI-friendly documentation formats that can be used by large language models (LLMs) to better understand and work with 11ui components. ## Available Formats We provide two different formats of documentation optimized for AI consumption: ### llms.txt A concise index format with links to individual component documentation. This format is ideal for: - Quick reference and component discovery - Integration with AI tools that need structured navigation - Systems that work better with linked content [See llms.txt](/llms.txt) ### llms-full.txt A comprehensive format containing the complete documentation for all components in a single file. This format is ideal for: - AI models that need full context in a single document - Local processing and analysis - Systems that work better with embedded content [See llms-full.txt](/llms-full.txt) ## Usage These files are automatically generated from the same MDX source files used for the website documentation, ensuring consistency and accuracy. The documentation includes: - Component descriptions and use cases - Installation instructions - Code examples and demos Both formats are updated automatically when the documentation is built, so they always reflect the latest component information. --- ### Next.js Setting up dark mode in your Next.js project. **Install .** ```bash title="Terminal" npm install next-themes ``` **Create .** ```tsx title="providers/theme-provider.tsx" "use client" import { ThemeProvider as NextThemesProvider } from "next-themes" export function ThemeProvider({ children, ...props }: React.ComponentProps) { return {children} } ``` **Wrap your root layout with the provider.** ```tsx {1,12-19} title="app/layout.tsx" import { ThemeProvider } from "@/providers/theme-provider" export default function RootLayout({ children, }: { children: React.ReactNode }) { return ( {children} ) } ``` **Add theme toggle component.** --- ### Remix Setting up dark mode in your Remix project. **Update tailwind.css file.** This will allow you to use `dark` class to apply dark mode styles. ```css {1-2} title="tailwind.css" .dark, :root[class~="dark"] { /* Your dark mode styles */ } ``` **Install .** ```bash title="Terminal" npm install remix-themes ``` **Create session storage.** ```tsx title="sessions.server.tsx" import { createCookieSessionStorage } from "@remix-run/node" import { createThemeSessionResolver } from "remix-themes" const sessionStorage = createCookieSessionStorage({ cookie: { name: "__remix-themes", // domain: 'remix.run', path: "/", httpOnly: true, sameSite: "lax", secrets: ["s3cr3t"], // secure: true, }, }) export const themeSessionResolver = createThemeSessionResolver(sessionStorage) ``` **Create action to set theme.** ```tsx title="routes/action.set-theme.tsx" import { createThemeAction } from "remix-themes" import { themeSessionResolver } from "../sessions.server" export const action = createThemeAction(themeSessionResolver) ``` **Add theme provider to root layout.** ```tsx {18-23, 25-32, 35, 36, 38, 42, 43} title="root.tsx" import "./tailwind.css" import { LoaderFunctionArgs } from "@remix-run/node" import { Links, LiveReload, Meta, Outlet, Scripts, ScrollRestoration, useLoaderData, } from "@remix-run/react" import clsx from "clsx" import { PreventFlashOnWrongTheme, ThemeProvider, useTheme } from "remix-themes" import { themeSessionResolver } from "./sessions.server" export async function loader({ request }: LoaderFunctionArgs) { const { getTheme } = await themeSessionResolver(request) return { theme: getTheme(), } } export default function AppWithProviders() { const data = useLoaderData() return ( ) } export function App() { const data = useLoaderData() const [theme] = useTheme() return ( ) } ``` **Add theme toggle component.** ```tsx title="components/theme-toggle.tsx" import * as React from "react" import { MoonIcon, SunIcon } from "lucide-react" import { Theme, useTheme } from "remix-themes" import { Button } from "./ui/button" export function ModeToggle() { const [theme, setTheme] = useTheme() const toggleTheme = React.useCallback(() => { setTheme(theme === Theme.LIGHT ? Theme.DARK : Theme.LIGHT) }, [theme, setTheme]) return ( ) } ``` --- ### Roadmap What's coming next We plan to add more components and features as Base UI continues to evolve, and 9ui will grow right alongside it. Development isn’t just about adding new components. We’ll also improve existing ones and enhance their usability over time. User feedback is incredibly valuable to us. To share your ideas or issues, feel free to open an issue on [GitHub](https://github.com/borabaloglu/9ui/issues) or reach out to [@borabalogluu](https://x.com/borabalogluu) on X. There’s no strict deadline, but we do have features in the pipeline. To follow our active development, check out [roadmap](https://9ui.featurebase.app/roadmap) for real-time updates. --- ### Theming Using CSS variables to customize the theme. ## Color Tokens The theme system is built with semantic color tokens that represent specific use cases rather than literal colors. Here are the main color tokens and their use cases: ### Base Colors - `background` / `foreground`: Primary background and text colors - `card` / `card-foreground`: Used for card components and their content - `popover` / `popover-foreground`: For popover, dropdown, dialog, etc. ### Interactive Elements - `primary` / `primary-foreground`: Main brand color, used for primary actions - `secondary` / `secondary-foreground`: Less prominent actions and elements - `muted` / `muted-foreground`: Subdued elements like secondary text - `accent` / `accent-foreground`: Highlighted or featured elements - `destructive` / `destructive-foreground`: Dangerous or destructive actions ### Status Colors - `danger` / `danger-foreground` / `danger-border`: Error states and critical alerts - `warning` / `warning-foreground` / `warning-border`: Warning messages and alerts - `info` / `info-foreground` / `info-border`: Informational messages - `success` / `success-foreground` / `success-border`: Success states and confirmations ### Utility Colors - `border`: Default border color - `input`: Form input borders - `ring`: Focus ring color for interactive elements ### Chart Colors - `chart-1` through `chart-5`: Predefined colors for data visualizations ## Why OKLCH? 1. **Wider Color Gamut**: OKLCH can represent a broader range of colors 2. **Better Color Interpolation**: Smoother transitions and animations 3. **Perceptual Uniformity**: More natural-looking color variations ## Customizing Colors ### Adding New Colors To add new colors to your theme: **Add the CSS variables in ** ```css title="globals.css" :root { /* Existing colors */ --custom-color: oklch(0.627 0.265 303.9); --custom-color-foreground: oklch(0.977 0.014 308.299); } .dark { /* Existing dark mode colors */ --custom-color: oklch(0.627 0.265 303.9); --custom-color-foreground: oklch(0.977 0.014 308.299); } @theme inline { /* Existing colors */ --color-custom-color: var(--custom-color); --color-custom-color-foreground: var(--custom-color-foreground); } ``` ### Using Custom Colors After adding new colors, you can use them with Tailwind's utility classes: ```jsx title="Usage"
Custom colored content
``` --- ### Vite Setting up dark mode in your Vite project. **Create a theme provider component.** ```tsx title="providers/theme-provider.tsx" import { createContext, useContext, useEffect, useState } from "react" type Theme = "dark" | "light" | "system" type ThemeProviderProps = { children: React.ReactNode defaultTheme?: Theme storageKey?: string } type ThemeProviderState = { theme: Theme setTheme: (theme: Theme) => void } const ThemeProviderContext = createContext( undefined ) export function ThemeProvider({ children, defaultTheme = "system", storageKey = "vite-ui-theme", ...props }: ThemeProviderProps) { const [theme, setTheme] = useState( () => (localStorage.getItem(storageKey) as Theme) || defaultTheme ) useEffect(() => { const root = window.document.documentElement root.classList.remove("light", "dark") if (theme === "system") { const systemTheme = window.matchMedia("(prefers-color-scheme: dark)") .matches ? "dark" : "light" root.classList.add(systemTheme) return } root.classList.add(theme) }, [theme]) useEffect(() => { const mediaQuery = window.matchMedia("(prefers-color-scheme: dark)") // Add listener for system theme changes const handleChange = () => { if (theme === "system") { const root = window.document.documentElement root.classList.remove("light", "dark") root.classList.add(mediaQuery.matches ? "dark" : "light") } } mediaQuery.addEventListener("change", handleChange) return () => mediaQuery.removeEventListener("change", handleChange) }, [theme]) const value = { theme, setTheme: (theme: Theme) => { localStorage.setItem(storageKey, theme) setTheme(theme) }, } return ( {children} ) } export const useTheme = () => { const context = useContext(ThemeProviderContext) if (context === undefined) throw new Error("useTheme must be used within a ThemeProvider") return context } ``` **Wrap your app with the provider.** ```tsx {1,5-7} title="main.tsx" import { ThemeProvider } from "@/providers/theme-provider" function App() { return ( {/* Your app content */} ) } export default App ``` **Add theme toggle component.** ```tsx title="components/theme-toggle.tsx" import * as React from "react" import { MoonIcon, SunIcon } from "lucide-react" import { Button } from "@/components/ui/button" import { useTheme } from "@/providers/theme-provider" export default function ThemeToggle() { const { setTheme, theme } = useTheme() const toggleTheme = React.useCallback(() => { setTheme(theme === "dark" ? "light" : "dark") }, [theme, setTheme]) return ( ) } ``` --- ## Components ### Accordion A collapsible section to show or hide content. ### Example ```tsx import { Accordion, AccordionContent, AccordionItem, AccordionTrigger, } from "@/components/ui/accordion" export default function AccordionDemo() { return ( Is it an accordion? Yes, it is an accordion. It is a component that allows you to collapse and expand content. Is it animated? Yes, it is animated. It is a component that allows you to collapse and expand content. Is it customizable? Yes, it is customizable. It is a component that allows you to collapse and expand content. ) } ``` ## Installation ```bash title="Terminal" npx shadcn@latest add https://9ui.dev/r/accordion.json ``` **Copy and paste the following code into your project.** ## Usage ```tsx title="Imports" import { Accordion, AccordionContent, AccordionItem, AccordionTrigger, } from "@/components/ui/accordion" ``` ```tsx title="Anatomy" ``` --- ### Alert Used to highlight important messages. ### Example ```tsx import { AlertTriangleIcon } from "lucide-react" import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert" export default function AlertDemo() { return ( No Internet Connection Please check your internet connection and try again. ) } ``` ## Installation ```bash title="Terminal" npx shadcn@latest add https://9ui.dev/r/alert.json ``` **Copy and paste the following code into your project.** ## Usage ```tsx title="Imports" import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert" ``` ```tsx title="Anatomy" ``` ## Examples ### Success ### Example ```tsx import { CircleCheckIcon } from "lucide-react" import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert" export default function AlertSuccess() { return ( Your account has been created You can now sign in with your new account credentials. ) } ``` --- ### Info ### Example ```tsx import { InfoIcon } from "lucide-react" import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert" export default function AlertInfo() { return ( Browser Update Available A new version of your browser is available. Updating your browser ensures better security and performance. ) } ``` --- ### Warning ### Example ```tsx import { AlertTriangleIcon } from "lucide-react" import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert" export default function AlertWarning() { return ( Your session is about to expire You will be logged out in 5 minutes. Please save your work and refresh the page. ) } ``` --- ### Danger ### Example ```tsx import { XCircleIcon } from "lucide-react" import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert" export default function AlertDanger() { return ( Your subscription has been canceled Your access to premium features will end in 30 days. You can reactivate your subscription anytime. ) } ``` --- ### With action ### Example ```tsx import { AlertTriangleIcon } from "lucide-react" import { Alert, AlertTitle } from "@/components/ui/alert" import { Button } from "@/components/ui/button" export default function AlertWithAction() { return ( No Internet Connection ) } ``` --- ### Alert Dialog A modal dialog for critical messages or confirmation actions. ### Example ```tsx import { AlertDialog, AlertDialogClose, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger, } from "@/components/ui/alert-dialog" import { Button } from "@/components/ui/button" export default function AlertDialogDemo() { return ( ( )} /> Are you sure? This action cannot be undone. Your post will be permanently deleted. ( )} /> ) } ``` ## Installation ```bash title="Terminal" npx shadcn@latest add https://9ui.dev/r/alert-dialog.json ``` **Copy and paste the following code into your project.** ## Usage ```tsx title="Imports" import { AlertDialog, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger, } from "@/components/ui/alert-dialog" ``` ```tsx title="Anatomy" ``` --- ### Aspect Ratio Allows you to display an element at a specific aspect ratio. ### Example ```tsx import { AspectRatio } from "@/components/ui/aspect-ratio" export default function AspectRatioDemo() { return (
Content
) } ``` ## Installation ```bash title="Terminal" npx shadcn@latest add https://9ui.dev/r/aspect-ratio.json ``` **Copy and paste the following code into your project.** ## Usage ```tsx title="Imports" import { AspectRatio } from "@/components/ui/aspect-ratio" ``` ```tsx title="Anatomy" ``` --- ### Avatar Displays an avatar with a fallback. ### Example ```tsx import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar" export default function AvatarDemo() { return ( BB ) } ``` ## Installation ```bash title="Terminal" npx shadcn@latest add https://9ui.dev/r/avatar.json ``` **Copy and paste the following code into your project.** ## Usage ```tsx title="Imports" import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar" ``` ```tsx title="Anatomy" ``` ## Examples ### Sizes ### Example ```tsx import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar" export default function AvatarSizes() { return (
BB BB BB
) } ``` --- ### With Fallback ### Example ```tsx import { Avatar, AvatarFallback } from "@/components/ui/avatar" export default function AvatarWithFallback() { return ( BB ) } ``` --- ### Badge Displays a badge for labeling or highlighting content. ### Example ```tsx import { Badge } from "@/components/ui/badge" export default function BadgeDemo() { return Badge } ``` ## Installation ```bash title="Terminal" npx shadcn@latest add https://9ui.dev/r/badge.json ``` **Copy and paste the following code into your project.** ## Usage ```tsx title="Imports" import { Badge } from "@/components/ui/badge" ``` ```tsx title="Anatomy" ``` ## Examples ### Outline ### Example ```tsx import { Badge } from "@/components/ui/badge" export default function BadgeOutline() { return Outline } ``` --- ### Secondary ### Example ```tsx import { Badge } from "@/components/ui/badge" export default function BadgeSecondary() { return Secondary } ``` --- ### Success ### Example ```tsx import { Badge } from "@/components/ui/badge" export default function BadgeSuccess() { return Success } ``` --- ### Warning ### Example ```tsx import { Badge } from "@/components/ui/badge" export default function BadgeWarning() { return Warning } ``` --- ### Info ### Example ```tsx import { Badge } from "@/components/ui/badge" export default function BadgeInfo() { return Info } ``` --- ### Danger ### Example ```tsx import { Badge } from "@/components/ui/badge" export default function BadgeDanger() { return Danger } ``` --- ### Breadcrumbs Displays a navigation path for better context. ### Example ```tsx import { Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, } from "@/components/ui/breadcrumbs" import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu" export default function BreadcrumbsDemo() { return ( Home Toggle menu Documentation Themes GitHub Components Breadcrumb ) } ``` ## Installation ```bash title="Terminal" npx shadcn@latest add https://9ui.dev/r/breadcrumbs.json ``` **Copy and paste the following code into your project.** ## Usage ```tsx title="Imports" import { Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, } from "@/components/ui/breadcrumbs" ``` ```tsx title="Anatomy" ``` ## Examples ### Custom Separator ### Example ```tsx import { SlashIcon } from "lucide-react" import { Breadcrumb, BreadcrumbEllipsis, BreadcrumbItem, BreadcrumbLink, BreadcrumbList, BreadcrumbPage, BreadcrumbSeparator, } from "@/components/ui/breadcrumbs" import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, } from "@/components/ui/dropdown-menu" export default function BreadcrumbsCustomSeparator() { return ( Home Toggle menu Documentation Themes GitHub Components Breadcrumb ) } ``` --- ### Button Displays a button for user interaction. ### Example ```tsx import { Button } from "@/components/ui/button" export default function ButtonDemo() { return } ``` ## Installation ```bash title="Terminal" npx shadcn@latest add https://9ui.dev/r/button.json ``` **Copy and paste the following code into your project.** ## Usage ```tsx title="Imports" import { Button } from "@/components/ui/button" ``` ```tsx title="Anatomy" ) } ``` --- ### With Icon ### Example ```tsx import { PencilIcon } from "lucide-react" import { Button } from "@/components/ui/button" export default function ButtonIcon() { return ( ) } ``` --- ### Secondary ### Example ```tsx import { Button } from "@/components/ui/button" export default function ButtonSecondary() { return } ``` --- ### Outline ### Example ```tsx import { Button } from "@/components/ui/button" export default function ButtonOutline() { return } ``` --- ### Ghost ### Example ```tsx import { Button } from "@/components/ui/button" export default function ButtonGhost() { return } ``` --- ### Link ### Example ```tsx import { Button } from "@/components/ui/button" export default function ButtonLink() { return } ``` --- ### Destructive ### Example ```tsx import { Button } from "@/components/ui/button" export default function ButtonDestructive() { return } ``` --- ### Loading ### Example ```tsx import { Loader2Icon } from "lucide-react" import { Button } from "@/components/ui/button" export default function ButtonLoading() { return ( ) } ``` --- ### Calendar Provides a visual interface for date selection. ### Example ```tsx import { Calendar } from "@/components/ui/calendar" export default function CalendarDemo() { return } ``` ## Installation ```bash title="Terminal" npx shadcn@latest add https://9ui.dev/r/calendar.json ``` **Install dependencies** ```bash title="Terminal" npm install react-day-picker ``` **Copy and paste the following code into your project.** ## Usage ```tsx title="Imports" import { Calendar } from "@/components/ui/calendar" ``` ```tsx title="Anatomy" ``` ## Examples ### Single Date ### Example ```tsx "use client" import { useState } from "react" import { Calendar } from "@/components/ui/calendar" export default function CalendarSingle() { const [selectedDate, setSelectedDate] = useState(undefined) return ( ) } ``` --- ### Multiple Dates ### Example ```tsx "use client" import { useState } from "react" import { Calendar } from "@/components/ui/calendar" export default function CalendarMultiple() { const [selectedDates, setSelectedDates] = useState( undefined ) return ( ) } ``` --- ### Date Range ### Example ```tsx "use client" import { useState } from "react" import { DateRange } from "react-day-picker" import { Calendar } from "@/components/ui/calendar" export default function CalendarRange() { const [range, setRange] = useState(undefined) return ( ) } ``` --- ### Disabled ### Example ```tsx "use client" import { useState } from "react" import { Calendar } from "@/components/ui/calendar" export default function CalendarDisabled() { const [selectedDate, setSelectedDate] = useState(undefined) return ( date < new Date()} selected={selectedDate} onSelect={setSelectedDate} /> ) } ``` --- ### Card Used to group and present information in a structured box. ### Example ```tsx import Image from "next/image" import { LinkIcon, SendIcon } from "lucide-react" import { toast } from "sonner" import { Button } from "@/components/ui/button" import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, } from "@/components/ui/card" import { Input } from "@/components/ui/input" export default function CardDemo() { return ( Invite Team Members Invite your team members to join your workspace.

You can invite up to 10 team members. You have 8 invites left.

Invited Members

Avatar

Karen Smith

karen@9.ui

Avatar

Chris Williams

chris@9.ui

) } ``` ## Installation ```bash title="Terminal" npx shadcn@latest add https://9ui.dev/r/card.json ``` **Copy and paste the following code into your project.** ## Usage ```tsx title="Imports" import { Card, CardAction, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, } from "@/components/ui/card" ``` ```tsx title="Anatomy" ``` ## Examples ### With image ### Example ```tsx import Image from "next/image" import { Button } from "@/components/ui/button" import { Card, CardDescription, CardFooter, CardHeader, CardTitle, } from "@/components/ui/card" export default function CardWithImage() { return (
Blog Image
What is 9ui? Deep dive into the 9ui components and learn how to use them in your own projects.
) } ``` --- ### Carousel A slider to display multiple items in a scrollable view. ### Example ```tsx import { AspectRatio } from "@/components/ui/aspect-ratio" import { Carousel, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious, } from "@/components/ui/carousel" const slides = [1, 2, 3, 4, 5] export default function CarouselDemo() { return (
{slides.map((slide) => (
{slide}
))}
) } ``` ## Installation ```bash title="Terminal" npx shadcn@latest add https://9ui.dev/r/carousel.json ``` **Install dependencies** ```bash title="Terminal" npm install embla-carousel-react embla-carousel ``` **Copy and paste the following code into your project.** ## Usage ```tsx title="Imports" import { Carousel, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious, } from "@/components/ui/carousel" ``` ```tsx title="Anatomy" ``` ## Examples ### Vertical ### Example ```tsx import { AspectRatio } from "@/components/ui/aspect-ratio" import { Carousel, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious, } from "@/components/ui/carousel" const slides = [1, 2, 3, 4, 5] export default function CarouselVertical() { return (
{slides.map((slide) => (
{slide}
))}
) } ``` --- ### Multiple ### Example ```tsx import { AspectRatio } from "@/components/ui/aspect-ratio" import { Carousel, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious, } from "@/components/ui/carousel" const slides = [1, 2, 3, 4, 5] export default function CarouselMultiple() { return (
{slides.map((slide) => (
{slide}
))}
) } ``` --- ### Looped ### Example ```tsx import { AspectRatio } from "@/components/ui/aspect-ratio" import { Carousel, CarouselContent, CarouselItem, CarouselNext, CarouselPrevious, } from "@/components/ui/carousel" const slides = [1, 2, 3, 4, 5] export default function CarouselLooped() { return (
{slides.map((slide) => (
{slide}
))}
) } ``` --- ### Thumbnail ### Example ```tsx import { useState } from "react" import Image from "next/image" import { AspectRatio } from "@/components/ui/aspect-ratio" import { Carousel, CarouselApi, CarouselContent, CarouselItem, } from "@/components/ui/carousel" import { cn } from "@/lib/utils" const slides = [ "https://images.pexels.com/photos/1616403/pexels-photo-1616403.jpeg?auto=compress&cs=tinysrgb&w=450&h=800&dpr=2", "https://images.pexels.com/photos/1293120/pexels-photo-1293120.jpeg?auto=compress&cs=tinysrgb&w=450&h=800&dpr=2", "https://images.pexels.com/photos/1103970/pexels-photo-1103970.jpeg?auto=compress&cs=tinysrgb&w=450&h=800&dpr=2", "https://images.pexels.com/photos/2011824/pexels-photo-2011824.jpeg?auto=compress&cs=tinysrgb&w=450&h=800&dpr=2", "https://images.pexels.com/photos/2471235/pexels-photo-2471235.jpeg?auto=compress&cs=tinysrgb&w=450&h=800&dpr=2", ] export default function CarouselThumbnail() { const [api, setApi] = useState() const [selectedIndex, setSelectedIndex] = useState(0) api?.on("select", () => { setSelectedIndex(api?.selectedScrollSnap() ?? 0) }) return (
{slides.map((slide) => ( Carousel slide ))}
{slides.map((slide, index) => ( ))}
) } ``` --- ### Chart A visual representation of data in various formats. ### Example ```tsx "use client" import { Bar, BarChart, CartesianGrid, XAxis } from "recharts" import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, } from "@/components/ui/card" import { ChartConfig, ChartContainer, ChartTooltip, ChartTooltipContent, } from "@/components/ui/chart" const chartData = [ { month: "Jan", revenue: 1500 }, { month: "Feb", revenue: 3200 }, { month: "Mar", revenue: 2900 }, { month: "Apr", revenue: 2100 }, { month: "May", revenue: 4000 }, { month: "Jun", revenue: 3700 }, { month: "Jul", revenue: 4300 }, { month: "Aug", revenue: 4900 }, { month: "Sep", revenue: 4700 }, { month: "Oct", revenue: 5200 }, { month: "Nov", revenue: 6000 }, { month: "Dec", revenue: 7200 }, ] const chartConfig = { revenue: { label: "Revenue", color: "var(--chart-2)", }, expenses: { label: "Expenses", color: "var(--chart-3)", }, } satisfies ChartConfig export default function ChartDemo() { const totalRevenue = chartData.reduce((sum, item) => sum + item.revenue, 0) const averageRevenue = totalRevenue / chartData.length const highestRevenue = Math.max(...chartData.map((item) => item.revenue)) return ( Monthly Revenue Performance overview for 2024 } />
Total Revenue: ${totalRevenue.toLocaleString()}
Monthly Average: $ {averageRevenue.toLocaleString(undefined, { maximumFractionDigits: 0, })}
Highest Month: ${highestRevenue.toLocaleString()}
) } ``` ## About The Chart is built on top of [`recharts`](https://recharts.org), which is a React component library for building charts. ## Installation ```bash title="Terminal" npx shadcn@latest add https://9ui.dev/r/chart.json ``` **Install the following dependencies:** ```bash npm install recharts ``` **Copy and paste the following code into your project.** ## Examples ### Area Chart ### Example ```tsx "use client" import { TrendingUpIcon } from "lucide-react" import { Area, AreaChart, CartesianGrid, XAxis } from "recharts" import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, } from "@/components/ui/card" import { ChartConfig, ChartContainer, ChartTooltip, ChartTooltipContent, } from "@/components/ui/chart" const chartData = [ { month: "Jan", revenue: 1500 }, { month: "Feb", revenue: 3200 }, { month: "Mar", revenue: 2900 }, { month: "Apr", revenue: 2100 }, { month: "May", revenue: 4000 }, { month: "Jun", revenue: 3700 }, { month: "Jul", revenue: 4300 }, { month: "Aug", revenue: 4900 }, { month: "Sep", revenue: 4700 }, { month: "Oct", revenue: 5200 }, { month: "Nov", revenue: 6000 }, { month: "Dec", revenue: 7200 }, ] const chartConfig = { revenue: { label: "Revenue", color: "var(--chart-1)", }, } satisfies ChartConfig export default function ChartAreaDemo() { const totalRevenue = chartData.reduce((sum, item) => sum + item.revenue, 0) const averageRevenue = totalRevenue / chartData.length const lastMonthGrowth = ((chartData[11].revenue - chartData[10].revenue) / chartData[10].revenue) * 100 return ( Monthly Revenue Trend Performance overview for 2024 value.slice(0, 3)} /> } />
Total Revenue: ${totalRevenue.toLocaleString()}
Monthly Average: $ {averageRevenue.toLocaleString(undefined, { maximumFractionDigits: 0, })}
Month-over-month growth: {lastMonthGrowth.toFixed(1)}%
) } ``` ### Bar Chart ### Example ```tsx "use client" import { TrendingUpIcon } from "lucide-react" import { Bar, BarChart, CartesianGrid, Legend, XAxis } from "recharts" import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, } from "@/components/ui/card" import { ChartConfig, ChartContainer, ChartTooltip, ChartTooltipContent, } from "@/components/ui/chart" const chartData = [ { month: "Jan", revenue: 1500, expenses: 1200 }, { month: "Feb", revenue: 3200, expenses: 2800 }, { month: "Mar", revenue: 2900, expenses: 2500 }, { month: "Apr", revenue: 2100, expenses: 1900 }, { month: "May", revenue: 4000, expenses: 3500 }, { month: "Jun", revenue: 3700, expenses: 3200 }, ] const chartConfig = { revenue: { label: "Revenue", color: "var(--chart-1)", }, expenses: { label: "Expenses", color: "var(--chart-3)", }, } satisfies ChartConfig export default function ChartBarDemo() { const totalRevenue = chartData.reduce((sum, item) => sum + item.revenue, 0) const totalExpenses = chartData.reduce((sum, item) => sum + item.expenses, 0) const netProfit = totalRevenue - totalExpenses const profitMargin = (netProfit / totalRevenue) * 100 return ( Revenue vs Expenses First half of 2024 value.slice(0, 3)} /> } />
Net Profit: ${netProfit.toLocaleString()}
Profit Margin: {profitMargin.toFixed(1)}%
Total Expenses: ${totalExpenses.toLocaleString()}
) } ``` ### Line Chart ### Example ```tsx "use client" import { CartesianGrid, Legend, Line, LineChart, XAxis } from "recharts" import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, } from "@/components/ui/card" import { ChartConfig, ChartContainer, ChartTooltip, ChartTooltipContent, } from "@/components/ui/chart" const chartData = [ { month: "Jan", users: 100, activeUsers: 80, newUsers: 20 }, { month: "Feb", users: 120, activeUsers: 90, newUsers: 30 }, { month: "Mar", users: 150, activeUsers: 100, newUsers: 50 }, { month: "Apr", users: 200, activeUsers: 140, newUsers: 60 }, { month: "May", users: 250, activeUsers: 180, newUsers: 70 }, { month: "Jun", users: 300, activeUsers: 220, newUsers: 80 }, ] const chartConfig = { users: { label: "Total Users", color: "var(--chart-1)", }, activeUsers: { label: "Active Users", color: "var(--chart-2)", }, newUsers: { label: "New Users", color: "var(--chart-3)", }, } satisfies ChartConfig export default function ChartLineDemo() { const totalUsers = chartData[chartData.length - 1].users const totalActiveUsers = chartData[chartData.length - 1].activeUsers const userGrowth = ((chartData[5].users - chartData[0].users) / chartData[0].users) * 100 const activeUsersRate = (totalActiveUsers / totalUsers) * 100 return ( User Growth User metrics for first half of 2024 value.slice(0, 3)} /> } />
Total Users: {totalUsers.toLocaleString()}
Active Users Rate: {activeUsersRate.toFixed(1)}%
6-Month Growth: {userGrowth.toFixed(1)}%
) } ``` ### Pie Chart ### Example ```tsx "use client" import { Cell, Legend, Pie, PieChart } from "recharts" import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, } from "@/components/ui/card" import { ChartConfig, ChartContainer, ChartTooltip, ChartTooltipContent, } from "@/components/ui/chart" const chartData = [ { category: "Sales", amount: 4000, fill: "var(--chart-1)" }, { category: "Marketing", amount: 3000, fill: "var(--chart-2)" }, { category: "IT", amount: 2000, fill: "var(--chart-3)" }, { category: "HR", amount: 1000, fill: "var(--chart-4)" }, { category: "Operations", amount: 1000, fill: "var(--chart-5)" }, ] const chartConfig = { sales: { label: "Sales", color: "var(--chart-1)", }, marketing: { label: "Marketing", color: "var(--chart-2)", }, it: { label: "IT", color: "var(--chart-3)", }, hr: { label: "HR", color: "var(--chart-4)", }, operations: { label: "Operations", color: "var(--chart-5)", }, } satisfies ChartConfig export default function ChartPieDemo() { const totalBudget = chartData.reduce((sum, item) => sum + item.amount, 0) const highestBudget = Math.max(...chartData.map((item) => item.amount)) const highestCategory = chartData.find( (item) => item.amount === highestBudget )?.category return ( Budget Distribution Department budget allocation for 2024 } /> {chartData.map((entry, index) => ( ))}
Total Budget: ${totalBudget.toLocaleString()}
Largest Department: {highestCategory}
Highest Budget: ${highestBudget.toLocaleString()}
) } ``` ### Radar Chart ### Example ```tsx "use client" import { Legend, PolarAngleAxis, PolarGrid, Radar, RadarChart } from "recharts" import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, } from "@/components/ui/card" import { ChartConfig, ChartContainer, ChartTooltip, ChartTooltipContent, } from "@/components/ui/chart" const chartData = [ { category: "Performance", a: 90, b: 60 }, { category: "Reliability", a: 75, b: 90 }, { category: "Scalability", a: 95, b: 90 }, { category: "Security", a: 88, b: 65 }, { category: "Usability", a: 92, b: 88 }, ] const chartConfig = { a: { label: "Product A", color: "var(--chart-1)", }, b: { label: "Product B", color: "var(--chart-2)", }, } satisfies ChartConfig export default function ChartRadarDemo() { const productAAverage = chartData.reduce((sum, item) => sum + item.a, 0) / chartData.length const productBAverage = chartData.reduce((sum, item) => sum + item.b, 0) / chartData.length const bestPerformer = productAAverage > productBAverage ? "Product A" : "Product B" return ( Product Comparison Performance metrics across key categories } />
Best Overall: {bestPerformer}
Product A Average: {productAAverage.toFixed(1)}%
Product B Average: {productBAverage.toFixed(1)}%
) } ``` ### Radial Bar Chart ### Example ```tsx "use client" import { RadialBar, RadialBarChart } from "recharts" import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, } from "@/components/ui/card" import { ChartConfig, ChartContainer, ChartTooltip, ChartTooltipContent, } from "@/components/ui/chart" const chartData = [ { browser: "chrome", visitors: 540, fill: "var(--color-chrome)" }, { browser: "safari", visitors: 410, fill: "var(--color-safari)" }, { browser: "firefox", visitors: 262, fill: "var(--color-firefox)" }, { browser: "edge", visitors: 160, fill: "var(--color-edge)" }, { browser: "other", visitors: 100, fill: "var(--color-other)" }, ] const chartConfig = { visitors: { label: "Visitors", }, chrome: { label: "Chrome", color: "var(--chart-1)", }, safari: { label: "Safari", color: "var(--chart-2)", }, firefox: { label: "Firefox", color: "var(--chart-3)", }, edge: { label: "Edge", color: "var(--chart-4)", }, other: { label: "Other", color: "var(--chart-5)", }, } satisfies ChartConfig export default function ChartRadialBarDemo() { const totalVisitors = chartData.reduce((sum, item) => sum + item.visitors, 0) const highestVisitors = Math.max(...chartData.map((item) => item.visitors)) const topBrowser = chartData.find( (item) => item.visitors === highestVisitors )?.browser return ( Browser Usage Visitor distribution by browser } />
Total Visitors: {totalVisitors.toLocaleString()}
Most Used Browser: {topBrowser}
Peak Visitors: {highestVisitors.toLocaleString()}
) } ``` ### Scatter Chart ### Example ```tsx "use client" import { CartesianGrid, Scatter, ScatterChart, XAxis, YAxis, ZAxis, } from "recharts" import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, } from "@/components/ui/card" import { ChartConfig, ChartContainer, ChartTooltip, ChartTooltipContent, } from "@/components/ui/chart" const chartData = [ { population: 850000, price: 425000, city: "San Francisco" }, { population: 2700000, price: 385000, city: "Chicago" }, { population: 8400000, price: 750000, city: "New York" }, { population: 4000000, price: 890000, city: "Los Angeles" }, { population: 2300000, price: 350000, city: "Houston" }, { population: 1600000, price: 420000, city: "Philadelphia" }, { population: 730000, price: 480000, city: "Seattle" }, { population: 690000, price: 445000, city: "Boston" }, { population: 710000, price: 320000, city: "Denver" }, { population: 950000, price: 295000, city: "Austin" }, ] const chartConfig = { scatter: { label: "Cities", color: "var(--chart-1)", }, } satisfies ChartConfig export default function ChartScatterDemo() { const averagePrice = chartData.reduce((sum, item) => sum + item.price, 0) / chartData.length const highestPrice = Math.max(...chartData.map((item) => item.price)) const mostExpensiveCity = chartData.find( (item) => item.price === highestPrice )?.city return ( Housing Market Analysis Population vs House Prices in Major Cities `$${(value / 1000).toFixed(0)}k`} /> `${(value / 1000000).toFixed(1)}M`} /> } />
Most Expensive City: {mostExpensiveCity}
Average House Price: ${averagePrice.toLocaleString()}
Highest House Price: ${highestPrice.toLocaleString()}
) } ``` --- ### Checkbox Displays a box that can be checked or unchecked by the user. ### Example ```tsx import { Checkbox } from "@/components/ui/checkbox" export default function CheckboxDemo() { return } ``` ## Installation ```bash title="Terminal" npx shadcn@latest add https://9ui.dev/r/checkbox.json ``` **Copy and paste the following code into your project.** ## Usage ```tsx title="Imports" import { Checkbox } from "@/components/ui/checkbox" ``` ```tsx title="Anatomy" ``` ## Examples ### With Label ### Example ```tsx import { Checkbox } from "@/components/ui/checkbox" import { Label } from "@/components/ui/label" export default function CheckboxWithLabel() { return ( ) } ``` --- ### Disabled ### Example ```tsx import { Checkbox } from "@/components/ui/checkbox" export default function CheckboxDisabled() { return } ``` --- ### Error ### Example ```tsx import { Checkbox } from "@/components/ui/checkbox" export default function CheckboxError() { return } ``` --- ### Checkbox Group Manages selection state across multiple checkboxes. ### Example ```tsx "use client" import { useState } from "react" import { Checkbox } from "@/components/ui/checkbox" import { CheckboxGroup } from "@/components/ui/checkbox-group" import { Label } from "@/components/ui/label" const groceries = ["milk", "cheese", "bread", "apples"] export default function CheckboxGroupDemo() { const [checkedItems, setCheckedItems] = useState([]) return ( setCheckedItems(value)} allValues={groceries} > {groceries.map((grocery) => ( ))} ) } ``` ## Installation ```bash title="Terminal" npx shadcn@latest add https://9ui.dev/r/checkbox-group.json ``` **Copy and paste the following code into your project.** ## Usage ```tsx title="Imports" import { CheckboxGroup } from "@/components/ui/checkbox-group" ``` ```tsx title="Anatomy" ``` --- ### Collapsible Display content in a collapsible container. ### Example ```tsx import { useState } from "react" import { ChevronRightIcon } from "lucide-react" import { Collapsible, CollapsibleContent, CollapsibleTrigger, } from "@/components/ui/collapsible" import { cn } from "@/lib/utils" export default function CollapsibleDemo() { const [open, setOpen] = useState(false) return ( Components
  1. Button
  2. Badge
  3. Breadcrumbs
) } ``` ## Installation ```bash title="Terminal" npx shadcn@latest add https://9ui.dev/r/collapsible.json ``` **Copy and paste the following code into your project.** ## Usage ```tsx title="Imports" import { Collapsible, CollapsibleContent, CollapsibleTrigger, } from "@/components/ui/collapsible" ``` ```tsx title="Anatomy" ``` --- ### Combobox Autocomplete component for selecting items from a list. ### Example ```tsx import * as React from "react" import { Check, ChevronsUpDownIcon } from "lucide-react" import { Button } from "@/components/ui/button" import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, } from "@/components/ui/command" import { Popover, PopoverContent, PopoverTrigger, } from "@/components/ui/popover" import { cn } from "@/lib/utils" const statuses = [ { value: "backlog", label: "Backlog", color: "bg-slate-500", }, { value: "todo", label: "Todo", color: "bg-blue-500", }, { value: "in-progress", label: "In Progress", color: "bg-yellow-500", }, { value: "done", label: "Done", color: "bg-green-500", }, { value: "canceled", label: "Canceled", color: "bg-red-500", }, ] export default function ComboboxDemo() { const [open, setOpen] = React.useState(false) const [value, setValue] = React.useState("todo") return ( ( )} /> No status found. {statuses.map((status) => ( { setValue(currentValue) setOpen(false) }} >
{status.label}
{value === status.value && ( )} ))} ) } ``` ## Installation The combobox component is a composition of the `Command` and `Popover` components. Follow installation instructions for the [`Command`](/docs/components/command) and [`Popover`](/docs/components/popover) components. ## Usage ```tsx title="Imports" import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, } from "@/components/ui/command" import { Popover, PopoverContent, PopoverTrigger, } from "@/components/ui/popover" ``` ```tsx title="Anatomy" ``` --- ### Command A searchable interface for quickly executing commands or actions. ### Example ```tsx import { ArrowRightIcon, LayoutGridIcon, PlusIcon, UsersIcon, } from "lucide-react" import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, } from "@/components/ui/command" import { Kbd } from "@/components/ui/kbd" export default function CommandDemo() { return ( No results found. Search projects... P Create new project... C Search teams... Create new team... T Go to home Go to profile Go to settings Go to billing ) } ``` ## About The Command is built on top of [`cmdk-base`](https://cmdk-base.vercel.app), which is ported from [`cmdk`](https://github.com/pacocoursey/cmdk), originally created by [@pacocoursey](https://x.com/pacocoursey). ## Installation ```bash title="Terminal" npx shadcn@latest add https://9ui.dev/r/command.json ``` **Install dependencies** ```bash title="Terminal" npm install cmdk-base ``` **Copy and paste the following code into your project.** ## Usage ```tsx title="Imports" import { Command, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, } from "@/components/ui/command" ``` ```tsx title="Anatomy" ``` ## Examples ### Dialog ### Example ```tsx "use client" import { useEffect, useState } from "react" import { ArrowRightIcon, LayoutGridIcon, PlusIcon, UsersIcon, } from "lucide-react" import { CommandDialog, CommandEmpty, CommandGroup, CommandInput, CommandItem, CommandList, CommandSeparator, CommandShortcut, } from "@/components/ui/command" import { Kbd } from "@/components/ui/kbd" export default function CommandDialogDemo() { const [open, setOpen] = useState(false) useEffect(() => { const down = (e: KeyboardEvent) => { if (e.key === "j" && (e.metaKey || e.ctrlKey)) { e.preventDefault() setOpen((open) => !open) } } document.addEventListener("keydown", down) return () => document.removeEventListener("keydown", down) }, []) return ( <>
+J
No results found. Search projects... P Create new project... C Search teams... Create new team... T Go to home Go to profile Go to settings Go to billing ) } ``` --- ### Context Menu Used to provide options specific to an element or area. ### Example ```tsx "use client" import { ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, } from "@/components/ui/context-menu" export default function ContextMenuDemo() { return (
Right Click Here Back ⌘[ Forward ⌘] Reload ⌘R More Save As Print Cast Inspect Settings Always on Top Show full URL Zoom 50% 100% 150%
) } ``` ## Installation ```bash title="Terminal" npx shadcn@latest add https://9ui.dev/r/context-menu.json ``` **Copy and paste the following code into your project.** ## Usage ```tsx title="Imports" import { ContextMenu, ContextMenuCheckboxItem, ContextMenuContent, ContextMenuGroup, ContextMenuItem, ContextMenuLabel, ContextMenuRadioGroup, ContextMenuRadioItem, ContextMenuSeparator, ContextMenuShortcut, ContextMenuSub, ContextMenuSubContent, ContextMenuSubTrigger, ContextMenuTrigger, } from "@/components/ui/context-menu" ``` ```tsx title="Anatomy" ``` --- ### Date Picker A date picker component. ### Example ```tsx import * as React from "react" import dayjs from "dayjs" import { CalendarIcon, ChevronsUpDownIcon } from "lucide-react" import { Button } from "@/components/ui/button" import { Calendar } from "@/components/ui/calendar" import { Popover, PopoverContent, PopoverTrigger, } from "@/components/ui/popover" export default function DatePickerDemo() { const [open, setOpen] = React.useState(false) const [value, setValue] = React.useState(undefined) return ( ( )} /> ) } ``` ## Installation The date picker component is a composition of the `Calendar` and `Popover` components. Follow installation instructions for the [`Calendar`](/docs/components/calendar) and [`Popover`](/docs/components/popover) components. ## Usage ```tsx title="Imports" import { Calendar } from "@/components/ui/calendar" import { Popover, PopoverContent, PopoverTrigger, } from "@/components/ui/popover" ``` ```tsx title="Anatomy" ``` --- ### Dialog A modal window for displaying content. ### Example ```tsx import { Button } from "@/components/ui/button" import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger, } from "@/components/ui/dialog" export default function DialogDemo() { return ( } /> Privacy Policy Please read our privacy policy carefully.
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed ultricies, odio quis blandit vestibulum, orci elit suscipit urna, at lobortis arcu enim vel purus. Maecenas luctus sem dui, lobortis dignissim enim consequat in. Nullam a volutpat purus. Aenean pellentesque eros nec rutrum suscipit. Fusce ac lectus volutpat, feugiat nulla et, suscipit dui. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Ut maximus, risus et convallis placerat, risus urna feugiat neque, in vestibulum leo arcu vitae justo. Duis magna mi, maximus at neque sed, tempor congue ligula. In iaculis metus nec euismod egestas. Donec id porttitor nulla. Donec feugiat iaculis lacus, ut elementum dui faucibus sed. Sed ut ipsum non tellus dignissim accumsan. Vivamus luctus malesuada lacus sed dictum.

Sed consectetur nibh mollis, ornare magna et, dictum tellus. Nam viverra dui a enim iaculis, sed blandit orci consectetur. Maecenas et nisi eleifend velit pretium eleifend sit amet eget nisl. Vestibulum eget ipsum semper purus pulvinar iaculis. Sed ut odio eu felis porttitor ultrices eu sed odio. Nullam lorem sapien, pellentesque convallis libero vel, tempus accumsan nisi. Morbi efficitur ex vitae felis luctus cursus. Suspendisse nibh neque, gravida sed elementum ullamcorper, gravida in nisi. Donec et luctus metus. Fusce sed est dictum, imperdiet nisi eu, suscipit odio. In id enim at tortor malesuada vulputate eu eu sem. Mauris blandit faucibus euismod.

Curabitur quam tortor, tristique euismod finibus viverra, bibendum sit amet nisl. Nulla lobortis pharetra mauris, ac semper urna tempor et. Maecenas enim magna, suscipit nec metus id, ornare pulvinar dolor. Cras rhoncus ante sit amet tempus luctus. Donec in nisl a dolor auctor tincidunt. Cras at arcu tortor. Pellentesque ante felis, convallis sit amet erat id, consectetur consequat sapien. Aliquam volutpat velit in est bibendum, vestibulum commodo leo interdum. Integer sodales ex eu tempus faucibus. Vestibulum ultricies erat vel leo accumsan posuere. Cras commodo felis vitae lacus suscipit, in tristique lectus venenatis. Sed et nibh urna. Praesent vitae eleifend turpis. Fusce sit amet pretium lorem, in tempus elit. Etiam at ornare est. Aenean felis arcu, fermentum scelerisque nibh at, lacinia sagittis neque.
) } ``` ## Installation ```bash title="Terminal" npx shadcn@latest add https://9ui.dev/r/dialog.json ``` **Copy and paste the following code into your project.** ## Usage ```tsx title="Imports" import { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger, } from "@/components/ui/dialog" ``` ```tsx title="Anatomy" ``` ## Examples ### Nested Dialogs ### Example ```tsx import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar" import { Button } from "@/components/ui/button" import { Dialog, DialogClose, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, DialogTrigger, } from "@/components/ui/dialog" export default function DialogNested() { return ( } /> Profile View and edit your profile details.
BB Bora Baloglu
( )} /> Edit Edit the details of the item ( )} />
) } ``` --- ### Drawer Displays a panel that slides out from the side of a screen to reveal more content. ### Example ```tsx "use client" import { useState } from "react" import { StarIcon } from "lucide-react" import { Button } from "@/components/ui/button" import { Drawer, DrawerClose, DrawerContent, DrawerDescription, DrawerFooter, DrawerHeader, DrawerTitle, DrawerTrigger, } from "@/components/ui/drawer" import { Textarea } from "@/components/ui/textarea" import { cn } from "@/lib/utils" export default function DrawerDemo() { const [rating, setRating] = useState(undefined) const handleChangeRating = (newRating: number) => { if (newRating === rating) { setRating(undefined) } else { setRating(newRating) } } return ( } />
Provide Your Feedback We value your feedback. Please rate your experience and leave a review.
{[1, 2, 3, 4, 5].map((star) => ( handleChangeRating(star)} /> ))}