2026-04-01 01:42:10 +07:00

423 lines
22 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="PettyUI showcase — 45 headless Web Components, zero dependencies, built on browser standards." />
<title>PettyUI — Component Showcase</title>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link href="https://fonts.googleapis.com/css2?family=Instrument+Sans:wght@400;500;600;700&family=IBM+Plex+Mono:wght@400;500&display=swap" rel="stylesheet" />
<script type="module">
import "pettyui/button"; import "pettyui/link"; import "pettyui/separator";
import "pettyui/badge"; import "pettyui/skeleton"; import "pettyui/avatar";
import "pettyui/card"; import "pettyui/text-field"; import "pettyui/checkbox";
import "pettyui/switch"; import "pettyui/radio-group"; import "pettyui/toggle";
import "pettyui/toggle-group"; import "pettyui/number-field"; import "pettyui/slider";
import "pettyui/tags-input"; import "pettyui/select"; import "pettyui/tabs";
import "pettyui/accordion"; import "pettyui/collapsible"; import "pettyui/breadcrumbs";
import "pettyui/pagination"; import "pettyui/dialog"; import "pettyui/alert-dialog";
import "pettyui/popover"; import "pettyui/tooltip"; import "pettyui/dropdown-menu";
import "pettyui/alert"; import "pettyui/progress"; import "pettyui/meter";
import "pettyui/toast"; import { toast } from "pettyui/toast";
import "pettyui/typewriter"; import "pettyui/counter";
import "pettyui/stagger"; import "pettyui/reveal";
import "pettyui/loading-indicator"; import "pettyui/animations";
document.querySelector("#demo-toast-btn")?.addEventListener("click", () => {
toast.success("Component loaded", { description: "PettyUI runs with zero deps" });
});
document.querySelector("#demo-toast-err")?.addEventListener("click", () => {
toast.error("Something broke", { description: "Just kidding" });
});
</script>
<link rel="stylesheet" href="./style.css" />
</head>
<body>
<a href="#main" class="skip-link">Skip to content</a>
<main class="page" id="main">
<section class="hero">
<h1><petty-typewriter speed="60">PettyUI</petty-typewriter></h1>
<p class="hero-sub"><petty-typewriter speed="25" delay="600">45 headless Web Components. Zero dependencies. Browser-native APIs. The smallest UI library that does everything.</petty-typewriter></p>
<div class="hero-stats">
<span class="hero-stat"><petty-counter to="45" duration="1500" delay="1200"></petty-counter> components</span>
<span class="hero-stat-dot" aria-hidden="true"></span>
<span class="hero-stat"><petty-counter to="0" duration="500" delay="1400"></petty-counter> dependencies</span>
<span class="hero-stat-dot" aria-hidden="true"></span>
<span class="hero-stat">~<petty-counter to="500" duration="1200" delay="1600" suffix="B"></petty-counter> runtime</span>
</div>
</section>
<section class="value-props">
<h2 class="sr-only">Why PettyUI</h2>
<dl class="value-list">
<div class="value-item">
<dt>Browser-Native</dt>
<dd>Popover API, native Dialog, Navigation API, Invoker Commands. No polyfills.</dd>
</div>
<div class="value-item">
<dt>Zero Runtime</dt>
<dd>500-byte signals. No virtual DOM, no framework. Just Custom Elements.</dd>
</div>
<div class="value-item">
<dt>AI-Native</dt>
<dd>Zod schemas for every prop. MCP tools for agent integration.</dd>
</div>
</dl>
</section>
<div class="section-separator"></div>
<section class="section">
<petty-reveal animation="fade-up" once><h2 class="section-title">Inputs &amp; Forms</h2></petty-reveal>
<petty-reveal animation="fade-up" once delay="100"><p class="section-desc">Form primitives with built-in ARIA, keyboard navigation, and event handling.</p></petty-reveal>
<div class="grid">
<article class="demo-card">
<h3>Button</h3>
<div class="demo-row">
<petty-button><button type="button">Default</button></petty-button>
<petty-button><button type="button" class="primary">Primary</button></petty-button>
<petty-button disabled><button type="button">Disabled</button></petty-button>
<petty-button loading><button type="button">Loading</button></petty-button>
</div>
<p class="tag-name">&lt;petty-button&gt;</p>
</article>
<article class="demo-card">
<h3>Text Field</h3>
<petty-text-field name="email">
<label data-part="label">Email address</label>
<input data-part="control" type="email" placeholder="you@example.com" aria-label="Email address" />
<span data-part="description">We will never share your email.</span>
<span data-part="error"></span>
</petty-text-field>
<p class="tag-name">&lt;petty-text-field&gt;</p>
</article>
<article class="demo-card">
<h3>Checkbox &amp; Switch</h3>
<div class="demo-area">
<petty-checkbox>
<input data-part="control" type="checkbox" aria-label="Accept terms" />
<label data-part="label">Accept terms</label>
</petty-checkbox>
<petty-checkbox checked>
<input data-part="control" type="checkbox" aria-label="Subscribe to updates" />
<label data-part="label">Subscribe to updates</label>
</petty-checkbox>
<petty-separator></petty-separator>
<petty-switch>
<button type="button" data-part="control" role="switch" aria-checked="false" aria-label="Dark mode"><span data-part="thumb"></span></button>
<span data-part="label">Dark mode</span>
</petty-switch>
</div>
<p class="tag-name">&lt;petty-checkbox&gt; &lt;petty-switch&gt;</p>
</article>
<article class="demo-card">
<h3>Radio Group</h3>
<petty-radio-group default-value="md" orientation="vertical">
<petty-radio-item value="sm">Small</petty-radio-item>
<petty-radio-item value="md">Medium</petty-radio-item>
<petty-radio-item value="lg">Large</petty-radio-item>
</petty-radio-group>
<p class="tag-name">&lt;petty-radio-group&gt;</p>
</article>
<article class="demo-card">
<h3>Toggle &amp; Toggle Group</h3>
<div class="demo-area">
<div class="demo-row">
<petty-toggle><button type="button" data-part="control">Mute</button></petty-toggle>
<petty-toggle pressed><button type="button" data-part="control">Pin</button></petty-toggle>
</div>
<petty-toggle-group type="single" default-value="left">
<petty-toggle-group-item value="left">Left</petty-toggle-group-item>
<petty-toggle-group-item value="center">Center</petty-toggle-group-item>
<petty-toggle-group-item value="right">Right</petty-toggle-group-item>
</petty-toggle-group>
</div>
<p class="tag-name">&lt;petty-toggle&gt; &lt;petty-toggle-group&gt;</p>
</article>
<article class="demo-card">
<h3>Number Field &amp; Slider</h3>
<petty-number-field min="0" max="99" step="1" value="3">
<label data-part="label">Qty</label>
<button type="button" data-part="decrement">&minus;</button>
<input data-part="control" type="number" aria-label="Quantity" />
<button type="button" data-part="increment">+</button>
</petty-number-field>
<petty-slider min="0" max="100" value="65">
<label data-part="label">Volume</label>
<input data-part="control" type="range" aria-label="Volume" />
<output data-part="output">65</output>
</petty-slider>
<p class="tag-name">&lt;petty-number-field&gt; &lt;petty-slider&gt;</p>
</article>
<article class="demo-card">
<h3>Select</h3>
<petty-select default-value="ts" placeholder="Pick a language">
<button type="button" data-part="trigger" popovertarget="lang-sel">Pick a language</button>
<div id="lang-sel" popover data-part="listbox" role="listbox">
<petty-select-option value="ts">TypeScript</petty-select-option>
<petty-select-option value="rs">Rust</petty-select-option>
<petty-select-option value="go">Go</petty-select-option>
<petty-select-option value="py">Python</petty-select-option>
</div>
</petty-select>
<p class="tag-name">&lt;petty-select&gt;</p>
</article>
<article class="demo-card">
<h3>Tags Input</h3>
<petty-tags-input value="pettyui,web-components,headless">
<span data-part="tags"></span>
<input data-part="input" placeholder="Add tag..." aria-label="Add tag" />
<input data-part="hidden" type="hidden" aria-label="Selected tags" />
</petty-tags-input>
<p class="tag-name">&lt;petty-tags-input&gt;</p>
</article>
</div>
</section>
<section class="section section-glow">
<petty-reveal animation="fade-up" once><h2 class="section-title">Navigation</h2></petty-reveal>
<petty-reveal animation="fade-up" once delay="100"><p class="section-desc">Tab bars, accordions, breadcrumbs, and pagination &mdash; all keyboard-accessible.</p></petty-reveal>
<div class="grid">
<article class="demo-card wide">
<h3>Tabs</h3>
<petty-tabs default-value="overview">
<div role="tablist">
<petty-tab value="overview">Overview</petty-tab>
<petty-tab value="features">Features</petty-tab>
<petty-tab value="api">API</petty-tab>
</div>
<petty-tab-panel value="overview">PettyUI is a headless component library built on vanilla Web Components. No framework required.</petty-tab-panel>
<petty-tab-panel value="features">Zero dependencies, Popover API, native dialog, Invoker Commands, Navigation API, View Transitions.</petty-tab-panel>
<petty-tab-panel value="api">Every component is a Custom Element. Import and use anywhere: React, Vue, Svelte, or plain HTML.</petty-tab-panel>
</petty-tabs>
<p class="tag-name">&lt;petty-tabs&gt;</p>
</article>
<article class="demo-card">
<h3>Accordion</h3>
<petty-accordion type="single">
<petty-accordion-item value="install">
<details><summary>Installation</summary><p data-part="content">npm install pettyui &mdash; zero peer dependencies.</p></details>
</petty-accordion-item>
<petty-accordion-item value="usage">
<details><summary>Usage</summary><p data-part="content">Import the component, write HTML. That is it.</p></details>
</petty-accordion-item>
<petty-accordion-item value="styling">
<details><summary>Styling</summary><p data-part="content">No Shadow DOM. Style with plain CSS, Tailwind, or anything.</p></details>
</petty-accordion-item>
</petty-accordion>
<p class="tag-name">&lt;petty-accordion&gt;</p>
</article>
<article class="demo-card">
<h3>Breadcrumbs &amp; Pagination</h3>
<petty-breadcrumbs>
<ol>
<petty-breadcrumb-item><a href="/home">Home</a></petty-breadcrumb-item>
<petty-breadcrumb-item><a href="/components">Components</a></petty-breadcrumb-item>
<petty-breadcrumb-item current>Button</petty-breadcrumb-item>
</ol>
</petty-breadcrumbs>
<petty-separator></petty-separator>
<petty-pagination total="50" page-size="10" current-page="2">
<nav aria-label="Pagination">
<petty-pagination-item type="prev">&larr;</petty-pagination-item>
<petty-pagination-item value="1">1</petty-pagination-item>
<petty-pagination-item value="2">2</petty-pagination-item>
<petty-pagination-item value="3">3</petty-pagination-item>
<petty-pagination-item value="4">4</petty-pagination-item>
<petty-pagination-item value="5">5</petty-pagination-item>
<petty-pagination-item type="next">&rarr;</petty-pagination-item>
</nav>
</petty-pagination>
<p class="tag-name">&lt;petty-breadcrumbs&gt; &lt;petty-pagination&gt;</p>
</article>
</div>
</section>
<section class="section">
<petty-reveal animation="fade-up" once><h2 class="section-title">Overlays</h2></petty-reveal>
<petty-reveal animation="fade-up" once delay="100"><p class="section-desc">Dialogs, popovers, tooltips, and drawers &mdash; powered by native browser APIs.</p></petty-reveal>
<div class="grid">
<article class="demo-card">
<h3>Dialog &amp; Alert Dialog</h3>
<div class="demo-row">
<petty-button><button type="button" onclick="document.getElementById('demo-dlg').showModal()">Open Dialog</button></petty-button>
<petty-button><button type="button" onclick="document.getElementById('demo-alert-dlg').showModal()">Confirm Delete</button></petty-button>
</div>
<p class="tag-name">&lt;petty-dialog&gt; &lt;petty-alert-dialog&gt;</p>
</article>
<article class="demo-card">
<h3>Popover &amp; Tooltip</h3>
<div class="demo-row">
<petty-popover>
<button type="button" class="btn-outline" popovertarget="demo-pop">Show Popover</button>
<div id="demo-pop" popover data-part="content">This uses the native Popover API. Click outside to dismiss.</div>
</petty-popover>
<petty-tooltip>
<span data-part="trigger" tabindex="0" class="hint-text">Hover me</span>
<div popover="manual" data-part="content" role="tooltip">Native tooltip via Popover API</div>
</petty-tooltip>
</div>
<p class="tag-name">&lt;petty-popover&gt; &lt;petty-tooltip&gt;</p>
</article>
<article class="demo-card">
<h3>Dropdown Menu</h3>
<petty-dropdown-menu>
<button type="button" data-part="trigger" class="btn-outline" popovertarget="demo-menu">Actions &#x25BE;</button>
<div id="demo-menu" popover data-part="content" role="menu">
<petty-menu-item>Edit</petty-menu-item>
<petty-menu-item>Duplicate</petty-menu-item>
<petty-menu-item>Archive</petty-menu-item>
<petty-menu-item disabled>Delete</petty-menu-item>
</div>
</petty-dropdown-menu>
<p class="tag-name">&lt;petty-dropdown-menu&gt;</p>
</article>
</div>
</section>
<section class="section section-glow">
<petty-reveal animation="fade-up" once><h2 class="section-title">Feedback &amp; Display</h2></petty-reveal>
<petty-reveal animation="fade-up" once delay="100"><p class="section-desc">Status indicators, progress bars, alerts, badges, and notifications.</p></petty-reveal>
<div class="grid">
<article class="demo-card">
<h3>Alert</h3>
<div class="demo-area">
<petty-alert variant="success"><span class="alert-icon" aria-hidden="true">&#10003;</span><div data-part="content"><div data-part="title">Deployed successfully</div><div data-part="description">Your changes are live and visible to all users.</div></div></petty-alert>
<petty-alert variant="error"><span class="alert-icon" aria-hidden="true">&#10007;</span><div data-part="content"><div data-part="title">Build failed</div><div data-part="description">Check the CI logs for error details.</div></div></petty-alert>
<petty-alert variant="warning"><span class="alert-icon" aria-hidden="true">&#9888;</span><div data-part="content"><div data-part="title">Rate limit approaching</div><div data-part="description">You have used 90% of your API quota this month.</div></div></petty-alert>
</div>
<p class="tag-name">&lt;petty-alert&gt;</p>
</article>
<article class="demo-card">
<h3>Progress &amp; Meter</h3>
<div class="demo-area">
<div class="progress-field">
<div class="progress-header"><span>Upload progress</span><span>72%</span></div>
<petty-progress value="72" max="100"><div data-part="track"><div data-part="fill"></div></div></petty-progress>
</div>
<div class="progress-field">
<div class="progress-header"><span>CPU usage</span><span class="meter-low">35%</span></div>
<petty-meter value="35" min="0" max="100" low="25" high="75" optimum="50"><div data-part="track"><div data-part="fill"></div></div></petty-meter>
</div>
<div class="progress-field">
<div class="progress-header"><span>Memory</span><span class="meter-high">85%</span></div>
<petty-meter value="85" min="0" max="100" low="25" high="75" optimum="50"><div data-part="track"><div data-part="fill"></div></div></petty-meter>
</div>
</div>
<div class="progress-field">
<div class="progress-header"><span>Loading indicator</span></div>
<div class="demo-row-spacious loading-demo">
<petty-loading-indicator size="20" aria-label="Loading tiny"></petty-loading-indicator>
<petty-loading-indicator size="28" aria-label="Loading small"></petty-loading-indicator>
<petty-loading-indicator size="36" aria-label="Loading medium"></petty-loading-indicator>
<petty-loading-indicator aria-label="Loading default"></petty-loading-indicator>
</div>
</div>
<p class="tag-name">&lt;petty-progress&gt; &lt;petty-meter&gt; &lt;petty-loading-indicator&gt;</p>
</article>
<article class="demo-card">
<h3>Badge &amp; Avatar</h3>
<div class="demo-area">
<div class="demo-row-loose">
<petty-badge>Default</petty-badge>
<petty-badge variant="success">Active</petty-badge>
<petty-badge variant="error">Offline</petty-badge>
<petty-badge variant="warning">Pending</petty-badge>
</div>
<div class="demo-row-loose">
<petty-avatar><span data-part="fallback">MB</span></petty-avatar>
<petty-avatar><span data-part="fallback">JD</span></petty-avatar>
<petty-avatar><span data-part="fallback">AK</span></petty-avatar>
</div>
</div>
<p class="tag-name">&lt;petty-badge&gt; &lt;petty-avatar&gt;</p>
</article>
<article class="demo-card">
<h3>Toast</h3>
<div class="demo-row">
<petty-button><button type="button" id="demo-toast-btn" class="primary">Success Toast</button></petty-button>
<petty-button><button type="button" id="demo-toast-err">Error Toast</button></petty-button>
</div>
<p class="tag-name">&lt;petty-toast-region&gt;</p>
</article>
<article class="demo-card">
<h3>Skeleton &amp; Card</h3>
<petty-card>
<petty-card-header><h4>Loading content</h4></petty-card-header>
<petty-card-content>
<petty-skeleton class="skel-80"></petty-skeleton>
<petty-skeleton class="skel-60"></petty-skeleton>
<petty-skeleton class="skel-70"></petty-skeleton>
</petty-card-content>
<petty-card-footer>
<petty-skeleton class="skel-btn"></petty-skeleton>
</petty-card-footer>
</petty-card>
<p class="tag-name">&lt;petty-card&gt; &lt;petty-skeleton&gt;</p>
</article>
<article class="demo-card">
<h3>Link &amp; Separator</h3>
<petty-link><a href="/docs">Internal documentation link</a></petty-link>
<petty-link external><a href="https://developer.mozilla.org" target="_blank" rel="noopener">MDN Web Docs &#x2197;</a></petty-link>
<petty-separator></petty-separator>
<span class="muted-sm">Separator shown above</span>
<p class="tag-name">&lt;petty-link&gt; &lt;petty-separator&gt;</p>
</article>
</div>
</section>
<section class="footer-section">
<petty-separator></petty-separator>
<p class="footer-text">PettyUI v2 &mdash; 45 Web Components, 0 dependencies, built on browser standards.</p>
</section>
<footer class="st3-sig"><span>//ST3</span></footer>
</main>
<petty-dialog>
<dialog id="demo-dlg">
<h2>Welcome to PettyUI</h2>
<p>This dialog uses the native dialog element. Focus trap, backdrop, and Escape key work out of the box.</p>
<petty-button><button type="button" onclick="document.getElementById('demo-dlg').close()">Got it</button></petty-button>
</dialog>
</petty-dialog>
<petty-alert-dialog>
<dialog id="demo-alert-dlg" role="alertdialog">
<h2>Delete project?</h2>
<p>This action cannot be undone. All data will be permanently removed.</p>
<div class="demo-row">
<petty-button><button type="button" onclick="document.getElementById('demo-alert-dlg').close()">Cancel</button></petty-button>
<petty-button><button type="button" class="primary" onclick="document.getElementById('demo-alert-dlg').close()">Delete</button></petty-button>
</div>
</dialog>
</petty-alert-dialog>
<petty-toast-region></petty-toast-region>
</body>
</html>