diff --git a/packages/showcase/src/app.tsx b/packages/showcase/src/app.tsx index 0e0bc80..5dbdbd7 100644 --- a/packages/showcase/src/app.tsx +++ b/packages/showcase/src/app.tsx @@ -1,4 +1,12 @@ import type { JSX } from "solid-js"; +import { LayoutDisplaySection } from "./sections/layout-display"; +import { InputsBasicSection } from "./sections/inputs-basic"; +import { InputsSelectionSection } from "./sections/inputs-selection"; +import { InputsAdvancedSection } from "./sections/inputs-advanced"; +import { NavigationSection } from "./sections/navigation"; +import { OverlaysSection } from "./sections/overlays"; +import { FeedbackStatusSection } from "./sections/feedback-status"; +import { DataSection } from "./sections/data"; const categories = [ { id: "layout-display", label: "Layout & Display" }, @@ -55,28 +63,28 @@ export function App() {
-

Coming soon...

+
-

Coming soon...

+
-

Coming soon...

+
-

Coming soon...

+
-

Coming soon...

+
-

Coming soon...

+
-

Coming soon...

+
diff --git a/packages/showcase/src/sections/data.tsx b/packages/showcase/src/sections/data.tsx new file mode 100644 index 0000000..079b3dc --- /dev/null +++ b/packages/showcase/src/sections/data.tsx @@ -0,0 +1,112 @@ +import { For } from "solid-js"; +import { Calendar } from "pettyui/calendar"; +import { DataTable } from "pettyui/data-table"; +import { VirtualList } from "pettyui/virtual-list"; +import { ComponentDemo } from "../component-demo"; + +const cellCls = "px-3 py-2 text-sm text-gray-700 border-b border-gray-100"; +const headCls = "px-3 py-2 text-xs font-semibold text-gray-500 uppercase tracking-wide border-b border-gray-200 bg-gray-50 text-left"; + +type Person = { id: number; name: string; role: string; status: string }; + +const people: Person[] = [ + { id: 1, name: "Alice Chen", role: "Engineer", status: "Active" }, + { id: 2, name: "Bob Kim", role: "Designer", status: "Active" }, + { id: 3, name: "Carol Diaz", role: "Manager", status: "Away" }, + { id: 4, name: "Dan Park", role: "Engineer", status: "Active" }, + { id: 5, name: "Eva Müller", role: "Product", status: "Inactive" }, +]; + +const tableColumns = [ + { id: "name", header: "Name", sortable: true, accessor: (r: Person) => r.name }, + { id: "role", header: "Role", sortable: true, accessor: (r: Person) => r.role }, + { id: "status", header: "Status", sortable: false, accessor: (r: Person) => r.status }, +]; + +/** Calendar demo showing a navigable month grid. */ +function CalendarDemo() { + const navBtn = "w-7 h-7 flex items-center justify-center rounded hover:bg-gray-100 text-gray-600 text-sm"; + const content = ( + + + + ‹ + › + + + + + + + + + ); + return content; +} + +/** DataTable demo with sortable columns and 5 sample rows. */ +function DataTableDemo() { + const content = ( +
+ + + + + + {(col) => } + + + + +
{col.header}
+
+
+ ); + return content; +} + +const ITEM_COUNT = 10000; +const ITEM_HEIGHT = 36; + +/** VirtualList demo rendering 10 000 items with windowed scroll. */ +function VirtualListDemo() { + const content = ( +
+
+ {ITEM_COUNT.toLocaleString()} items — only visible rows are rendered +
+ + {(item) => ( +
+ #{item.index + 1} + Item {item.index + 1} +
+ )} +
+
+ ); + return content; +} + +/** Data section with calendar, table, and virtual list components. */ +export function DataSection() { + const content = ( + <> + + + + + + + + + + + ); + return content; +} diff --git a/packages/showcase/src/sections/feedback-status.tsx b/packages/showcase/src/sections/feedback-status.tsx new file mode 100644 index 0000000..8ba3fab --- /dev/null +++ b/packages/showcase/src/sections/feedback-status.tsx @@ -0,0 +1,116 @@ +import { Alert } from "pettyui/alert"; +import { Toast, toast } from "pettyui/toast"; +import { Progress } from "pettyui/progress"; +import { Meter } from "pettyui/meter"; +import { ComponentDemo } from "../component-demo"; + +const btnBase = "px-3 py-1.5 text-sm font-medium rounded border"; + +/** Alert demo showing info, success, and error variants. */ +function AlertDemo() { + const content = ( +
+ + Info: Your session will expire in 5 minutes. + + + Success: Your changes have been saved. + + + Error: Failed to connect to the server. + +
+ ); + return content; +} + +/** Toast demo with imperative API triggering different toast types. */ +function ToastDemo() { + const content = ( +
+
+ + + + +
+ +
+ ); + return content; +} + +/** Progress demo showing a determinate bar at 60%. */ +function ProgressDemo() { + const content = ( +
+
+
+ Uploading file... + 60% +
+
+ +
+
+
+
+ Processing... + indeterminate +
+
+ +
+
+
+ ); + return content; +} + +/** Meter demo showing a scalar measurement at 75%. */ +function MeterDemo() { + const content = ( +
+
+
+ Disk usage + 75 / 100 GB +
+
+ +
+
+
+
+ Password strength + Strong +
+
+ +
+
+
+ ); + return content; +} + +/** Feedback and Status section with notification and indicator components. */ +export function FeedbackStatusSection() { + const content = ( + <> + + + + + + + + + + + + + + ); + return content; +} diff --git a/packages/showcase/src/sections/inputs-advanced.tsx b/packages/showcase/src/sections/inputs-advanced.tsx new file mode 100644 index 0000000..5a9c1b3 --- /dev/null +++ b/packages/showcase/src/sections/inputs-advanced.tsx @@ -0,0 +1,56 @@ +import { Form } from "pettyui/form"; +import { DatePicker } from "pettyui/date-picker"; +import { ComponentDemo } from "../component-demo"; + +/** Form demo with validation and error display. */ +function FormDemo() { + const content = ( +
{ alert(`Submitted: ${JSON.stringify(data)}`); }} + class="flex flex-col gap-4 max-w-sm" + > + + Name + + Required field + + + + Email + + + + Submit +
+ ); + return content; +} + +/** DatePicker demo with calendar dropdown. */ +function DatePickerDemo() { + const content = ( + +
+ + 📅 +
+ +
+ ); + return content; +} + +/** Inputs Advanced section with complex input components. */ +export function InputsAdvancedSection() { + const content = ( + <> + + + + + + + + ); + return content; +} diff --git a/packages/showcase/src/sections/inputs-basic.tsx b/packages/showcase/src/sections/inputs-basic.tsx new file mode 100644 index 0000000..23f770a --- /dev/null +++ b/packages/showcase/src/sections/inputs-basic.tsx @@ -0,0 +1,116 @@ +import { Button } from "pettyui/button"; +import { TextField } from "pettyui/text-field"; +import { NumberField } from "pettyui/number-field"; +import { Checkbox } from "pettyui/checkbox"; +import { Switch } from "pettyui/switch"; +import { Toggle } from "pettyui/toggle"; +import { ComponentDemo } from "../component-demo"; + +/** Button demo with primary, secondary, ghost, disabled variants. */ +const ButtonDemo = () => ( +
+ + + + +
+); + +/** TextField demo with label, description, and error state. */ +const TextFieldDemo = () => ( +
+ + Name + + Your full name + + + Email + + Invalid email address + +
+); + +/** NumberField demo with increment and decrement buttons. */ +const NumberFieldDemo = () => ( + + Quantity +
+ - + + + +
+
+); + +/** Checkbox demo with checked and unchecked states. */ +const CheckboxDemo = () => ( +
+ + {(state) => ( + <> +
+ {state.checked() ? "✓" : ""} +
+ Accept terms and conditions + + )} +
+ + {(state) => ( + <> +
+ {state.checked() ? "✓" : ""} +
+ Subscribe to newsletter + + )} +
+
+); + +/** Switch demo with on/off toggle. */ +const SwitchDemo = () => ( + + {(state) => ( + <> +
+
+
+ {state.checked() ? "On" : "Off"} + + )} + +); + +/** Toggle demo with pressed/unpressed states. */ +const ToggleDemo = () => ( + + Bold + +); + +/** Inputs Basic section with fundamental input components. */ +export const InputsBasicSection = () => ( + <> + + + + + + + + + + + + + + + + + + + +); diff --git a/packages/showcase/src/sections/inputs-selection.tsx b/packages/showcase/src/sections/inputs-selection.tsx new file mode 100644 index 0000000..705aef3 --- /dev/null +++ b/packages/showcase/src/sections/inputs-selection.tsx @@ -0,0 +1,146 @@ +import { createSignal, For } from "solid-js"; +import { RadioGroup } from "pettyui/radio-group"; +import { ToggleGroup } from "pettyui/toggle-group"; +import { Select, SelectTrigger, SelectValue, SelectContent, SelectItem } from "pettyui/select"; +import { Combobox, ComboboxInput, ComboboxTrigger, ComboboxContent, ComboboxItem } from "pettyui/combobox"; +import { Listbox } from "pettyui/listbox"; +import { Slider } from "pettyui/slider"; +import { ComponentDemo } from "../component-demo"; + +const fruits = ["Apple", "Banana", "Cherry", "Date", "Elderberry"]; + +/** RadioGroup demo with 3 mutually exclusive options. */ +function RadioGroupDemo() { + const content = ( + + + {(value) => ( + + {(itemState) => ( + <> +
+ {itemState.checked() &&
} +
+ Option {value.split("-")[1]?.toUpperCase()} + + )} + + )} + + + ); + return content; +} + +/** ToggleGroup demo with single selection alignment. */ +function ToggleGroupDemo() { + const content = ( + + Left + Center + Right + + ); + return content; +} + +/** Select demo with fruit dropdown. */ +function SelectDemo() { + const content = ( + + ); + return content; +} + +/** Combobox demo with searchable fruit list. */ +function ComboboxDemo() { + const content = ( + +
+ + â–¾ +
+ + + {(fruit) => ( + {fruit} + )} + + +
+ ); + return content; +} + +/** Listbox demo with inline selectable items. */ +function ListboxDemo() { + const content = ( + + + {(fruit) => ( + {fruit} + )} + + + ); + return content; +} + +/** Slider demo with value display. */ +function SliderDemo() { + const [value, setValue] = createSignal(40); + const content = ( +
+
+ Volume + {value()}% +
+ + + + + + +
+ ); + return content; +} + +/** Inputs Selection section with choice and range components. */ +export function InputsSelectionSection() { + const content = ( + <> + + + + + + + + + + + + + + + + + + + + ); + return content; +} diff --git a/packages/showcase/src/sections/layout-display.tsx b/packages/showcase/src/sections/layout-display.tsx new file mode 100644 index 0000000..3b509f4 --- /dev/null +++ b/packages/showcase/src/sections/layout-display.tsx @@ -0,0 +1,107 @@ +import { Avatar } from "pettyui/avatar"; +import { Badge } from "pettyui/badge"; +import { Card } from "pettyui/card"; +import { Image } from "pettyui/image"; +import { Separator } from "pettyui/separator"; +import { Skeleton } from "pettyui/skeleton"; +import { ComponentDemo } from "../component-demo"; + +/** Avatar demo with image and fallback variants. */ +const AvatarDemo = () => ( +
+ + + MB + + + + JD + +
+); + +/** Badge demo with multiple variants. */ +const BadgeDemo = () => ( +
+ Default + Info + Success + Warning + Error +
+); + +/** Card demo with header, content, and footer. */ +const CardDemo = () => ( + + + Card Title + A short description of this card. + + +

Card body content goes here.

+
+ + + + +
+); + +/** Image demo with working and broken sources. */ +const ImageDemo = () => ( +
+ + + Loading... + + + + No image + +
+); + +/** Separator demo with horizontal divider. */ +const SeparatorDemo = () => ( +
+

Above the separator

+ +

Below the separator

+
+); + +/** Skeleton demo with different shapes. */ +const SkeletonDemo = () => ( +
+ +
+ + +
+
+); + +/** Layout and Display section with all display components. */ +export const LayoutDisplaySection = () => ( + <> + + + + + + + + + + + + + + + + + + + +); diff --git a/packages/showcase/src/sections/navigation.tsx b/packages/showcase/src/sections/navigation.tsx new file mode 100644 index 0000000..6fd9bcd --- /dev/null +++ b/packages/showcase/src/sections/navigation.tsx @@ -0,0 +1,201 @@ +import { For } from "solid-js"; +import { Link } from "pettyui/link"; +import { Breadcrumbs } from "pettyui/breadcrumbs"; +import { Tabs } from "pettyui/tabs"; +import { Accordion } from "pettyui/accordion"; +import { Collapsible } from "pettyui/collapsible"; +import { Pagination } from "pettyui/pagination"; +import { NavigationMenu } from "pettyui/navigation-menu"; +import { Wizard } from "pettyui/wizard"; +import { ComponentDemo } from "../component-demo"; + +/** Link demo with internal, external, and disabled variants. */ +function LinkDemo() { + const content = ( +
+ Internal link + External link ↗ + Disabled link +
+ ); + return content; +} + +/** Breadcrumbs demo with 3-level trail. */ +function BreadcrumbsDemo() { + const content = ( + + + Home + / + + + Components + / + + + Breadcrumbs + + + ); + return content; +} + +/** Tabs demo with 3 content panels. */ +function TabsDemo() { + const content = ( + + + Account + Password + Settings + + Account settings content + Password settings content + General settings content + + ); + return content; +} + +const accordionItems = [ + { value: "item-1", title: "What is PettyUI?", content: "A headless SolidJS component library." }, + { value: "item-2", title: "Is it accessible?", content: "Yes, all components follow WAI-ARIA patterns." }, + { value: "item-3", title: "Can I style it?", content: "Absolutely. It's headless — bring your own styles." }, +]; + +/** Accordion demo with 3 collapsible sections. */ +function AccordionDemo() { + const content = ( + + + {(item) => ( + + + + {item.title} + ▾ + + + {item.content} + + )} + + + ); + return content; +} + +/** Collapsible demo with expand/collapse toggle. */ +function CollapsibleDemo() { + const content = ( + + + ▶ Show more details + + + Here are the additional details that were hidden. Click again to collapse. + + + ); + return content; +} + +/** Pagination demo with page navigation. */ +function PaginationDemo() { + const content = ; + return content; +} + +/** NavigationMenu demo with dropdown submenu. */ +function NavigationMenuDemo() { + const content = ( + + + + Home + + + Products ▾ + + Widget A + Widget B + + + + About + + + + ); + return content; +} + +/** Wizard step indicators helper for the wizard demo. */ +function WizardSteps() { + const content = ( + + + {(label, i) => ( + + + {i() + 1} + + {label} + + )} + + + ); + return content; +} + +/** Wizard demo with 3-step flow. */ +function WizardDemo() { + const content = ( + + + Step 1: Enter your details here. + Step 2: Review your information. + Step 3: Confirm and submit. +
+ Previous + Next +
+
+ ); + return content; +} + +/** Navigation section with all navigation components. */ +export function NavigationSection() { + const content = ( + <> + + + + + + + + + + + + + + + + + + + + + + + + + + ); + return content; +} diff --git a/packages/showcase/src/sections/overlays.tsx b/packages/showcase/src/sections/overlays.tsx new file mode 100644 index 0000000..16a7479 --- /dev/null +++ b/packages/showcase/src/sections/overlays.tsx @@ -0,0 +1,209 @@ +import { createSignal } from "solid-js"; +import { Dialog } from "pettyui/dialog"; +import { AlertDialog } from "pettyui/alert-dialog"; +import { Drawer } from "pettyui/drawer"; +import { Popover } from "pettyui/popover"; +import { TooltipRoot, TooltipTrigger, TooltipContent } from "pettyui/tooltip"; +import { HoverCardRoot, HoverCardTrigger, HoverCardContent } from "pettyui/hover-card"; +import { DropdownMenuRoot, DropdownMenuTrigger, DropdownMenuContent, DropdownMenuItem, DropdownMenuSeparator } from "pettyui/dropdown-menu"; +import { ContextMenuRoot, ContextMenuTrigger, ContextMenuContent, ContextMenuItem } from "pettyui/context-menu"; +import { CommandPalette } from "pettyui/command-palette"; +import { ComponentDemo } from "../component-demo"; + +const triggerBtn = "px-3 py-1.5 text-sm font-medium rounded border border-gray-300 hover:bg-gray-50"; +const overlayBg = "fixed inset-0 bg-black/40 z-40"; +const panelBase = "bg-white rounded-lg shadow-xl p-6 z-50"; +const modalPos = "fixed top-1/2 left-1/2 -translate-x-1/2 -translate-y-1/2 w-96"; + +/** Dialog demo with modal overlay. */ +function DialogDemo() { + const content = ( + + Open Dialog + + + + Dialog Title + + This is a modal dialog. Press Escape or click Close to dismiss. + + Close + + + + ); + return content; +} + +/** AlertDialog demo with confirm/cancel actions. */ +function AlertDialogDemo() { + const content = ( + + Delete Item + + + + Are you sure? + This action cannot be undone. +
+ Cancel + Delete +
+
+
+
+ ); + return content; +} + +/** Drawer demo sliding in from the right edge. */ +function DrawerDemo() { + const content = ( + + Open Drawer + + + + Drawer Panel + This drawer slides in from the right. + Close + + + + ); + return content; +} + +/** Popover demo with floating content panel. */ +function PopoverDemo() { + const content = ( + + Toggle Popover + + +

This is a popover with interactive content.

+ Dismiss +
+
+
+ ); + return content; +} + +/** Tooltip demo that appears on hover. */ +function TooltipDemo() { + const content = ( + + Hover me + + This is a tooltip + + + ); + return content; +} + +/** HoverCard demo with rich preview on hover. */ +function HoverCardDemo() { + const content = ( + + @pettyui + +

PettyUI

+

AI-native headless UI for SolidJS. 44 components.

+
+
+ ); + return content; +} + +/** DropdownMenu demo with action items. */ +function DropdownMenuDemo() { + const content = ( + + Actions â–¾ + + Edit + Duplicate + + Delete + + + ); + return content; +} + +/** ContextMenu demo with right-click trigger area. */ +function ContextMenuDemo() { + const content = ( + + + Right-click here + + + Copy + Paste + Inspect + + + ); + return content; +} + +/** CommandPalette demo with searchable commands. */ +function CommandPaletteDemo() { + const [open, setOpen] = createSignal(false); + const content = ( +
+ + + + + + New File + Open File + Save + + No results found + + +
+ ); + return content; +} + +/** Overlays section showcasing all overlay and modal components. */ +export function OverlaysSection() { + const content = ( + <> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); + return content; +}