diff --git a/apps/docs/app/components/preview/ComponentPreview.css b/apps/docs/app/components/preview/ComponentPreview.css
new file mode 100644
index 0000000..9b22306
--- /dev/null
+++ b/apps/docs/app/components/preview/ComponentPreview.css
@@ -0,0 +1,15 @@
+.hui-preview-container {
+ border: 1px solid var(--hui-color-border);
+ border-radius: var(--hui-radius-lg);
+ overflow: hidden;
+ background-color: var(--hui-color-background);
+}
+
+.hui-preview-content {
+ padding: var(--hui-spacing-6);
+}
+
+/* Fumadocs Tabs trigger cursor fix */
+[role="tab"] {
+ cursor: pointer;
+}
diff --git a/apps/docs/app/components/preview/ComponentPreview.tsx b/apps/docs/app/components/preview/ComponentPreview.tsx
new file mode 100644
index 0000000..8f965f1
--- /dev/null
+++ b/apps/docs/app/components/preview/ComponentPreview.tsx
@@ -0,0 +1,30 @@
+'use client';
+
+import { Suspense } from 'react';
+import { demos } from './demo-registry';
+import './ComponentPreview.css';
+
+interface ComponentPreviewProps {
+ name: string;
+}
+
+export function ComponentPreview({ name }: ComponentPreviewProps) {
+ const Demo = demos[name];
+ if (!Demo) {
+ return (
+
+
Demo "{name}" not found.
+
+ );
+ }
+
+ return (
+
+
+ Loading preview...
}>
+
+
+
+
+ );
+}
diff --git a/apps/docs/app/components/preview/demo-registry.ts b/apps/docs/app/components/preview/demo-registry.ts
new file mode 100644
index 0000000..13b0b50
--- /dev/null
+++ b/apps/docs/app/components/preview/demo-registry.ts
@@ -0,0 +1,10 @@
+import { type ComponentType, lazy } from 'react';
+
+export const demos: Record = {
+ 'button-variants': lazy(() => import('./demos/button-variants')),
+ 'card-demo': lazy(() => import('./demos/card-demo')),
+ 'dialog-demo': lazy(() => import('./demos/dialog-demo')),
+ 'input-demo': lazy(() => import('./demos/input-demo')),
+ 'badge-demo': lazy(() => import('./demos/badge-demo')),
+ 'tabs-demo': lazy(() => import('./demos/tabs-demo')),
+};
diff --git a/apps/docs/app/components/preview/demos/badge-demo.tsx b/apps/docs/app/components/preview/demos/badge-demo.tsx
new file mode 100644
index 0000000..b6644b4
--- /dev/null
+++ b/apps/docs/app/components/preview/demos/badge-demo.tsx
@@ -0,0 +1,14 @@
+'use client';
+
+import { Badge } from '@hareru/ui';
+
+export default function BadgeDemo() {
+ return (
+
+ Default
+ Secondary
+ Destructive
+ Outline
+
+ );
+}
diff --git a/apps/docs/app/components/preview/demos/button-variants.tsx b/apps/docs/app/components/preview/demos/button-variants.tsx
new file mode 100644
index 0000000..fa9b9df
--- /dev/null
+++ b/apps/docs/app/components/preview/demos/button-variants.tsx
@@ -0,0 +1,23 @@
+'use client';
+
+import { Button } from '@hareru/ui';
+
+export default function ButtonVariantsDemo() {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
diff --git a/apps/docs/app/components/preview/demos/card-demo.tsx b/apps/docs/app/components/preview/demos/card-demo.tsx
new file mode 100644
index 0000000..9259487
--- /dev/null
+++ b/apps/docs/app/components/preview/demos/card-demo.tsx
@@ -0,0 +1,29 @@
+'use client';
+
+import {
+ Button,
+ Card,
+ CardContent,
+ CardDescription,
+ CardFooter,
+ CardHeader,
+ CardTitle,
+} from '@hareru/ui';
+
+export default function CardDemo() {
+ return (
+
+
+ Card Title
+ Card description with supporting text.
+
+
+ This is the main content area of the card component.
+
+
+
+
+
+
+ );
+}
diff --git a/apps/docs/app/components/preview/demos/dialog-demo.tsx b/apps/docs/app/components/preview/demos/dialog-demo.tsx
new file mode 100644
index 0000000..94f5712
--- /dev/null
+++ b/apps/docs/app/components/preview/demos/dialog-demo.tsx
@@ -0,0 +1,38 @@
+'use client';
+
+import {
+ Button,
+ Dialog,
+ DialogClose,
+ DialogContent,
+ DialogDescription,
+ DialogFooter,
+ DialogHeader,
+ DialogTitle,
+ DialogTrigger,
+} from '@hareru/ui';
+
+export default function DialogDemo() {
+ return (
+
+ );
+}
diff --git a/apps/docs/app/components/preview/demos/input-demo.tsx b/apps/docs/app/components/preview/demos/input-demo.tsx
new file mode 100644
index 0000000..682665d
--- /dev/null
+++ b/apps/docs/app/components/preview/demos/input-demo.tsx
@@ -0,0 +1,18 @@
+'use client';
+
+import { Input, Label } from '@hareru/ui';
+
+export default function InputDemo() {
+ return (
+
+ );
+}
diff --git a/apps/docs/app/components/preview/demos/tabs-demo.tsx b/apps/docs/app/components/preview/demos/tabs-demo.tsx
new file mode 100644
index 0000000..eb3d01e
--- /dev/null
+++ b/apps/docs/app/components/preview/demos/tabs-demo.tsx
@@ -0,0 +1,24 @@
+'use client';
+
+import { Tabs, TabsContent, TabsList, TabsTrigger } from '@hareru/ui';
+
+export default function TabsDemo() {
+ return (
+
+
+ Account
+ Password
+ Settings
+
+
+ Manage your account settings and preferences.
+
+
+ Change your password and security options.
+
+
+ Configure application settings.
+
+
+ );
+}
diff --git a/apps/docs/app/components/preview/index.ts b/apps/docs/app/components/preview/index.ts
new file mode 100644
index 0000000..cc939c2
--- /dev/null
+++ b/apps/docs/app/components/preview/index.ts
@@ -0,0 +1 @@
+export { ComponentPreview } from './ComponentPreview';
diff --git a/apps/docs/app/docs/[[...slug]]/page.tsx b/apps/docs/app/docs/[[...slug]]/page.tsx
index 1c498cc..587768d 100644
--- a/apps/docs/app/docs/[[...slug]]/page.tsx
+++ b/apps/docs/app/docs/[[...slug]]/page.tsx
@@ -1,5 +1,7 @@
+import { ComponentPreview } from '@/app/components/preview';
import { RegistryA11y, RegistrySlots, RegistryStates } from '@/app/components/registry';
import { source } from '@/lib/source';
+import { Tab, Tabs } from 'fumadocs-ui/components/tabs';
import { DocsBody, DocsDescription, DocsPage, DocsTitle } from 'fumadocs-ui/layouts/notebook/page';
import defaultMdxComponents from 'fumadocs-ui/mdx';
import { notFound } from 'next/navigation';
@@ -20,7 +22,15 @@ export default async function Page(props: {
{page.data.description}
diff --git a/apps/docs/app/layout.tsx b/apps/docs/app/layout.tsx
index 86319cf..c724cbe 100644
--- a/apps/docs/app/layout.tsx
+++ b/apps/docs/app/layout.tsx
@@ -1,5 +1,8 @@
import { RootProvider } from 'fumadocs-ui/provider/next';
import 'fumadocs-ui/style.css';
+import '@hareru/tokens/css';
+import '@hareru/ui/styles/components.layer.css';
+import '@hareru/ui/styles/scope.css';
import type { ReactNode } from 'react';
export const metadata = {
@@ -20,7 +23,7 @@ export default function RootLayout({ children }: { children: ReactNode }) {
return (
- {children}
+ {children}
);
diff --git a/apps/docs/content/docs/components/badge.mdx b/apps/docs/content/docs/components/badge.mdx
index ae1d263..f584a41 100644
--- a/apps/docs/content/docs/components/badge.mdx
+++ b/apps/docs/content/docs/components/badge.mdx
@@ -5,6 +5,24 @@ description: Compact status label with semantic color variants.
**Category:** Data Display / Standalone
+## Preview
+
+
+
+
+
+
+ ```tsx
+ import { Badge } from "@hareru/ui"
+
+ Default
+ Secondary
+ Destructive
+ Outline
+ ```
+
+
+
## Import
```tsx
diff --git a/apps/docs/content/docs/components/button.mdx b/apps/docs/content/docs/components/button.mdx
index 167c62d..796f0f2 100644
--- a/apps/docs/content/docs/components/button.mdx
+++ b/apps/docs/content/docs/components/button.mdx
@@ -5,6 +5,26 @@ description: Interactive button element with variant and size support via CVA.
**Category:** Form / Standalone
+## Preview
+
+
+
+
+
+
+ ```tsx
+ import { Button } from "@hareru/ui"
+
+
+
+
+
+
+
+ ```
+
+
+
## Import
```tsx
diff --git a/apps/docs/content/docs/components/card.mdx b/apps/docs/content/docs/components/card.mdx
index 56dc3cf..b0c36a0 100644
--- a/apps/docs/content/docs/components/card.mdx
+++ b/apps/docs/content/docs/components/card.mdx
@@ -5,6 +5,33 @@ description: Semantic content container using article, header, and footer HTML e
**Category:** Layout / Composite
+## Preview
+
+
+
+
+
+
+ ```tsx
+ import { Card, CardHeader, CardTitle, CardDescription, CardContent, CardFooter, Button } from "@hareru/ui"
+
+
+
+ Card Title
+ Card description with supporting text.
+
+
+ Main content area of the card.
+
+
+
+
+
+
+ ```
+
+
+
## Import
```tsx
diff --git a/apps/docs/content/docs/components/dialog.mdx b/apps/docs/content/docs/components/dialog.mdx
index cc0b87c..479d9a6 100644
--- a/apps/docs/content/docs/components/dialog.mdx
+++ b/apps/docs/content/docs/components/dialog.mdx
@@ -7,6 +7,36 @@ description: Accessible modal dialog built on Base UI Dialog primitives.
**Dependency:** `@base-ui-components/react/dialog`
+## Preview
+
+
+
+
+
+
+ ```tsx
+ import { Dialog, DialogTrigger, DialogContent, DialogHeader, DialogTitle, DialogDescription, DialogFooter, DialogClose, Button } from "@hareru/ui"
+
+
+ ```
+
+
+
## Import
```tsx
diff --git a/apps/docs/content/docs/components/input.mdx b/apps/docs/content/docs/components/input.mdx
index 397ddbf..ac94919 100644
--- a/apps/docs/content/docs/components/input.mdx
+++ b/apps/docs/content/docs/components/input.mdx
@@ -5,6 +5,25 @@ description: Single-line text input with error state and file input support.
**Category:** Form / Standalone
+## Preview
+
+
+
+
+
+
+ ```tsx
+ import { Input, Label } from "@hareru/ui"
+
+
+
+
+
+
+ ```
+
+
+
## Import
```tsx
diff --git a/apps/docs/content/docs/components/tabs.mdx b/apps/docs/content/docs/components/tabs.mdx
index 706d111..36e7aca 100644
--- a/apps/docs/content/docs/components/tabs.mdx
+++ b/apps/docs/content/docs/components/tabs.mdx
@@ -7,6 +7,30 @@ description: Accessible tabbed interface for switching between related content p
**Dependency:** `@base-ui-components/react/tabs`
+## Preview
+
+
+
+
+
+
+ ```tsx
+ import { Tabs, TabsList, TabsTrigger, TabsContent } from "@hareru/ui"
+
+
+
+ Account
+ Password
+ Settings
+
+ Account settings content.
+ Password settings content.
+ Application settings content.
+
+ ```
+
+
+
## Import
```tsx