Last active
June 14, 2025 12:17
-
-
Save sunmeat/f18c190fd37bd2a2da81151d17ae021d to your computer and use it in GitHub Desktop.
color theme change (second slice) todo list redux example
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
App.jsx: | |
import {useSelector, useDispatch, Provider} from 'react-redux'; | |
import {configureStore, createSlice} from '@reduxjs/toolkit'; | |
import {useState} from 'react'; | |
import './App.css'; | |
// создание среза (slice) для управления задачами | |
const todoSlice = createSlice({ | |
name: 'todo', // имя среза | |
initialState: { // начальное состояние хранилища | |
todos: [], // массив задач | |
filter: 'ALL', // текущий фильтр для отображения задач | |
}, | |
reducers: { // редьюсеры для обработки действий | |
addTodo: (state, action) => { // действие для добавления новой задачи | |
state.todos.push({ | |
id: Date.now(), | |
text: action.payload, | |
completed: false, | |
}); | |
}, | |
toggleTodo: (state, action) => { // действие для переключения статуса задачи | |
const todo = state.todos.find((todo) => todo.id === action.payload); | |
if (todo) { | |
todo.completed = !todo.completed; | |
} | |
}, | |
editTodo: (state, action) => { // действие для редактирования текста задачи | |
const {id, text} = action.payload; | |
const todo = state.todos.find((todo) => todo.id === id); | |
if (todo) { | |
todo.text = text; | |
} | |
}, | |
deleteTodo: (state, action) => { // действие для удаления задачи | |
state.todos = state.todos.filter((todo) => todo.id !== action.payload); | |
}, | |
clearCompleted: (state) => { // действие для очистки завершённых задач | |
state.todos = state.todos.filter((todo) => !todo.completed); | |
}, | |
setFilter: (state, action) => { // действие для установки фильтра | |
state.filter = action.payload; | |
}, | |
}, | |
}); | |
// создание среза (slice) для управления темой | |
const themeSlice = createSlice({ | |
name: 'theme', // имя среза | |
initialState: { // начальное состояние темы | |
mode: 'dark', // текущая тема (dark, light или neon) | |
}, | |
reducers: { // редьюсеры для обработки действий | |
cycleTheme: (state) => { // действие для циклического переключения темы | |
if (state.mode === 'dark') state.mode = 'light'; | |
else if (state.mode === 'light') state.mode = 'neon'; | |
else state.mode = 'dark'; | |
}, | |
}, | |
}); | |
// извлечение действий для упрощения их использования | |
const {addTodo, toggleTodo, editTodo, deleteTodo, clearCompleted, setFilter} = todoSlice.actions; | |
const {cycleTheme} = themeSlice.actions; | |
// настройка хранилища redux с комбинированными редьюсерами | |
const store = configureStore({ | |
reducer: { | |
todo: todoSlice.reducer, // редьюсер для задач | |
theme: themeSlice.reducer, // редьюсер для темы | |
}, | |
}); | |
// компонент списка задач | |
function TodoList() { | |
const [input, setInput] = useState(''); | |
const [editingId, setEditingId] = useState(null); | |
const [editText, setEditText] = useState(''); | |
const dispatch = useDispatch(); // хук для отправки действий в redux | |
const filter = useSelector((state) => state.todo.filter); // хук для получения фильтра из состояния redux | |
const themeMode = useSelector((state) => state.theme.mode); // хук для получения текущей темы | |
// выбор задач на основе текущего фильтра | |
const todos = useSelector((state) => { | |
if (state.todo.filter === 'COMPLETED') return state.todo.todos.filter((todo) => todo.completed); | |
if (state.todo.filter === 'ACTIVE') return state.todo.todos.filter((todo) => !todo.completed); | |
return state.todo.todos; | |
}); | |
const handleAddTodo = () => { | |
if (input.trim()) { | |
dispatch(addTodo(input)); // отправка действия добавления задачи | |
setInput(''); | |
} | |
}; | |
const handleEditStart = (todo) => { | |
setEditingId(todo.id); | |
setEditText(todo.text); | |
}; | |
const handleEditSave = (id) => { | |
if (editText.trim()) { | |
dispatch(editTodo({id, text: editText})); // отправка действия редактирования задачи | |
} | |
setEditingId(null); | |
setEditText(''); | |
}; | |
return ( | |
<div className={`todo-app ${themeMode}`}> | |
<h1 className="todo-title">Список задач</h1> | |
<button | |
className="todo-theme-button" | |
onClick={() => dispatch(cycleTheme())} // отправка действия циклического переключения темы | |
> | |
Переключить тему | |
(Текущая: {themeMode === 'dark' ? 'Тёмная' : themeMode === 'light' ? 'Светлая' : 'Неоновая'}) | |
</button> | |
<div className="todo-input-container"> | |
<input | |
className="todo-input" | |
value={input} | |
onChange={(e) => setInput(e.target.value)} | |
placeholder="Текст задачи" | |
onKeyPress={(e) => e.key === 'Enter' && handleAddTodo()} | |
/> | |
<button className="todo-add-button" onClick={handleAddTodo}> | |
Добавить | |
</button> | |
</div> | |
<div className="todo-filter-container"> | |
<button | |
className={`todo-filter-button ${filter === 'ALL' ? 'active' : ''}`} | |
onClick={() => dispatch(setFilter('ALL'))} // отправка действия установки фильтра "все" | |
> | |
Все | |
</button> | |
<button | |
className={`todo-filter-button ${filter === 'ACTIVE' ? 'active' : ''}`} | |
onClick={() => dispatch(setFilter('ACTIVE'))} // отправка действия установки фильтра "активные" | |
> | |
В процессе | |
</button> | |
<button | |
className={`todo-filter-button ${filter === 'COMPLETED' ? 'active' : ''}`} | |
onClick={() => dispatch(setFilter('COMPLETED'))} // отправка действия установки фильтра "завершенные" | |
> | |
Выполненные | |
</button> | |
</div> | |
<ul className="todo-list"> | |
{todos.map((todo) => ( | |
<li key={todo.id} className={`todo-item ${todo.completed ? 'completed' : ''}`}> | |
{editingId === themeMode.id ? ( | |
<div className="todo-edit-container"> | |
<input | |
className="todo-edit-input" | |
value={editText} | |
onChange={(e) => setEditText(e.target.value)} | |
onKeyPress={(e) => e.key === 'Enter' && handleEditSave(todo.id)} | |
autoFocus | |
/> | |
<button className="todo-save-button" onClick={() => handleEditSave(todo.id)}> | |
Сохранить | |
</button> | |
<button className="todo-cancel-button" onClick={() => setEditingId(null)}> | |
Отмена | |
</button> | |
</div> | |
) : ( | |
<div className="todo-content"> | |
<span className="todo-text">{todo.text}</span> | |
<div className="todo-actions"> | |
<button | |
className={`todo-status-button ${todo.completed ? 'done' : 'not-done'}`} | |
onClick={() => dispatch(toggleTodo(todo.id))} // отправка действия переключения статуса задачи | |
> | |
{todo.completed ? 'Готово' : 'Отметить как выполненную'} | |
</button> | |
<button | |
className="todo-edit-button" | |
onClick={() => handleEditStart(todo)} | |
> | |
Редактировать | |
</button> | |
<button | |
className="todo-delete-button" | |
onClick={() => dispatch(deleteTodo(todo.id))} // отправка действия удаления задачи | |
> | |
Удалить | |
</button> | |
</div> | |
</div> | |
)} | |
</li> | |
))} | |
</ul> | |
{todos.some((todo) => todo.completed) && ( | |
<button | |
className="todo-clear-completed" | |
onClick={() => dispatch(clearCompleted())} // отправка действия очистки завершённых задач | |
> | |
Удалить выполненные задачи | |
</button> | |
)} | |
</div> | |
); | |
} | |
function App() { | |
return ( | |
<Provider store={store}> | |
<TodoList/> | |
</Provider> | |
); | |
} | |
export default App; | |
================================================================================================================= | |
App.css: | |
@import url('https://fonts.googleapis.com/css2?family=Segoe+UI:wght@400;500;600;700&display=swap'); | |
:root { | |
--bg-gradient-start: #1a2525; | |
--bg-gradient-end: #2e3b3b; | |
--text-color: #e6f0fa; | |
--app-bg-start: rgba(30, 40, 50, 0.85); | |
--app-bg-end: rgba(50, 60, 70, 0.85); | |
--input-bg: rgba(80, 100, 120, 0.3); | |
--input-focus-bg: rgba(100, 120, 140, 0.4); | |
--placeholder-color: #a0b0c0; | |
--completed-bg: rgba(40, 150, 80, 0.2); | |
--completed-text: #90a0b0; | |
--item-bg: rgba(60, 80, 100, 0.2); | |
--add-button-bg: linear-gradient(90deg, #4682b4, #6495ed); | |
--add-button-hover: linear-gradient(90deg, #3a70a0, #5580d0); | |
--filter-button-bg: rgba(80, 100, 120, 0.3); | |
--filter-button-hover: rgba(100, 120, 140, 0.4); | |
--filter-active-bg: linear-gradient(90deg, #4682b4, #6495ed); | |
--status-done-bg: linear-gradient(90deg, #2e8b57, #3cb371); | |
--status-not-done-bg: linear-gradient(90deg, #708090, #8797a7); | |
--edit-button-bg: linear-gradient(90deg, #ffa500, #ffb732); | |
--edit-button-hover: linear-gradient(90deg, #e69500, #e6a52e); | |
--delete-button-bg: linear-gradient(90deg, #dc143c, #ff4040); | |
--delete-button-hover: linear-gradient(90deg, #b22222, #cc3333); | |
--save-button-bg: linear-gradient(90deg, #4682b4, #6495ed); | |
--save-button-hover: linear-gradient(90deg, #3a70a0, #5580d0); | |
--cancel-button-bg: linear-gradient(90deg, #708090, #8797a7); | |
--cancel-button-hover: linear-gradient(90deg, #607080, #768697); | |
--clear-button-bg: linear-gradient(90deg, #dc143c, #ff4040); | |
--clear-button-hover: linear-gradient(90deg, #b22222, #cc3333); | |
--theme-button-bg: linear-gradient(90deg, #6a5acd, #836fff); | |
--theme-button-hover: linear-gradient(90deg, #5a4ab8, #7360e6); | |
--border-glow: rgba(100, 149, 237, 0.5); | |
} | |
.light { | |
--bg-gradient-start: #e6f0fa; | |
--bg-gradient-end: #f5faff; | |
--text-color: #2e3b3b; | |
--app-bg-start: rgba(240, 248, 255, 0.85); | |
--app-bg-end: rgba(255, 255, 255, 0.85); | |
--input-bg: rgba(200, 210, 220, 0.3); | |
--input-focus-bg: rgba(210, 220, 230, 0.4); | |
--placeholder-color: #6a8299; | |
--completed-bg: rgba(40, 150, 80, 0.1); | |
--completed-text: #6a8299; | |
--item-bg: rgba(220, 230, 240, 0.2); | |
--add-button-bg: linear-gradient(90deg, #87ceeb, #b0e0e6); | |
--add-button-hover: linear-gradient(90deg, #73b8d3, #9acad0); | |
--filter-button-bg: rgba(200, 210, 220, 0.3); | |
--filter-button-hover: rgba(210, 220, 230, 0.4); | |
--filter-active-bg: linear-gradient(90deg, #87ceeb, #b0e0e6); | |
--status-done-bg: linear-gradient(90deg, #32cd32, #3cb371); | |
--status-not-done-bg: linear-gradient(90deg, #a0a0a0, #b4b4b4); | |
--edit-button-bg: linear-gradient(90deg, #ffd700, #ffec8b); | |
--edit-button-hover: linear-gradient(90deg, #e6c200, #e6d47a); | |
--delete-button-bg: linear-gradient(90deg, #ff4500, #ff6347); | |
--delete-button-hover: linear-gradient(90deg, #e63d00, #e6583f); | |
--save-button-bg: linear-gradient(90deg, #87ceeb, #b0e0e6); | |
--save-button-hover: linear-gradient(90deg, #73b8d3, #9acad0); | |
--cancel-button-bg: linear-gradient(90deg, #a0a0a0, #b4b4b4); | |
--cancel-button-hover: linear-gradient(90deg, #909090, #a4a4a4); | |
--clear-button-bg: linear-gradient(90deg, #ff4500, #ff6347); | |
--clear-button-hover: linear-gradient(90deg, #e63d00, #e6583f); | |
--theme-button-bg: linear-gradient(90deg, #20b2aa, #48d1cc); | |
--theme-button-hover: linear-gradient(90deg, #1c9c95, #40bfb9); | |
--border-glow: rgba(135, 206, 235, 0.5); | |
} | |
.neon { | |
--bg-gradient-start: #1c2526; | |
--bg-gradient-end: #2c3e50; | |
--text-color: #00ffcc; | |
--app-bg-start: rgba(20, 30, 40, 0.85); | |
--app-bg-end: rgba(30, 40, 50, 0.85); | |
--input-bg: rgba(0, 150, 136, 0.3); | |
--input-focus-bg: rgba(0, 170, 150, 0.4); | |
--placeholder-color: #26a69a; | |
--completed-bg: rgba(0, 230, 118, 0.2); | |
--completed-text: #4db6ac; | |
--item-bg: rgba(0, 150, 136, 0.2); | |
--add-button-bg: linear-gradient(90deg, #00ffcc, #26a69a); | |
--add-button-hover: linear-gradient(90deg, #00e6b8, #219187); | |
--filter-button-bg: rgba(0, 150, 136, 0.3); | |
--filter-button-hover: rgba(0, 170, 150, 0.4); | |
--filter-active-bg: linear-gradient(90deg, #00ffcc, #26a69a); | |
--status-done-bg: linear-gradient(90deg, #00e676, #00ff7f); | |
--status-not-done-bg: linear-gradient(90deg, #ff4081, #f06292); | |
--edit-button-bg: linear-gradient(90deg, #ffeb3b, #fff176); | |
--edit-button-hover: linear-gradient(90deg, #e6d433, #e6da68); | |
--delete-button-bg: linear-gradient(90deg, #ff1744, #ff4081); | |
--delete-button-hover: linear-gradient(90deg, #e6153d, #e63874); | |
--save-button-bg: linear-gradient(90deg, #00ffcc, #26a69a); | |
--save-button-hover: linear-gradient(90deg, #00e6b8, #219187); | |
--cancel-button-bg: linear-gradient(90deg, #ff4081, #f06292); | |
--cancel-button-hover: linear-gradient(90deg, #e63874, #d95783); | |
--clear-button-bg: linear-gradient(90deg, #ff1744, #ff4081); | |
--clear-button-hover: linear-gradient(90deg, #e6153d, #e63874); | |
--theme-button-bg: linear-gradient(90deg, #ff00ff, #ff69b4); | |
--theme-button-hover: linear-gradient(90deg, #e600e6, #e661a3); | |
--border-glow: rgba(0, 255, 204, 0.5); | |
} | |
* { | |
margin: 0; | |
padding: 0; | |
box-sizing: border-box; | |
} | |
body { | |
background: linear-gradient(135deg, var(--bg-gradient-start), var(--bg-gradient-end)); | |
color: var(--text-color); | |
font-family: 'Segoe UI', sans-serif; | |
min-height: 100vh; | |
display: flex; | |
justify-content: center; | |
align-items: center; | |
padding: 20px; | |
} | |
.todo-app { | |
max-width: 700px; | |
width: 100%; | |
background: linear-gradient(145deg, var(--app-bg-start), var(--app-bg-end)); | |
backdrop-filter: blur(15px); | |
padding: 30px; | |
border-radius: 12px; | |
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.4); | |
border: 1px solid var(--border-glow); | |
animation: fadeIn 0.5s ease-in-out; | |
} | |
@keyframes fadeIn { | |
from { | |
opacity: 0; | |
transform: translateY(-20px); | |
} | |
to { | |
opacity: 1; | |
transform: translateY(0); | |
} | |
} | |
.todo-title { | |
text-align: center; | |
color: var(--text-color); | |
font-size: 2.5em; | |
font-weight: 600; | |
margin-bottom: 20px; | |
text-shadow: 0 2px 6px rgba(0, 0, 0, 0.2); | |
} | |
.todo-theme-button { | |
display: block; | |
margin: 0 auto 20px; | |
padding: 10px 20px; | |
background: var(--theme-button-bg); | |
color: #ffffff; | |
border: none; | |
border-radius: 6px; | |
cursor: pointer; | |
font-size: 1em; | |
font-weight: 500; | |
transition: all 0.3s ease; | |
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2); | |
} | |
.todo-theme-button:hover { | |
background: var(--theme-button-hover); | |
transform: translateY(-2px); | |
box-shadow: 0 6px 16px rgba(0, 0, 0, 0.3); | |
} | |
.todo-theme-button:active { | |
transform: scale(0.95); | |
} | |
.todo-input-container { | |
display: flex; | |
gap: 15px; | |
margin-bottom: 25px; | |
} | |
.todo-input { | |
flex: 1; | |
padding: 12px 16px; | |
border: none; | |
border-radius: 6px; | |
background: var(--input-bg); | |
color: var(--text-color); | |
font-size: 1.1em; | |
transition: all 0.3s ease; | |
box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.1); | |
} | |
.todo-input::placeholder { | |
color: var(--placeholder-color); | |
} | |
.todo-input:focus { | |
outline: none; | |
background: var(--input-focus-bg); | |
box-shadow: 0 0 0 3px var(--border-glow); | |
} | |
.todo-add-button { | |
padding: 12px 24px; | |
background: var(--add-button-bg); | |
color: #ffffff; | |
border: none; | |
border-radius: 6px; | |
cursor: pointer; | |
font-size: 1.1em; | |
font-weight: 500; | |
transition: all 0.3s ease; | |
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2); | |
} | |
.todo-add-button:hover { | |
background: var(--add-button-hover); | |
transform: translateY(-2px); | |
box-shadow: 0 6px 16px rgba(0, 0, 0, 0.3); | |
} | |
.todo-add-button:active { | |
transform: scale(0.95); | |
} | |
.todo-filter-container { | |
display: flex; | |
gap: 12px; | |
justify-content: center; | |
margin-bottom: 30px; | |
} | |
.todo-filter-button { | |
padding: 10px 20px; | |
background: var(--filter-button-bg); | |
color: var(--text-color); | |
border: none; | |
border-radius: 6px; | |
cursor: pointer; | |
font-size: 1em; | |
font-weight: 500; | |
transition: all 0.3s ease; | |
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); | |
} | |
.todo-filter-button:hover { | |
background: var(--filter-button-hover); | |
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2); | |
} | |
.todo-filter-button.active { | |
background: var(--filter-active-bg); | |
color: #ffffff; | |
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2); | |
} | |
.todo-list { | |
list-style: none; | |
padding: 0; | |
} | |
.todo-item { | |
display: flex; | |
align-items: center; | |
padding: 15px; | |
background: var(--item-bg); | |
border-radius: 8px; | |
margin-bottom: 12px; | |
transition: all 0.3s ease; | |
animation: slideIn 0.3s ease-in-out; | |
border: 1px solid var(--border-glow); | |
} | |
@keyframes slideIn { | |
from { | |
opacity: 0; | |
transform: translateX(-20px); | |
} | |
to { | |
opacity: 1; | |
transform: translateX(0); | |
} | |
} | |
.todo-item.completed { | |
background: var(--completed-bg); | |
} | |
.todo-item.completed .todo-text { | |
text-decoration: line-through; | |
color: var(--completed-text); | |
} | |
.todo-content { | |
display: flex; | |
justify-content: space-between; | |
align-items: center; | |
width: 100%; | |
} | |
.todo-text { | |
flex: 1; | |
font-size: 1.1em; | |
color: var(--text-color); | |
margin-right: 15px; | |
} | |
.todo-actions { | |
display: flex; | |
gap: 10px; | |
} | |
.todo-status-button { | |
padding: 8px 16px; | |
border: none; | |
border-radius: 6px; | |
cursor: pointer; | |
font-size: 0.95em; | |
font-weight: 500; | |
transition: all 0.3s ease; | |
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); | |
} | |
.todo-status-button.done { | |
background: var(--status-done-bg); | |
color: #ffffff; | |
} | |
.todo-status-button.not-done { | |
background: var(--status-not-done-bg); | |
color: #ffffff; | |
} | |
.todo-status-button:hover { | |
transform: translateY(-1px); | |
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2); | |
} | |
.todo-status-button:active { | |
transform: scale(0.95); | |
} | |
.todo-edit-button, | |
.todo-delete-button { | |
padding: 8px 16px; | |
border: none; | |
border-radius: 6px; | |
cursor: pointer; | |
font-size: 0.95em; | |
font-weight: 500; | |
transition: all 0.3s ease; | |
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); | |
} | |
.todo-edit-button { | |
background: var(--edit-button-bg); | |
color: #ffffff; | |
} | |
.todo-edit-button:hover { | |
background: var(--edit-button-hover); | |
transform: translateY(-1px); | |
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2); | |
} | |
.todo-delete-button { | |
background: var(--delete-button-bg); | |
color: #ffffff; | |
} | |
.todo-delete-button:hover { | |
background: var(--delete-button-hover); | |
transform: translateY(-1px); | |
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2); | |
} | |
.todo-edit-button:active, | |
.todo-delete-button:active { | |
transform: scale(0.95); | |
} | |
.todo-edit-container { | |
display: flex; | |
gap: 10px; | |
width: 100%; | |
} | |
.todo-edit-input { | |
flex: 1; | |
padding: 10px; | |
border: none; | |
border-radius: 6px; | |
background: var(--input-bg); | |
color: var(--text-color); | |
font-size: 1.1em; | |
transition: all 0.3s ease; | |
box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.1); | |
} | |
.todo-edit-input:focus { | |
outline: none; | |
background: var(--input-focus-bg); | |
box-shadow: 0 0 0 3px var(--border-glow); | |
} | |
.todo-save-button, | |
.todo-cancel-button { | |
padding: 8px 16px; | |
border: none; | |
border-radius: 6px; | |
cursor: pointer; | |
font-size: 0.95em; | |
font-weight: 500; | |
transition: all 0.3s ease; | |
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); | |
} | |
.todo-save-button { | |
background: var(--save-button-bg); | |
color: #ffffff; | |
} | |
.todo-save-button:hover { | |
background: var(--save-button-hover); | |
transform: translateY(-1px); | |
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2); | |
} | |
.todo-cancel-button { | |
background: var(--cancel-button-bg); | |
color: #ffffff; | |
} | |
.todo-cancel-button:hover { | |
background: var(--cancel-button-hover); | |
transform: translateY(-1px); | |
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2); | |
} | |
.todo-save-button:active, | |
.todo-cancel-button:active { | |
transform: scale(0.95); | |
} | |
.todo-clear-completed { | |
display: block; | |
margin: 25px auto 0; | |
padding: 12px 24px; | |
background: var(--clear-button-bg); | |
color: #ffffff; | |
border: none; | |
border-radius: 6px; | |
cursor: pointer; | |
font-size: 1.1em; | |
font-weight: 500; | |
transition: all 0.3s ease; | |
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2); | |
} | |
.todo-clear-completed:hover { | |
background: var(--clear-button-hover); | |
transform: translateY(-2px); | |
box-shadow: 0 6px 16px rgba(0, 0, 0, 0.3); | |
} | |
.todo-clear-completed:active { | |
transform: scale(0.95); | |
} | |
@media (max-width: 500px) { | |
.todo-app { | |
padding: 20px; | |
} | |
.todo-input-container, | |
.todo-filter-container { | |
flex-direction: column; | |
gap: 10px; | |
} | |
.todo-add-button, | |
.todo-filter-button, | |
.todo-theme-button, | |
.todo-clear-completed { | |
width: 100%; | |
padding: 12px; | |
} | |
.todo-actions { | |
flex-wrap: wrap; | |
gap: 8px; | |
} | |
.todo-status-button, | |
.todo-edit-button, | |
.todo-delete-button { | |
flex: 1; | |
text-align: center; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment