addComponent($title); // Input section $inputContainer = new Container('flex flex-row mb-4'); $input = new TextInput( placeholder: 'What needs to be done?', style: 'flex-1 p-2 border border-gray-300 rounded mr-2', ); $addButton = new Button('Add', 'bg-blue-500 text-white p-2 rounded-lg hover:bg-blue-600'); $inputContainer->addComponent($input); $inputContainer->addComponent($addButton); $mainContainer->addComponent($inputContainer); // Todo list container $todoListContainer = new Container('flex flex-col'); $mainContainer->addComponent($todoListContainer); // Stats $statsLabel = new Label('0 items', 'mt-4 text-gray-600 text-sm h-10'); $mainContainer->addComponent($statsLabel); // Todos array $todos = []; // Function to update stats $updateStats = function () use (&$todos, $statsLabel) { $total = count($todos); $completed = count(array_filter($todos, fn($t) => $t['completed'])); $statsLabel->setText("{$total} items ({$completed} completed)"); }; // Function to render todos - use a reference so it can be used in closures $renderTodos = null; $renderTodos = function () use (&$todos, $todoListContainer, $updateStats, &$renderTodos, $window) { // Clear existing todos $todoListContainer->clearChildren(); foreach ($todos as $index => $todo) { $todoItem = new Container('flex flex-row items-center p-2 mb-2 bg-white border border-gray-200 rounded h-12'); // Checkbox $checkbox = new Checkbox( label: '', checked: $todo['completed'], style: 'mr-2 w-6 h-6', ); $checkbox->setOnChange(function ($checked) use (&$todos, $index, &$renderTodos, $updateStats) { $todos[$index]['completed'] = $checked; $updateStats(); }); // Text $textStyle = $todo['completed'] ? 'flex-1 text-gray-400 line-through' : 'flex-1 text-gray-800'; $todoText = new Label($todo['text'], $textStyle); // Delete button $deleteButton = new Button('Delete', 'bg-red-500 text-white px-2 py-1 rounded text-sm hover:bg-red-600'); $deleteButton->setOnClick(function () use (&$todos, $index, &$renderTodos, $updateStats) { array_splice($todos, $index, 1); $renderTodos(); $updateStats(); }); $todoItem->addComponent($checkbox); $todoItem->addComponent($todoText); $todoItem->addComponent($deleteButton); $todoListContainer->addComponent($todoItem); } $updateStats(); // Trigger re-layout after adding new components $window->setShouldBeReLayouted(true); }; // Add button click handler $addButton->setOnClick(function () use ($input, &$todos, &$renderTodos) { $text = trim($input->getValue()); if (!empty($text)) { $todos[] = [ 'text' => $text, 'completed' => false, ]; $input->setValue(''); // Clear input $renderTodos(); } }); // Handle Enter key in input $input->setOnChange(function ($value) { // Could add live validation here }); $window->setRoot($mainContainer); $app->addWindow($window); echo "Todo App started!\n"; echo "- Type in the input field and click 'Add' or press Enter\n"; echo "- Click checkboxes to mark todos as complete\n"; echo "- Click 'Delete' to remove a todo\n\n"; $app->run();