From 7b80824ac1086767eccc936c3597276392fc4de9 Mon Sep 17 00:00:00 2001 From: Kayla Inoa Date: Tue, 17 Feb 2026 19:43:05 -0500 Subject: [PATCH 1/2] front end changes for to-do list --- frontend/package-lock.json | 12 -- frontend/src/ToDoList.tsx | 378 ++++++++++++++++++++++++++++++++----- 2 files changed, 331 insertions(+), 59 deletions(-) diff --git a/frontend/package-lock.json b/frontend/package-lock.json index c0ee928..4655864 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -79,7 +79,6 @@ "integrity": "sha512-yDBHV9kQNcr2/sUr9jghVyz9C3Y5G2zUM2H2lo+9mKv4sFgbA8s8Z9t8D1jiTkGoO/NoIfKMyKWr4s6CN23ZwQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@ampproject/remapping": "^2.2.0", "@babel/code-frame": "^7.27.1", @@ -1534,7 +1533,6 @@ "integrity": "sha512-uWN8YqxXxqFMX2RqGOrumsKeti4LlmIMIyV0lgut4jx7KQBcBiW6vkDtIBvHnHIquwNfJhk8v2OtmO8zXWHfPA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "undici-types": "~7.16.0" } @@ -1545,7 +1543,6 @@ "integrity": "sha512-cMoR+FoAf/Jyq6+Df2/Z41jISvGZZ2eTlnsaJRptmZ76Caldwy1odD4xTr/gNV9VLj0AWgg/nmkevIyUfIIq5w==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "csstype": "^3.0.2" } @@ -1596,7 +1593,6 @@ "integrity": "sha512-gTtSdWX9xiMPA/7MV9STjJOOYtWwIJIYxkQxnSV1U3xcE+mnJSH3f6zI0RYP+ew66WSlZ5ed+h0VCxsvdC1jJg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "8.41.0", "@typescript-eslint/types": "8.41.0", @@ -1823,7 +1819,6 @@ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, "license": "MIT", - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -1977,7 +1972,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "caniuse-lite": "^1.0.30001737", "electron-to-chromium": "^1.5.211", @@ -2254,7 +2248,6 @@ "integrity": "sha512-RNCHRX5EwdrESy3Jc9o8ie8Bog+PeYvvSR8sDGoZxNFTvZ4dlxUB3WzQ3bQMztFrSRODGrLLj8g6OFuGY/aiQg==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.12.1", @@ -3219,7 +3212,6 @@ "resolved": "https://registry.npmjs.org/react/-/react-19.1.1.tgz", "integrity": "sha512-w8nqGImo45dmMIfljjMwOGtbmC/mk4CMYhWIicdSflH91J9TyCyczcPFXJzrZ/ZXcgGRFeP6BU0BEJTw6tZdfQ==", "license": "MIT", - "peer": true, "engines": { "node": ">=0.10.0" } @@ -3524,7 +3516,6 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, @@ -3587,7 +3578,6 @@ "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==", "dev": true, "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -3660,7 +3650,6 @@ "integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "esbuild": "^0.25.0", "fdir": "^6.4.4", @@ -3774,7 +3763,6 @@ "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=12" }, diff --git a/frontend/src/ToDoList.tsx b/frontend/src/ToDoList.tsx index 053ac52..ae2ca97 100644 --- a/frontend/src/ToDoList.tsx +++ b/frontend/src/ToDoList.tsx @@ -1,5 +1,266 @@ import { useState } from "react"; -import "./App.css"; + +const styles = ` + @import url('https://fonts.googleapis.com/css2?family=Caveat:wght@600;700&family=DM+Sans:wght@300;400;500&display=swap'); + + * { + box-sizing: border-box; + margin: 0; + padding: 0; + } + + body { + background: #f5f0e8; + } + + .todo-root { + min-height: 100vh; + background: #f5f0e8; + display: flex; + justify-content: center; + align-items: flex-start; + padding: 60px 20px; + font-family: 'DM Sans', sans-serif; + } + + .todo-card { + width: 100%; + max-width: 440px; + background: #fffef9; + border-radius: 24px; + box-shadow: + 0 2px 0 #d9c9a8, + 0 4px 0 #cbb896, + 0 8px 32px rgba(0,0,0,0.08); + padding: 36px 32px 40px; + position: relative; + } + + .todo-card::before { + content: ''; + position: absolute; + top: 0; + left: 48px; + right: 48px; + height: 3px; + background: linear-gradient(90deg, #f28b50, #e8b86d, #82c9a5); + border-radius: 0 0 4px 4px; + } + + .todo-header { + margin-bottom: 28px; + } + + .todo-header h1 { + font-family: 'Caveat', cursive; + font-size: 2.6rem; + font-weight: 700; + color: #2d2416; + line-height: 1; + letter-spacing: -0.5px; + } + + .todo-header .subtitle { + font-size: 0.8rem; + font-weight: 300; + color: #a08c6e; + letter-spacing: 0.12em; + text-transform: uppercase; + margin-top: 4px; + } + + .todo-form { + display: flex; + gap: 8px; + margin-bottom: 28px; + } + + .todo-input { + flex: 1; + border: 2px solid #e8dcc8; + background: #faf7f0; + border-radius: 12px; + padding: 12px 16px; + font-family: 'DM Sans', sans-serif; + font-size: 0.9rem; + color: #2d2416; + outline: none; + transition: border-color 0.2s, box-shadow 0.2s; + } + + .todo-input::placeholder { + color: #c4b49a; + } + + .todo-input:focus { + border-color: #f28b50; + box-shadow: 0 0 0 3px rgba(242,139,80,0.12); + } + + .todo-add-btn { + background: #2d2416; + color: #f5f0e8; + border: none; + border-radius: 12px; + padding: 12px 20px; + font-family: 'DM Sans', sans-serif; + font-size: 0.85rem; + font-weight: 500; + cursor: pointer; + letter-spacing: 0.04em; + transition: background 0.2s, transform 0.1s; + white-space: nowrap; + } + + .todo-add-btn:hover { + background: #f28b50; + } + + .todo-add-btn:active { + transform: scale(0.97); + } + + .todo-divider { + height: 1px; + background: linear-gradient(90deg, transparent, #e8dcc8, transparent); + margin-bottom: 20px; + } + + .todo-list { + list-style: none; + display: flex; + flex-direction: column; + gap: 8px; + } + + .todo-item { + display: flex; + align-items: center; + gap: 12px; + background: #faf7f0; + border: 2px solid #efe6d4; + border-radius: 14px; + padding: 14px 16px; + transition: border-color 0.2s, opacity 0.2s, transform 0.15s; + animation: slideIn 0.25s ease-out; + } + + @keyframes slideIn { + from { + opacity: 0; + transform: translateY(-8px); + } + to { + opacity: 1; + transform: translateY(0); + } + } + + .todo-item:hover { + border-color: #d9c9a8; + } + + .todo-item.checked { + opacity: 0.55; + } + + .todo-checkbox-wrapper { + position: relative; + flex-shrink: 0; + } + + .todo-checkbox-wrapper input[type="checkbox"] { + opacity: 0; + position: absolute; + width: 22px; + height: 22px; + cursor: pointer; + z-index: 1; + } + + .custom-checkbox { + width: 22px; + height: 22px; + border: 2px solid #d4c4a8; + border-radius: 6px; + background: #fff; + display: flex; + align-items: center; + justify-content: center; + transition: background 0.2s, border-color 0.2s; + cursor: pointer; + } + + .todo-checkbox-wrapper input[type="checkbox"]:checked + .custom-checkbox { + background: #82c9a5; + border-color: #82c9a5; + } + + .checkmark { + opacity: 0; + color: white; + font-size: 13px; + font-weight: 700; + transition: opacity 0.15s; + line-height: 1; + } + + .todo-checkbox-wrapper input[type="checkbox"]:checked + .custom-checkbox .checkmark { + opacity: 1; + } + + .todo-label { + flex: 1; + font-size: 0.92rem; + color: #3d2e18; + font-weight: 400; + cursor: pointer; + transition: text-decoration 0.2s; + user-select: none; + } + + .todo-item.checked .todo-label { + text-decoration: line-through; + color: #a08c6e; + } + + .todo-del-btn { + background: none; + border: none; + cursor: pointer; + color: #d4c4a8; + padding: 4px; + border-radius: 6px; + display: flex; + align-items: center; + justify-content: center; + transition: color 0.2s, background 0.2s; + font-size: 16px; + line-height: 1; + flex-shrink: 0; + } + + .todo-del-btn:hover { + color: #e05c5c; + background: rgba(224,92,92,0.08); + } + + .todo-empty { + text-align: center; + padding: 28px 0; + color: #c4b49a; + font-size: 0.85rem; + font-style: italic; + } + + .todo-footer { + margin-top: 20px; + text-align: right; + font-size: 0.75rem; + color: #c4b49a; + font-weight: 300; + } +`; export default function ToDoList() { const [items, setItems] = useState([ @@ -19,7 +280,6 @@ export default function ToDoList() { const addItem = (event: React.FormEvent) => { event.preventDefault(); if (!newItem.trim()) return; - setItems((prev) => [...prev, newItem]); setCheckedItems((prev) => ({ ...prev, [newItem]: false })); setNewItem(""); @@ -38,52 +298,76 @@ export default function ToDoList() { }); }; + const completed = items.filter((i) => checkedItems[i]).length; + return ( -
-
-

Goober To Do List

-
+ <> + +
+
+
+

Goober To Do

+

+ {completed} of {items.length} done +

+
-
- setNewItem(e.target.value)} - /> - -
- -
    - {items.map((item) => ( -
  • -
    - checkItem(item)} - /> - -
    - -
  • - ))} -
-
+ + +
+ +
    + {items.length === 0 && ( +

    All clear — enjoy your day ✦

    + )} + {items.map((item) => ( +
  • +
    + checkItem(item)} + /> +
    + +
    +
    + + +
  • + ))} +
+ + {items.length > 0 && ( +
+ {items.length - completed} remaining +
+ )} +
+
+ ); -} +} \ No newline at end of file From 1f3f2f1ea0c43c42bab847ddcffa0c7187a907db Mon Sep 17 00:00:00 2001 From: Kayla Inoa Date: Tue, 17 Feb 2026 21:59:03 -0500 Subject: [PATCH 2/2] updated UI dark ui made to match dark of rest of site, as well as delete button showing when hovering --- frontend/src/ToDoList.tsx | 610 +++++++++++++++++++++++++++----------- 1 file changed, 430 insertions(+), 180 deletions(-) diff --git a/frontend/src/ToDoList.tsx b/frontend/src/ToDoList.tsx index ae2ca97..3b04d62 100644 --- a/frontend/src/ToDoList.tsx +++ b/frontend/src/ToDoList.tsx @@ -1,189 +1,320 @@ import { useState } from "react"; const styles = ` - @import url('https://fonts.googleapis.com/css2?family=Caveat:wght@600;700&family=DM+Sans:wght@300;400;500&display=swap'); + @import url('https://fonts.googleapis.com/css2?family=Syne:wght@700;800&family=Outfit:wght@300;400;500&display=swap'); - * { + *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; } - body { - background: #f5f0e8; - } - - .todo-root { - min-height: 100vh; - background: #f5f0e8; + /* ── Overlay backdrop ── */ + .todo-overlay { + position: fixed; + inset: 0; + background: rgba(8, 6, 18, 0.72); + backdrop-filter: blur(14px) saturate(0.6); + -webkit-backdrop-filter: blur(14px) saturate(0.6); + z-index: 100; display: flex; + align-items: center; justify-content: center; - align-items: flex-start; - padding: 60px 20px; - font-family: 'DM Sans', sans-serif; + animation: fadeIn 0.3s ease; } + @keyframes fadeIn { + from { opacity: 0; } + to { opacity: 1; } + } + + /* ── Card ── */ .todo-card { - width: 100%; - max-width: 440px; - background: #fffef9; - border-radius: 24px; + width: min(460px, 92vw); + background: #0f0d1a; + border-radius: 28px; + border: 1px solid rgba(255,255,255,0.07); box-shadow: - 0 2px 0 #d9c9a8, - 0 4px 0 #cbb896, - 0 8px 32px rgba(0,0,0,0.08); + 0 0 0 1px rgba(120,80,255,0.15), + 0 32px 80px rgba(0,0,0,0.7), + inset 0 1px 0 rgba(255,255,255,0.06); padding: 36px 32px 40px; position: relative; + overflow: hidden; + animation: slideUp 0.35s cubic-bezier(0.22,1,0.36,1); + } + + @keyframes slideUp { + from { opacity: 0; transform: translateY(24px) scale(0.97); } + to { opacity: 1; transform: translateY(0) scale(1); } } .todo-card::before { content: ''; position: absolute; - top: 0; - left: 48px; - right: 48px; - height: 3px; - background: linear-gradient(90deg, #f28b50, #e8b86d, #82c9a5); - border-radius: 0 0 4px 4px; + top: -80px; + right: -60px; + width: 260px; + height: 260px; + background: radial-gradient(circle, rgba(120,80,255,0.22) 0%, transparent 70%); + pointer-events: none; } + .todo-card::after { + content: ''; + position: absolute; + bottom: -60px; + left: -40px; + width: 200px; + height: 200px; + background: radial-gradient(circle, rgba(255,100,160,0.14) 0%, transparent 70%); + pointer-events: none; + } + + /* ── Header ── */ .todo-header { + display: flex; + align-items: flex-start; + justify-content: space-between; margin-bottom: 28px; + position: relative; + z-index: 1; } - .todo-header h1 { - font-family: 'Caveat', cursive; - font-size: 2.6rem; - font-weight: 700; - color: #2d2416; + .todo-header-text h1 { + font-family: 'Syne', sans-serif; + font-size: 2rem; + font-weight: 800; + color: #fff; + letter-spacing: -0.03em; line-height: 1; - letter-spacing: -0.5px; } - .todo-header .subtitle { - font-size: 0.8rem; - font-weight: 300; - color: #a08c6e; - letter-spacing: 0.12em; + .todo-header-text h1 span { + background: linear-gradient(135deg, #a78bfa, #f472b6); + -webkit-background-clip: text; + -webkit-text-fill-color: transparent; + background-clip: text; + } + + .todo-badge { + font-family: 'Outfit', sans-serif; + font-size: 0.7rem; + font-weight: 500; + color: rgba(255,255,255,0.35); + letter-spacing: 0.14em; text-transform: uppercase; - margin-top: 4px; + margin-top: 6px; } + .todo-progress-ring { + flex-shrink: 0; + position: relative; + width: 48px; + height: 48px; + } + + .todo-progress-ring svg { + transform: rotate(-90deg); + } + + .ring-bg { + fill: none; + stroke: rgba(255,255,255,0.07); + stroke-width: 3; + } + + .ring-fill { + fill: none; + stroke: url(#ringGrad); + stroke-width: 3; + stroke-linecap: round; + transition: stroke-dashoffset 0.5s cubic-bezier(0.4,0,0.2,1); + } + + .ring-label { + position: absolute; + inset: 0; + display: flex; + align-items: center; + justify-content: center; + font-family: 'Outfit', sans-serif; + font-size: 0.65rem; + font-weight: 500; + color: rgba(255,255,255,0.5); + } + + /* ── Form ── */ .todo-form { display: flex; gap: 8px; - margin-bottom: 28px; + margin-bottom: 24px; + position: relative; + z-index: 1; } .todo-input { flex: 1; - border: 2px solid #e8dcc8; - background: #faf7f0; - border-radius: 12px; - padding: 12px 16px; - font-family: 'DM Sans', sans-serif; - font-size: 0.9rem; - color: #2d2416; + background: rgba(255,255,255,0.05); + border: 1px solid rgba(255,255,255,0.1); + border-radius: 14px; + padding: 13px 16px; + font-family: 'Outfit', sans-serif; + font-size: 0.88rem; + color: #fff; outline: none; - transition: border-color 0.2s, box-shadow 0.2s; + transition: border-color 0.2s, background 0.2s, box-shadow 0.2s; } .todo-input::placeholder { - color: #c4b49a; + color: rgba(255,255,255,0.2); } .todo-input:focus { - border-color: #f28b50; - box-shadow: 0 0 0 3px rgba(242,139,80,0.12); + border-color: rgba(167,139,250,0.5); + background: rgba(255,255,255,0.07); + box-shadow: 0 0 0 3px rgba(167,139,250,0.1); } .todo-add-btn { - background: #2d2416; - color: #f5f0e8; + background: linear-gradient(135deg, #7c3aed, #a855f7); + color: #fff; border: none; - border-radius: 12px; - padding: 12px 20px; - font-family: 'DM Sans', sans-serif; - font-size: 0.85rem; + border-radius: 14px; + padding: 13px 20px; + font-family: 'Outfit', sans-serif; + font-size: 0.88rem; font-weight: 500; cursor: pointer; - letter-spacing: 0.04em; - transition: background 0.2s, transform 0.1s; + letter-spacing: 0.02em; + transition: opacity 0.2s, transform 0.15s, box-shadow 0.2s; + box-shadow: 0 4px 14px rgba(124,58,237,0.4); white-space: nowrap; + display: flex; + align-items: center; + gap: 6px; } .todo-add-btn:hover { - background: #f28b50; + opacity: 0.88; + box-shadow: 0 6px 20px rgba(124,58,237,0.5); } .todo-add-btn:active { - transform: scale(0.97); + transform: scale(0.96); } + /* ── Divider ── */ .todo-divider { height: 1px; - background: linear-gradient(90deg, transparent, #e8dcc8, transparent); - margin-bottom: 20px; + background: linear-gradient(90deg, transparent, rgba(255,255,255,0.08), transparent); + margin-bottom: 18px; + position: relative; + z-index: 1; } + /* ── List ── */ .todo-list { list-style: none; display: flex; flex-direction: column; - gap: 8px; + gap: 7px; + position: relative; + z-index: 1; } .todo-item { display: flex; align-items: center; gap: 12px; - background: #faf7f0; - border: 2px solid #efe6d4; + background: rgba(255,255,255,0.04); + border: 1px solid rgba(255,255,255,0.07); border-radius: 14px; - padding: 14px 16px; - transition: border-color 0.2s, opacity 0.2s, transform 0.15s; - animation: slideIn 0.25s ease-out; + padding: 13px 14px; + transition: background 0.2s, border-color 0.2s, transform 0.15s; + animation: itemIn 0.28s cubic-bezier(0.22,1,0.36,1) both; + position: relative; } - @keyframes slideIn { - from { - opacity: 0; - transform: translateY(-8px); - } - to { - opacity: 1; - transform: translateY(0); - } + @keyframes itemIn { + from { opacity: 0; transform: translateX(-10px); } + to { opacity: 1; transform: translateX(0); } } .todo-item:hover { - border-color: #d9c9a8; + background: rgba(255,255,255,0.07); + border-color: rgba(167,139,250,0.2); + transform: translateX(2px); } .todo-item.checked { - opacity: 0.55; + opacity: 0.4; + } + + /* Delete hidden by default, revealed on hover */ + .todo-del-btn { + opacity: 0; + pointer-events: none; + background: rgba(239,68,68,0.12); + border: 1px solid rgba(239,68,68,0.2); + color: #f87171; + cursor: pointer; + padding: 5px 10px; + border-radius: 9px; + display: flex; + align-items: center; + gap: 5px; + font-family: 'Outfit', sans-serif; + font-size: 0.72rem; + font-weight: 500; + flex-shrink: 0; + transition: opacity 0.18s, background 0.18s, transform 0.15s; + } + + .todo-del-btn svg { + width: 13px; + height: 13px; + flex-shrink: 0; } + .todo-item:hover .todo-del-btn { + opacity: 1; + pointer-events: auto; + } + + .todo-del-btn:hover { + background: rgba(239,68,68,0.22); + transform: scale(1.05); + } + + .todo-del-btn:active { + transform: scale(0.95); + } + + /* ── Checkbox ── */ .todo-checkbox-wrapper { position: relative; flex-shrink: 0; + width: 22px; + height: 22px; } .todo-checkbox-wrapper input[type="checkbox"] { opacity: 0; position: absolute; - width: 22px; - height: 22px; + inset: 0; cursor: pointer; - z-index: 1; + z-index: 2; + width: 100%; + height: 100%; } .custom-checkbox { - width: 22px; - height: 22px; - border: 2px solid #d4c4a8; - border-radius: 6px; - background: #fff; + position: absolute; + inset: 0; + border: 2px solid rgba(255,255,255,0.18); + border-radius: 7px; + background: rgba(255,255,255,0.04); display: flex; align-items: center; justify-content: center; @@ -192,77 +323,153 @@ const styles = ` } .todo-checkbox-wrapper input[type="checkbox"]:checked + .custom-checkbox { - background: #82c9a5; - border-color: #82c9a5; + background: linear-gradient(135deg, #7c3aed, #a855f7); + border-color: transparent; } .checkmark { opacity: 0; color: white; - font-size: 13px; + font-size: 12px; font-weight: 700; - transition: opacity 0.15s; + transition: opacity 0.15s, transform 0.15s; + transform: scale(0.5); line-height: 1; } .todo-checkbox-wrapper input[type="checkbox"]:checked + .custom-checkbox .checkmark { opacity: 1; + transform: scale(1); } + /* ── Label ── */ .todo-label { flex: 1; - font-size: 0.92rem; - color: #3d2e18; + font-family: 'Outfit', sans-serif; + font-size: 0.9rem; + color: rgba(255,255,255,0.85); font-weight: 400; cursor: pointer; - transition: text-decoration 0.2s; user-select: none; + transition: color 0.2s; + letter-spacing: 0.01em; } .todo-item.checked .todo-label { text-decoration: line-through; - color: #a08c6e; + color: rgba(255,255,255,0.3); } - .todo-del-btn { - background: none; + /* ── Empty state ── */ + .todo-empty { + text-align: center; + padding: 32px 0; + color: rgba(255,255,255,0.18); + font-family: 'Outfit', sans-serif; + font-size: 0.85rem; + font-style: italic; + } + + /* ── Footer ── */ + .todo-footer { + margin-top: 20px; + display: flex; + justify-content: flex-end; + position: relative; + z-index: 1; + } + + .todo-footer-pill { + font-family: 'Outfit', sans-serif; + font-size: 0.72rem; + font-weight: 500; + color: rgba(255,255,255,0.3); + background: rgba(255,255,255,0.05); + border: 1px solid rgba(255,255,255,0.07); + border-radius: 999px; + padding: 4px 12px; + letter-spacing: 0.06em; + text-transform: uppercase; + } + + /* ── Trigger button ── */ + .todo-trigger { + position: fixed; + bottom: 32px; + right: 32px; + z-index: 50; + background: linear-gradient(135deg, #7c3aed, #a855f7); + color: #fff; border: none; + border-radius: 999px; + padding: 14px 24px; + font-family: 'Outfit', sans-serif; + font-size: 0.9rem; + font-weight: 500; cursor: pointer; - color: #d4c4a8; - padding: 4px; - border-radius: 6px; + box-shadow: 0 8px 24px rgba(124,58,237,0.5); display: flex; align-items: center; - justify-content: center; - transition: color 0.2s, background 0.2s; - font-size: 16px; - line-height: 1; - flex-shrink: 0; + gap: 8px; + transition: transform 0.2s, box-shadow 0.2s; + letter-spacing: 0.02em; } - .todo-del-btn:hover { - color: #e05c5c; - background: rgba(224,92,92,0.08); + .todo-trigger:hover { + transform: translateY(-2px); + box-shadow: 0 12px 32px rgba(124,58,237,0.6); } - .todo-empty { - text-align: center; - padding: 28px 0; - color: #c4b49a; - font-size: 0.85rem; - font-style: italic; + .todo-trigger:active { + transform: scale(0.96); } - .todo-footer { - margin-top: 20px; - text-align: right; - font-size: 0.75rem; - color: #c4b49a; - font-weight: 300; + /* ── Close button ── */ + .todo-close-btn { + position: absolute; + top: 14px; + right: 14px; + background: rgba(255,255,255,0.05); + border: 1px solid rgba(255,255,255,0.08); + color: rgba(255,255,255,0.4); + border-radius: 8px; + width: 30px; + height: 30px; + display: flex; + align-items: center; + justify-content: center; + cursor: pointer; + font-size: 14px; + transition: background 0.2s, color 0.2s; + z-index: 2; + } + + .todo-close-btn:hover { + background: rgba(255,255,255,0.1); + color: rgba(255,255,255,0.8); } `; +const TrashIcon = () => ( + + + + + + +); + +const PlusIcon = () => ( + + + +); + +const RADIUS = 20; +const CIRC = 2 * Math.PI * RADIUS; + export default function ToDoList() { + const [isOpen, setIsOpen] = useState(false); const [items, setItems] = useState([ "Lock in time", "Read Chapters 2-3", @@ -299,75 +506,118 @@ export default function ToDoList() { }; const completed = items.filter((i) => checkedItems[i]).length; + const progress = items.length === 0 ? 0 : completed / items.length; + const dashOffset = CIRC * (1 - progress); return ( <> -
-
-
-

Goober To Do

-

- {completed} of {items.length} done -

-
-
- setNewItem(e.target.value)} - placeholder="Add something new..." - /> - -
- -
- -
    - {items.length === 0 && ( -

    All clear — enjoy your day ✦

    - )} - {items.map((item) => ( -
  • -
    - checkItem(item)} + {/* Floating trigger */} + + + {/* Full-screen overlay — hides page content behind blur */} + {isOpen && ( +
    { if (e.target === e.currentTarget) setIsOpen(false); }} + > +
    + + +
    +
    +

    Goober Tasks

    +

    {completed} of {items.length} complete

    +
    + +
    + + + + + + + + + -
    - -
    -
    - - -
  • - ))} -
- - {items.length > 0 && ( -
- {items.length - completed} remaining + +
{items.length === 0 ? "—" : `${Math.round(progress * 100)}%`}
+
- )} + +
+ setNewItem(e.target.value)} + placeholder="Add a new task..." + autoFocus + /> + +
+ +
+ +
    + {items.length === 0 && ( +

    All clear — enjoy your day ✦

    + )} + {items.map((item) => ( +
  • +
    + checkItem(item)} + /> +
    + +
    +
    + + +
  • + ))} +
+ + {items.length > 0 && ( +
+ + {items.length - completed} remaining + +
+ )} +
-
+ )} ); } \ No newline at end of file