Skip to content

feat: Add Dark Mode, Pixel Art theme, Drag-and-Drop, and Local Storage persistence - #5

Open
PrimeDeV-824 wants to merge 3 commits into
burakorkmez:masterfrom
PrimeDeV-824:master
Open

feat: Add Dark Mode, Pixel Art theme, Drag-and-Drop, and Local Storage persistence#5
PrimeDeV-824 wants to merge 3 commits into
burakorkmez:masterfrom
PrimeDeV-824:master

Conversation

@PrimeDeV-824

@PrimeDeV-824 PrimeDeV-824 commented Jul 17, 2026

Copy link
Copy Markdown

Overview
This PR focuses on upgrading the overall user experience and adding personalization options to the Todo app. The main additions include a dynamic theme engine (featuring Dark Mode and a retro Pixel Art style), intuitive drag-and-drop task reordering, and robust local storage persistence to keep user data intact across sessions.

What's New?
Dynamic Theme Engine (including Dark Mode & Pixel Art):

Built out a flexible styling system supporting multiple themes (Main and Other).

Added a dedicated Dark Mode toggle for better low-light usability.

Designed a custom, retro Pixel Art theme for a unique, nostalgic aesthetic.

Interactive Drag-and-Drop Tiles:

Implemented seamless drag-and-drop functionality, allowing users to intuitively reorder and prioritize tasks.

State Persistence via Local Storage:

Hooked the application state into localStorage. Todos, completion statuses, and theme preferences now persist across page refreshes.

Technical Implementation & Edge Cases Handled
State Syncing: Side effects handle syncing state to local storage smoothly, preventing any blocking UI lags during rapid updates.

UX & Interaction: Finetuned pointer events on the todo tiles to ensure dragging feels fluid and doesn't conflict with normal click/tap interactions (like toggling a todo or hitting delete).

CSS Architecture: Kept the Pixel Art theme lightweight by relying on clean, native CSS configurations rather than heavy external asset dependencies.

How to Test
Persistence: Create a few tasks, switch to Dark Mode or the Pixel Art theme, and refresh your browser. Everything should restore exactly as you left it.

Drag-and-Drop: Drag a tile from the top to the bottom of the list. Reordering should feel responsive and look smooth.

Theme Toggle: Cycle through the configurations (Main, Other, Dark, Pixel Art) to verify that colors, borders, and text scale correctly without UI breakage.

Note to Reviewer:
I wanted to give the app a bit more personality—let me know what you think of the pixel art styling! Also, keep an eye on the drag-and-drop transitions during your review and let me know if the animations feel smooth on your setup.

Screenshot From 2026-07-17 23-00-52 Screenshot From 2026-07-17 23-01-30 Screenshot From 2026-07-17 23-02-06

Summary by CodeRabbit

  • New Features
    • Added light/dark theme switching and a synthwave color palette option.
    • Added drag-and-drop task reordering.
    • Added a refreshed game-inspired interface with updated icons, fonts, labels, and visual styling.
  • Improvements
    • Updated task filters to “ALL,” “ACTIVE,” and “DONE.”
    • Improved empty-state messaging and animations.
    • Enhanced task controls, including clearer delete interactions and completion styling.
    • Updated progress text to display XP remaining and dates in uppercase.

@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The todo app is restyled as “QUEST LOG,” with light and synthwave themes, updated labels and controls, draggable todo reordering, revised empty and footer states, and responsive themed components.

Changes

Quest Log refresh

Layer / File(s) Summary
Quest Log UI and state wiring
08-todo-app/index.html, 08-todo-app/script.js
The page adds themed controls and updated quest labels, while JavaScript handles theme state, direct task creation, counters, empty-state visibility, filters, and date initialization.
Theme foundation and application shell
08-todo-app/style.css
Semantic color variables and light/synthwave overrides are added across the body, app shell, and header.
Draggable todo rendering and reordering
08-todo-app/script.js
Todo rows become draggable; drag placement updates the DOM, synchronizes the todo array, and conditionally persists the reordered list.
Themed controls and todo components
08-todo-app/style.css
Inputs, buttons, filters, todo tiles, checkboxes, delete controls, empty state, footer, scrolling, and mobile sizing adopt the new theme styling.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant TodoListDOM
  participant todos
  participant saveTodos
  User->>TodoListDOM: Drag a todo item
  TodoListDOM->>TodoListDOM: Calculate insertion position
  TodoListDOM->>todos: Synchronize reordered items
  todos->>saveTodos: Persist order when filter is all
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main additions: dark mode, pixel art theming, drag-and-drop, and persistence features.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@08-todo-app/index.html`:
- Around line 29-34: Add aria-pressed="false" to the palette-toggle and
theme-toggle buttons, then update each button’s aria-pressed value whenever its
corresponding body class changes so assistive technology reflects the current
mode state.
- Around line 42-44: Add the accessible name “Add quest” to the icon-only
`#add-task` button in 08-todo-app/index.html:42-44. In
08-todo-app/script.js:115-118, update the deleteBtn creation in the
todo-rendering logic to set its aria-label to “Delete ” followed by todo.text.

In `@08-todo-app/script.js`:
- Around line 89-94: Update the todo item setup around todoItem.draggable and
the reorder handling near the existing persistence logic so drag operations are
enabled only in the “all” view, or ensure reordered filtered items are merged
back into todos before saving. Preserve drag behavior and persistence
consistency so the DOM cannot show a reorder that is later discarded.
- Around line 24-37: Update the themeToggle and paletteToggle handlers to
persist their respective states in localStorage, then restore both preferences
during script bootstrap. Restoration must synchronize body classes, the theme
icon’s moon/sun state, and each toggle’s aria-pressed value, while preserving
the existing toggle behavior.

In `@08-todo-app/style.css`:
- Around line 61-69: The body.theme-synthwave.light-mode palette needs higher
normal-text contrast. Add separate foreground variables for tile and accent
surfaces, update the affected todo, filter, and header text rules to use them,
and adjust the palette values so every foreground/background pairing reaches at
least 4.5:1 while preserving the existing theme structure.
- Around line 320-340: Update the checkbox focus styling around `.todo-checkbox`
and `.checkmark` so keyboard focus on the transparent input produces a visible
indicator on the associated checkmark, using an appropriate focus-visible
selector and preserving the existing checkbox appearance otherwise.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 0ce943e9-32c1-490e-bc3f-25d71e9ca4e8

📥 Commits

Reviewing files that changed from the base of the PR and between 11f2e5a and 73b1bd8.

⛔ Files ignored due to path filters (1)
  • 08-todo-app/todo.png is excluded by !**/*.png
📒 Files selected for processing (3)
  • 08-todo-app/index.html
  • 08-todo-app/script.js
  • 08-todo-app/style.css

Comment thread 08-todo-app/index.html
Comment on lines +29 to +34
<button id="palette-toggle" class="pixel-btn" title="Change Color Palette">
<i class="fas fa-palette"></i>
</button>
<button id="theme-toggle" class="pixel-btn" title="Toggle Light/Dark">
<i class="fas fa-moon"></i>
</button>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Expose the toggle state to assistive technology.

These controls visually change modes but never communicate whether each mode is active. Add aria-pressed="false" initially and update it alongside the body classes.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@08-todo-app/index.html` around lines 29 - 34, Add aria-pressed="false" to the
palette-toggle and theme-toggle buttons, then update each button’s aria-pressed
value whenever its corresponding body class changes so assistive technology
reflects the current mode state.

Comment thread 08-todo-app/index.html
Comment on lines +42 to 44
<button id="add-task" class="pixel-btn">
<i class="fas fa-plus"></i>
</button>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Give icon-only action buttons accessible names.

Neither button exposes its purpose when the icon is unavailable to assistive technology.

  • 08-todo-app/index.html#L42-L44: add aria-label="Add quest".
  • 08-todo-app/script.js#L115-L118: set deleteBtn.setAttribute("aria-label", \Delete ${todo.text}`)`.
📍 Affects 2 files
  • 08-todo-app/index.html#L42-L44 (this comment)
  • 08-todo-app/script.js#L115-L118
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@08-todo-app/index.html` around lines 42 - 44, Add the accessible name “Add
quest” to the icon-only `#add-task` button in 08-todo-app/index.html:42-44. In
08-todo-app/script.js:115-118, update the deleteBtn creation in the
todo-rendering logic to set its aria-label to “Delete ” followed by todo.text.

Comment thread 08-todo-app/script.js
Comment on lines +24 to +37
themeToggle.addEventListener("click", () => {
document.body.classList.toggle("light-mode");
const icon = themeToggle.querySelector("i");
if (document.body.classList.contains("light-mode")) {
icon.classList.replace("fa-moon", "fa-sun");
} else {
icon.classList.replace("fa-sun", "fa-moon");
}
});

// Synthwave Palette Toggle
paletteToggle.addEventListener("click", () => {
document.body.classList.toggle("theme-synthwave");
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Persist and restore the selected theme.

Both toggles only mutate body classes, so palette and dark-mode preferences reset on every reload. Store both states in localStorage and restore them, including the moon/sun icon and aria-pressed values, during bootstrap.

As required by the PR objective: “Local storage persistence for todos, completion statuses, and theme preferences.”

Also applies to: 239-242

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@08-todo-app/script.js` around lines 24 - 37, Update the themeToggle and
paletteToggle handlers to persist their respective states in localStorage, then
restore both preferences during script bootstrap. Restoration must synchronize
body classes, the theme icon’s moon/sun state, and each toggle’s aria-pressed
value, while preserving the existing toggle behavior.

Comment thread 08-todo-app/script.js
Comment on lines +89 to +94
// Setup for Drag and Drop Tile
todoItem.draggable = true;
todoItem.dataset.id = todo.id;

todoItem.addEventListener("dragstart", handleDragStart);
todoItem.addEventListener("dragend", handleDragEnd);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Do not enable drag operations whose result is discarded.

Todos remain draggable in active and completed views, but Line 180 refuses to persist those reorders. The DOM appears reordered until the next render and then snaps back. Either disable dragging outside "all" or merge the filtered order back into todos.

Minimal fix
-    todoItem.draggable = true;
+    todoItem.draggable = currentFilter === "all";

Also applies to: 179-183

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@08-todo-app/script.js` around lines 89 - 94, Update the todo item setup
around todoItem.draggable and the reorder handling near the existing persistence
logic so drag operations are enabled only in the “all” view, or ensure reordered
filtered items are merged back into todos before saving. Preserve drag behavior
and persistence consistency so the DOM cannot show a reorder that is later
discarded.

Comment thread 08-todo-app/style.css
Comment on lines +61 to +69
body.theme-synthwave.light-mode {
--bg-color: #4cc9f0;
--app-bg: #4895ef;
--text-main: #000000;
--text-muted: #3a0ca3;
--border-color: #3f37c9;
--accent: #f72585;
--tile-bg: #4361ee;
--tile-hover: #3f37c9;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift

Increase contrast in the synthwave light palette.

Several foreground/background pairs fail normal-text contrast: black on --tile-bg is about 4.15:1, --text-muted about 2.35:1, and pink --accent about 1.34:1. This affects todo text, filters, and header text. Introduce separate tile/accent foreground variables and verify each pairing reaches 4.5:1.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@08-todo-app/style.css` around lines 61 - 69, The
body.theme-synthwave.light-mode palette needs higher normal-text contrast. Add
separate foreground variables for tile and accent surfaces, update the affected
todo, filter, and header text rules to use them, and adjust the palette values
so every foreground/background pairing reaches at least 4.5:1 while preserving
the existing theme structure.

Comment thread 08-todo-app/style.css
Comment on lines 320 to +340
.todo-checkbox {
opacity: 0;
position: absolute;
width: 100%;
height: 100%;
cursor: pointer;
z-index: 2;
}

.checkmark {
display: inline-block;
width: 20px;
height: 20px;
border: 2px solid #dee2e6;
border-radius: 4px;
position: relative;
cursor: pointer;
transition: all 0.2s;
position: absolute;
top: 0;
left: 0;
width: 28px;
height: 28px;
background-color: var(--bg-color);
border: 2px solid var(--border-color);
box-shadow: inset 2px 2px 0px rgba(0, 0, 0, 0.5);
transition:
background-color 0.2s,
border-color 0.4s ease;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

Add a visible keyboard-focus indicator for checkboxes.

The focused input is fully transparent, and .checkmark has no corresponding focus style, leaving keyboard users unable to see which task checkbox is selected.

Proposed fix
+.todo-checkbox:focus-visible + .checkmark {
+  outline: 3px solid var(--accent);
+  outline-offset: 3px;
+}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
.todo-checkbox {
opacity: 0;
position: absolute;
width: 100%;
height: 100%;
cursor: pointer;
z-index: 2;
}
.checkmark {
display: inline-block;
width: 20px;
height: 20px;
border: 2px solid #dee2e6;
border-radius: 4px;
position: relative;
cursor: pointer;
transition: all 0.2s;
position: absolute;
top: 0;
left: 0;
width: 28px;
height: 28px;
background-color: var(--bg-color);
border: 2px solid var(--border-color);
box-shadow: inset 2px 2px 0px rgba(0, 0, 0, 0.5);
transition:
background-color 0.2s,
border-color 0.4s ease;
.todo-checkbox {
opacity: 0;
position: absolute;
width: 100%;
height: 100%;
cursor: pointer;
z-index: 2;
}
.todo-checkbox:focus-visible + .checkmark {
outline: 3px solid var(--accent);
outline-offset: 3px;
}
.checkmark {
position: absolute;
top: 0;
left: 0;
width: 28px;
height: 28px;
background-color: var(--bg-color);
border: 2px solid var(--border-color);
box-shadow: inset 2px 2px 0px rgba(0, 0, 0, 0.5);
transition:
background-color 0.2s,
border-color 0.4s ease;
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@08-todo-app/style.css` around lines 320 - 340, Update the checkbox focus
styling around `.todo-checkbox` and `.checkmark` so keyboard focus on the
transparent input produces a visible indicator on the associated checkmark,
using an appropriate focus-visible selector and preserving the existing checkbox
appearance otherwise.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant