Building a Complete App
Learn by building a task manager app that uses all of Uizy's features.
What We'll Build
A simple task manager with:
- Responsive layout (header, sidebar, main content)
- Task list with add/complete/delete
- Theme switching (light/dark)
- Reactive state management
Step 1: Setup
Create your HTML file:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Task Manager</title>
<link
rel="stylesheet"
href="https://unpkg.com/@dufeut/uizy/dist/index.css"
/>
<script type="module">
import uizy from "https://unpkg.com/@dufeut/uizy";
window.uizy = uizy;
// We'll add our app code here
</script>
</head>
<body>
<!-- App goes here -->
</body>
</html>
Step 2: Layout Structure
Add the app shell using web components:
<uizy-app id="app">
<!-- Header -->
<uizy-header shadow="4">
<uizy-box class="d-flex dx-sb dy-ce ew-100p px-4">
<uizy-box class="d-flex dy-ce gx-2">
<button
class="d-md-none pa-2 br-2"
onclick="uizy.emit('drawer.toggle')"
>
☰
</button>
<span class="ts-4 td-b">Task Manager</span>
</uizy-box>
<button class="pa-2 br-2" onclick="uizy.emit('theme.toggle')">🌓</button>
</uizy-box>
</uizy-header>
<!-- Sidebar (open on desktop, auto-closed on mobile via breakpoint.drawer) -->
<uizy-drawer open clip-top clip-bottom shadow="2">
<uizy-box class="pa-4">
<uizy-box class="ts-5 td-b mb-4">Categories</uizy-box>
<uizy-box class="d-flex dy-ce gx-2 pa-2 br-2 mb-2 e-p">
📋 All Tasks
</uizy-box>
<uizy-box class="d-flex dy-ce gx-2 pa-2 br-2 mb-2 e-p">
⭐ Important
</uizy-box>
<uizy-box class="d-flex dy-ce gx-2 pa-2 br-2 e-p">
✅ Completed
</uizy-box>
</uizy-box>
</uizy-drawer>
<!-- Overlay -->
<uizy-overlay clip-top clip-bottom></uizy-overlay>
<!-- Main Content -->
<uizy-main clip-top clip-bottom clip-left>
<uizy-box class="pa-4">
<!-- Add task form -->
<uizy-box class="d-flex gx-2 mb-4">
<input
id="task-input"
type="text"
placeholder="Add a new task..."
class="ew-100p pa-3 br-2 bd-a bw-1"
onkeypress="if(event.key==='Enter') uizy.emit('task.add')"
/>
<button class="px-4 py-2 br-2 td-b" onclick="uizy.emit('task.add')">
Add
</button>
</uizy-box>
<!-- Task list -->
<uizy-box id="task-list">
<!-- Tasks will be rendered here -->
</uizy-box>
</uizy-box>
</uizy-main>
</uizy-app>
Step 3: Configure Uizy
Initialize with stores, actions, and layout:
import uizy from "https://unpkg.com/@dufeut/uizy";
window.uizy = uizy;
uizy.start({
// Layout dimensions
layout: {
layout: {
header: 56,
left: 240,
leftMini: 0,
},
breakpoint: {
name: "md",
left: true,
main: true,
header: true,
drawer: true, // Auto-close sidebar on mobile
},
},
// Theme colors
theme: {
colors: {
primary: "#6366f1",
background: "#ffffff",
surface: "#f8fafc",
text: "#1e293b",
},
},
// Reactive state
stores: {
app: {
theme: uizy.store.atom("light"),
},
tasks: {
list: uizy.store.atom([
{ id: 1, text: "Learn Uizy basics", done: false },
{ id: 2, text: "Build a complete app", done: false },
{ id: 3, text: "Deploy to production", done: false },
]),
},
},
// Event handlers
actions: {
drawer: {
toggle: () => {
const app = document.getElementById("app");
app?.action("left", ({ toggle }) => toggle());
},
},
theme: {
toggle: () => {
const current = uizy.$("app.theme");
const next = current === "light" ? "dark" : "light";
uizy.$set("app.theme", next);
},
},
task: {
add: () => {
const input = document.getElementById("task-input");
const text = input.value.trim();
if (!text) return;
const tasks = uizy.$("tasks.list");
const newTask = {
id: Date.now(),
text,
done: false,
};
uizy.$set("tasks.list", [...tasks, newTask]);
input.value = "";
},
toggle: (id) => {
const tasks = uizy.$("tasks.list");
const updated = tasks.map((t) =>
t.id === id ? { ...t, done: !t.done } : t,
);
uizy.$set("tasks.list", updated);
},
remove: (id) => {
const tasks = uizy.$("tasks.list");
uizy.$set(
"tasks.list",
tasks.filter((t) => t.id !== id),
);
},
},
},
onReady: () => {
// Render initial tasks
renderTasks();
// Subscribe to task changes
uizy.$sub("tasks.list", renderTasks);
// Subscribe to theme changes
uizy.$sub("app.theme", (theme) => {
document.documentElement.dataset.theme = theme;
applyTheme(theme);
});
},
});
function renderTasks() {
const tasks = uizy.$("tasks.list");
const container = document.getElementById("task-list");
container.innerHTML = tasks
.map(
(task) => `
<uizy-box class="d-flex dx-sb dy-ce pa-3 mb-2 br-2 sb-1 ${
task.done ? "task-done" : ""
}">
<uizy-box class="d-flex dy-ce gx-3">
<input
type="checkbox"
${task.done ? "checked" : ""}
onchange="uizy.emit('task.toggle', ${task.id})"
>
<span class="${task.done ? "td-s" : ""}">${task.text}</span>
</uizy-box>
<button
class="pa-2 br-2 e-p"
onclick="uizy.emit('task.remove', ${task.id})"
>
🗑️
</button>
</uizy-box>
`,
)
.join("");
}
function applyTheme(theme) {
if (theme === "dark") {
uizy.theme({
colors: {
primary: "#818cf8",
background: "#0f172a",
surface: "#1e293b",
text: "#f1f5f9",
},
});
} else {
uizy.theme({
colors: {
primary: "#6366f1",
background: "#ffffff",
surface: "#f8fafc",
text: "#1e293b",
},
});
}
}
Step 4: Add Styles
Add custom styles that use CSS variables:
<style>
body {
background: var(--color-background);
color: var(--color-text);
transition:
background 0.3s,
color 0.3s;
}
uizy-header {
background: var(--color-surface);
}
uizy-drawer {
background: var(--color-surface);
}
input[type="text"] {
background: var(--color-background);
color: var(--color-text);
border-color: var(--color-primary);
}
button {
background: var(--color-primary);
color: white;
border: none;
cursor: pointer;
transition: opacity 0.2s;
}
button:hover {
opacity: 0.9;
}
.task-done {
opacity: 0.6;
}
</style>
Key Concepts Used
| Feature | Usage in App |
|---|---|
| Layout | <uizy-app>, <uizy-header>, <uizy-drawer>, <uizy-main> |
| CSS Utilities | d-flex, pa-4, br-2, sb-1, gx-2 |
| Stores | tasks.list, app.theme for reactive state |
| Actions | task.add, task.toggle, theme.toggle |
| Theme | uizy.theme() for runtime color updates |
| Responsive | d-md-none for mobile menu button |
Next Steps
- Add task editing
- Persist tasks to localStorage
- Add due dates and priorities
- Create custom components with
uizy.add() - Add animations with directives
Full Source Code
See the complete example on GitHub.