Wire DSL Code Generator
Generate syntactically correct Wire DSL code for wireframes and interactive UI prototypes.
What This Skill Does
This skill enables LLMs to generate valid, current Wire DSL by providing:
- Complete syntax reference and grammar rules
- Catalog of all 30 available components
- Layout container patterns (stack, grid, split, panel, card, tabs, modal)
- Best practices for code generation
- Event and interactivity rules used by play test
Branch-Synced Changes
This skill is updated for the changes in feature/add-event-system, including:
- Event system with component and layout event handlers
- New actions:
enable(id)anddisable(id)(plusnavigate,show,hide,toggle,setTab) - New layouts:
layout tabs(...)andlayout modal(...) component Modalreplaced bylayout modal(...)component Tabsnow supportsinitialActiveandtabsIdlayout card(...)supportsonClickCheckbox,Radio, andTogglesupportclickable: falsefor non-interactive rendering
When to Use This Skill
Use this skill when you need to:
- Generate
.wirefiles for wireframe prototypes - Create UI mockups using declarative syntax
- Add clickable interactions for play test flows
- Build multi-screen application wireframes
- Design forms, dashboards, product catalogs, or admin interfaces
- Convert UI requirements into Wire DSL code
Core Concepts
Structure: Every Wire DSL file follows this hierarchy:
project -> [style|colors|mocks|define] -> screen -> layout -> childrenSyntax Style: Block-declarative with curly braces, similar to CSS/HCL:
project "App Name" {
style { ... } // optional
screen ScreenName {
layout <type> { ... }
}
}Key Rules:
- String values MUST be quoted:
text: "Hello" - Numbers, booleans, enums are NOT quoted:
height: 200,checked: true,variant: primary - Property format:
key: value - Comments:
//for line,/* */for block
Instructions for Code Generation
Step 1: Start with Project Structure
Begin with the project wrapper. The style block is optional. If omitted, defaults apply (density: "normal", spacing: "md", radius: "md", stroke: "normal", font: "base").
project "Project Name" {
style {
density: "compact" // compact | normal | comfortable
radius: "lg" // none | sm | md | lg | full
}
// screens go here
}Step 2: Create Screens
Each screen represents a unique view in the application:
screen ScreenName {
layout <type> {
// content
}
}Naming: Use CamelCase for screen names (for example: UsersList, ProductDetail, Dashboard).
Step 3: Choose a Layout Container
Select the appropriate layout based on UI structure:
| Layout | Use Case | Children | Example |
|---|---|---|---|
| stack | Linear arrangement | Multiple | Forms, lists, vertical/horizontal sections |
| grid | Multi-column (12-col) | cells | Dashboards, product grids, responsive layouts |
| split | Two-column area | Exactly 2 | Admin panels, navigation + content |
| panel | Bordered container | Exactly 1 | Highlighted sections, form groups |
| card | Content cards | Multiple | Product cards, user profiles, info boxes |
| tabs | Tabbed content panels | tab blocks | Settings pages, profile tabs, step flows |
| modal | Overlay dialog | Multiple (or body / footer) | Confirmation and form dialogs |
Step 4: Add Components
Choose from 30 available components organized in 8 categories:
Text: Heading, Text, Label, Paragraph, Code Input: Input, Textarea, Select, Checkbox, Radio, Toggle Action: Button, IconButton, Link Navigation: Topbar, SidebarMenu, Sidebar, Breadcrumbs, Tabs Data: Table, List, Stat, Chart Media: Image, Icon Layout: Card, Divider, Separate Feedback: Badge, Alert
Step 5: Add Events and Actions (When Needed)
Events are metadata for play test interactions.
Supported event props:
onClick: Button, IconButton, Link, andlayout card(...)onChangeoronActive+onInactive: Toggle, Checkbox, RadioonItemsClick: SidebarMenuonItemClick: ListonRowClick: TableonClose:layout modal(...)
Supported actions:
navigate(ScreenName)show(id)/hide(id)/toggle(id)enable(id)/disable(id)setTab(tabsId, index)- Use
selffor self-targeting:hide(self),show(self),toggle(self),enable(self),disable(self)
Action chaining:
component Button text: "Delete"
onClick: hide(listModal) & show(confirmModal) & disable(submitBtn)Step 6: Validate Before Output
Before outputting, check:
- All strings are quoted
- Numbers/booleans/enums are NOT quoted
- All braces are closed
- Required properties are present
- Component names match exactly (case-sensitive)
- Split has 2 children, Panel has 1 child
- Grid cells have valid
spanvalues (1-12) tabsIdpoints to an existinglayout tabs(id:...)in the same screenshow/hide/toggle/enable/disabletargets exist on the same screen (or useself)onChangeis not combined withonActive/onInactivelayout modal(...)does not mixbody/footersections with direct children
Reference Files
| File | Purpose |
|---|---|
| ../../docs/DSL-SYNTAX.md | Current language syntax and event rules |
| ../../docs/COMPONENTS-REFERENCE.md | Current component properties and event support |
| ../../docs/CONTAINERS-REFERENCE.md | Current layout/container rules (tabs, modal, card onClick) |
| ../../specs/VALIDATION-RULES.md | Event, modal, and semantic validation rules |
| core-syntax.md | Skill-local syntax summary |
| components-catalog.md | Skill-local component catalog |
| layouts-guide.md | Skill-local layout guide |
| best-practices.md | Validation checklist, common mistakes, gotchas |
| common-patterns.md | Reusable patterns for forms, dashboards, navigation, cards |
Examples
Example 1: Interactive Modal + Enable/Disable
project "Confirm Action" {
style {
density: "normal"
spacing: "md"
radius: "md"
stroke: "normal"
font: "base"
}
screen Main {
layout stack(direction: vertical, gap: md, padding: lg) {
component Input id: reasonInput label: "Reason" disabled: true
component Checkbox label: "I understand the consequences"
onActive: enable(reasonInput) & enable(deleteBtn)
onInactive: disable(reasonInput) & disable(deleteBtn)
component Button id: deleteBtn text: "Delete Item" variant: danger disabled: true
onClick: show(confirmDelete)
layout modal(id: confirmDelete, title: "Delete item?", visible: false, onClose: hide(self)) {
body {
component Text text: "This action cannot be undone."
}
footer {
component Button text: "Cancel" variant: secondary onClick: hide(self)
component Button text: "Confirm Delete" variant: danger onClick: hide(self)
}
}
}
}
}Example 2: Tabs Linked to Tabs Layout
project "Profile Settings" {
style {
density: "normal"
spacing: "md"
radius: "md"
stroke: "normal"
font: "base"
}
screen Settings {
layout stack(direction: vertical, gap: md, padding: lg) {
component Tabs items: "Profile,Security,Billing" initialActive: 0 tabsId: settingsTabs
layout tabs(id: settingsTabs) {
tab {
component Heading text: "Profile"
component Input label: "Full name"
component Input label: "Email"
}
tab {
component Heading text: "Security"
component Toggle label: "Two-factor auth"
component Button text: "Go Billing" onClick: setTab(settingsTabs, 2)
}
tab {
component Heading text: "Billing"
component Table columns: "Date,Amount,Status" rows: 4
}
}
}
}
}Example 3: Clickable Card + Sidebar Navigation
project "Admin" {
style {
density: "normal"
spacing: "md"
radius: "md"
stroke: "normal"
font: "base"
}
define Component "MainMenu" {
layout stack(direction: vertical, gap: md, padding: md) {
component SidebarMenu items: "Dashboard,Users,Settings"
onItemsClick: "DashboardScreen,UsersScreen,SettingsScreen"
active: prop_active
}
}
screen DashboardScreen {
layout split(left: 260, gap: md) {
component MainMenu active: 0
layout grid(columns: 12, gap: md, padding: md) {
cell span: 6 {
layout card(padding: md, gap: md, onClick: navigate(UsersScreen)) {
component Heading text: "Users"
component Text text: "Open users section"
}
}
}
}
}
screen UsersScreen {
layout split(left: 260, gap: md) {
component MainMenu active: 1
layout stack(direction: vertical, gap: md, padding: lg) {
component Heading text: "Users"
}
}
}
screen SettingsScreen {
layout split(left: 260, gap: md) {
component MainMenu active: 2
layout stack(direction: vertical, gap: md, padding: lg) {
component Heading text: "Settings"
}
}
}
}Quick Tips
Padding default: Layouts have 0px padding by default. Add padding explicitly. Grid system: 12-column grid. cell span must be 1-12. IDs: Use valid identifiers: [a-zA-Z_][a-zA-Z0-9_]*. CSV lists: Use quoted comma-separated strings: items: "Home,Users,Settings". Tabs linking: component Tabs tabsId: X must match layout tabs(id: X) in same screen. Modal model: Use layout modal(...), not component Modal. Boolean controls: Checkbox, Radio, Toggle support clickable: false when needed.
Common Mistakes to Avoid
- Forgetting quotes on strings:
text: Hello->text: "Hello" - Adding quotes to numbers/enums:
rows: "8"->rows: 8 - Wrong component case:
button->Button - Using
component Modal-> uselayout modal(...) - Missing
tabsIdand matchinglayout tabs(id:...) - Using
activeas design-time default on Tabs -> preferinitialActive - Mixing
onChangewithonActive/onInactiveon same control - Referencing unknown IDs in
show/hide/toggle/enable/disable - Split with 3 children -> must be exactly 2
- Panel with multiple children -> must be exactly 1
- Mixing modal
body/footerwith direct children in the same modal
Output Guidelines
When generating Wire DSL code:
- Always validate syntax before outputting
- Return complete, runnable
.wirefiles (not partial snippets) - Use realistic names and data
- Keep component names and property names exact
- Add explicit layout spacing (
gap,padding) - For interactive flows, wire IDs and events consistently
- Use comments only when they clarify non-obvious structures
Interactive Example Snippet
layout stack(direction: vertical, gap: md, padding: md) {
component Input id: nameInput label: "Name" disabled: true
component Button text: "Unlock" onClick: enable(nameInput)
component Button text: "Lock" onClick: disable(nameInput)
component Button text: "Open confirm" onClick: show(confirmModal)
layout modal(id: confirmModal, title: "Confirm?", visible: false, onClose: hide(confirmModal)) {
body {
layout stack(direction: vertical, padding: sm) {
component Text text: "Proceed?"
}
}
footer {
layout stack(direction: vertical, padding: sm) {
component Button text: "Close" onClick: hide(confirmModal)
}
}
}
}