Models 44

Claude Haiku 4.5

by AnthropicReasoningClean
Open in new window

Running live in a sandboxed frame. Click inside it before using the keyboard.

How it went

Total time
16.0 s
Cost
$0.027
Output tokens
5,349
Spent thinking
0 tokens
Speed
352.1 tok/s
Console errors
0
First token after
850 ms
First visible text after
850 ms
Prompt tokens
523
Code size
18.9 KB
Finish reason
stop
Served by
Amazon Bedrock
Model id
anthropic/claude-haiku-4.5
Reasoning sent
{"effort":"none"}
Max output
32,000 tokens
Generated
Nov 10, 2026

What it was asked

The prompt
Build an interactive Kanban board in vanilla HTML, CSS and JavaScript (no framework, no library). Requirements: - Three columns: "To do", "In progress", "Done", each showing its card count. - Pre-populate the board with 6 realistic cards spread across the columns so the first screenshot looks alive. - Each card has a title and a priority (low / medium / high) shown as a colored badge. - Add a card through a small modal form (title required), and delete a card with a button on it. - Drag and drop cards between columns with the mouse, with a clear visual drop indicator. - A search field that filters cards live by title. - A light / dark theme toggle. - State lives in memory only (no storage APIs).
System prompt, sent with every prompt
You are generating a self-contained web demo. It will be rendered automatically in a sandboxed iframe and compared side by side with the output of other AI models given the exact same task.

Output rules:
- Reply with exactly ONE fenced code block containing the complete file: ```html (or ```svg when the task asks for an SVG). No text before or after the code block.
- Everything must be inline: CSS in <style>, JavaScript in <script>. No external files, images, fonts or network requests, except the CDN URLs explicitly allowed by the task.
- Do not use localStorage, sessionStorage, cookies, IndexedDB, alert(), confirm(), prompt() or window.open(): they are blocked in the sandbox and will throw.
- The page must look right in a 1280×800 viewport and adapt gracefully down to 375px wide. No horizontal scrollbar.
- Something meaningful must be visible on first paint: a screenshot is taken automatically about 3 seconds after load, without any interaction.
- Everything that makes the demo interesting must be visible within the first seconds: nothing hidden behind a high score, a later level or a long play session.
- Games must start in a self-playing demo mode (a simple AI plays) behind a "Click or press a key to start" message, so the game can be judged in action without playing.
- The iframe only receives keyboard events after the user clicks it: if the demo uses the keyboard, display a clear "Click or press a key to start" message.
- The code must run with zero errors in the console of the latest Chrome.

Code run-1.html · 647 lines

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Kanban Board</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        :root {
            --bg-primary: #f5f5f5;
            --bg-secondary: #ffffff;
            --bg-tertiary: #e8e8e8;
            --text-primary: #333333;
            --text-secondary: #666666;
            --border-color: #ddd;
            --shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
            --shadow-hover: 0 4px 12px rgba(0, 0, 0, 0.15);
        }

        body.dark-theme {
            --bg-primary: #1a1a1a;
            --bg-secondary: #2d2d2d;
            --bg-tertiary: #404040;
            --text-primary: #f5f5f5;
            --text-secondary: #b0b0b0;
            --border-color: #404040;
            --shadow: 0 2px 4px rgba(0, 0, 0, 0.3);
            --shadow-hover: 0 4px 12px rgba(0, 0, 0, 0.4);
        }

        body {
            font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, sans-serif;
            background-color: var(--bg-primary);
            color: var(--text-primary);
            transition: background-color 0.3s, color 0.3s;
            padding: 20px;
            min-height: 100vh;
        }

        .header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 30px;
            gap: 20px;
            flex-wrap: wrap;
        }

        h1 {
            font-size: 28px;
            font-weight: 600;
        }

        .controls {
            display: flex;
            gap: 15px;
            align-items: center;
            flex-wrap: wrap;
        }

        .search-box {
            position: relative;
        }

        .search-box input {
            padding: 10px 15px 10px 40px;
            border: 1px solid var(--border-color);
            border-radius: 6px;
            background-color: var(--bg-secondary);
            color: var(--text-primary);
            font-size: 14px;
            width: 200px;
            transition: border-color 0.3s, box-shadow 0.3s;
        }

        .search-box input:focus {
            outline: none;
            border-color: #3b82f6;
            box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
        }

        .search-box::before {
            content: '🔍';
            position: absolute;
            left: 12px;
            top: 50%;
            transform: translateY(-50%);
            pointer-events: none;
        }

        .btn {
            padding: 10px 20px;
            border: none;
            border-radius: 6px;
            font-size: 14px;
            font-weight: 500;
            cursor: pointer;
            transition: all 0.3s;
            background-color: #3b82f6;
            color: white;
        }

        .btn:hover {
            background-color: #2563eb;
            transform: translateY(-2px);
            box-shadow: var(--shadow-hover);
        }

        .btn-theme {
            background-color: var(--bg-secondary);
            color: var(--text-primary);
            border: 1px solid var(--border-color);
            padding: 8px 12px;
            width: 44px;
        }

        .btn-theme:hover {
            background-color: var(--bg-tertiary);
        }

        .board {
            display: grid;
            grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
            gap: 20px;
            max-width: 1400px;
            margin: 0 auto;
        }

        .column {
            background-color: var(--bg-secondary);
            border-radius: 8px;
            padding: 20px;
            box-shadow: var(--shadow);
            display: flex;
            flex-direction: column;
            min-height: 400px;
        }

        .column-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 20px;
            padding-bottom: 12px;
            border-bottom: 2px solid var(--border-color);
        }

        .column-title {
            font-size: 18px;
            font-weight: 600;
        }

        .column-count {
            background-color: var(--bg-tertiary);
            color: var(--text-secondary);
            padding: 4px 10px;
            border-radius: 12px;
            font-size: 12px;
            font-weight: 600;
        }

        .cards-container {
            flex: 1;
            display: flex;
            flex-direction: column;
            gap: 12px;
            min-height: 200px;
            border-radius: 6px;
            padding: 4px;
            transition: background-color 0.2s;
        }

        .cards-container.drag-over {
            background-color: var(--bg-tertiary);
        }

        .card {
            background-color: var(--bg-primary);
            border: 1px solid var(--border-color);
            border-radius: 6px;
            padding: 12px;
            cursor: move;
            transition: all 0.2s;
            box-shadow: var(--shadow);
            display: flex;
            justify-content: space-between;
            align-items: flex-start;
            gap: 10px;
        }

        .card:hover {
            box-shadow: var(--shadow-hover);
            transform: translateY(-2px);
        }

        .card.dragging {
            opacity: 0.5;
        }

        .card-content {
            flex: 1;
            min-width: 0;
        }

        .card-title {
            font-weight: 500;
            font-size: 14px;
            margin-bottom: 8px;
            word-break: break-word;
            color: var(--text-primary);
        }

        .card-priority {
            display: inline-block;
            padding: 3px 10px;
            border-radius: 12px;
            font-size: 11px;
            font-weight: 600;
            text-transform: uppercase;
        }

        .priority-low {
            background-color: #d1fae5;
            color: #065f46;
        }

        .dark-theme .priority-low {
            background-color: #064e3b;
            color: #d1fae5;
        }

        .priority-medium {
            background-color: #fef3c7;
            color: #92400e;
        }

        .dark-theme .priority-medium {
            background-color: #78350f;
            color: #fef3c7;
        }

        .priority-high {
            background-color: #fee2e2;
            color: #7f1d1d;
        }

        .dark-theme .priority-high {
            background-color: #7f1d1d;
            color: #fee2e2;
        }

        .card-delete {
            background: none;
            border: none;
            color: var(--text-secondary);
            cursor: pointer;
            font-size: 18px;
            padding: 4px;
            transition: color 0.2s;
            flex-shrink: 0;
        }

        .card-delete:hover {
            color: #ef4444;
        }

        .empty-message {
            color: var(--text-secondary);
            text-align: center;
            padding: 40px 20px;
            font-size: 14px;
        }

        .modal {
            display: none;
            position: fixed;
            top: 0;
            left: 0;
            right: 0;
            bottom: 0;
            background-color: rgba(0, 0, 0, 0.5);
            z-index: 1000;
            justify-content: center;
            align-items: center;
        }

        .modal.active {
            display: flex;
        }

        .modal-content {
            background-color: var(--bg-secondary);
            border-radius: 8px;
            padding: 30px;
            box-shadow: 0 10px 40px rgba(0, 0, 0, 0.2);
            max-width: 400px;
            width: 90%;
        }

        .modal-header {
            font-size: 20px;
            font-weight: 600;
            margin-bottom: 20px;
            color: var(--text-primary);
        }

        .form-group {
            margin-bottom: 20px;
        }

        .form-group label {
            display: block;
            font-size: 14px;
            font-weight: 500;
            margin-bottom: 8px;
            color: var(--text-primary);
        }

        .form-group input,
        .form-group select {
            width: 100%;
            padding: 10px;
            border: 1px solid var(--border-color);
            border-radius: 6px;
            font-size: 14px;
            background-color: var(--bg-primary);
            color: var(--text-primary);
            transition: border-color 0.3s;
        }

        .form-group input:focus,
        .form-group select:focus {
            outline: none;
            border-color: #3b82f6;
        }

        .modal-buttons {
            display: flex;
            gap: 10px;
            justify-content: flex-end;
        }

        .btn-secondary {
            background-color: var(--bg-tertiary);
            color: var(--text-primary);
        }

        .btn-secondary:hover {
            background-color: var(--border-color);
        }

        @media (max-width: 768px) {
            .header {
                flex-direction: column;
                align-items: flex-start;
            }

            .controls {
                width: 100%;
            }

            .search-box input {
                width: 100%;
            }

            .board {
                grid-template-columns: 1fr;
            }

            .column {
                min-height: 300px;
            }
        }

        @media (max-width: 480px) {
            body {
                padding: 12px;
            }

            h1 {
                font-size: 22px;
            }

            .column {
                padding: 16px;
                min-height: 250px;
            }

            .btn, .search-box input {
                font-size: 13px;
            }
        }
    </style>
</head>
<body>
    <div class="header">
        <h1>📋 Kanban Board</h1>
        <div class="controls">
            <div class="search-box">
                <input type="text" id="searchInput" placeholder="Search cards...">
            </div>
            <button class="btn" id="addCardBtn">+ Add Card</button>
            <button class="btn btn-theme" id="themeToggle" title="Toggle theme">🌙</button>
        </div>
    </div>

    <div class="board">
        <div class="column" data-column="todo">
            <div class="column-header">
                <div class="column-title">To Do</div>
                <div class="column-count" id="count-todo">0</div>
            </div>
            <div class="cards-container" id="cards-todo"></div>
        </div>

        <div class="column" data-column="inprogress">
            <div class="column-header">
                <div class="column-title">In Progress</div>
                <div class="column-count" id="count-inprogress">0</div>
            </div>
            <div class="cards-container" id="cards-inprogress"></div>
        </div>

        <div class="column" data-column="done">
            <div class="column-header">
                <div class="column-title">Done</div>
                <div class="column-count" id="count-done">0</div>
            </div>
            <div class="cards-container" id="cards-done"></div>
        </div>
    </div>

    <div class="modal" id="addCardModal">
        <div class="modal-content">
            <div class="modal-header">Add New Card</div>
            <form id="cardForm">
                <div class="form-group">
                    <label for="cardTitle">Title *</label>
                    <input type="text" id="cardTitle" placeholder="Enter card title" required>
                </div>
                <div class="form-group">
                    <label for="cardPriority">Priority</label>
                    <select id="cardPriority">
                        <option value="low">Low</option>
                        <option value="medium" selected>Medium</option>
                        <option value="high">High</option>
                    </select>
                </div>
                <div class="modal-buttons">
                    <button type="button" class="btn btn-secondary" id="cancelBtn">Cancel</button>
                    <button type="submit" class="btn">Add Card</button>
                </div>
            </form>
        </div>
    </div>

    <script>
        let cards = [
            { id: 1, title: 'Design homepage mockups', priority: 'high', column: 'todo' },
            { id: 2, title: 'Review design feedback', priority: 'medium', column: 'todo' },
            { id: 3, title: 'Implement authentication', priority: 'high', column: 'inprogress' },
            { id: 4, title: 'Set up database schema', priority: 'medium', column: 'inprogress' },
            { id: 5, title: 'Write unit tests', priority: 'low', column: 'done' },
            { id: 6, title: 'Deploy to staging', priority: 'medium', column: 'done' }
        ];

        let nextId = 7;
        let draggedCard = null;
        let searchFilter = '';

        const modal = document.getElementById('addCardModal');
        const cardForm = document.getElementById('cardForm');
        const cardTitleInput = document.getElementById('cardTitle');
        const addCardBtn = document.getElementById('addCardBtn');
        const cancelBtn = document.getElementById('cancelBtn');
        const searchInput = document.getElementById('searchInput');
        const themeToggle = document.getElementById('themeToggle');

        function updateTheme() {
            const isDark = document.body.classList.toggle('dark-theme');
            themeToggle.textContent = isDark ? '☀️' : '🌙';
        }

        function openModal() {
            cardTitleInput.value = '';
            document.getElementById('cardPriority').value = 'medium';
            modal.classList.add('active');
            cardTitleInput.focus();
        }

        function closeModal() {
            modal.classList.remove('active');
        }

        function addCard(title, priority) {
            const newCard = {
                id: nextId++,
                title: title,
                priority: priority,
                column: 'todo'
            };
            cards.push(newCard);
            render();
        }

        function deleteCard(id) {
            cards = cards.filter(card => card.id !== id);
            render();
        }

        function moveCard(id, newColumn) {
            const card = cards.find(c => c.id === id);
            if (card) {
                card.column = newColumn;
                render();
            }
        }

        function getVisibleCards(column) {
            return cards.filter(card => 
                card.column === column && 
                card.title.toLowerCase().includes(searchFilter.toLowerCase())
            );
        }

        function render() {
            const columns = ['todo', 'inprogress', 'done'];
            
            columns.forEach(column => {
                const container = document.getElementById(`cards-${column}`);
                const count = document.getElementById(`count-${column}`);
                const visibleCards = getVisibleCards(column);
                
                count.textContent = cards.filter(c => c.column === column).length;
                
                container.innerHTML = '';
                
                if (visibleCards.length === 0) {
                    container.innerHTML = '<div class="empty-message">No cards</div>';
                } else {
                    visibleCards.forEach(card => {
                        const cardEl = document.createElement('div');
                        cardEl.className = 'card';
                        cardEl.draggable = true;
                        cardEl.dataset.cardId = card.id;
                        
                        cardEl.innerHTML = `
                            <div class="card-content">
                                <div class="card-title">${escapeHtml(card.title)}</div>
                                <span class="card-priority priority-${card.priority}">${card.priority}</span>
                            </div>
                            <button class="card-delete" title="Delete">✕</button>
                        `;
                        
                        const deleteBtn = cardEl.querySelector('.card-delete');
                        deleteBtn.addEventListener('click', () => deleteCard(card.id));
                        
                        cardEl.addEventListener('dragstart', handleDragStart);
                        cardEl.addEventListener('dragend', handleDragEnd);
                        
                        container.appendChild(cardEl);
                    });
                }
            });
        }

        function handleDragStart(e) {
            draggedCard = this;
            this.classList.add('dragging');
            e.dataTransfer.effectAllowed = 'move';
        }

        function handleDragEnd(e) {
            this.classList.remove('dragging');
            document.querySelectorAll('.cards-container').forEach(c => {
                c.classList.remove('drag-over');
            });
        }

        function setupDragDropZones() {
            document.querySelectorAll('.cards-container').forEach(container => {
                container.addEventListener('dragover', (e) => {
                    e.preventDefault();
                    e.dataTransfer.dropEffect = 'move';
                    container.classList.add('drag-over');
                });

                container.addEventListener('dragleave', (e) => {
                    if (e.target === container) {
                        container.classList.remove('drag-over');
                    }
                });

                container.addEventListener('drop', (e) => {
                    e.preventDefault();
                    container.classList.remove('drag-over');
                    
                    if (draggedCard) {
                        const cardId = parseInt(draggedCard.dataset.cardId);
                        const newColumn = container.id.replace('cards-', '');
                        moveCard(cardId, newColumn);
                    }
                });
            });
        }

        function escapeHtml(text) {
            const div = document.createElement('div');
            div.textContent = text;
            return div.innerHTML;
        }

        addCardBtn.addEventListener('click', openModal);
        cancelBtn.addEventListener('click', closeModal);
        themeToggle.addEventListener('click', updateTheme);

        cardForm.addEventListener('submit', (e) => {
            e.preventDefault();
            const title = cardTitleInput.value.trim();
            const priority = document.getElementById('cardPriority').value;
            if (title) {
                addCard(title, priority);
                closeModal();
            }
        });

        searchInput.addEventListener('input', (e) => {
            searchFilter = e.target.value;
            render();
        });

        modal.addEventListener('click', (e) => {
            if (e.target === modal) {
                closeModal();
            }
        });

        setupDragDropZones();
        render();
    </script>
</body>
</html>