Loading...
Loading...
Create new UI elements for tryelements.dev registry. Use when: (1) Adding new UI components (buttons, inputs, cards), (2) Building integration components (Clerk, Stripe, Uploadthing), (3) Creating theme-related elements, (4) Any shadcn-style registry component. IMPORTANT: For logo components with variants (icon/wordmark/logo + dark/light), use the logo-with-variants skill instead. This skill includes scaffolding, registry schema, and component patterns. ALWAYS use Context7 MCP to fetch latest dependency docs before implementing.
npx skill4agent add crafter-station/elements create-elementStep 1: Scaffold
bun run .claude/skills/create-element/scripts/scaffold-element.ts <category> <name>
Step 2: Implement
Edit component following patterns in references/component-patterns.md
Step 3: Register
bun run build:registry && bun run devmcp__context7__resolve-library-id
libraryName: "radix-ui"
query: "dialog component accessibility patterns"mcp__context7__query-docs
libraryId: "/radix-ui/primitives"
query: "Dialog API controlled vs uncontrolled portal usage"| Library | Query For |
|---|---|
| Primitives (Dialog, Dropdown, Tabs, Select) |
| Theme provider, useTheme hook, hydration |
| Command palette patterns |
| CVA variant patterns |
| Carousel implementation |
| Icon usage patterns |
| Type | Example | When to Use |
|---|---|---|
| button, card, input | Base UI primitives |
| theme-switcher, polar-checkout | Feature-complete blocks |
| button-demo | Usage examples |
registry/default/blocks/{category}/{component-name}/
├── registry-item.json # Metadata
├── components/
│ └── elements/
│ └── {component}.tsx # Main component
└── routes/ # Optional demo routes
├── layout.tsx
└── page.tsxbun run .claude/skills/create-element/scripts/scaffold-element.ts theme theme-switcher-tabsmcp__context7__resolve-library-id
libraryName: "next-themes"
query: "useTheme hook theme switching"
mcp__context7__query-docs
libraryId: "/pacocoursey/next-themes"
query: "useTheme setTheme resolvedTheme hydration"registry/default/blocks/theme/theme-switcher-tabs/components/elements/theme-switcher-tabs.tsx"use client";
import { useTheme } from "next-themes";
import { useEffect, useState } from "react";
import { cn } from "@/lib/utils";
export function ThemeSwitcherTabs({ className }: { className?: string }) {
const { theme, setTheme } = useTheme();
const [mounted, setMounted] = useState(false);
useEffect(() => { setMounted(true); }, []);
if (!mounted) return <div className="h-8 w-24 animate-pulse bg-muted rounded" />;
return (
<div data-slot="theme-switcher-tabs" className={cn("...", className)}>
{/* Implementation */}
</div>
);
}{
"name": "theme-switcher-tabs",
"type": "registry:ui",
"title": "Theme Switcher Tabs",
"description": "Tab-based theme switcher with Light/Dark/System options",
"registryDependencies": [],
"dependencies": ["next-themes"],
"files": [...],
"docs": "Requires ThemeProvider. Tab-style theme switcher with system support."
}bun run build:registry
bun run devexport function ThemeSwitcherTabscn()data-slot"use client"bun run build:registry# Scaffold new element
bun run .claude/skills/create-element/scripts/scaffold-element.ts <category> <name>
# Build registry
bun run build:registry
# Development server
bun run dev
# Lint/format
bun run lint
bun run formatimport { cn } from "@/lib/utils";
interface BadgeProps extends React.ComponentProps<"span"> {}
export function Badge({ className, ...props }: BadgeProps) {
return (
<span
data-slot="badge"
className={cn("inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-semibold", className)}
{...props}
/>
);
}import { cva, type VariantProps } from "class-variance-authority";
import { cn } from "@/lib/utils";
const badgeVariants = cva("inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-semibold", {
variants: {
variant: {
default: "bg-primary text-primary-foreground",
secondary: "bg-secondary text-secondary-foreground",
destructive: "bg-destructive text-white",
},
},
defaultVariants: {
variant: "default",
},
});
interface BadgeProps extends React.ComponentProps<"span">, VariantProps<typeof badgeVariants> {}
export function Badge({ className, variant, ...props }: BadgeProps) {
return (
<span
data-slot="badge"
className={cn(badgeVariants({ variant, className }))}
{...props}
/>
);
}
export { badgeVariants };"use client";
import * as DialogPrimitive from "@radix-ui/react-dialog";
import { cn } from "@/lib/utils";
export function Dialog({ children, ...props }: DialogPrimitive.DialogProps) {
return <DialogPrimitive.Root {...props}>{children}</DialogPrimitive.Root>;
}
export function DialogTrigger({ className, ...props }: DialogPrimitive.DialogTriggerProps) {
return <DialogPrimitive.Trigger data-slot="dialog-trigger" className={cn("", className)} {...props} />;
}"use client"text-foregroundbg-backgroundanybuild:registrycharts/payments/analytics/src/lib/registry-loader.tsgetProviderFromName()// Special case: chart components go to "charts" provider
if (
name === "area-chart" ||
name === "bar-chart-vertical" ||
name === "heatmap-grid" ||
name === "growth-stats"
) {
return "charts";
}getProviderMetadata()charts: {
displayName: "Charts",
description: "Data visualization primitives - area charts, heatmaps, bar charts",
category: "DATA VIZ",
brandColor: "#14B8A6",
},src/lib/providers.tsxproviderConfigcharts: {
isEnabled: true,
displayName: "Charts",
description: "Data visualization primitives - area charts, heatmaps, bar charts",
category: "Data Viz",
},ProviderIcon()charts: <ChartIcon className="w-10 h-10" />,src/components/icons/{provider}.tsx| Field | Example | Purpose |
|---|---|---|
| "Charts" | Landing page card title |
| "Data visualization..." | Card description |
| "DATA VIZ" | Badge shown on card |
| "#14B8A6" | Diagonal hatch pattern color |
| Provider Key | Display Name | Category |
|---|---|---|
| Clerk | USER MGMT |
| Polar | MONETIZATION |
| Theme Switcher | UI |
| Brand Logos | BRAND |
| UploadThing | FILES |
| Tinte | THEMING |
| Charts | DATA VIZ |
clerk-sign-inclerkpolar-checkoutpolararea-chartheatmap-gridtheme-switcher-*theme/registry/default/examples/{component}-demo.tsx"use client";
import { MyComponent } from "@/registry/default/blocks/{category}/{component}/components/elements/{component}";
export default function MyComponentDemo() {
return (
<div className="flex items-center justify-center p-4">
<MyComponent />
</div>
);
}/src/mdx-components.tsx// Add import
import MyComponentDemo from "@/registry/default/examples/my-component-demo";
// Add to getMDXComponents return object
MyComponent: MyComponentDemo,/src/content/providers/{provider}.mdx---
title: My Provider
description: Description of the category
category: CATEGORY TAG
brandColor: "#hexcolor"
---
## Overview
Brief description.
## Components
### Component Name
<ComponentPreviewItem
componentKey="component-name"
installUrl="@elements/component-name"
category="Category"
name="Component Name"
>
<ComponentName />
</ComponentPreviewItem>/src/content/components/{provider}/{component}.mdx---
title: Component Name
description: Brief description
---
<ComponentPreviewItem
componentKey="component-name"
installUrl="@elements/component-name"
category="Category"
name="Component Name"
>
<ComponentName />
</ComponentPreviewItem>
## Overview
## Installation
## Usage
## Props
## Features