diff --git a/web/README.md b/web/README.md index cb030af..a0be5d4 100644 --- a/web/README.md +++ b/web/README.md @@ -47,10 +47,16 @@ src/views/ HomeView (lists), ListView (items), LoginView, RegisterV ## List detail -`/lists/:id` shows one list's items. Each row is a checkbox, an inline-editable -text field (saved on blur), a delete button, and a drag handle. Reordering uses -`vuedraggable`; on drop the whole new order is persisted via -`PUT /api/lists/:id/items/order`, and the server response replaces local state. +`/lists/:id` shows one list. The title and description are inline-editable +(saved on blur via `PATCH /api/lists/:id`; the description shows an "Add a +description" placeholder when empty). A **Manage** menu (top right) has a +**Delete list** action that opens a confirmation modal; confirming calls +`DELETE /api/lists/:id` and returns to the all-lists view. + +Each item row is a checkbox, an inline-editable text field (saved on blur), a +delete button, and a drag handle. Reordering uses `vuedraggable`; on drop the +whole new order is persisted via `PUT /api/lists/:id/items/order`, and the +server response replaces local state. ## Auth flow diff --git a/web/src/style.css b/web/src/style.css index 45caf1f..79872fa 100644 --- a/web/src/style.css +++ b/web/src/style.css @@ -233,6 +233,188 @@ h1 { background: var(--bg); } +/* --- list detail: header, inline title/description, manage menu -------- */ + +.list-head { + display: flex; + align-items: flex-start; + gap: 0.5rem; +} + +.list-head__title { + flex: 1; + min-width: 0; + margin: 0 0 0.5rem; +} + +.list-head__title input, +.list-head__desc { + width: 100%; + font: inherit; + color: var(--text); + background: transparent; + border: 1px solid transparent; + border-radius: 6px; + padding: 0.25rem 0.4rem; +} + +.list-head__title input { + font-size: 1.4rem; + font-weight: 600; +} + +.list-head__desc { + display: block; + resize: vertical; + min-height: 2.75rem; + font-size: 0.95rem; + color: var(--muted); + margin-bottom: 0.75rem; +} + +.list-head__title input:hover, +.list-head__desc:hover { + border-color: var(--border); +} + +.list-head__title input:focus, +.list-head__desc:focus { + outline: none; + color: var(--text); + background: var(--bg); + border-color: var(--accent); +} + +.menu { + position: relative; + flex: none; +} + +.menu__toggle { + border: 1px solid var(--border); + background: var(--bg); + color: var(--text); + border-radius: 8px; + padding: 0.35rem 0.7rem; + font: inherit; + font-size: 0.9rem; + cursor: pointer; +} + +.menu__toggle:hover { + border-color: var(--muted); +} + +.menu__backdrop { + position: fixed; + inset: 0; + z-index: 10; +} + +.menu__list { + position: absolute; + right: 0; + top: calc(100% + 4px); + z-index: 20; + min-width: 10rem; + margin: 0; + padding: 0.25rem; + list-style: none; + background: var(--surface); + border: 1px solid var(--border); + border-radius: 8px; + box-shadow: 0 6px 20px rgba(0, 0, 0, 0.12); +} + +.menu__item { + display: block; + width: 100%; + text-align: left; + border: none; + background: none; + color: var(--text); + font: inherit; + padding: 0.45rem 0.6rem; + border-radius: 6px; + cursor: pointer; +} + +.menu__item:hover { + background: var(--bg); +} + +.menu__item--danger { + color: var(--error); +} + +/* --- confirmation modal --------------------------------------------------- */ + +.modal { + position: fixed; + inset: 0; + z-index: 100; + display: flex; + align-items: center; + justify-content: center; + padding: 1rem; +} + +.modal__backdrop { + position: absolute; + inset: 0; + background: rgba(0, 0, 0, 0.45); +} + +.modal__dialog { + position: relative; + z-index: 1; + width: 100%; + max-width: 24rem; + background: var(--surface); + border: 1px solid var(--border); + border-radius: 12px; + padding: 1.5rem; +} + +.modal__dialog h2 { + margin: 0 0 0.5rem; + font-size: 1.15rem; +} + +.modal__actions { + display: flex; + justify-content: flex-end; + gap: 0.6rem; + margin-top: 1.25rem; +} + +.btn-secondary, +.btn-danger { + border: 1px solid var(--border); + border-radius: 8px; + padding: 0.5rem 0.9rem; + font: inherit; + font-size: 0.95rem; + cursor: pointer; +} + +.btn-secondary { + background: var(--bg); + color: var(--text); +} + +.btn-danger { + background: #b3261e; + border-color: #b3261e; + color: #fff; +} + +.btn-secondary:disabled, +.btn-danger:disabled { + opacity: 0.6; + cursor: default; +} + .form { display: grid; gap: 1rem; diff --git a/web/src/views/ListView.vue b/web/src/views/ListView.vue index ce5038e..bbfa6fa 100644 --- a/web/src/views/ListView.vue +++ b/web/src/views/ListView.vue @@ -1,20 +1,32 @@