diff --git a/.github/workflows/qa.yml b/.github/workflows/qa.yml index c7bcb6d..d27d5e2 100644 --- a/.github/workflows/qa.yml +++ b/.github/workflows/qa.yml @@ -39,7 +39,7 @@ jobs: QA_TIMEOUT_SCALE: 2 run: | for group in \ - actions calendar data-display docs feedback input \ + actions calendar coverage data-display docs feedback input \ layout navigation showcase surfaces theming unlisted do ps-qa --app tests/ps-qa/ps-qa.ron \ diff --git a/README.md b/README.md index fbb0302..a33d679 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ The kitchen sink demo and documentation for our UI components. ## Native QA Build the site, then run every declared outcome with the font-enabled chuzz host -and ps-qa 0.7.1 or newer: +and ps-qa 0.7.2 or newer: ```sh bun run build @@ -14,8 +14,9 @@ ps-qa --app tests/ps-qa/ps-qa.ron qa-hosted \ --checks tests/ps-qa/checks ``` -The UI 3.2 registry build passes all 330 native checks across 12 groups, -including Calendar selection and month navigation. CI includes every group. +The UI 3.2 registry build passes all 600 native checks across 13 groups, +including Calendar selection, month navigation, and keyboard and pointer-driven +Slider and Color Picker outcomes. CI includes every group. The Layouts route uses its own document marker, and decorative cards are articles rather than controls that promise an action. diff --git a/package.json b/package.json index b54bcb5..b5d3e65 100644 --- a/package.json +++ b/package.json @@ -35,7 +35,7 @@ "@iconify-json/lucide": "^1.2.127", "@iconify-json/mdi": "^1.2.3", "@iconify/tailwind4": "^1.0.6", - "@pathscale/ui": "^3.1.0", + "@pathscale/ui": "^3.2.1", "@rsbuild/core": "^1.3.20", "@rsbuild/plugin-babel": "^1.0.5", "@solidjs/router": "2.0.0-next.19", diff --git a/src/App.tsx b/src/App.tsx index 701edd6..1af6c26 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,11 +1,18 @@ -import { createRouter } from "@solidjs/router"; -import { ParentComponent } from "solid-js"; +import { createRouter, useLocation } from "@solidjs/router"; +import { ParentComponent, createEffect } from "solid-js"; import { routes } from "./routes"; import { BaseLayout } from "./layouts/BaseLayout"; import { MarketingHeader } from "./components/layout/Header/MarketingHeader"; const Layout: ParentComponent = (props) => { + const location = useLocation(); + + createEffect( + () => location.pathname, + () => window.scrollTo(0, 0), + ); + return ( {theme() === "dark" ? : } - + ); } diff --git a/src/components/AlertShowcase.tsx b/src/components/AlertShowcase.tsx index 9edc4f6..0fedd3a 100644 --- a/src/components/AlertShowcase.tsx +++ b/src/components/AlertShowcase.tsx @@ -1,11 +1,14 @@ -import { Component } from "solid-js"; +import { Component, createSignal } from "solid-js"; import ShowcaseLayout from "./ShowcaseLayout"; import { Alert, Button, Flex } from "@pathscale/ui"; import { PropsTable } from "./showcase/PropsTable"; import { CodeBlock } from "./showcase/CodeBlock"; import { ShowcaseSection } from "./showcase/ShowcaseSection"; +import { ActionStatus, createActionStatus } from "./showcase/ActionStatus"; const AlertShowcase: Component = () => { + const [cookieChoice, setCookieChoice] = createSignal<"accept" | "deny" | null>(null); + const actions = createActionStatus(); const sections = [ { id: "contents", title: "Contents" }, { id: "default", title: "Default" }, @@ -154,15 +157,20 @@ const AlertShowcase: Component = () => { justify="start" gap="md" > - - we use cookies for no reason. -
- - -
-
+
+ + we use cookies for no reason. +
+ + +
+
+

+ {cookieChoice() ? `Cookie preference saved: ${cookieChoice()}.` : "Choose a cookie preference."} +

+
@@ -182,8 +190,9 @@ const AlertShowcase: Component = () => { > You have 1 unread message - + + diff --git a/src/components/BadgeShowcase.tsx b/src/components/BadgeShowcase.tsx index 21380ab..ccbd711 100644 --- a/src/components/BadgeShowcase.tsx +++ b/src/components/BadgeShowcase.tsx @@ -1,8 +1,10 @@ import { Badge, Button, Chip, Flex, Icon } from "@pathscale/ui"; +import { createSignal } from "solid-js"; import ShowcaseLayout from "./ShowcaseLayout"; import { CodeBlock } from "./showcase/CodeBlock"; import { PropsTable } from "./showcase/PropsTable"; import { ShowcaseSection } from "./showcase/ShowcaseSection"; +import { ActionStatus, createActionStatus } from "./showcase/ActionStatus"; const badgeProps = [ { name: "size", type: '"sm" | "md" | "lg"', default: '"md"', description: "Indicator size." }, @@ -13,19 +15,21 @@ const badgeProps = [ ]; export default function BadgeShowcase() { + const [selectedPlacement, setSelectedPlacement] = createSignal<"top-right" | "top-left" | "bottom-right" | "bottom-left">("top-right"); + const actions = createActionStatus(); return ( - 3 - + 12 @@ -38,12 +42,23 @@ export default function BadgeShowcase() { {(["top-left", "top-right", "bottom-left", "bottom-right"] as const).map((placement) => ( - - - - + ))} + + Preview + + + diff --git a/src/components/ButtonShowcase.tsx b/src/components/ButtonShowcase.tsx index aa673bd..35a33fa 100644 --- a/src/components/ButtonShowcase.tsx +++ b/src/components/ButtonShowcase.tsx @@ -1,8 +1,10 @@ import { Button, Flex, Icon } from "@pathscale/ui"; +import { createSignal } from "solid-js"; import ShowcaseLayout from "./ShowcaseLayout"; import { CodeBlock } from "./showcase/CodeBlock"; import { PropsTable } from "./showcase/PropsTable"; import { ShowcaseSection } from "./showcase/ShowcaseSection"; +import { ActionStatus, createActionStatus } from "./showcase/ActionStatus"; const buttonProps = [ { name: "variant", type: '"primary" | "secondary" | "tertiary" | "outline" | "ghost" | "danger" | "danger-soft"', default: '"primary"', description: "Semantic visual treatment." }, @@ -16,6 +18,8 @@ const buttonProps = [ ]; export default function ButtonShowcase() { + const actions = createActionStatus(); + const [pressed, setPressed] = createSignal(true); const startIcon = ; const endIcon = ; @@ -24,13 +28,13 @@ export default function ButtonShowcase() { - - - - - - - + + + + + + + Primary @@ -39,9 +43,9 @@ export default function ButtonShowcase() { - - - + + + Small @@ -50,9 +54,9 @@ export default function ButtonShowcase() { - - - + + @@ -65,7 +69,14 @@ export default function ButtonShowcase() { - + Saving @@ -73,10 +84,12 @@ export default function ButtonShowcase() { - + Continue`} /> + +

Button deliberately renders a button. Use a native anchor or the Link component for diff --git a/src/components/CalendarShowcase.tsx b/src/components/CalendarShowcase.tsx index af16cb9..e7b1b0f 100644 --- a/src/components/CalendarShowcase.tsx +++ b/src/components/CalendarShowcase.tsx @@ -142,9 +142,8 @@ export default function CalendarShowcase() { setRangePreview(undefined); }; - const today = new Date(); - const minDate = new Date(today.getFullYear(), today.getMonth(), 1); - const maxDate = new Date(today.getFullYear(), today.getMonth() + 2, 0); + const minDate = new Date(2025, 5, 1); + const maxDate = new Date(2025, 6, 31); return ( @@ -164,7 +163,7 @@ export default function CalendarShowcase() { - + `} /> @@ -172,6 +171,7 @@ export default function CalendarShowcase() { setSelectedDate(value)} /> @@ -191,6 +191,8 @@ export default function CalendarShowcase() { - + `} /> - + Shoes!

If a dog chews shoes whose shoes does he choose?

- + @@ -131,8 +135,8 @@ export default function CardShowcase() { - - + + @@ -167,7 +171,7 @@ export default function CardShowcase() {

Shoes!

If a dog chews shoes whose shoes does he choose?

- + @@ -250,13 +254,18 @@ export default function CardShowcase() { console.log("card pressed")} + aria-pressed={cardPressed() ? "true" : "false"} + onClick={() => { + setCardPressed((value) => !value); + actions.announce(`Pressable card ${cardPressed() ? "selected" : "cleared"}`); + }} >

Press me

Acts like a button; Enter/Space activates.

+ +
Buttons
- - - - - - - - + {variants.map(([label, props]) => ( + + ))}
diff --git a/src/components/ComponentsDemo.tsx b/src/components/ComponentsDemo.tsx index 9d039c8..e25b355 100644 --- a/src/components/ComponentsDemo.tsx +++ b/src/components/ComponentsDemo.tsx @@ -2,13 +2,31 @@ import { createSignal } from "solid-js"; import { Alert, Avatar, Breadcrumb, BreadcrumbItem, Button, Card, ChatBubble, Checkbox, Chip, Dialog, Drawer, Dropdown, Flex, Form, Icon, Input, Navbar, Pagination, Progress, Radio, Select, Skeleton, Slider, Spinner, Switch, Table, Tabs, Tooltip, TooltipContent, TooltipTrigger } from "@pathscale/ui"; import { Menu, Join } from "@pathscale/ui/lab"; import { ROUTES } from "../config/routes"; +import { ActionStatus, createActionStatus } from "./showcase/ActionStatus"; export default function ComponentsDemo() { const [modalOpen, setModalOpen] = createSignal(false); const [page, setPage] = createSignal(2); + const [price, setPrice] = createSignal(25); + const [selectedDay, setSelectedDay] = createSignal(5); + const [hoodies, setHoodies] = createSignal(false); + const [bags, setBags] = createSignal(true); + const [shoes, setShoes] = createSignal(false); + const [accessories, setAccessories] = createSignal(false); + const [eventSearch, setEventSearch] = createSignal(""); + const [showAllDay, setShowAllDay] = createSignal(false); + const [minimumPrice, setMinimumPrice] = createSignal(""); + const [maximumPrice, setMaximumPrice] = createSignal(""); + const [themeSwitch, setThemeSwitch] = createSignal(false); + const [previewSearch, setPreviewSearch] = createSignal(""); + const [recommendation, setRecommendation] = createSignal("yes"); + const actionStatus = createActionStatus("Preview ready"); return (
+
+ +
@@ -17,7 +35,7 @@ export default function ComponentsDemo() { Filters - @@ -28,7 +46,7 @@ export default function ComponentsDemo() { - + Hoodies @@ -37,7 +55,7 @@ export default function ComponentsDemo() { - + Bags @@ -46,7 +64,7 @@ export default function ComponentsDemo() { - + Shoes @@ -55,7 +73,7 @@ export default function ComponentsDemo() { - + Accessories @@ -95,36 +113,34 @@ export default function ComponentsDemo() { S - - - - - - - + {[1, 2, 3, 4, 5, 6, 7].map((day) => ( + + ))} } size="sm" + value={eventSearch()} + onInput={(event) => setEventSearch(event.currentTarget.value)} /> Show all day events - + @@ -142,7 +158,7 @@ export default function ComponentsDemo() { - + Tab 1 Tab 2 @@ -166,7 +182,16 @@ export default function ComponentsDemo() { Price Range - {}} /> + `$${value}`} + onChange={setPrice} + /> $0 $25 @@ -176,11 +201,11 @@ export default function ComponentsDemo() { - + setMinimumPrice(event.currentTarget.value)} /> to - + setMaximumPrice(event.currentTarget.value)} /> - @@ -255,7 +280,7 @@ export default function ComponentsDemo() { - @@ -294,7 +319,7 @@ export default function ComponentsDemo() { - {" "} to verify email @@ -303,7 +328,7 @@ export default function ComponentsDemo() { Access denied - @@ -342,7 +367,7 @@ export default function ComponentsDemo() { - + Monthly @@ -368,7 +393,7 @@ export default function ComponentsDemo() { Advanced analytics - @@ -436,7 +461,7 @@ export default function ComponentsDemo() { - Are you sure you want to continue? - - + @@ -470,7 +495,7 @@ export default function ComponentsDemo() { - @@ -480,13 +505,13 @@ export default function ComponentsDemo() { 3 - - + Theme Switch @@ -518,13 +543,13 @@ export default function ComponentsDemo() { - - - @@ -533,7 +558,7 @@ export default function ComponentsDemo() { - + actionStatus.announce(`Menu opened: ${String(key)}`)}> @@ -594,17 +619,17 @@ export default function ComponentsDemo() { - - - - @@ -633,16 +658,14 @@ export default function ComponentsDemo() { - - - + + + - Dashboard - Settings - Logout + Dashboard + Settings + Logout @@ -650,7 +673,7 @@ export default function ComponentsDemo() { Brand - @@ -685,23 +708,26 @@ export default function ComponentsDemo() { - - - setPreviewSearch(event.currentTarget.value)} /> - @@ -714,7 +740,7 @@ export default function ComponentsDemo() {
How did you hear about us? - Search Engine Social Media Friend @@ -732,10 +758,12 @@ export default function ComponentsDemo() {
- + checked && setRecommendation("yes")} /> Would recommend + checked && setRecommendation("no")} /> + Would not recommend -
@@ -745,12 +773,12 @@ export default function ComponentsDemo() { - Home - Products + Home + { event.preventDefault(); actionStatus.announce("Products opened"); }}>Products Details
- + { setPage(nextPage); actionStatus.announce(`Page ${nextPage} selected`); }} /> diff --git a/src/components/CoverageShowcase.tsx b/src/components/CoverageShowcase.tsx index 802d231..6def452 100644 --- a/src/components/CoverageShowcase.tsx +++ b/src/components/CoverageShowcase.tsx @@ -1,7 +1,60 @@ import type { JSX } from "@solidjs/web"; -import { createErrorBoundary, For } from "solid-js"; -import { Accordion, Button, Card, Checkbox, Chip, Collapsible, createI18n, Empty, Flex, Header, Input, InputOTP, LanguageSwitcher, ListBox, LiveChatBubble, MetalBorder, Popover, Progress, ScrollArea, Separator, Slider, Spinner, Text, Textarea, ThemeColorPicker } from "@pathscale/ui"; -import { ButtonGroup, CheckboxGroup, CloseButton, Meter, RadialProgress, SizePicker, TimeField, DateField, ColorPicker, ColorArea, ColorField, ColorSlider, ComboBox, DatePicker, DateRangePicker, RangeCalendar, Toolbar, Kbd } from "@pathscale/ui/lab"; +import { createErrorBoundary, createSignal, For, onCleanup, Show } from "solid-js"; +import { + Accordion, + Address, + AuthCard, + AuthFieldGroup, + AuthFooterLinks, + AuthMessage, + AuthPoweredBy, + AuthSubmitButton, + Button, + Card, + Checkbox, + Chip, + Collapsible, + ColorSwatch, + ColorWheel, + ComplexColorWheel, + Composer, + ConnectionSettings, + CookieConsent, + createConnectionSettings, + createI18n, + Empty, + FieldGroup, + FirefoxPWABanner, + Flex, + FlexGrid, + Header, + ImmersiveLanding, + InlineEdit, + Input, + InputOTP, + Label, + LanguageSwitcher, + ListBox, + LiveChatBubble, + LiveChatPanel, + MetalBorder, + PanelToggle, + PasswordField, + PasswordRequirements, + Popover, + Progress, + PWAInstallPrompt, + ScrollArea, + Separator, + Slider, + Spinner, + Text, + Textarea, + ThemeColorPicker, + type ComponentFamilyId, +} from "@pathscale/ui"; +import CloseButton from "@pathscale/ui/components/close-button"; +import { ButtonGroup, CheckboxGroup, Meter, RadialProgress, SizePicker, TimeField, DateField, ColorPicker, ColorArea, ColorField, ColorSlider, ColorSwatchPicker, ColorWheelFlower, ComboBox, DatePicker, DateRangePicker, RangeCalendar, Toolbar, Kbd } from "@pathscale/ui/lab"; import ShowcaseLayout from "./ShowcaseLayout"; /** @@ -22,26 +75,448 @@ type Example = { render: () => JSX.Element; }; +function CloseButtonExample() { + const [closed, setClosed] = createSignal(false); + return ( + <> + setClosed(true)} + /> +

{closed() ? "Dismissed" : "Coverage notice open"}

+ + ); +} + +const [activeFullscreenExample, setActiveFullscreenExample] = createSignal(null); + +const savedDocumentStyle: Record = {}; + +function openFullscreenExample(name: string) { + const root = document.documentElement.style; + const body = document.body.style; + for (const [key, value] of [ + ["rootHeight", root.height], + ["rootMinHeight", root.minHeight], + ["rootOverflow", root.overflow], + ["bodyHeight", body.height], + ["bodyMinHeight", body.minHeight], + ["bodyOverflow", body.overflow], + ]) savedDocumentStyle[key] = value; + root.height = "100vh"; + root.minHeight = "0"; + root.overflow = "hidden"; + body.height = "100vh"; + body.minHeight = "0"; + body.overflow = "hidden"; + window.scrollTo({ top: 0, behavior: "instant" }); + setActiveFullscreenExample(name); +} + +function closeFullscreenExample() { + setActiveFullscreenExample(null); + const root = document.documentElement.style; + const body = document.body.style; + root.height = savedDocumentStyle.rootHeight ?? ""; + root.minHeight = savedDocumentStyle.rootMinHeight ?? ""; + root.overflow = savedDocumentStyle.rootOverflow ?? ""; + body.height = savedDocumentStyle.bodyHeight ?? ""; + body.minHeight = savedDocumentStyle.bodyMinHeight ?? ""; + body.overflow = savedDocumentStyle.bodyOverflow ?? ""; +} + +function DeferredExample(props: { name: string; render: () => JSX.Element }) { + return ( + <> + {activeFullscreenExample() === props.name + ? props.render() + : } + + ); +} + +function AddressExample() { + const [copied, setCopied] = createSignal("Nothing copied"); + return ( + <> +
setCopied(`Copied ${value}`)} /> +

{copied()}

+ + ); +} + +function AuthActionsExample() { + const [result, setResult] = createSignal("No auth action yet"); + return ( + + + + + + setResult("Sign in submitted")}>Sign in + + setResult("Privacy opened") }, + { key: "help", label: "Help", onClick: () => setResult("Help opened") }, + ]} + /> + +

{result()}

+
+ ); +} + +function ComposerExample() { + const [value, setValue] = createSignal(""); + const [sent, setSent] = createSignal("Nothing sent"); + return ( + <> + setSent(`Sent ${message}`)} + /> +

{sent()}

+ + ); +} + +function ConnectionSettingsExample() { + const [result, setResult] = createSignal("Default backend active"); + const store = createConnectionSettings({ + storageKey: "js-software-coverage-connection", + endpoints: [{ name: "api", fallback: "https://api.example.com" }], + onApply: ({ urls }) => { + setResult(`Connected to ${urls.api}`); + }, + }); + return ( + <> + { setResult(`Saved ${store.urls.api}`); }} + onResetDone={() => { setResult("Default backend restored"); }} + /> +

{result()}

+ + ); +} + +function InlineEditExample() { + const [value, setValue] = createSignal("Showcase title"); + return ( + <> + +

Saved title: {value()}

+ + ); +} + +function PanelToggleExample() { + const [expanded, setExpanded] = createSignal(true); + return ( +
+ setExpanded((value) => !value)} + /> + +
+ ); +} + +function PasswordFieldExample() { + const [value, setValue] = createSignal(""); + return ( + <> + + = 8 }, + { key: "number", message: "Contains a number", passed: /\d/.test(value()) }, + ]} + /> + + ); +} + +function LiveChatPanelExample() { + const [sent, setSent] = createSignal("Nothing sent"); + const [closed, setClosed] = createSignal(false); + return ( + Chat closed

}> + setClosed(true)} + onSendMessage={async ({ message }) => { + setSent(`Sent ${message}`); + return { messageId: "coverage-message", timestamp: Date.now() }; + }} + /> +

{sent()}

+
+ ); +} + +function ImmersiveLandingExample() { + const [page, setPage] = createSignal("intro"); + return ( + <> + setPage(to)} + > +

Introduction

+

Details

+
+

Landing page: {page()}

+ + ); +} + +function PWAExamples() { + const [result, setResult] = createSignal("No install choice"); + setTimeout(() => { + const installEvent = new Event("beforeinstallprompt", { cancelable: true }); + Object.defineProperties(installEvent, { + prompt: { value: () => undefined }, + userChoice: { value: Promise.resolve({ outcome: "accepted", platform: "web" }) }, + }); + window.dispatchEvent(installEvent); + }, 0); + return ( + <> + setResult("Install accepted")} + onDismiss={() => setResult("Install dismissed")} + /> +

{result()}

+ + ); +} + +function FirefoxPWAExample() { + const [result, setResult] = createSignal("Firefox prompt open"); + const descriptor = Object.getOwnPropertyDescriptor(navigator, "userAgent"); + Object.defineProperty(navigator, "userAgent", { + configurable: true, + value: "Mozilla/5.0 Firefox/130.0", + }); + const originalOpen = globalThis.open; + globalThis.open = (() => null) as typeof globalThis.open; + onCleanup(() => { + if (descriptor) Object.defineProperty(navigator, "userAgent", descriptor); + globalThis.open = originalOpen; + }); + return ( + <> + setResult("Firefox install opened")} + onDismiss={() => setResult("Firefox prompt dismissed")} + /> +

{result()}

+ + ); +} + +function CookieConsentExample() { + const [result, setResult] = createSignal("No cookie choice"); + return ( + <> + setResult(`Cookie consent ${type}`)} + /> +

{result()}

+ + ); +} + +function LanguageSwitcherExample() { + const [result, setResult] = createSignal("No language selected"); + const i18n = createI18n({ + languages: [ + { code: "en", name: "English" }, + { code: "es", name: "Espanol" }, + ], + storageKey: "coverage-locale", + }); + return ( + <> + setResult(`Language selected ${code}`)} + /> +

{result()}

+ + ); +} + const EXAMPLES: Example[] = [ + { name: "Address", render: () => }, + { name: "Auth composition", render: () => }, { - name: "ButtonGroup", + name: "FieldGroup", render: () => ( - - - - + + + + ), }, + { name: "Composer", render: () => }, + { name: "ConnectionSettings", render: () => }, + { + name: "ColorSwatch", + render: () => { + const [selected, setSelected] = createSignal("No swatch selected"); + return ( + <> + setSelected(`Selected ${value}`)} /> +

{selected()}

+ + ); + }, + }, + { + name: "ColorSwatchPicker", + render: () => { + const [value, setValue] = createSignal("#ef4444"); + return ( + + + + + ); + }, + }, + { + name: "ColorWheel", + render: () => { + const [value, setValue] = createSignal("#6366f1"); + return ; + }, + }, + { + name: "ColorWheelFlower", + render: () => { + const [value, setValue] = createSignal("#6366f1"); + return setValue(next.hex)} />; + }, + }, + { + name: "ComplexColorWheel", + render: () => { + const [value, setValue] = createSignal("#6366f1"); + const [strength, setStrength] = createSignal(10); + return ( + + ); + }, + }, + { name: "InlineEdit", render: () => }, + { name: "PanelToggle", render: () => }, + { name: "PasswordField and PasswordRequirements", render: () => }, + { + name: "FlexGrid", + render: () => ( + } + > + {(row) =>
{String(row)}
} +
+ ), + }, + { name: "LiveChatPanel", render: () => } /> }, + { name: "ImmersiveLanding", render: () => } /> }, + { name: "CookieConsent", render: () => } /> }, + { name: "PWAInstallPrompt", render: () => } /> }, + { name: "FirefoxPWABanner", render: () => } /> }, + { + name: "ButtonGroup", + render: () => { + const [selected, setSelected] = createSignal(""); + return ( + <> + + + + +

{selected() ? `Selected ${selected()}` : "No button selected"}

+ + ); + }, + }, { name: "CheckboxGroup", render: () => ( - First - Second + First + Second ), }, - { name: "CloseButton", render: () => }, + { + name: "CloseButton", + render: () => , + }, { // Kbd itself is shown on its own page, but its Abbr is used nowhere: it // renders a glyph for a named key and titles itself with that key's name. @@ -53,12 +528,12 @@ const EXAMPLES: Example[] = [ ), }, - { name: "Input (placeholder)", render: () => }, + { name: "Input (placeholder)", render: () => }, { name: "Collapsible", render: () => ( - - More + + More Hidden until opened. ), @@ -66,9 +541,9 @@ const EXAMPLES: Example[] = [ { name: "Accordion", render: () => ( - - - First + + + First One. @@ -83,18 +558,32 @@ const EXAMPLES: Example[] = [ ), }, - { name: "Input (issues)", render: () => }, - { name: "Input (invalid)", render: () => }, + { name: "Input (issues)", render: () => }, + { name: "Input (invalid)", render: () => }, { name: "Input (grouped)", - render: () => ( - - - - - ), + render: () => { + const [value, setValue] = createSignal(""); + const [submitted, setSubmitted] = createSignal("Nothing submitted"); + let submissions = 0; + return ( + <> + + setValue(event.currentTarget.value)} + /> + + +

{submitted()}

+ + ); + }, }, - { name: "InputOTP", render: () => }, + { name: "InputOTP", render: () => }, { name: "ListBox", render: () => ( @@ -105,19 +594,35 @@ const EXAMPLES: Example[] = [ name: "MetalBorder", render: () => Bordered, }, - { name: "Meter", render: () => }, - { name: "Input (number)", render: () => }, + { name: "Meter", render: () => }, + { name: "Input (number)", render: () => }, { name: "Popover", render: () => ( - - Open + + Open Content. ), }, - { name: "Progress", render: () => }, - { name: "RadialProgress", render: () => }, + { + name: "Progress", + render: () => { + const [value, setValue] = createSignal(40); + return ( + + + + + ); + }, + }, + { name: "RadialProgress", render: () => }, { name: "ScrollArea", render: () => ( @@ -126,12 +631,15 @@ const EXAMPLES: Example[] = [ ), }, - { name: "Input (search)", render: () => }, + { name: "Input (search)", render: () => }, { name: "Separator", render: () => }, - { name: "SizePicker", render: () => }, + { name: "SizePicker", render: () => }, { name: "Slider", - render: () => {}} />, + render: () => { + const [value, setValue] = createSignal(40); + return ; + }, }, { name: "Spinner", render: () => }, { name: "Card (surface)", render: () => On a surface. }, @@ -146,10 +654,22 @@ const EXAMPLES: Example[] = [ ), }, { name: "Text", render: () => Body text. }, - { name: "Textarea", render: () =>