Loading...
Loading...
Develop high-quality, accessible React components using shadcn-ui, Tailwind CSS, and Radix UI. Use when building forms, layouts, dialogs, tables, or any UI components. Supports Next.js, Vite, Remix, Astro, and more. Integrates with shadcn MCP server for component discovery and installation.
npx skill4agent add majesteitbart/talentmatcher shadcn-ui-expertnpx shadcn-ui@latest initcomponents.json# Install a button component
npx shadcn-ui@latest add button
# Install form components
npx shadcn-ui@latest add form input select checkbox
# Install a data table
npx shadcn-ui@latest add data-tableforminputtextareaselectcheckboxradio-groupswitchdate-pickercomboboxsidebartabsaccordionbreadcrumbnavigation-menuscroll-areadialogalert-dialogdrawerpopovertooltipdropdown-menucontext-menutabledata-tableavatarbadgecardalerttoastprogressskeletonspinnerinputselectcomboboxcheckboxswitchforminputselectdialogdrawertooltipfieldformbuttondata-tableformfieldinputselectimport { useForm } from "react-hook-form"
import { zodResolver } from "@hookform/resolvers/zod"
import * as z from "zod"
import { Button } from "@/components/ui/button"
import { Form, FormField, FormItem, FormLabel, FormControl } from "@/components/ui/form"
import { Input } from "@/components/ui/input"
const formSchema = z.object({
email: z.string().email(),
password: z.string().min(8),
})
export function LoginForm() {
const form = useForm<z.infer<typeof formSchema>>({
resolver: zodResolver(formSchema),
})
function onSubmit(values: z.infer<typeof formSchema>) {
console.log(values)
}
return (
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-8">
<FormField
control={form.control}
name="email"
render={({ field }) => (
<FormItem>
<FormLabel>Email</FormLabel>
<FormControl>
<Input placeholder="you@example.com" {...field} />
</FormControl>
</FormItem>
)}
/>
<Button type="submit">Submit</Button>
</form>
</Form>
)
}import { Button } from "@/components/ui/button"
import {
Dialog,
DialogContent,
DialogDescription,
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog"
export function DeleteDialog() {
return (
<Dialog>
<DialogTrigger asChild>
<Button variant="destructive">Delete</Button>
</DialogTrigger>
<DialogContent>
<DialogHeader>
<DialogTitle>Are you sure?</DialogTitle>
<DialogDescription>
This action cannot be undone.
</DialogDescription>
</DialogHeader>
<div className="flex gap-3 justify-end">
<Button variant="outline">Cancel</Button>
<Button variant="destructive">Delete</Button>
</div>
</DialogContent>
</Dialog>
)
}<Button className="w-full text-lg">Full Width</Button>
<Input className="rounded-lg border-2" />app/globals.css@layer base {
:root {
--primary: 222.2 47.4% 11.2%;
--secondary: 210 40% 96%;
}
}next.config.jstailwind.config.jsdark<Button variant="outline" />
<Button variant="ghost" />
<Button variant="destructive" />
<Badge variant="secondary" />// ✅ Good: Compose components
<Card>
<CardHeader>
<CardTitle>Title</CardTitle>
</CardHeader>
<CardContent>
<Form>...</Form>
</CardContent>
</Card>
// ❌ Avoid: Over-modifying single component
<CustomDialog withHeader={true} withForm={true} />import { Button } from "@/components/ui/button"
import type { ButtonProps } from "@/components/ui/button"
type CustomButtonProps = ButtonProps & {
label: string
}React.memoshadcn-ui@latest add formnext-themestailwind.config.jsremixcomponents.jsonglobals.csscomponents/ui/// components/ui/my-component.tsx
import * as React from "react"
export interface MyComponentProps
extends React.HTMLAttributes<HTMLDivElement> {}
const MyComponent = React.forwardRef<HTMLDivElement, MyComponentProps>(
({ className, ...props }, ref) => (
<div
ref={ref}
className={className}
{...props}
/>
)
)
MyComponent.displayName = "MyComponent"
export { MyComponent }.brand-a {
--primary: 220 90% 56%;
--secondary: 0 0% 100%;
}
.brand-b {
--primary: 0 100% 50%;
--secondary: 200 100% 50%;
}npm install react-hook-form zod @hookform/resolversnpm install @tanstack/react-formtailwind.config.jscomponents.jsonpathnpm install/components/ui/namezod@hookform/resolverszodResolveruseForm