Layout & Display, Inputs Basic, Inputs Selection, Inputs Advanced, Navigation, Overlays, Feedback & Status, and Data sections with live interactive demos for every PettyUI component.
117 lines
5.6 KiB
TypeScript
117 lines
5.6 KiB
TypeScript
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 = () => (
|
|
<div class="flex items-center gap-3">
|
|
<Button class="px-4 py-2 text-sm font-medium rounded bg-indigo-600 text-white hover:bg-indigo-700">Primary</Button>
|
|
<Button class="px-4 py-2 text-sm font-medium rounded border border-gray-300 hover:bg-gray-50">Secondary</Button>
|
|
<Button class="px-4 py-2 text-sm font-medium rounded text-indigo-600 hover:bg-indigo-50">Ghost</Button>
|
|
<Button disabled class="px-4 py-2 text-sm font-medium rounded bg-gray-100 text-gray-400 cursor-not-allowed">Disabled</Button>
|
|
</div>
|
|
);
|
|
|
|
/** TextField demo with label, description, and error state. */
|
|
const TextFieldDemo = () => (
|
|
<div class="flex gap-6">
|
|
<TextField class="flex flex-col gap-1">
|
|
<TextField.Label class="text-sm font-medium text-gray-700">Name</TextField.Label>
|
|
<TextField.Input placeholder="Enter your name" class="border border-gray-300 rounded px-3 py-1.5 text-sm focus:outline-none focus:ring-2 focus:ring-indigo-500" />
|
|
<TextField.Description class="text-xs text-gray-400">Your full name</TextField.Description>
|
|
</TextField>
|
|
<TextField validationState="invalid" class="flex flex-col gap-1">
|
|
<TextField.Label class="text-sm font-medium text-red-600">Email</TextField.Label>
|
|
<TextField.Input value="not-an-email" class="border border-red-300 rounded px-3 py-1.5 text-sm focus:outline-none focus:ring-2 focus:ring-red-500" />
|
|
<TextField.ErrorMessage class="text-xs text-red-500">Invalid email address</TextField.ErrorMessage>
|
|
</TextField>
|
|
</div>
|
|
);
|
|
|
|
/** NumberField demo with increment and decrement buttons. */
|
|
const NumberFieldDemo = () => (
|
|
<NumberField defaultValue={5} min={0} max={100} class="flex flex-col gap-1">
|
|
<NumberField.Label class="text-sm font-medium text-gray-700">Quantity</NumberField.Label>
|
|
<div class="flex items-center gap-1">
|
|
<NumberField.DecrementTrigger class="w-8 h-8 flex items-center justify-center border border-gray-300 rounded hover:bg-gray-50 text-sm">-</NumberField.DecrementTrigger>
|
|
<NumberField.Input class="w-16 text-center border border-gray-300 rounded px-2 py-1 text-sm focus:outline-none focus:ring-2 focus:ring-indigo-500" />
|
|
<NumberField.IncrementTrigger class="w-8 h-8 flex items-center justify-center border border-gray-300 rounded hover:bg-gray-50 text-sm">+</NumberField.IncrementTrigger>
|
|
</div>
|
|
</NumberField>
|
|
);
|
|
|
|
/** Checkbox demo with checked and unchecked states. */
|
|
const CheckboxDemo = () => (
|
|
<div class="flex flex-col gap-3">
|
|
<Checkbox class="flex items-center gap-2 cursor-pointer">
|
|
{(state) => (
|
|
<>
|
|
<div class={`w-4 h-4 border rounded flex items-center justify-center text-xs ${state.checked() ? "bg-indigo-600 border-indigo-600 text-white" : "border-gray-300"}`}>
|
|
{state.checked() ? "✓" : ""}
|
|
</div>
|
|
<span class="text-sm text-gray-700">Accept terms and conditions</span>
|
|
</>
|
|
)}
|
|
</Checkbox>
|
|
<Checkbox defaultChecked class="flex items-center gap-2 cursor-pointer">
|
|
{(state) => (
|
|
<>
|
|
<div class={`w-4 h-4 border rounded flex items-center justify-center text-xs ${state.checked() ? "bg-indigo-600 border-indigo-600 text-white" : "border-gray-300"}`}>
|
|
{state.checked() ? "✓" : ""}
|
|
</div>
|
|
<span class="text-sm text-gray-700">Subscribe to newsletter</span>
|
|
</>
|
|
)}
|
|
</Checkbox>
|
|
</div>
|
|
);
|
|
|
|
/** Switch demo with on/off toggle. */
|
|
const SwitchDemo = () => (
|
|
<Switch class="flex items-center gap-3 cursor-pointer">
|
|
{(state) => (
|
|
<>
|
|
<div class={`w-10 h-6 rounded-full relative transition-colors ${state.checked() ? "bg-indigo-600" : "bg-gray-300"}`}>
|
|
<div class={`absolute top-0.5 w-5 h-5 rounded-full bg-white shadow transition-transform ${state.checked() ? "translate-x-4" : "translate-x-0.5"}`} />
|
|
</div>
|
|
<span class="text-sm text-gray-700">{state.checked() ? "On" : "Off"}</span>
|
|
</>
|
|
)}
|
|
</Switch>
|
|
);
|
|
|
|
/** Toggle demo with pressed/unpressed states. */
|
|
const ToggleDemo = () => (
|
|
<Toggle class="px-3 py-1.5 text-sm border rounded transition-colors data-[pressed]:bg-indigo-100 data-[pressed]:text-indigo-700 data-[pressed]:border-indigo-300 border-gray-300 hover:bg-gray-50">
|
|
Bold
|
|
</Toggle>
|
|
);
|
|
|
|
/** Inputs Basic section with fundamental input components. */
|
|
export const InputsBasicSection = () => (
|
|
<>
|
|
<ComponentDemo name="Button" description="Clickable element that triggers an action">
|
|
<ButtonDemo />
|
|
</ComponentDemo>
|
|
<ComponentDemo name="TextField" description="Text input field with label, description, and error message support">
|
|
<TextFieldDemo />
|
|
</ComponentDemo>
|
|
<ComponentDemo name="NumberField" description="Numeric input with increment/decrement buttons and keyboard support">
|
|
<NumberFieldDemo />
|
|
</ComponentDemo>
|
|
<ComponentDemo name="Checkbox" description="Toggle control for boolean input, supports indeterminate state">
|
|
<CheckboxDemo />
|
|
</ComponentDemo>
|
|
<ComponentDemo name="Switch" description="Toggle control for on/off states, visually distinct from checkbox">
|
|
<SwitchDemo />
|
|
</ComponentDemo>
|
|
<ComponentDemo name="Toggle" description="Two-state button that can be toggled on or off">
|
|
<ToggleDemo />
|
|
</ComponentDemo>
|
|
</>
|
|
);
|