···11+# Counter
22+33+Simple interactive counter demonstrating Volt.js reactive primitives.
44+55+## Features
66+77+- Signal-based state with `count` tracking the current value
88+- Computed values deriving `doubled` and `squared` from count
99+- Conditional rendering showing status (Positive/Negative/Zero)
1010+- Dynamic class binding for visual feedback
1111+1212+## Running
1313+1414+1. Build the project: `pnpm build` from root
1515+2. Open `index.html` in a browser
1616+1717+## Implementation
1818+1919+The counter uses three Volt.js primitives:
2020+2121+**Signals** store reactive state:
2222+2323+```js
2424+const count = signal(0);
2525+```
2626+2727+**Computed** derive values automatically:
2828+2929+```js
3030+const doubled = computed(() => count.get() * 2, [count]);
3131+const isPositive = computed(() => count.get() > 0, [count]);
3232+```
3333+3434+**Bindings** connect state to DOM:
3535+3636+```html
3737+<span data-x-text="count">0</span>
3838+<button data-x-on-click="increment">+</button>
3939+<div data-x-if="isPositive">Positive</div>
4040+<div data-x-class="countClass"></div>
4141+```
4242+4343+When `count` changes, all dependent computed values recalculate and bindings update automatically.
+80
examples/todomvc/README.md
···11+# TodoMVC
22+33+Complete TodoMVC implementation using Volt.js and Volt CSS (classless framework).
44+55+## Features
66+77+- Add/edit/delete todos
88+- Mark complete/incomplete
99+- Filter by All/Active/Completed
1010+- Toggle all at once
1111+- Clear completed
1212+- Persistent reactive state
1313+1414+## Running
1515+1616+1. Build the project: `pnpm build` from root
1717+2. Open `index.html` in a browser
1818+1919+## Implementation
2020+2121+### State Management
2222+2323+Two base signals control all state:
2424+2525+```js
2626+const todos = signal([...]);
2727+const filter = signal('all');
2828+```
2929+3030+Computed signals derive UI state:
3131+3232+```js
3333+const filteredTodos = computed(() => {
3434+ if (filter.get() === 'active') return todos.get().filter(t => !t.completed);
3535+ if (filter.get() === 'completed') return todos.get().filter(t => t.completed);
3636+ return todos.get();
3737+}, [todos, filter]);
3838+3939+const activeCount = computed(() =>
4040+ todos.get().filter(t => !t.completed).length,
4141+ [todos]
4242+);
4343+```
4444+4545+### List Rendering
4646+4747+`data-x-for` renders todos reactively:
4848+4949+```html
5050+<li data-x-for="(todo, index) in filteredTodos" data-x-class="getTodoClass(todo)">
5151+ <input type="checkbox" data-x-on-click="toggleTodo($event, index)">
5252+ <label data-x-text="todo.text"></label>
5353+</li>
5454+```
5555+5656+### Event Handling
5757+5858+All interactions use declarative bindings:
5959+6060+- `data-x-on-click` for buttons and checkboxes
6161+- `data-x-on-keyup` for Enter/Escape in inputs
6262+- `data-x-on-dblclick` for editing mode
6363+- `data-x-on-blur` to save edits
6464+6565+### Index Mapping
6666+6767+Because the UI displays filtered todos but operations need the full array, handlers map filtered indices to actual positions:
6868+6969+```js
7070+const deleteTodo = (indexInFiltered) => {
7171+ const filteredList = filteredTodos.get();
7272+ const todoToFind = filteredList[indexInFiltered];
7373+ const actualIndex = todos.get().findIndex(t => t.id === todoToFind.id);
7474+ todos.set(todos.get().filter((_, i) => i !== actualIndex));
7575+};
7676+```
7777+7878+### Styling
7979+8080+Uses only Volt CSS. Semantic HTML elements are styled automatically with no custom classes needed.