Models 44

Dots3-Note Preview (free)

by Dots StudioReasoningClean
Open in new window

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

How it went

Total time
39.7 s
Cost
$0
Output tokens
4,187
Spent thinking
0 tokens
Speed
107.3 tok/s
Console errors
0
First token after
673 ms
First visible text after
673 ms
Prompt tokens
495
Code size
14.6 KB
Finish reason
stop
Served by
AtlasCloud
Model id
dots-studio/dots-3-note-preview:free
Reasoning sent
{"effort":"none"}
Max output
32,000 tokens
Generated
Nov 9, 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 · 624 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>
  :root {
    --bg: #f4f5f7;
    --surface: #ffffff;
    --text: #172b4d;
    --text-secondary: #5e6c84;
    --border: #dfe1e6;
    --accent: #0079bf;
    --shadow: rgba(0, 0, 0, 0.1);
    --low: #61bd4f;
    --medium: #ffab4a;
    --high: #eb5a46;
  }

  [data-theme="dark"] {
    --bg: #1d2125;
    --surface: #2c3338;
    --text: #e6e6e6;
    --text-secondary: #9da6b0;
    --border: #4a5559;
    --accent: #4fa9e6;
    --shadow: rgba(0, 0, 0, 0.3);
    --low: #57a64f;
    --medium: #e6a532;
    --high: #d9484f;
  }

  * {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
    transition: background-color 0.3s ease, color 0.3s ease, border-color 0.3s ease;
  }

  body {
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;
    background-color: var(--bg);
    color: var(--text);
    min-height: 100vh;
    display: flex;
    flex-direction: column;
  }

  header {
    background-color: var(--surface);
    padding: 1rem 2rem;
    display: flex;
    justify-content: space-between;
    align-items: center;
    border-bottom: 1px solid var(--border);
    box-shadow: 0 1px 3px var(--shadow);
    flex-wrap: wrap;
    gap: 1rem;
  }

  h1 {
    font-size: 1.5rem;
    font-weight: 600;
  }

  .controls {
    display: flex;
    gap: 1rem;
    align-items: center;
    flex-wrap: wrap;
  }

  .search {
    padding: 0.5rem;
    border: 1px solid var(--border);
    border-radius: 4px;
    background-color: var(--surface);
    color: var(--text);
    width: 250px;
    font-size: 0.9rem;
  }

  .theme-toggle {
    background: none;
    border: 1px solid var(--border);
    border-radius: 4px;
    padding: 0.5rem 1rem;
    cursor: pointer;
    color: var(--text);
    background-color: var(--surface);
    font-size: 0.9rem;
  }

  .add-btn {
    background-color: var(--accent);
    color: white;
    border: none;
    border-radius: 4px;
    padding: 0.5rem 1rem;
    cursor: pointer;
    font-size: 0.9rem;
    font-weight: 500;
  }

  .add-btn:hover {
    opacity: 0.9;
  }

  main {
    flex: 1;
    display: flex;
    gap: 1rem;
    padding: 2rem;
    overflow-x: auto;
  }

  .column {
    background-color: var(--surface);
    border-radius: 6px;
    padding: 1rem;
    width: 300px;
    min-width: 300px;
    display: flex;
    flex-direction: column;
    box-shadow: 0 1px 3px var(--shadow);
  }

  .column-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 1rem;
    padding-bottom: 0.5rem;
    border-bottom: 1px solid var(--border);
  }

  .column-title {
    font-weight: 600;
    font-size: 1rem;
  }

  .card-count {
    background-color: var(--border);
    color: var(--text-secondary);
    border-radius: 12px;
    padding: 0.1rem 0.6rem;
    font-size: 0.8rem;
  }

  [data-theme="dark"] .card-count {
    background-color: #4a5559;
  }

  .cards {
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    min-height: 100px;
    padding: 0.5rem;
    border-radius: 4px;
    transition: background-color 0.2s ease;
  }

  .cards.drag-over {
    background-color: var(--accent);
    opacity: 0.1;
  }

  .card {
    background-color: var(--surface);
    border: 1px solid var(--border);
    border-radius: 4px;
    padding: 0.75rem;
    cursor: grab;
    box-shadow: 0 1px 2px var(--shadow);
    position: relative;
    transition: transform 0.1s ease, box-shadow 0.1s ease;
  }

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

  .card.dragging {
    opacity: 0.5;
    cursor: grabbing;
  }

  .card-title {
    font-size: 0.9rem;
    margin-bottom: 0.5rem;
    word-break: break-word;
  }

  .card-footer {
    display: flex;
    justify-content: space-between;
    align-items: center;
  }

  .priority-badge {
    font-size: 0.7rem;
    padding: 0.2rem 0.5rem;
    border-radius: 12px;
    color: white;
    font-weight: 500;
    text-transform: uppercase;
  }

  .priority-low { background-color: var(--low); }
  .priority-medium { background-color: var(--medium); }
  .priority-high { background-color: var(--high); }

  .delete-btn {
    background: none;
    border: none;
    color: var(--text-secondary);
    cursor: pointer;
    font-size: 1rem;
    padding: 0.2rem;
    border-radius: 2px;
    opacity: 0.7;
  }

  .delete-btn:hover {
    opacity: 1;
    color: var(--high);
    background-color: rgba(235, 90, 70, 0.1);
  }

  /* Modal */
  .modal-overlay {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background-color: rgba(0, 0, 0, 0.5);
    display: none;
    justify-content: center;
    align-items: center;
    z-index: 1000;
  }

  .modal {
    background-color: var(--surface);
    padding: 1.5rem;
    border-radius: 6px;
    width: 90%;
    max-width: 400px;
    box-shadow: 0 4px 12px var(--shadow);
  }

  .modal h2 {
    margin-bottom: 1rem;
    font-size: 1.2rem;
  }

  .form-group {
    margin-bottom: 1rem;
  }

  .form-group label {
    display: block;
    margin-bottom: 0.5rem;
    font-size: 0.9rem;
    font-weight: 500;
  }

  .form-group input,
  .form-group select {
    width: 100%;
    padding: 0.5rem;
    border: 1px solid var(--border);
    border-radius: 4px;
    background-color: var(--surface);
    color: var(--text);
    font-size: 0.9rem;
  }

  .modal-buttons {
    display: flex;
    justify-content: flex-end;
    gap: 0.5rem;
    margin-top: 1.5rem;
  }

  .modal-btn {
    padding: 0.5rem 1rem;
    border: none;
    border-radius: 4px;
    cursor: pointer;
    font-size: 0.9rem;
  }

  .cancel-btn {
    background-color: var(--border);
    color: var(--text);
  }

  .save-btn {
    background-color: var(--accent);
    color: white;
  }

  .empty-state {
    text-align: center;
    color: var(--text-secondary);
    padding: 2rem 0;
    font-size: 0.9rem;
  }

  @media (max-width: 768px) {
    main {
      padding: 1rem;
      gap: 0.5rem;
    }
    .column {
      width: 280px;
      min-width: 280px;
    }
  }
</style>
</head>
<body>
  <header>
    <h1>Kanban Board</h1>
    <div class="controls">
      <input type="text" class="search" placeholder="Search cards by title...">
      <button class="theme-toggle" id="themeToggle">🌙 Dark</button>
      <button class="add-btn" id="addCardBtn">+ Add Card</button>
    </div>
  </header>

  <main>
    <div class="column" data-status="todo">
      <div class="column-header">
        <div class="column-title">To do</div>
        <div class="card-count" id="count-todo">0</div>
      </div>
      <div class="cards" id="todo-cards"></div>
    </div>

    <div class="column" data-status="inprogress">
      <div class="column-header">
        <div class="column-title">In progress</div>
        <div class="card-count" id="count-inprogress">0</div>
      </div>
      <div class="cards" id="inprogress-cards"></div>
    </div>

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

  <div class="modal-overlay" id="modalOverlay">
    <div class="modal">
      <h2>Add New Card</h2>
      <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 class="modal-btn cancel-btn" id="cancelBtn">Cancel</button>
        <button class="modal-btn save-btn" id="saveCardBtn">Save</button>
      </div>
    </div>
  </div>

<script>
  // State
  let cards = [
    { id: 1, title: "Design landing page", priority: "high", status: "todo" },
    { id: 2, title: "Write API documentation", priority: "medium", status: "inprogress" },
    { id: 3, title: "Fix login bug", priority: "high", status: "inprogress" },
    { id: 4, title: "Update user profile", priority: "low", status: "done" },
    { id: 5, title: "Implement dark mode", priority: "medium", status: "todo" },
    { id: 6, title: "Refactor authentication", priority: "high", status: "done" }
  ];

  let nextId = 7;
  let currentTheme = "light";
  let draggedCardId = null;

  // DOM Elements
  const themeToggle = document.getElementById("themeToggle");
  const addCardBtn = document.getElementById("addCardBtn");
  const modalOverlay = document.getElementById("modalOverlay");
  const cardTitleInput = document.getElementById("cardTitle");
  const cardPrioritySelect = document.getElementById("cardPriority");
  const saveCardBtn = document.getElementById("saveCardBtn");
  const cancelBtn = document.getElementById("cancelBtn");
  const searchInput = document.querySelector(".search");

  // Initialize
  document.addEventListener("DOMContentLoaded", () => {
    renderBoard();
    setupEventListeners();
  });

  // Event Listeners
  function setupEventListeners() {
    themeToggle.addEventListener("click", toggleTheme);
    addCardBtn.addEventListener("click", openModal);
    cancelBtn.addEventListener("click", closeModal);
    saveCardBtn.addEventListener("click", saveCard);
    searchInput.addEventListener("input", filterCards);

    // Close modal on overlay click
    modalOverlay.addEventListener("click", (e) => {
      if (e.target === modalOverlay) {
        closeModal();
      }
    });

    // Close modal on Escape key
    document.addEventListener("keydown", (e) => {
      if (e.key === "Escape" && modalOverlay.style.display === "flex") {
        closeModal();
      }
    });
  }

  // Render Board
  function renderBoard() {
    renderColumn("todo");
    renderColumn("inprogress");
    renderColumn("done");
    updateCounts();
  }

  function renderColumn(status) {
    const container = document.getElementById(`${status}-cards`);
    container.innerHTML = "";

    const filteredCards = getFilteredCards().filter(card => card.status === status);

    if (filteredCards.length === 0) {
      const emptyState = document.createElement("div");
      emptyState.className = "empty-state";
      emptyState.textContent = "No cards";
      container.appendChild(emptyState);
      return;
    }

    filteredCards.forEach(card => {
      const cardElement = createCardElement(card);
      container.appendChild(cardElement);
    });
  }

  function createCardElement(card) {
    const cardDiv = document.createElement("div");
    cardDiv.className = "card";
    cardDiv.draggable = true;
    cardDiv.dataset.id = card.id;

    cardDiv.innerHTML = `
      <div class="card-title">${escapeHtml(card.title)}</div>
      <div class="card-footer">
        <span class="priority-badge priority-${card.priority}">${card.priority}</span>
        <button class="delete-btn" title="Delete card">×</button>
      </div>
    `;

    // Drag events
    cardDiv.addEventListener("dragstart", handleDragStart);
    cardDiv.addEventListener("dragend", handleDragEnd);

    // Delete button
    const deleteBtn = cardDiv.querySelector(".delete-btn");
    deleteBtn.addEventListener("click", (e) => {
      e.stopPropagation();
      deleteCard(card.id);
    });

    return cardDiv;
  }

  // Drag and Drop
  function handleDragStart(e) {
    draggedCardId = parseInt(e.target.dataset.id);
    e.target.classList.add("dragging");
    e.dataTransfer.effectAllowed = "move";
    e.dataTransfer.setData("text/html", e.target.innerHTML);
  }

  function handleDragEnd(e) {
    e.target.classList.remove("dragging");
    draggedCardId = null;
  }

  // Setup drop zones
  document.querySelectorAll(".cards").forEach(container => {
    container.addEventListener("dragover", handleDragOver);
    container.addEventListener("dragleave", handleDragLeave);
    container.addEventListener("drop", handleDrop);
  });

  function handleDragOver(e) {
    e.preventDefault();
    e.dataTransfer.dropEffect = "move";
    const container = e.currentTarget;
    container.classList.add("drag-over");
  }

  function handleDragLeave(e) {
    const container = e.currentTarget;
    container.classList.remove("drag-over");
  }

  function handleDrop(e) {
    e.preventDefault();
    const container = e.currentTarget;
    container.classList.remove("drag-over");

    if (draggedCardId === null) return;

    const newStatus = container.parentElement.dataset.status;
    const card = cards.find(c => c.id === draggedCardId);

    if (card && card.status !== newStatus) {
      card.status = newStatus;
      renderBoard();
    }
  }

  // Modal Functions
  function openModal() {
    modalOverlay.style.display = "flex";
    cardTitleInput.value = "";
    cardPrioritySelect.value = "medium";
    cardTitleInput.focus();
  }

  function closeModal() {
    modalOverlay.style.display = "none";
  }

  function saveCard() {
    const title = cardTitleInput.value.trim();
    const priority = cardPrioritySelect.value;

    if (!title) {
      alert("Title is required");
      cardTitleInput.focus();
      return;
    }

    const newCard = {
      id: nextId++,
      title: title,
      priority: priority,
      status: "todo"
    };

    cards.push(newCard);
    renderBoard();
    closeModal();
  }

  function deleteCard(id) {
    if (confirm("Are you sure you want to delete this card?")) {
      cards = cards.filter(card => card.id !== id);
      renderBoard();
    }
  }

  // Search Filter
  function filterCards() {
    renderBoard();
  }

  function getFilteredCards() {
    const query = searchInput.value.toLowerCase().trim();
    if (!query) return cards;

    return cards.filter(card => 
      card.title.toLowerCase().includes(query)
    );
  }

  // Theme Toggle
  function toggleTheme() {
    currentTheme = currentTheme === "light" ? "dark" : "light";
    document.body.dataset.theme = currentTheme;
    themeToggle.textContent = currentTheme === "light" ? "🌙 Dark" : "☀️ Light";
  }

  // Update Counts
  function updateCounts() {
    document.getElementById("count-todo").textContent = 
      getFilteredCards().filter(c => c.status === "todo").length;
    document.getElementById("count-inprogress").textContent = 
      getFilteredCards().filter(c => c.status === "inprogress").length;
    document.getElementById("count-done").textContent = 
      getFilteredCards().filter(c => c.status === "done").length;
  }

  // Utility
  function escapeHtml(text) {
    const div = document.createElement("div");
    div.textContent = text;
    return div.innerHTML;
  }
</script>
</body>
</html>