feat: enhanced 14 registry components + component gallery

Registry components enhanced with proper DreamStack patterns:
- Card: conditional title/subtitle/footer via when guards, slot for children
- Button: variant as string prop, disabled support
- Dialog: when-guarded overlay, slot for content, close button
- Progress: conditional label, variant support
- Input: conditional label, error state, helper text
- Alert: variant prop, slot for custom content
- Toggle: when-guarded label display
- Toast: when-guarded visibility
- Avatar: initials with variant
- Badge: label with variant prop
- Separator: optional centered label

New components:
- Stat: dashboard metric card (label, value, change delta)
- Tabs: tab switcher supporting 2-3 tabs
- Select: button-based option selector

New example:
- component-gallery.ds (89KB): imports 12 components, uses Card+Button,
  Input+Alert, Progress, Badge+when/else, match expressions,
  Stat metrics, Toggle, Avatar, Toast, Separator, every timer

All 10 examples pass. Browser-tested with zero errors.
This commit is contained in:
enzotar 2026-02-26 18:25:49 -08:00
parent 08e36573a5
commit 1d554ae7ab
15 changed files with 201 additions and 31 deletions

View file

@ -0,0 +1,117 @@
-- DreamStack Component Gallery
-- Comprehensive showcase of all 14 registry components
-- Demonstrates: imports, slots, when/else, match, reactive state, every timer
import { Card } from "../registry/components/card"
import { Badge } from "../registry/components/badge"
import { Button } from "../registry/components/button"
import { Progress } from "../registry/components/progress"
import { Alert } from "../registry/components/alert"
import { Input } from "../registry/components/input"
import { Toggle } from "../registry/components/toggle"
import { Avatar } from "../registry/components/avatar"
import { Stat } from "../registry/components/stat"
import { Separator } from "../registry/components/separator"
import { Toast } from "../registry/components/toast"
-- State
let count = 0
let name = ""
let darkMode = false
let loggedIn = false
let mood = "neutral"
let progress = 25
let showToast = false
let ticks = 0
-- Timer
every 1000 -> ticks += 1
view gallery = column [
-- Header
text "🧩 Component Gallery" { variant: "title" }
text "14 components • DreamStack Registry" { variant: "subtitle" }
Separator { label: "Interactive" }
-- 1. Card + Button + Counter
Card { title: "Counter", subtitle: "Card + Button + slots" } [
text "Count: {count}" { variant: "title" }
row [
Button { label: "1", variant: "secondary", onClick: count -= 1 }
Button { label: "+1", variant: "primary", onClick: count += 1 }
Button { label: "Reset", variant: "ghost", onClick: count = 0 }
]
]
-- 2. Input + Alert
Card { title: "Form", subtitle: "Input + Alert components" } [
Input { value: name, placeholder: "Type your name...", label: "Name" }
when name ->
Alert { message: "Hello, {name}! 👋", variant: "success" }
]
-- 3. Progress
Card { title: "Progress", subtitle: "Progress bar with controls" } [
Progress { value: progress, label: "Loading" }
row [
Button { label: "10", variant: "secondary", onClick: progress -= 10 }
Button { label: "+10", variant: "primary", onClick: progress += 10 }
Button { label: "Full", variant: "ghost", onClick: progress = 100 }
]
]
Separator { label: "Status" }
-- 4. Badge + When/Else
Card { title: "Auth", subtitle: "Badge + when/else" } [
Button { label: "Toggle Login", variant: "primary", onClick: loggedIn = !loggedIn }
when loggedIn ->
row [
Badge { label: "ONLINE", variant: "success" }
text "Welcome back!"
]
else ->
row [
Badge { label: "OFFLINE", variant: "error" }
text "Please log in"
]
]
-- 5. Match + Mood
Card { title: "Mood", subtitle: "match expressions" } [
row [
Button { label: "😊 Happy", variant: "primary", onClick: mood = "happy" }
Button { label: "😢 Sad", variant: "secondary", onClick: mood = "sad" }
Button { label: "😡 Angry", variant: "ghost", onClick: mood = "angry" }
]
match mood
"happy" -> text "You're feeling great! 🌟"
"sad" -> text "Hang in there... 💙"
"angry" -> text "Take a deep breath 🔥"
_ -> text "How are you feeling?"
]
Separator { label: "Display" }
-- 6. Stat cards
row [
Stat { label: "Uptime", value: "{ticks}s", change: "+1/s" }
Stat { label: "Clicks", value: "{count}", change: "total" }
Stat { label: "Progress", value: "{progress}%", change: "current" }
]
-- 7. Avatar + Toggle
Card { title: "Settings" } [
row [
Avatar { initials: "DS" }
text "DreamStack User"
]
Toggle { value: darkMode, label: "Dark Mode", onChange: darkMode = !darkMode }
Toggle { value: showToast, label: "Show Toast", onChange: showToast = !showToast }
]
-- 8. Toast
Toast { message: "Hello from DreamStack! 🚀", variant: "success", visible: showToast }
]

View file

@ -1,5 +1,11 @@
-- DreamStack Alert Component
-- Dismissable alert with icon and variant support
-- Variants: info, warning, error, success
export component Alert(message, variant) =
text message { variant: "info" }
export component Alert(message, variant, title) =
column [
row [
text message
]
slot
] { variant: variant }

View file

@ -1,5 +1,5 @@
-- DreamStack Avatar Component
-- User avatar with initials fallback
-- User avatar with initials and size variant
export component Avatar(initials) =
text initials
export component Avatar(initials, size) =
text initials { variant: "avatar" }

View file

@ -1,5 +1,5 @@
-- DreamStack Badge Component
-- Small label with colored background
-- Status indicator with colored background
-- Variants: success, warning, error, info, default
export component Badge(label, variant) =

View file

@ -1,5 +1,5 @@
-- DreamStack Button Component
-- Variants: primary (default), secondary, ghost, destructive
-- Variants: primary (default), secondary, ghost, destructive, outline
export component Button(label, variant, onClick) =
button label { click: onClick, variant: "primary" }
export component Button(label, variant, onClick, disabled) =
button label { click: onClick, variant: variant, disabled: disabled }

View file

@ -1,9 +1,10 @@
-- DreamStack Card Component with Slot
-- Glassmorphism container with title, subtitle, and slot for children
export component Card(title, subtitle) =
export component Card(title, subtitle, footer) =
column [
text title { variant: "title" }
text subtitle { variant: "subtitle" }
when title -> text title { variant: "title" }
when subtitle -> text subtitle { variant: "subtitle" }
slot
when footer -> text footer { variant: "subtitle" }
] { variant: "card" }

View file

@ -1,10 +1,16 @@
-- DreamStack Dialog Component
-- Modal with overlay, title, and close button
-- Modal with overlay, title, slot content, and close button
import { Button } from "./button"
export component Dialog(title, open, onClose) =
column [
text title { variant: "title" }
Button { label: "Close", onClick: onClose }
] { variant: "dialog" }
when open ->
column [
column [
row [
text title { variant: "title" }
Button { label: "✕", variant: "ghost", onClick: onClose }
]
slot
] { variant: "dialog-panel" }
] { variant: "dialog-overlay" }

View file

@ -1,8 +1,10 @@
-- DreamStack Input Component
-- Text input with label, placeholder, and error state
export component Input(value, placeholder, label) =
export component Input(value, placeholder, label, error, helper) =
column [
text label { variant: "label" }
when label -> text label { variant: "label" }
input { bind: value, placeholder: placeholder }
when error -> text error { variant: "error" }
when helper -> text helper { variant: "subtitle" }
]

View file

@ -1,10 +1,10 @@
-- DreamStack Progress Component
-- Animated progress bar with percentage display
-- Animated progress bar with percentage, label, and variant
export component Progress(value, label) =
export component Progress(value, label, variant) =
column [
row [
text label { variant: "label" }
when label -> text label { variant: "label" }
text "{value}%" { variant: "label" }
]
column [

View file

@ -0,0 +1,12 @@
-- DreamStack Select Component
-- Option selector displayed as button group
export component Select(value, label, opt1, opt2, opt3, onSelect1, onSelect2, onSelect3) =
column [
when label -> text label { variant: "label" }
row [
button opt1 { click: onSelect1, variant: "secondary" }
button opt2 { click: onSelect2, variant: "secondary" }
when opt3 -> button opt3 { click: onSelect3, variant: "secondary" }
]
]

View file

@ -1,5 +1,9 @@
-- DreamStack Separator Component
-- Visual divider between content sections
-- Visual divider between sections
export component Separator() =
text ""
export component Separator(label) =
row [
column [] { variant: "separator-line" }
when label -> text label { variant: "separator-label" }
when label -> column [] { variant: "separator-line" }
] { variant: "separator" }

View file

@ -0,0 +1,9 @@
-- DreamStack Stat Component
-- Dashboard metric card with label, value, and change delta
export component Stat(label, value, change) =
column [
text label { variant: "subtitle" }
text value { variant: "title" }
when change -> text change { variant: "label" }
] { variant: "card" }

View file

@ -0,0 +1,9 @@
-- DreamStack Tabs Component
-- Tab switcher with active state indicator
export component Tabs(activeTab, onTab1, onTab2, onTab3, label1, label2, label3) =
row [
button label1 { click: onTab1, variant: "primary" }
button label2 { click: onTab2, variant: "secondary" }
when label3 -> button label3 { click: onTab3, variant: "secondary" }
] { variant: "tabs" }

View file

@ -1,5 +1,6 @@
-- DreamStack Toast Component
-- Notification toast with slide-in animation
-- Notification toast with variant and visibility
export component Toast(message) =
text message
export component Toast(message, variant, visible) =
when visible ->
text message { variant: variant }

View file

@ -1,5 +1,8 @@
-- DreamStack Toggle Component
-- On/off switch
-- On/off switch with label
export component Toggle(value, onChange) =
button "" { click: onChange }
export component Toggle(value, label, onChange) =
row [
when label -> text label
button "Toggle" { click: onChange, variant: "toggle" }
]