diff --git a/apps/docs/app/api/demo/repos/route.ts b/apps/docs/app/api/demo/repos/route.ts new file mode 100644 index 0000000..75fc101 --- /dev/null +++ b/apps/docs/app/api/demo/repos/route.ts @@ -0,0 +1,17 @@ +const items = [ + { value: 'hareru-ui', label: 'hareru-ai/ui' }, + { value: 'next-js', label: 'vercel/next.js' }, + { value: 'react', label: 'facebook/react' }, + { value: 'typescript', label: 'microsoft/typescript' }, + { value: 'vite', label: 'vitejs/vite' }, + { value: 'tailwindcss', label: 'tailwindlabs/tailwindcss' }, + { value: 'biome', label: 'biomejs/biome' }, + { value: 'vitest', label: 'vitest-dev/vitest' }, +]; + +export function GET(req: Request) { + const url = new URL(req.url); + const q = (url.searchParams.get('q') ?? '').toLowerCase(); + const filtered = q ? items.filter((i) => i.label.toLowerCase().includes(q)) : items; + return Response.json({ items: filtered }); +} diff --git a/apps/docs/app/api/demo/search/route.ts b/apps/docs/app/api/demo/search/route.ts new file mode 100644 index 0000000..b00ae70 --- /dev/null +++ b/apps/docs/app/api/demo/search/route.ts @@ -0,0 +1,19 @@ +const items = [ + { value: 'apple', label: 'Apple' }, + { value: 'banana', label: 'Banana' }, + { value: 'cherry', label: 'Cherry' }, + { value: 'grape', label: 'Grape' }, + { value: 'lemon', label: 'Lemon' }, + { value: 'mango', label: 'Mango' }, + { value: 'orange', label: 'Orange' }, + { value: 'peach', label: 'Peach' }, + { value: 'strawberry', label: 'Strawberry' }, + { value: 'watermelon', label: 'Watermelon' }, +]; + +export function GET(req: Request) { + const url = new URL(req.url); + const q = (url.searchParams.get('q') ?? '').toLowerCase(); + const filtered = q ? items.filter((i) => i.label.toLowerCase().includes(q)) : items; + return Response.json({ items: filtered }); +} diff --git a/apps/docs/app/components/preview/ComponentPreview.tsx b/apps/docs/app/components/preview/ComponentPreview.tsx index 8f965f1..4b12a19 100644 --- a/apps/docs/app/components/preview/ComponentPreview.tsx +++ b/apps/docs/app/components/preview/ComponentPreview.tsx @@ -1,5 +1,6 @@ 'use client'; +import { Toaster, TooltipProvider } from '@hareru/ui'; import { Suspense } from 'react'; import { demos } from './demo-registry'; import './ComponentPreview.css'; @@ -21,9 +22,12 @@ export function ComponentPreview({ name }: ComponentPreviewProps) { return (
- Loading preview...
}> - - + + Loading preview...
}> + + + + ); diff --git a/apps/docs/app/components/preview/demo-registry.ts b/apps/docs/app/components/preview/demo-registry.ts index 13b0b50..e49242d 100644 --- a/apps/docs/app/components/preview/demo-registry.ts +++ b/apps/docs/app/components/preview/demo-registry.ts @@ -1,10 +1,64 @@ import { type ComponentType, lazy } from 'react'; export const demos: Record = { + 'accordion-demo': lazy(() => import('./demos/accordion-demo')), + 'alert-demo': lazy(() => import('./demos/alert-demo')), + 'alert-dialog-demo': lazy(() => import('./demos/alert-dialog-demo')), + 'approval-card-demo': lazy(() => import('./demos/approval-card-demo')), + 'aspect-ratio-demo': lazy(() => import('./demos/aspect-ratio-demo')), + 'async-combobox-field-demo': lazy(() => import('./demos/async-combobox-field-demo')), + 'avatar-demo': lazy(() => import('./demos/avatar-demo')), + 'badge-demo': lazy(() => import('./demos/badge-demo')), + 'bento-grid-demo': lazy(() => import('./demos/bento-grid-demo')), + 'breadcrumb-demo': lazy(() => import('./demos/breadcrumb-demo')), 'button-variants': lazy(() => import('./demos/button-variants')), 'card-demo': lazy(() => import('./demos/card-demo')), + 'chat-composer-demo': lazy(() => import('./demos/chat-composer-demo')), + 'chat-container-demo': lazy(() => import('./demos/chat-container-demo')), + 'chat-message-demo': lazy(() => import('./demos/chat-message-demo')), + 'checkbox-demo': lazy(() => import('./demos/checkbox-demo')), + 'checkbox-group-demo': lazy(() => import('./demos/checkbox-group-demo')), + 'collapsible-demo': lazy(() => import('./demos/collapsible-demo')), + 'combobox-demo': lazy(() => import('./demos/combobox-demo')), + 'command-demo': lazy(() => import('./demos/command-demo')), + 'confidence-badge-demo': lazy(() => import('./demos/confidence-badge-demo')), + 'context-menu-demo': lazy(() => import('./demos/context-menu-demo')), + 'data-quality-indicator-demo': lazy(() => import('./demos/data-quality-indicator-demo')), + 'definition-browser-demo': lazy(() => import('./demos/definition-browser-demo')), 'dialog-demo': lazy(() => import('./demos/dialog-demo')), + 'dropdown-menu-demo': lazy(() => import('./demos/dropdown-menu-demo')), + 'empty-state-demo': lazy(() => import('./demos/empty-state-demo')), + 'field-diff-demo': lazy(() => import('./demos/field-diff-demo')), + 'form-field-demo': lazy(() => import('./demos/form-field-demo')), 'input-demo': lazy(() => import('./demos/input-demo')), - 'badge-demo': lazy(() => import('./demos/badge-demo')), + 'key-value-list-demo': lazy(() => import('./demos/key-value-list-demo')), + 'label-demo': lazy(() => import('./demos/label-demo')), + 'metric-card-demo': lazy(() => import('./demos/metric-card-demo')), + 'navigation-menu-demo': lazy(() => import('./demos/navigation-menu-demo')), + 'pagination-demo': lazy(() => import('./demos/pagination-demo')), + 'popover-demo': lazy(() => import('./demos/popover-demo')), + 'preview-card-demo': lazy(() => import('./demos/preview-card-demo')), + 'progress-demo': lazy(() => import('./demos/progress-demo')), + 'query-feedback-demo': lazy(() => import('./demos/query-feedback-demo')), + 'radio-group-demo': lazy(() => import('./demos/radio-group-demo')), + 'readonly-field-demo': lazy(() => import('./demos/readonly-field-demo')), + 'reasoning-panel-demo': lazy(() => import('./demos/reasoning-panel-demo')), + 'scroll-area-demo': lazy(() => import('./demos/scroll-area-demo')), + 'select-demo': lazy(() => import('./demos/select-demo')), + 'semantic-suggest-demo': lazy(() => import('./demos/semantic-suggest-demo')), + 'separator-demo': lazy(() => import('./demos/separator-demo')), + 'sheet-demo': lazy(() => import('./demos/sheet-demo')), + 'skeleton-demo': lazy(() => import('./demos/skeleton-demo')), + 'slider-demo': lazy(() => import('./demos/slider-demo')), + 'streaming-text-demo': lazy(() => import('./demos/streaming-text-demo')), + 'switch-demo': lazy(() => import('./demos/switch-demo')), + 'table-demo': lazy(() => import('./demos/table-demo')), 'tabs-demo': lazy(() => import('./demos/tabs-demo')), + 'textarea-demo': lazy(() => import('./demos/textarea-demo')), + 'toast-demo': lazy(() => import('./demos/toast-demo')), + 'toggle-demo': lazy(() => import('./demos/toggle-demo')), + 'toggle-group-demo': lazy(() => import('./demos/toggle-group-demo')), + 'tool-call-card-demo': lazy(() => import('./demos/tool-call-card-demo')), + 'toolbar-demo': lazy(() => import('./demos/toolbar-demo')), + 'tooltip-demo': lazy(() => import('./demos/tooltip-demo')), }; diff --git a/apps/docs/app/components/preview/demos/accordion-demo.tsx b/apps/docs/app/components/preview/demos/accordion-demo.tsx new file mode 100644 index 0000000..e3a0be0 --- /dev/null +++ b/apps/docs/app/components/preview/demos/accordion-demo.tsx @@ -0,0 +1,43 @@ +'use client'; + +import { + Accordion, + AccordionContent, + AccordionHeader, + AccordionItem, + AccordionTrigger, +} from '@hareru/ui'; + +export default function AccordionDemo() { + return ( + + + + What is Hareru UI? + + + Hareru UI is a semantic CSS design system with accessible React components built on Base + UI. + + + + + Is it accessible? + + + Yes. All interactive components follow WAI-ARIA guidelines and support keyboard + navigation. + + + + + Can I customize the styles? + + + Yes. Components expose CSS custom properties under the --hui- prefix for full + theming control. + + + + ); +} diff --git a/apps/docs/app/components/preview/demos/alert-demo.tsx b/apps/docs/app/components/preview/demos/alert-demo.tsx new file mode 100644 index 0000000..1fb64cd --- /dev/null +++ b/apps/docs/app/components/preview/demos/alert-demo.tsx @@ -0,0 +1,30 @@ +'use client'; + +import { Alert, AlertDescription, AlertTitle } from '@hareru/ui'; + +export default function AlertDemo() { + return ( +
+ + Heads up! + + You can add components and dependencies to your app using the CLI. + + + + Error + + Your session has expired. Please log in again to continue. + + +
+ ); +} diff --git a/apps/docs/app/components/preview/demos/alert-dialog-demo.tsx b/apps/docs/app/components/preview/demos/alert-dialog-demo.tsx new file mode 100644 index 0000000..fd4ebdd --- /dev/null +++ b/apps/docs/app/components/preview/demos/alert-dialog-demo.tsx @@ -0,0 +1,34 @@ +'use client'; + +import { + AlertDialog, + AlertDialogAction, + AlertDialogCancel, + AlertDialogContent, + AlertDialogDescription, + AlertDialogFooter, + AlertDialogHeader, + AlertDialogTitle, + AlertDialogTrigger, +} from '@hareru/ui'; + +export default function AlertDialogDemo() { + return ( + + Delete account + + + Are you absolutely sure? + + This action cannot be undone. This will permanently delete your account and remove your + data from our servers. + + + + Cancel + Continue + + + + ); +} diff --git a/apps/docs/app/components/preview/demos/approval-card-demo.tsx b/apps/docs/app/components/preview/demos/approval-card-demo.tsx new file mode 100644 index 0000000..bd6b373 --- /dev/null +++ b/apps/docs/app/components/preview/demos/approval-card-demo.tsx @@ -0,0 +1,30 @@ +'use client'; + +import { ApprovalCard } from '@hareru/ui'; + +export default function ApprovalCardDemo() { + return ( +
+ {}} + onReject={() => {}} + /> + + +
+ ); +} diff --git a/apps/docs/app/components/preview/demos/aspect-ratio-demo.tsx b/apps/docs/app/components/preview/demos/aspect-ratio-demo.tsx new file mode 100644 index 0000000..0134939 --- /dev/null +++ b/apps/docs/app/components/preview/demos/aspect-ratio-demo.tsx @@ -0,0 +1,26 @@ +'use client'; + +import { AspectRatio } from '@hareru/ui'; + +export default function AspectRatioDemo() { + return ( +
+ +
+ 16 / 9 +
+
+
+ ); +} diff --git a/apps/docs/app/components/preview/demos/async-combobox-field-demo.tsx b/apps/docs/app/components/preview/demos/async-combobox-field-demo.tsx new file mode 100644 index 0000000..9955e80 --- /dev/null +++ b/apps/docs/app/components/preview/demos/async-combobox-field-demo.tsx @@ -0,0 +1,22 @@ +'use client'; + +import { AsyncComboboxField } from '@hareru/ui'; + +export default function AsyncComboboxFieldDemo() { + return ( +
+ + + +
+ ); +} diff --git a/apps/docs/app/components/preview/demos/avatar-demo.tsx b/apps/docs/app/components/preview/demos/avatar-demo.tsx new file mode 100644 index 0000000..038478f --- /dev/null +++ b/apps/docs/app/components/preview/demos/avatar-demo.tsx @@ -0,0 +1,21 @@ +'use client'; + +import { Avatar, AvatarFallback, AvatarImage } from '@hareru/ui'; + +export default function AvatarDemo() { + return ( +
+ + + SC + + + + VC + + + JD + +
+ ); +} diff --git a/apps/docs/app/components/preview/demos/bento-grid-demo.tsx b/apps/docs/app/components/preview/demos/bento-grid-demo.tsx new file mode 100644 index 0000000..76b04d4 --- /dev/null +++ b/apps/docs/app/components/preview/demos/bento-grid-demo.tsx @@ -0,0 +1,60 @@ +'use client'; + +import { BentoGrid, BentoGridItem } from '@hareru/ui'; + +const layouts = { + lg: [ + { i: 'a', x: 0, y: 0, w: 6, h: 2 }, + { i: 'b', x: 6, y: 0, w: 6, h: 2 }, + { i: 'c', x: 0, y: 2, w: 4, h: 2 }, + { i: 'd', x: 4, y: 2, w: 8, h: 2 }, + ], + sm: [ + { i: 'a', x: 0, y: 0, w: 2, h: 2 }, + { i: 'b', x: 2, y: 0, w: 2, h: 2 }, + { i: 'c', x: 0, y: 2, w: 2, h: 2 }, + { i: 'd', x: 2, y: 2, w: 2, h: 2 }, + ], +}; + +const items = [ + { key: 'a', label: 'Card A' }, + { key: 'b', label: 'Card B' }, + { key: 'c', label: 'Card C' }, + { key: 'd', label: 'Card D' }, +]; + +export default function BentoGridDemo() { + return ( +
+ + {items.map((item) => ( + +
+ {item.label} +
+
+ ))} +
+
+ ); +} diff --git a/apps/docs/app/components/preview/demos/breadcrumb-demo.tsx b/apps/docs/app/components/preview/demos/breadcrumb-demo.tsx new file mode 100644 index 0000000..ec828d3 --- /dev/null +++ b/apps/docs/app/components/preview/demos/breadcrumb-demo.tsx @@ -0,0 +1,30 @@ +'use client'; + +import { + Breadcrumb, + BreadcrumbItem, + BreadcrumbLink, + BreadcrumbList, + BreadcrumbPage, + BreadcrumbSeparator, +} from '@hareru/ui'; + +export default function BreadcrumbDemo() { + return ( + + + + Home + + + + Components + + + + Breadcrumb + + + + ); +} diff --git a/apps/docs/app/components/preview/demos/chat-composer-demo.tsx b/apps/docs/app/components/preview/demos/chat-composer-demo.tsx new file mode 100644 index 0000000..83d10fc --- /dev/null +++ b/apps/docs/app/components/preview/demos/chat-composer-demo.tsx @@ -0,0 +1,16 @@ +'use client'; + +import { ChatComposer, ChatComposerActions, ChatComposerInput, ChatComposerSend } from '@hareru/ui'; + +export default function ChatComposerDemo() { + return ( +
+ + + + + + +
+ ); +} diff --git a/apps/docs/app/components/preview/demos/chat-container-demo.tsx b/apps/docs/app/components/preview/demos/chat-container-demo.tsx new file mode 100644 index 0000000..05b2720 --- /dev/null +++ b/apps/docs/app/components/preview/demos/chat-container-demo.tsx @@ -0,0 +1,36 @@ +'use client'; + +import { + ChatContainer, + ChatContainerFooter, + ChatContainerHeader, + ChatContainerMessages, + ChatMessage, + ChatMessageContent, +} from '@hareru/ui'; + +export default function ChatContainerDemo() { + return ( +
+ + + Assistant + + + + How do I reset my password? + + + + You can reset your password from the account settings page. Click "Forgot password" on + the login screen. + + + + + Type a message... + + +
+ ); +} diff --git a/apps/docs/app/components/preview/demos/chat-message-demo.tsx b/apps/docs/app/components/preview/demos/chat-message-demo.tsx new file mode 100644 index 0000000..169e40a --- /dev/null +++ b/apps/docs/app/components/preview/demos/chat-message-demo.tsx @@ -0,0 +1,22 @@ +'use client'; + +import { ChatMessage, ChatMessageContent } from '@hareru/ui'; + +export default function ChatMessageDemo() { + return ( +
+ + Can you summarize the quarterly report? + + + + The Q3 report shows a 12% revenue increase year-over-year, with strong performance in the + enterprise segment. + + + + Conversation started + +
+ ); +} diff --git a/apps/docs/app/components/preview/demos/checkbox-demo.tsx b/apps/docs/app/components/preview/demos/checkbox-demo.tsx new file mode 100644 index 0000000..3fd558b --- /dev/null +++ b/apps/docs/app/components/preview/demos/checkbox-demo.tsx @@ -0,0 +1,29 @@ +'use client'; + +import { Checkbox, Label } from '@hareru/ui'; +import { useState } from 'react'; + +export default function CheckboxDemo() { + const [checked, setChecked] = useState(false); + + return ( +
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ ); +} diff --git a/apps/docs/app/components/preview/demos/checkbox-group-demo.tsx b/apps/docs/app/components/preview/demos/checkbox-group-demo.tsx new file mode 100644 index 0000000..59f634f --- /dev/null +++ b/apps/docs/app/components/preview/demos/checkbox-group-demo.tsx @@ -0,0 +1,26 @@ +'use client'; + +import { Checkbox, CheckboxGroup, Label } from '@hareru/ui'; + +export default function CheckboxGroupDemo() { + return ( +
+ +
+
+ + +
+
+ + +
+
+ + +
+
+
+
+ ); +} diff --git a/apps/docs/app/components/preview/demos/collapsible-demo.tsx b/apps/docs/app/components/preview/demos/collapsible-demo.tsx new file mode 100644 index 0000000..4151575 --- /dev/null +++ b/apps/docs/app/components/preview/demos/collapsible-demo.tsx @@ -0,0 +1,63 @@ +'use client'; + +import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@hareru/ui'; +import { useState } from 'react'; + +export default function CollapsibleDemo() { + const [open, setOpen] = useState(false); + + return ( + +
+ Keyboard shortcuts + + {open ? 'Hide' : 'Show'} + +
+
+ ⌘ K — Open command palette +
+ +
+
+ ⌘ B — Toggle sidebar +
+
+ ⌘ S — Save file +
+
+
+
+ ); +} diff --git a/apps/docs/app/components/preview/demos/combobox-demo.tsx b/apps/docs/app/components/preview/demos/combobox-demo.tsx new file mode 100644 index 0000000..5ccd6fb --- /dev/null +++ b/apps/docs/app/components/preview/demos/combobox-demo.tsx @@ -0,0 +1,46 @@ +'use client'; + +import { + Combobox, + ComboboxContent, + ComboboxEmpty, + ComboboxInput, + ComboboxItem, + ComboboxList, + ComboboxTrigger, +} from '@hareru/ui'; +import { useState } from 'react'; + +const fruits = [ + { value: 'apple', label: 'Apple' }, + { value: 'banana', label: 'Banana' }, + { value: 'cherry', label: 'Cherry' }, + { value: 'grape', label: 'Grape' }, + { value: 'mango', label: 'Mango' }, + { value: 'orange', label: 'Orange' }, +]; + +export default function ComboboxDemo() { + const [selected, setSelected] = useState(''); + + return ( + + {selected || 'Select a fruit...'} + + + + No fruit found. + {fruits.map((fruit) => ( + setSelected(fruit.label)} + > + {fruit.label} + + ))} + + + + ); +} diff --git a/apps/docs/app/components/preview/demos/command-demo.tsx b/apps/docs/app/components/preview/demos/command-demo.tsx new file mode 100644 index 0000000..ddd8baa --- /dev/null +++ b/apps/docs/app/components/preview/demos/command-demo.tsx @@ -0,0 +1,33 @@ +'use client'; + +import { + Command, + CommandEmpty, + CommandGroup, + CommandInput, + CommandItem, + CommandList, +} from '@hareru/ui'; + +export default function CommandDemo() { + return ( + + + + No results found. + + Calendar + Search emoji + Calculator + Launch settings + + + + ); +} diff --git a/apps/docs/app/components/preview/demos/confidence-badge-demo.tsx b/apps/docs/app/components/preview/demos/confidence-badge-demo.tsx new file mode 100644 index 0000000..264027d --- /dev/null +++ b/apps/docs/app/components/preview/demos/confidence-badge-demo.tsx @@ -0,0 +1,21 @@ +'use client'; + +import { ConfidenceBadge } from '@hareru/ui'; + +export default function ConfidenceBadgeDemo() { + return ( +
+
+ + + + +
+
+ + + +
+
+ ); +} diff --git a/apps/docs/app/components/preview/demos/context-menu-demo.tsx b/apps/docs/app/components/preview/demos/context-menu-demo.tsx new file mode 100644 index 0000000..ff2a779 --- /dev/null +++ b/apps/docs/app/components/preview/demos/context-menu-demo.tsx @@ -0,0 +1,41 @@ +'use client'; + +import { + ContextMenu, + ContextMenuContent, + ContextMenuItem, + ContextMenuSeparator, + ContextMenuTrigger, +} from '@hareru/ui'; + +export default function ContextMenuDemo() { + return ( + + +
+ Right-click here +
+
+ + Back + Forward + Reload + + View Page Source + +
+ ); +} diff --git a/apps/docs/app/components/preview/demos/data-quality-indicator-demo.tsx b/apps/docs/app/components/preview/demos/data-quality-indicator-demo.tsx new file mode 100644 index 0000000..5d2d5ad --- /dev/null +++ b/apps/docs/app/components/preview/demos/data-quality-indicator-demo.tsx @@ -0,0 +1,28 @@ +'use client'; + +import { DataQualityIndicator } from '@hareru/ui'; + +export default function DataQualityIndicatorDemo() { + return ( +
+ +
+ ); +} diff --git a/apps/docs/app/components/preview/demos/definition-browser-demo.tsx b/apps/docs/app/components/preview/demos/definition-browser-demo.tsx new file mode 100644 index 0000000..0e2a1f4 --- /dev/null +++ b/apps/docs/app/components/preview/demos/definition-browser-demo.tsx @@ -0,0 +1,51 @@ +'use client'; + +import { DefinitionBrowser } from '@hareru/ui'; + +export default function DefinitionBrowserDemo() { + return ( +
+ +
+ ); +} diff --git a/apps/docs/app/components/preview/demos/dropdown-menu-demo.tsx b/apps/docs/app/components/preview/demos/dropdown-menu-demo.tsx new file mode 100644 index 0000000..42defe2 --- /dev/null +++ b/apps/docs/app/components/preview/demos/dropdown-menu-demo.tsx @@ -0,0 +1,30 @@ +'use client'; + +import { + Button, + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuLabel, + DropdownMenuSeparator, + DropdownMenuTrigger, +} from '@hareru/ui'; + +export default function DropdownMenuDemo() { + return ( + + + + + + My Account + + Profile + Billing + Settings + + Log out + + + ); +} diff --git a/apps/docs/app/components/preview/demos/empty-state-demo.tsx b/apps/docs/app/components/preview/demos/empty-state-demo.tsx new file mode 100644 index 0000000..0cf8903 --- /dev/null +++ b/apps/docs/app/components/preview/demos/empty-state-demo.tsx @@ -0,0 +1,23 @@ +'use client'; + +import { + Button, + EmptyState, + EmptyStateAction, + EmptyStateDescription, + EmptyStateTitle, +} from '@hareru/ui'; + +export default function EmptyStateDemo() { + return ( + + No results found + + Try adjusting your search or filter to find what you are looking for. + + + + + + ); +} diff --git a/apps/docs/app/components/preview/demos/field-diff-demo.tsx b/apps/docs/app/components/preview/demos/field-diff-demo.tsx new file mode 100644 index 0000000..2f3b32d --- /dev/null +++ b/apps/docs/app/components/preview/demos/field-diff-demo.tsx @@ -0,0 +1,16 @@ +'use client'; + +import { FieldDiff } from '@hareru/ui'; + +export default function FieldDiffDemo() { + return ( +
+ +
+ ); +} diff --git a/apps/docs/app/components/preview/demos/form-field-demo.tsx b/apps/docs/app/components/preview/demos/form-field-demo.tsx new file mode 100644 index 0000000..0ac5299 --- /dev/null +++ b/apps/docs/app/components/preview/demos/form-field-demo.tsx @@ -0,0 +1,33 @@ +'use client'; + +import { + FormField, + FormFieldControl, + FormFieldDescription, + FormFieldLabel, + FormFieldMessage, + Input, +} from '@hareru/ui'; + +export default function FormFieldDemo() { + return ( +
+ + Username + + + + This is your public display name. + + + + Email + + + + We will never share your email. + Please enter a valid email address. + +
+ ); +} diff --git a/apps/docs/app/components/preview/demos/key-value-list-demo.tsx b/apps/docs/app/components/preview/demos/key-value-list-demo.tsx new file mode 100644 index 0000000..e0c724f --- /dev/null +++ b/apps/docs/app/components/preview/demos/key-value-list-demo.tsx @@ -0,0 +1,17 @@ +'use client'; + +import { KeyValueList } from '@hareru/ui'; + +export default function KeyValueListDemo() { + return ( +
+ +
+ ); +} diff --git a/apps/docs/app/components/preview/demos/label-demo.tsx b/apps/docs/app/components/preview/demos/label-demo.tsx new file mode 100644 index 0000000..0663735 --- /dev/null +++ b/apps/docs/app/components/preview/demos/label-demo.tsx @@ -0,0 +1,18 @@ +'use client'; + +import { Input, Label } from '@hareru/ui'; + +export default function LabelDemo() { + return ( +
+
+ + +
+
+ + +
+
+ ); +} diff --git a/apps/docs/app/components/preview/demos/metric-card-demo.tsx b/apps/docs/app/components/preview/demos/metric-card-demo.tsx new file mode 100644 index 0000000..21f2b7f --- /dev/null +++ b/apps/docs/app/components/preview/demos/metric-card-demo.tsx @@ -0,0 +1,43 @@ +'use client'; + +import { MetricCard } from '@hareru/ui'; + +export default function MetricCardDemo() { + return ( +
+ + + +
+ ); +} diff --git a/apps/docs/app/components/preview/demos/navigation-menu-demo.tsx b/apps/docs/app/components/preview/demos/navigation-menu-demo.tsx new file mode 100644 index 0000000..4be9b8c --- /dev/null +++ b/apps/docs/app/components/preview/demos/navigation-menu-demo.tsx @@ -0,0 +1,73 @@ +'use client'; + +import { + NavigationMenu, + NavigationMenuContent, + NavigationMenuItem, + NavigationMenuLink, + NavigationMenuList, + NavigationMenuTrigger, +} from '@hareru/ui'; + +export default function NavigationMenuDemo() { + return ( + + + + Getting started + +
+ +
Introduction
+
+ Overview of Hareru UI and its design principles. +
+
+ +
Installation
+
+ How to install and set up in your project. +
+
+
+
+
+ + Components + +
+ +
Button
+
+ Triggers an action or event. +
+
+ +
Input
+
+ Accepts text input from the user. +
+
+
+
+
+
+
+ ); +} diff --git a/apps/docs/app/components/preview/demos/pagination-demo.tsx b/apps/docs/app/components/preview/demos/pagination-demo.tsx new file mode 100644 index 0000000..08be73a --- /dev/null +++ b/apps/docs/app/components/preview/demos/pagination-demo.tsx @@ -0,0 +1,40 @@ +'use client'; + +import { + Pagination, + PaginationContent, + PaginationEllipsis, + PaginationItem, + PaginationLink, + PaginationNext, + PaginationPrevious, +} from '@hareru/ui'; + +export default function PaginationDemo() { + return ( + + + + Previous + + + 1 + + + + 2 + + + + 3 + + + + + + Next + + + + ); +} diff --git a/apps/docs/app/components/preview/demos/popover-demo.tsx b/apps/docs/app/components/preview/demos/popover-demo.tsx new file mode 100644 index 0000000..5e93c11 --- /dev/null +++ b/apps/docs/app/components/preview/demos/popover-demo.tsx @@ -0,0 +1,21 @@ +'use client'; + +import { Button, Popover, PopoverContent, PopoverTrigger } from '@hareru/ui'; + +export default function PopoverDemo() { + return ( + + + + + +
+

Dimensions

+

+ Set the dimensions for the layer. +

+
+
+
+ ); +} diff --git a/apps/docs/app/components/preview/demos/preview-card-demo.tsx b/apps/docs/app/components/preview/demos/preview-card-demo.tsx new file mode 100644 index 0000000..32a9446 --- /dev/null +++ b/apps/docs/app/components/preview/demos/preview-card-demo.tsx @@ -0,0 +1,21 @@ +'use client'; + +import { PreviewCard, PreviewCardContent, PreviewCardTrigger } from '@hareru/ui'; + +export default function PreviewCardDemo() { + return ( + + + @hareru/ui + + +
+

Hareru UI

+

+ A semantic CSS design system with accessible React components. +

+
+
+
+ ); +} diff --git a/apps/docs/app/components/preview/demos/progress-demo.tsx b/apps/docs/app/components/preview/demos/progress-demo.tsx new file mode 100644 index 0000000..ea277be --- /dev/null +++ b/apps/docs/app/components/preview/demos/progress-demo.tsx @@ -0,0 +1,21 @@ +'use client'; + +import { Progress } from '@hareru/ui'; + +export default function ProgressDemo() { + return ( +
+ + + +
+ ); +} diff --git a/apps/docs/app/components/preview/demos/query-feedback-demo.tsx b/apps/docs/app/components/preview/demos/query-feedback-demo.tsx new file mode 100644 index 0000000..aed1f50 --- /dev/null +++ b/apps/docs/app/components/preview/demos/query-feedback-demo.tsx @@ -0,0 +1,22 @@ +'use client'; + +import { QueryFeedback } from '@hareru/ui'; + +export default function QueryFeedbackDemo() { + return ( +
+
+ Was this response helpful? + console.log('feedback:', v)} /> +
+
+ Pre-selected helpful: + +
+
+ Disabled: + +
+
+ ); +} diff --git a/apps/docs/app/components/preview/demos/radio-group-demo.tsx b/apps/docs/app/components/preview/demos/radio-group-demo.tsx new file mode 100644 index 0000000..a55699f --- /dev/null +++ b/apps/docs/app/components/preview/demos/radio-group-demo.tsx @@ -0,0 +1,22 @@ +'use client'; + +import { RadioGroup, RadioGroupItem } from '@hareru/ui'; +import { useState } from 'react'; + +export default function RadioGroupDemo() { + const [value, setValue] = useState('standard'); + + return ( +
+ + Free + Standard + Pro + + Enterprise (contact sales) + + +

Selected: {value}

+
+ ); +} diff --git a/apps/docs/app/components/preview/demos/readonly-field-demo.tsx b/apps/docs/app/components/preview/demos/readonly-field-demo.tsx new file mode 100644 index 0000000..7dbeda8 --- /dev/null +++ b/apps/docs/app/components/preview/demos/readonly-field-demo.tsx @@ -0,0 +1,13 @@ +'use client'; + +import { ReadonlyField } from '@hareru/ui'; + +export default function ReadonlyFieldDemo() { + return ( +
+ + + +
+ ); +} diff --git a/apps/docs/app/components/preview/demos/reasoning-panel-demo.tsx b/apps/docs/app/components/preview/demos/reasoning-panel-demo.tsx new file mode 100644 index 0000000..28bec34 --- /dev/null +++ b/apps/docs/app/components/preview/demos/reasoning-panel-demo.tsx @@ -0,0 +1,20 @@ +'use client'; + +import { ReasoningPanel } from '@hareru/ui'; + +export default function ReasoningPanelDemo() { + return ( +
+ +

+ The user is asking about revenue trends. I should query the orders dataset filtered by + date range and aggregate by month. +

+

Joining with the products table will allow breakdown by category.

+
+ +

Analyzing the semantic model to identify relevant metrics...

+
+
+ ); +} diff --git a/apps/docs/app/components/preview/demos/scroll-area-demo.tsx b/apps/docs/app/components/preview/demos/scroll-area-demo.tsx new file mode 100644 index 0000000..301d310 --- /dev/null +++ b/apps/docs/app/components/preview/demos/scroll-area-demo.tsx @@ -0,0 +1,33 @@ +'use client'; + +import { ScrollArea } from '@hareru/ui'; + +const items = Array.from({ length: 20 }, (_, i) => `Item ${i + 1}`); + +export default function ScrollAreaDemo() { + return ( + +
+ {items.map((item) => ( +
+ {item} +
+ ))} +
+
+ ); +} diff --git a/apps/docs/app/components/preview/demos/select-demo.tsx b/apps/docs/app/components/preview/demos/select-demo.tsx new file mode 100644 index 0000000..185319e --- /dev/null +++ b/apps/docs/app/components/preview/demos/select-demo.tsx @@ -0,0 +1,40 @@ +'use client'; + +import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@hareru/ui'; + +export default function SelectDemo() { + return ( +
+ + + + + +
+ ); +} diff --git a/apps/docs/app/components/preview/demos/semantic-suggest-demo.tsx b/apps/docs/app/components/preview/demos/semantic-suggest-demo.tsx new file mode 100644 index 0000000..5efbd40 --- /dev/null +++ b/apps/docs/app/components/preview/demos/semantic-suggest-demo.tsx @@ -0,0 +1,32 @@ +'use client'; + +import { SemanticSuggest } from '@hareru/ui'; + +export default function SemanticSuggestDemo() { + return ( +
+ {}} + onReject={() => {}} + /> + + +
+ ); +} diff --git a/apps/docs/app/components/preview/demos/separator-demo.tsx b/apps/docs/app/components/preview/demos/separator-demo.tsx new file mode 100644 index 0000000..3496790 --- /dev/null +++ b/apps/docs/app/components/preview/demos/separator-demo.tsx @@ -0,0 +1,29 @@ +'use client'; + +import { Separator } from '@hareru/ui'; + +export default function SeparatorDemo() { + return ( +
+
+

Above the separator

+ +

Below the separator

+
+
+ Blog + + Docs + + Source +
+
+ ); +} diff --git a/apps/docs/app/components/preview/demos/sheet-demo.tsx b/apps/docs/app/components/preview/demos/sheet-demo.tsx new file mode 100644 index 0000000..94a1f70 --- /dev/null +++ b/apps/docs/app/components/preview/demos/sheet-demo.tsx @@ -0,0 +1,38 @@ +'use client'; + +import { + Button, + Sheet, + SheetContent, + SheetDescription, + SheetHeader, + SheetTitle, + SheetTrigger, +} from '@hareru/ui'; + +export default function SheetDemo() { + return ( + + + + + + + Edit profile + + Make changes to your profile here. Click save when you are done. + + +
+ Profile form fields would go here. +
+
+
+ ); +} diff --git a/apps/docs/app/components/preview/demos/skeleton-demo.tsx b/apps/docs/app/components/preview/demos/skeleton-demo.tsx new file mode 100644 index 0000000..5d21212 --- /dev/null +++ b/apps/docs/app/components/preview/demos/skeleton-demo.tsx @@ -0,0 +1,33 @@ +'use client'; + +import { Skeleton } from '@hareru/ui'; + +export default function SkeletonDemo() { + return ( +
+
+ +
+ + +
+
+
+ + + +
+ +
+ ); +} diff --git a/apps/docs/app/components/preview/demos/slider-demo.tsx b/apps/docs/app/components/preview/demos/slider-demo.tsx new file mode 100644 index 0000000..38cc8bd --- /dev/null +++ b/apps/docs/app/components/preview/demos/slider-demo.tsx @@ -0,0 +1,45 @@ +'use client'; + +import { Slider, SliderRange, SliderThumb, SliderTrack } from '@hareru/ui'; +import { useState } from 'react'; + +export default function SliderDemo() { + const [value, setValue] = useState(40); + + return ( +
+
+
+ Volume + {value}% +
+ setValue(v as number)} min={0} max={100}> + + + + + +
+ +
+ Default value + + + + + + +
+ +
+ Disabled + + + + + + +
+
+ ); +} diff --git a/apps/docs/app/components/preview/demos/streaming-text-demo.tsx b/apps/docs/app/components/preview/demos/streaming-text-demo.tsx new file mode 100644 index 0000000..1b56203 --- /dev/null +++ b/apps/docs/app/components/preview/demos/streaming-text-demo.tsx @@ -0,0 +1,34 @@ +'use client'; + +import { StreamingText } from '@hareru/ui'; + +export default function StreamingTextDemo() { + return ( +
+
+

+ Completed (streaming=false) +

+ + The analysis is complete. All metrics are within expected ranges. + +
+
+

+ Streaming with blink cursor +

+ + Generating response + +
+
+

+ Streaming with pulse cursor +

+ + Loading data + +
+
+ ); +} diff --git a/apps/docs/app/components/preview/demos/switch-demo.tsx b/apps/docs/app/components/preview/demos/switch-demo.tsx new file mode 100644 index 0000000..d4004c6 --- /dev/null +++ b/apps/docs/app/components/preview/demos/switch-demo.tsx @@ -0,0 +1,22 @@ +'use client'; + +import { Label, Switch } from '@hareru/ui'; + +export default function SwitchDemo() { + return ( +
+
+ + +
+
+ + +
+
+ + +
+
+ ); +} diff --git a/apps/docs/app/components/preview/demos/table-demo.tsx b/apps/docs/app/components/preview/demos/table-demo.tsx new file mode 100644 index 0000000..4fd2505 --- /dev/null +++ b/apps/docs/app/components/preview/demos/table-demo.tsx @@ -0,0 +1,34 @@ +'use client'; + +import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@hareru/ui'; + +export default function TableDemo() { + return ( + + + + Name + Status + Amount + + + + + Alice Johnson + Active + $1,200 + + + Bob Smith + Pending + $840 + + + Carol White + Inactive + $2,450 + + +
+ ); +} diff --git a/apps/docs/app/components/preview/demos/textarea-demo.tsx b/apps/docs/app/components/preview/demos/textarea-demo.tsx new file mode 100644 index 0000000..7106cdb --- /dev/null +++ b/apps/docs/app/components/preview/demos/textarea-demo.tsx @@ -0,0 +1,13 @@ +'use client'; + +import { Textarea } from '@hareru/ui'; + +export default function TextareaDemo() { + return ( +
+