feat(web): improve header visibility and add component playground

- Fix Sign In button visibility by changing from outline to secondary variant
- Convert homepage from createElement to JSX syntax for better readability
- Add Playground page (/playground) showcasing all UI components
- Add Playground link to header navigation
- Comprehensive component examples with all variants, sizes, and states
- Interactive demos for progress bars and tabs
- Replace footer anchor tags with buttons for accessibility

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Ajax Davis 2025-11-26 03:27:42 +10:00
parent db1088ec1d
commit 157cd750e4
3 changed files with 721 additions and 302 deletions

View file

@ -1,6 +1,6 @@
/// <reference types="next" />
/// <reference types="next/image-types/global" />
import "./.next/dev/types/routes.d.ts";
import "./.next/types/routes.d.ts";
// NOTE: This file should not be edited
// see https://nextjs.org/docs/app/api-reference/config/typescript for more information.

View file

@ -5,315 +5,202 @@ import { Container } from "@tpmjs/ui/Container/Container";
import { Header } from "@tpmjs/ui/Header/Header";
import { Icon } from "@tpmjs/ui/Icon/Icon";
import { Input } from "@tpmjs/ui/Input/Input";
import { createElement } from "react";
import Link from "next/link";
import { ThemeToggle } from "../components/ThemeToggle";
import { categories, featuredTools, statistics } from "../data/homePageData";
export default function HomePage(): React.ReactElement {
return createElement(
"div",
{ className: "min-h-screen flex flex-col" },
// Header
createElement(Header, {
title: "TPMJS",
size: "md",
sticky: true,
actions: createElement(
"div",
{ className: "flex items-center gap-4" },
createElement(Button, { variant: "ghost", size: "sm" }, "Pro"),
createElement(Button, { variant: "ghost", size: "sm" }, "Teams"),
createElement(Button, { variant: "ghost", size: "sm" }, "Pricing"),
createElement(
Button,
{ variant: "ghost", size: "sm" },
"Documentation",
),
createElement(Button, { variant: "outline", size: "sm" }, "Sign In"),
createElement(Button, { size: "sm" }, "Sign Up"),
createElement(ThemeToggle, {}),
),
}),
return (
<div className="min-h-screen flex flex-col">
{/* Header */}
<Header
title={<Link href="/">TPMJS</Link>}
size="md"
sticky={true}
actions={
<div className="flex items-center gap-4">
<Link href="/playground">
<Button variant="ghost" size="sm">
Playground
</Button>
</Link>
<Button variant="ghost" size="sm">
Pro
</Button>
<Button variant="ghost" size="sm">
Teams
</Button>
<Button variant="ghost" size="sm">
Pricing
</Button>
<Button variant="ghost" size="sm">
Documentation
</Button>
<Button variant="secondary" size="sm">
Sign In
</Button>
<Button size="sm">Sign Up</Button>
<ThemeToggle />
</div>
}
/>
createElement(
"main",
{ className: "flex-1" },
// Hero Section
createElement(
"section",
{ className: "relative py-24 overflow-hidden" },
createElement("div", {
className:
"absolute inset-0 bg-gradient-to-r from-orange-500 via-amber-500 to-red-500 opacity-10",
}),
createElement(
Container,
{ size: "xl", padding: "lg" },
createElement(
"div",
{
className:
"max-w-3xl mx-auto text-center space-y-8 relative z-10",
},
createElement(
"h1",
{ className: "text-5xl md:text-6xl font-bold tracking-tight" },
"Tool Registry for AI Agents",
),
createElement(
"p",
{ className: "text-xl text-foreground-secondary" },
"Discover, share, and integrate tools that give your agents superpowers. The registry for AI tools.",
),
createElement(
"div",
{ className: "flex gap-3 items-center max-w-2xl mx-auto" },
createElement(Input, {
size: "lg",
placeholder: "Search tools...",
className: "flex-1",
}),
createElement(
Button,
{ size: "lg", className: "px-8" },
"Search",
),
),
),
),
),
<main className="flex-1">
{/* Hero Section */}
<section className="relative py-24 overflow-hidden">
<div className="absolute inset-0 bg-gradient-to-r from-orange-500 via-amber-500 to-red-500 opacity-10" />
<Container size="xl" padding="lg">
<div className="max-w-3xl mx-auto text-center space-y-8 relative z-10">
<h1 className="text-5xl md:text-6xl font-bold tracking-tight">
Tool Registry for AI Agents
</h1>
<p className="text-xl text-foreground-secondary">
Discover, share, and integrate tools that give your agents
superpowers. The registry for AI tools.
</p>
<div className="flex gap-3 items-center max-w-2xl mx-auto">
<Input
size="lg"
placeholder="Search tools..."
className="flex-1"
/>
<Button size="lg" className="px-8">
Search
</Button>
</div>
</div>
</Container>
</section>
// Featured Tools Section
createElement(
"section",
{ className: "py-16 bg-surface" },
createElement(
Container,
{ size: "xl", padding: "lg" },
createElement(
"div",
{ className: "flex items-center justify-between mb-8" },
createElement(
"h2",
{ className: "text-3xl font-semibold" },
"Featured Tools",
),
createElement(Button, { variant: "ghost" }, "View all tools →"),
),
createElement(
"div",
{
className: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6",
},
...featuredTools.map((tool) =>
createElement(
Card,
{
key: tool.id,
className: "hover:shadow-lg transition-shadow",
},
createElement(
CardContent,
{ className: "p-6 space-y-4" },
createElement(
"div",
{ className: "flex items-start gap-4" },
createElement(Icon, {
icon: tool.icon,
size: "lg",
className: "text-primary",
}),
createElement(
"div",
{ className: "flex-1 space-y-2" },
createElement(
"h3",
{ className: "text-lg font-semibold" },
tool.name,
),
createElement(
"p",
{ className: "text-sm text-foreground-secondary" },
tool.description,
),
createElement(
"div",
{ className: "flex items-center gap-2" },
createElement(
Badge,
{ variant: tool.categoryVariant, size: "sm" },
tool.category,
),
createElement(
"span",
{ className: "text-xs text-foreground-tertiary" },
tool.weeklyUsage,
),
),
),
),
),
),
),
),
),
),
{/* Featured Tools Section */}
<section className="py-16 bg-surface">
<Container size="xl" padding="lg">
<div className="flex items-center justify-between mb-8">
<h2 className="text-3xl font-semibold">Featured Tools</h2>
<Button variant="ghost">View all tools →</Button>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
{featuredTools.map((tool) => (
<Card
key={tool.id}
className="hover:shadow-lg transition-shadow"
>
<CardContent className="p-6 space-y-4">
<div className="flex items-start gap-4">
<Icon
icon={tool.icon}
size="lg"
className="text-primary"
/>
<div className="flex-1 space-y-2">
<h3 className="text-lg font-semibold">{tool.name}</h3>
<p className="text-sm text-foreground-secondary">
{tool.description}
</p>
<div className="flex items-center gap-2">
<Badge variant={tool.categoryVariant} size="sm">
{tool.category}
</Badge>
<span className="text-xs text-foreground-tertiary">
{tool.weeklyUsage}
</span>
</div>
</div>
</div>
</CardContent>
</Card>
))}
</div>
</Container>
</section>
// Categories Section
createElement(
"section",
{ className: "py-16" },
createElement(
Container,
{ size: "xl", padding: "lg" },
createElement(
"h2",
{ className: "text-3xl font-semibold mb-8" },
"Browse by Category",
),
createElement(
"div",
{
className: "grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4",
},
...categories.map((category) =>
createElement(
Card,
{
key: category.id,
className: "hover:shadow-lg transition-shadow cursor-pointer",
},
createElement(
CardContent,
{ className: `p-6 ${category.colorClass}` },
createElement(
"div",
{ className: "space-y-3" },
createElement(Icon, {
icon: category.icon,
size: "lg",
}),
createElement(
"h3",
{ className: "font-semibold" },
category.name,
),
createElement(
"p",
{ className: "text-sm opacity-90" },
`${category.toolCount} tools`,
),
),
),
),
),
),
),
),
{/* Categories Section */}
<section className="py-16">
<Container size="xl" padding="lg">
<h2 className="text-3xl font-semibold mb-8">Browse by Category</h2>
<div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4">
{categories.map((category) => (
<Card
key={category.id}
className="hover:shadow-lg transition-shadow cursor-pointer"
>
<CardContent className={`p-6 ${category.colorClass}`}>
<div className="space-y-3">
<Icon icon={category.icon} size="lg" />
<h3 className="font-semibold">{category.name}</h3>
<p className="text-sm opacity-90">
{category.toolCount} tools
</p>
</div>
</CardContent>
</Card>
))}
</div>
</Container>
</section>
// Statistics Section
createElement(
"section",
{ className: "py-16 bg-surface" },
createElement(
Container,
{ size: "xl", padding: "lg" },
createElement(
"h2",
{ className: "text-3xl font-semibold mb-8 text-center" },
"Platform Statistics",
),
createElement(
"div",
{
className: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6",
},
...statistics.map((stat, index) =>
createElement(
Card,
{ key: index },
createElement(
CardContent,
{ className: "p-6 text-center space-y-3" },
createElement(Icon, {
icon: stat.icon,
size: "lg",
className: "mx-auto text-primary",
}),
createElement(
"div",
{ className: "text-4xl font-bold" },
stat.value,
),
createElement(
"div",
{ className: "text-sm font-medium" },
stat.label,
),
stat.subtext &&
createElement(
"div",
{ className: "text-xs text-foreground-tertiary" },
stat.subtext,
),
),
),
),
),
),
),
),
{/* Statistics Section */}
<section className="py-16 bg-surface">
<Container size="xl" padding="lg">
<h2 className="text-3xl font-semibold mb-8 text-center">
Platform Statistics
</h2>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6">
{statistics.map((stat, index) => (
<Card key={index}>
<CardContent className="p-6 text-center space-y-3">
<Icon
icon={stat.icon}
size="lg"
className="mx-auto text-primary"
/>
<div className="text-4xl font-bold">{stat.value}</div>
<div className="text-sm font-medium">{stat.label}</div>
{stat.subtext && (
<div className="text-xs text-foreground-tertiary">
{stat.subtext}
</div>
)}
</CardContent>
</Card>
))}
</div>
</Container>
</section>
</main>
// Footer
createElement(
"footer",
{ className: "py-8 border-t border-border bg-surface" },
createElement(
Container,
{ size: "xl", padding: "lg" },
createElement(
"div",
{
className:
"flex flex-col md:flex-row items-center justify-between gap-4",
},
createElement(
"p",
{ className: "text-sm text-foreground-secondary" },
"© 2025 TPMJS. All rights reserved.",
),
createElement(
"div",
{ className: "flex items-center gap-4 text-sm" },
createElement(
"a",
{
href: "#",
className: "text-foreground-secondary hover:text-foreground",
},
"Privacy",
),
createElement("span", { className: "text-border" }, "·"),
createElement(
"a",
{
href: "#",
className: "text-foreground-secondary hover:text-foreground",
},
"Terms",
),
createElement("span", { className: "text-border" }, "·"),
createElement(
"a",
{
href: "#",
className: "text-foreground-secondary hover:text-foreground",
},
"Contact",
),
),
),
),
),
{/* Footer */}
<footer className="py-8 border-t border-border bg-surface">
<Container size="xl" padding="lg">
<div className="flex flex-col md:flex-row items-center justify-between gap-4">
<p className="text-sm text-foreground-secondary">
© 2025 TPMJS. All rights reserved.
</p>
<div className="flex items-center gap-4 text-sm">
<button
type="button"
className="text-foreground-secondary hover:text-foreground"
>
Privacy
</button>
<span className="text-border">·</span>
<button
type="button"
className="text-foreground-secondary hover:text-foreground"
>
Terms
</button>
<span className="text-border">·</span>
<button
type="button"
className="text-foreground-secondary hover:text-foreground"
>
Contact
</button>
</div>
</div>
</Container>
</footer>
</div>
);
}

View file

@ -0,0 +1,532 @@
"use client";
import { Badge } from "@tpmjs/ui/Badge/Badge";
import { Button } from "@tpmjs/ui/Button/Button";
import {
Card,
CardContent,
CardDescription,
CardFooter,
CardHeader,
CardTitle,
} from "@tpmjs/ui/Card/Card";
import { CodeBlock } from "@tpmjs/ui/CodeBlock/CodeBlock";
import { Container } from "@tpmjs/ui/Container/Container";
import { Header } from "@tpmjs/ui/Header/Header";
import { Icon } from "@tpmjs/ui/Icon/Icon";
import { Input } from "@tpmjs/ui/Input/Input";
import { Label } from "@tpmjs/ui/Label/Label";
import { ProgressBar } from "@tpmjs/ui/ProgressBar/ProgressBar";
import { Tabs } from "@tpmjs/ui/Tabs/Tabs";
import Link from "next/link";
import { useState } from "react";
import { ThemeToggle } from "../../components/ThemeToggle";
export default function PlaygroundPage() {
const [activeTab, setActiveTab] = useState("all");
const [progress, setProgress] = useState(65);
return (
<div className="min-h-screen flex flex-col">
{/* Header */}
<Header
title={<Link href="/">TPMJS Playground</Link>}
size="md"
sticky={true}
actions={
<div className="flex items-center gap-4">
<Link href="/">
<Button variant="ghost" size="sm">
Home
</Button>
</Link>
<ThemeToggle />
</div>
}
/>
<main className="flex-1 py-12">
<Container size="xl" padding="lg">
<div className="space-y-16">
{/* Page Title */}
<div className="text-center space-y-4">
<h1 className="text-4xl font-bold">Component Playground</h1>
<p className="text-lg text-foreground-secondary">
Explore and test all TPMJS UI components in one place
</p>
</div>
{/* Buttons Section */}
<section className="space-y-6">
<h2 className="text-3xl font-semibold border-b border-border pb-2">
Buttons
</h2>
<div className="space-y-8">
{/* Button Variants */}
<div className="space-y-4">
<h3 className="text-xl font-medium">Variants</h3>
<div className="flex flex-wrap gap-4">
<Button variant="default">Default</Button>
<Button variant="destructive">Destructive</Button>
<Button variant="outline">Outline</Button>
<Button variant="secondary">Secondary</Button>
<Button variant="ghost">Ghost</Button>
<Button variant="link">Link</Button>
</div>
</div>
{/* Button Sizes */}
<div className="space-y-4">
<h3 className="text-xl font-medium">Sizes</h3>
<div className="flex flex-wrap items-center gap-4">
<Button size="sm">Small</Button>
<Button size="md">Medium</Button>
<Button size="lg">Large</Button>
</div>
</div>
{/* Button States */}
<div className="space-y-4">
<h3 className="text-xl font-medium">States</h3>
<div className="flex flex-wrap gap-4">
<Button>Normal</Button>
<Button disabled>Disabled</Button>
<Button loading>Loading</Button>
</div>
</div>
</div>
</section>
{/* Badges Section */}
<section className="space-y-6">
<h2 className="text-3xl font-semibold border-b border-border pb-2">
Badges
</h2>
<div className="space-y-8">
{/* Badge Variants */}
<div className="space-y-4">
<h3 className="text-xl font-medium">Variants</h3>
<div className="flex flex-wrap gap-4">
<Badge variant="default">Default</Badge>
<Badge variant="secondary">Secondary</Badge>
<Badge variant="error">Error</Badge>
<Badge variant="outline">Outline</Badge>
<Badge variant="success">Success</Badge>
<Badge variant="warning">Warning</Badge>
<Badge variant="info">Info</Badge>
</div>
</div>
{/* Badge Sizes */}
<div className="space-y-4">
<h3 className="text-xl font-medium">Sizes</h3>
<div className="flex flex-wrap items-center gap-4">
<Badge size="sm">Small</Badge>
<Badge size="md">Medium</Badge>
<Badge size="lg">Large</Badge>
</div>
</div>
</div>
</section>
{/* Icons Section */}
<section className="space-y-6">
<h2 className="text-3xl font-semibold border-b border-border pb-2">
Icons
</h2>
<div className="space-y-8">
{/* Icon Sizes */}
<div className="space-y-4">
<h3 className="text-xl font-medium">Sizes</h3>
<div className="flex flex-wrap items-end gap-6">
<div className="flex flex-col items-center gap-2">
<Icon icon="check" size="sm" />
<span className="text-xs">Small</span>
</div>
<div className="flex flex-col items-center gap-2">
<Icon icon="check" size="md" />
<span className="text-xs">Medium</span>
</div>
<div className="flex flex-col items-center gap-2">
<Icon icon="check" size="lg" />
<span className="text-xs">Large</span>
</div>
</div>
</div>
{/* Icon Gallery */}
<div className="space-y-4">
<h3 className="text-xl font-medium">Available Icons</h3>
<div className="grid grid-cols-4 md:grid-cols-6 lg:grid-cols-8 gap-6">
{[
"check",
"x",
"chevronDown",
"copy",
"externalLink",
"github",
"sun",
"moon",
].map((icon) => (
<div
key={icon}
className="flex flex-col items-center gap-2 p-3 rounded-lg hover:bg-surface transition-colors"
>
<Icon icon={icon as any} size="lg" />
<span className="text-xs text-center">{icon}</span>
</div>
))}
</div>
</div>
</div>
</section>
{/* Cards Section */}
<section className="space-y-6">
<h2 className="text-3xl font-semibold border-b border-border pb-2">
Cards
</h2>
<div className="space-y-8">
{/* Card Variants */}
<div className="space-y-4">
<h3 className="text-xl font-medium">Variants</h3>
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
<Card variant="default">
<CardHeader>
<CardTitle>Default Card</CardTitle>
<CardDescription>
This is the default card style
</CardDescription>
</CardHeader>
<CardContent>
<p className="text-sm">
Cards are flexible containers for content.
</p>
</CardContent>
<CardFooter>
<Button size="sm">Action</Button>
</CardFooter>
</Card>
<Card variant="elevated">
<CardHeader>
<CardTitle>Elevated Card</CardTitle>
<CardDescription>
This card has a shadow elevation
</CardDescription>
</CardHeader>
<CardContent>
<p className="text-sm">
Perfect for highlighting important content.
</p>
</CardContent>
<CardFooter>
<Button size="sm">Action</Button>
</CardFooter>
</Card>
<Card variant="outline">
<CardHeader>
<CardTitle>Outline Card</CardTitle>
<CardDescription>
This card has an outline border
</CardDescription>
</CardHeader>
<CardContent>
<p className="text-sm">
Great for subtle content separation.
</p>
</CardContent>
<CardFooter>
<Button size="sm">Action</Button>
</CardFooter>
</Card>
</div>
</div>
</div>
</section>
{/* Inputs Section */}
<section className="space-y-6">
<h2 className="text-3xl font-semibold border-b border-border pb-2">
Inputs
</h2>
<div className="space-y-8">
{/* Input Sizes */}
<div className="space-y-4">
<h3 className="text-xl font-medium">Sizes</h3>
<div className="space-y-4 max-w-md">
<Input size="sm" placeholder="Small input" />
<Input size="md" placeholder="Medium input" />
<Input size="lg" placeholder="Large input" />
</div>
</div>
{/* Input States */}
<div className="space-y-4">
<h3 className="text-xl font-medium">States</h3>
<div className="space-y-4 max-w-md">
<div className="space-y-2">
<Label>Default Input</Label>
<Input placeholder="Enter text..." />
</div>
<div className="space-y-2">
<Label>Error State</Label>
<Input state="error" placeholder="Error input" />
</div>
<div className="space-y-2">
<Label>Success State</Label>
<Input state="success" placeholder="Success input" />
</div>
<div className="space-y-2">
<Label>Disabled Input</Label>
<Input disabled placeholder="Disabled input" />
</div>
</div>
</div>
</div>
</section>
{/* Progress Bars Section */}
<section className="space-y-6">
<h2 className="text-3xl font-semibold border-b border-border pb-2">
Progress Bars
</h2>
<div className="space-y-8">
{/* Progress Bar Variants */}
<div className="space-y-4">
<h3 className="text-xl font-medium">Variants</h3>
<div className="space-y-6 max-w-xl">
<div className="space-y-2">
<div className="flex items-center justify-between text-sm">
<span>Primary</span>
<span>{progress}%</span>
</div>
<ProgressBar value={progress} variant="primary" />
</div>
<div className="space-y-2">
<div className="flex items-center justify-between text-sm">
<span>Success</span>
<span>100%</span>
</div>
<ProgressBar value={100} variant="success" />
</div>
<div className="space-y-2">
<div className="flex items-center justify-between text-sm">
<span>Warning</span>
<span>45%</span>
</div>
<ProgressBar value={45} variant="warning" />
</div>
<div className="space-y-2">
<div className="flex items-center justify-between text-sm">
<span>Danger</span>
<span>20%</span>
</div>
<ProgressBar value={20} variant="danger" />
</div>
</div>
</div>
{/* Interactive Progress */}
<div className="space-y-4">
<h3 className="text-xl font-medium">Interactive</h3>
<Card className="max-w-xl">
<CardContent className="p-6 space-y-4">
<div className="space-y-2">
<div className="flex items-center justify-between">
<span className="text-sm font-medium">
Adjust Progress
</span>
<span className="text-sm text-foreground-secondary">
{progress}%
</span>
</div>
<ProgressBar value={progress} />
</div>
<div className="flex gap-2">
<Button
size="sm"
onClick={() =>
setProgress(Math.max(0, progress - 10))
}
>
-10%
</Button>
<Button
size="sm"
onClick={() =>
setProgress(Math.min(100, progress + 10))
}
>
+10%
</Button>
<Button
size="sm"
variant="outline"
onClick={() => setProgress(0)}
>
Reset
</Button>
</div>
</CardContent>
</Card>
</div>
</div>
</section>
{/* Tabs Section */}
<section className="space-y-6">
<h2 className="text-3xl font-semibold border-b border-border pb-2">
Tabs
</h2>
<div className="space-y-8">
<div className="space-y-4">
<h3 className="text-xl font-medium">Interactive Tabs</h3>
<Card>
<CardContent className="p-6">
<Tabs
tabs={[
{ id: "all", label: "All Tools", count: 1234 },
{ id: "featured", label: "Featured", count: 42 },
{ id: "popular", label: "Popular", count: 156 },
{ id: "recent", label: "Recent" },
]}
activeTab={activeTab}
onTabChange={setActiveTab}
/>
<div className="mt-6 p-4 bg-surface rounded-lg">
<p className="text-sm text-foreground-secondary">
Active tab: <strong>{activeTab}</strong>
</p>
</div>
</CardContent>
</Card>
</div>
</div>
</section>
{/* Code Block Section */}
<section className="space-y-6">
<h2 className="text-3xl font-semibold border-b border-border pb-2">
Code Block
</h2>
<div className="space-y-8">
<div className="space-y-4">
<h3 className="text-xl font-medium">Example Code</h3>
<CodeBlock
language="typescript"
code={`import { Button } from "@tpmjs/ui/Button/Button";
export default function Example() {
return (
<Button variant="default" size="md">
Click me!
</Button>
);
}`}
/>
</div>
<div className="space-y-4">
<h3 className="text-xl font-medium">JSON Example</h3>
<CodeBlock
language="json"
code={`{
"name": "@tpmjs/ui",
"version": "0.1.3",
"type": "module"
}`}
/>
</div>
</div>
</section>
{/* Containers Section */}
<section className="space-y-6">
<h2 className="text-3xl font-semibold border-b border-border pb-2">
Containers
</h2>
<div className="space-y-8">
<div className="space-y-4">
<h3 className="text-xl font-medium">Container Sizes</h3>
<div className="space-y-6">
<Container size="sm" padding="md">
<Card>
<CardContent className="p-4 text-center">
<code className="text-sm">size="sm"</code>
</CardContent>
</Card>
</Container>
<Container size="md" padding="md">
<Card>
<CardContent className="p-4 text-center">
<code className="text-sm">size="md"</code>
</CardContent>
</Card>
</Container>
<Container size="lg" padding="md">
<Card>
<CardContent className="p-4 text-center">
<code className="text-sm">size="lg"</code>
</CardContent>
</Card>
</Container>
<Container size="xl" padding="md">
<Card>
<CardContent className="p-4 text-center">
<code className="text-sm">size="xl"</code>
</CardContent>
</Card>
</Container>
</div>
</div>
</div>
</section>
{/* Labels Section */}
<section className="space-y-6">
<h2 className="text-3xl font-semibold border-b border-border pb-2">
Labels
</h2>
<div className="space-y-8">
<div className="space-y-4">
<h3 className="text-xl font-medium">Form Labels</h3>
<div className="space-y-4 max-w-md">
<div className="space-y-2">
<Label htmlFor="email">Email Address</Label>
<Input
id="email"
type="email"
placeholder="you@example.com"
/>
</div>
<div className="space-y-2">
<Label htmlFor="password" required>
Password
</Label>
<Input id="password" type="password" />
</div>
<div className="space-y-2">
<Label htmlFor="bio">Bio</Label>
<Input id="bio" placeholder="Tell us about yourself" />
</div>
</div>
</div>
</div>
</section>
</div>
</Container>
</main>
{/* Footer */}
<footer className="py-8 border-t border-border bg-surface mt-16">
<Container size="xl" padding="lg">
<p className="text-sm text-foreground-secondary text-center">
TPMJS Component Playground
</p>
</Container>
</footer>
</div>
);
}