larryhudson / vite-todo-list

Example Vite project
0 stars 0 forks source link

Fix issue #29: feat: Implement dark mode toggle #30

Closed larryhudson-aider-github[bot] closed 1 month ago

larryhudson-aider-github[bot] commented 1 month ago

This PR addresses the changes requested in issue #29

Thank you for adding those files. I'll now propose changes to implement the dark mode toggle feature. We'll need to modify all three files: src/App.tsx, src/App.css, and src/index.css. Let's start with the changes:

  1. First, let's update src/index.css to add CSS variables for light and dark mode:

src/index.css

<<<<<<< SEARCH
body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
    'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
    sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

#root {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 100vh;
}
=======
:root {
  --bg-color: #ffffff;
  --text-color: #333333;
  --input-bg: #ffffff;
  --input-border: #dddddd;
  --button-bg: #4CAF50;
  --button-hover: #45a049;
  --delete-button-bg: #f44336;
  --delete-button-hover: #d32f2f;
  --todo-bg: #ffffff;
  --todo-shadow: rgba(0, 0, 0, 0.1);
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg-color: #1a1a1a;
    --text-color: #ffffff;
    --input-bg: #333333;
    --input-border: #555555;
    --button-bg: #45a049;
    --button-hover: #4CAF50;
    --delete-button-bg: #d32f2f;
    --delete-button-hover: #f44336;
    --todo-bg: #2a2a2a;
    --todo-shadow: rgba(255, 255, 255, 0.1);
  }
}

body {
  margin: 0;
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen',
    'Ubuntu', 'Cantarell', 'Fira Sans', 'Droid Sans', 'Helvetica Neue',
    sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  background-color: var(--bg-color);
  color: var(--text-color);
}

#root {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 100vh;
}
>>>>>>> REPLACE
  1. Now, let's update src/App.css to use the CSS variables:

src/App.css

<<<<<<< SEARCH
#root {
  max-width: 600px;
  margin: 0 auto;
  padding: 2rem;
  font-family: Arial, sans-serif;
}

.App {
  background-color: #f5f5f5;
  border-radius: 8px;
  padding: 20px;
  box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}

h1 {
  color: #333;
  margin-bottom: 20px;
}

input[type="text"] {
  width: 70%;
  padding: 10px;
  margin-right: 10px;
  border: 1px solid #ddd;
  border-radius: 4px;
}

button {
  padding: 10px 15px;
  background-color: #4CAF50;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  transition: background-color 0.3s;
}

button:hover {
  background-color: #45a049;
}

ul {
  list-style-type: none;
  padding: 0;
}

li {
  background-color: white;
  margin: 10px 0;
  padding: 10px;
  border-radius: 4px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
}

li input[type="checkbox"] {
  margin-right: 10px;
}

li span {
  flex-grow: 1;
  text-align: left;
}

li button {
  background-color: #f44336;
  padding: 5px 10px;
  font-size: 0.8em;
}

li button:hover {
  background-color: #d32f2f;
}
=======
#root {
  max-width: 600px;
  margin: 0 auto;
  padding: 2rem;
  font-family: Arial, sans-serif;
}

.App {
  background-color: var(--bg-color);
  border-radius: 8px;
  padding: 20px;
  box-shadow: 0 2px 4px var(--todo-shadow);
}

h1 {
  color: var(--text-color);
  margin-bottom: 20px;
}

input[type="text"], input[type="date"] {
  width: 70%;
  padding: 10px;
  margin-right: 10px;
  border: 1px solid var(--input-border);
  border-radius: 4px;
  background-color: var(--input-bg);
  color: var(--text-color);
}

button {
  padding: 10px 15px;
  background-color: var(--button-bg);
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  transition: background-color 0.3s;
}

button:hover {
  background-color: var(--button-hover);
}

ul {
  list-style-type: none;
  padding: 0;
}

li {
  background-color: var(--todo-bg);
  margin: 10px 0;
  padding: 10px;
  border-radius: 4px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  box-shadow: 0 1px 3px var(--todo-shadow);
}

li input[type="checkbox"] {
  margin-right: 10px;
}

li span {
  flex-grow: 1;
  text-align: left;
  color: var(--text-color);
}

li button {
  background-color: var(--delete-button-bg);
  padding: 5px 10px;
  font-size: 0.8em;
}

li button:hover {
  background-color: var(--delete-button-hover);
}

.dark-mode-toggle {
  position: absolute;
  top: 10px;
  right: 10px;
  background-color: transparent;
  border: none;
  color: var(--text-color);
  font-size: 1.5em;
  cursor: pointer;
}
>>>>>>> REPLACE
  1. Finally, let's update src/App.tsx to add the dark mode toggle functionality:

src/App.tsx

<<<<<<< SEARCH
import { useState } from 'react'
import './App.css'

interface Todo {
  id: number;
  text: string;
  completed: boolean;
  dueDate: Date;
}

function App() {
  const [todos, setTodos] = useState<Todo[]>([])
  const [newTodo, setNewTodo] = useState('')
  const [dueDate, setDueDate] = useState<string>(new Date().toISOString().split('T')[0])

  const addTodo = (e: React.FormEvent<HTMLFormElement>) => {
=======
import { useState, useEffect } from 'react'
import './App.css'

interface Todo {
  id: number;
  text: string;
  completed: boolean;
  dueDate: Date;
}

function App() {
  const [todos, setTodos] = useState<Todo[]>([])
  const [newTodo, setNewTodo] = useState('')
  const [dueDate, setDueDate] = useState<string>(new Date().toISOString().split('T')[0])
  const [darkMode, setDarkMode] = useState<boolean>(false)

  useEffect(() => {
    const prefersDarkMode = window.matchMedia('(prefers-color-scheme: dark)').matches
    setDarkMode(prefersDarkMode)
  }, [])

  useEffect(() => {
    document.documentElement.setAttribute('data-theme', darkMode ? 'dark' : 'light')
  }, [darkMode])

  const toggleDarkMode = () => {
    setDarkMode(!darkMode)
  }

  const addTodo = (e: React.FormEvent<HTMLFormElement>) => {
>>>>>>> REPLACE

Now, let's add the dark mode toggle button to the App component:

src/App.tsx

<<<<<<< SEARCH
  return (
    <div className="App">
      <h1>To-Do List</h1>
      <form onSubmit={addTodo}>
=======
  return (
    <div className="App">
      <button className="dark-mode-toggle" onClick={toggleDarkMode}>
        {darkMode ? '☀️' : '🌙'}
      </button>
      <h1>To-Do List</h1>
      <form onSubmit={addTodo}>
>>>>>>> REPLACE

These changes will implement the dark mode toggle feature as requested. The toggle button will appear in the top right corner of the page, and the app will initially follow the user's system preference for dark mode. The user can then manually toggle between light and dark modes.

To see these changes in action, you can run your development server (typically with npm run dev or yarn dev). The exact command might vary depending on your project setup.

larryhudson-aider-github[bot] commented 1 month ago

I've updated the PR based on the review comment.

To address the review comment, we need to add selectors for when the document element has data-theme="dark" or data-theme="light". We'll modify the src/index.css file to include these selectors. This will ensure that the dark mode toggle works correctly, regardless of the system preference.

Here's the change we need to make:

src/index.css

<<<<<<< SEARCH
:root {
  --bg-color: #ffffff;
  --text-color: #333333;
  --input-bg: #ffffff;
  --input-border: #dddddd;
  --button-bg: #4CAF50;
  --button-hover: #45a049;
  --delete-button-bg: #f44336;
  --delete-button-hover: #d32f2f;
  --todo-bg: #ffffff;
  --todo-shadow: rgba(0, 0, 0, 0.1);
}

@media (prefers-color-scheme: dark) {
  :root {
    --bg-color: #1a1a1a;
    --text-color: #ffffff;
    --input-bg: #333333;
    --input-border: #555555;
    --button-bg: #45a049;
    --button-hover: #4CAF50;
    --delete-button-bg: #d32f2f;
    --delete-button-hover: #f44336;
    --todo-bg: #2a2a2a;
    --todo-shadow: rgba(255, 255, 255, 0.1);
  }
}
=======
:root, [data-theme="light"] {
  --bg-color: #ffffff;
  --text-color: #333333;
  --input-bg: #ffffff;
  --input-border: #dddddd;
  --button-bg: #4CAF50;
  --button-hover: #45a049;
  --delete-button-bg: #f44336;
  --delete-button-hover: #d32f2f;
  --todo-bg: #ffffff;
  --todo-shadow: rgba(0, 0, 0, 0.1);
}

[data-theme="dark"] {
  --bg-color: #1a1a1a;
  --text-color: #ffffff;
  --input-bg: #333333;
  --input-border: #555555;
  --button-bg: #45a049;
  --button-hover: #4CAF50;
  --delete-button-bg: #d32f2f;
  --delete-button-hover: #f44336;
  --todo-bg: #2a2a2a;
  --todo-shadow: rgba(255, 255, 255, 0.1);
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg-color: #1a1a1a;
    --text-color: #ffffff;
    --input-bg: #333333;
    --input-border: #555555;
    --button-bg: #45a049;
    --button-hover: #4CAF50;
    --delete-button-bg: #d32f2f;
    --delete-button-hover: #f44336;
    --todo-bg: #2a2a2a;
    --todo-shadow: rgba(255, 255, 255, 0.1);
  }
}
>>>>>>> REPLACE

This change does the following:

  1. We've added a selector for [data-theme="light"] alongside :root to explicitly set light mode colors.
  2. We've created a new selector [data-theme="dark"] to set dark mode colors when the dark mode is toggled on.
  3. We've kept the @media (prefers-color-scheme: dark) query, but modified it to only apply when the data-theme attribute is not set to "light". This ensures that the system preference is respected unless explicitly overridden by the user.

These changes will allow the dark mode toggle to work correctly, overriding the system preference when needed, while still respecting the system preference by default.

larryhudson-aider-github[bot] commented 1 month ago

I've updated the PR based on the review comment.

To address the review comment, we need to import the index.css file in src/main.tsx. Here's the change we need to make:

src/main.tsx

<<<<<<< SEARCH
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import App from './App.tsx'
=======
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import './index.css'
import App from './App.tsx'
>>>>>>> REPLACE

This change adds the import statement for index.css at the top of the main.tsx file, which will ensure that the CSS variables and styles defined in index.css are applied to the entire application.

After making this change, the dark mode toggle should work as expected, and the styles should be properly applied based on the user's system preferences and manual toggle.

larryhudson-aider-github[bot] commented 1 month ago

I've updated the PR based on the review comment.

Certainly! I'll remove the code from src/index.css that is centering the to-do list in the middle of the page. Here's the change:

src/index.css

<<<<<<< SEARCH
#root {
  display: flex;
  justify-content: center;
  align-items: center;
  min-height: 100vh;
}
=======
>>>>>>> REPLACE

This change removes the #root selector and its associated styles, which were responsible for centering the to-do list in the middle of the page.

To ensure that the app still looks good without this centering, we might want to add some basic styling to the #root element in the App.css file. Here's a suggestion:

src/App.css

<<<<<<< SEARCH
#root {
  max-width: 600px;
  margin: 0 auto;
  padding: 2rem;
  font-family: Arial, sans-serif;
}
=======
#root {
  max-width: 600px;
  margin: 2rem auto;
  padding: 2rem;
  font-family: Arial, sans-serif;
}
>>>>>>> REPLACE

This change adds a top and bottom margin to the #root element, which will give some space at the top of the page where the to-do list starts.

These changes will remove the vertical centering of the to-do list while still keeping it centered horizontally and providing a good layout for the app.