mirror of
https://github.com/aculix/negotium.git
synced 2026-09-11 07:28:17 +00:00
fix: give editing its own button and hand the text back to dragging
Making the task text clickable turned it into a button, and the drag handler skips anything inside a button. That quietly cost the row its best drag handle: press and move across the text and nothing picked the card up, so you got a text selection instead. Verified before changing anything, dragging from the text did nothing while dragging from the row's padding worked. Editing moves to a pencil next to the arrow and the bin, and the text goes back to being text. Rows also stop being selectable, since the row is a drag handle and highlighting words across one is never what you meant. The edit field keeps selection so text can still be copied out of it. A third button costs width on a phone, where all three stay visible because there is no hover. Grouping the actions so their gaps stop multiplying across the row, and drawing them at 26px, keeps most of it back: 199px of text becomes 187, 24 characters a line becomes 23. The 44px tap targets come from the overlay underneath, so a smaller drawn button does not shrink them. Also drops the click-after-drag guard, which only existed because the text was clickable.
This commit is contained in:
@@ -90,7 +90,7 @@ The date, storage, rollover, task and undo logic lives in `src/lib/` as plain mo
|
|||||||
### Managing Tasks
|
### Managing Tasks
|
||||||
- **Add a task**: Type in the input field and press Enter
|
- **Add a task**: Type in the input field and press Enter
|
||||||
- **Complete a task**: Click the checkbox next to the task
|
- **Complete a task**: Click the checkbox next to the task
|
||||||
- **Edit a task**: Click its text. Enter saves, Escape cancels, and clicking away saves too
|
- **Edit a task**: Click the pencil on the task. Enter saves, Escape cancels, and clicking away saves too
|
||||||
- **Delete a task**: Click the delete icon on the task (it shows on hover, and is always visible on touch), or press `Delete` with the task focused
|
- **Delete a task**: Click the delete icon on the task (it shows on hover, and is always visible on touch), or press `Delete` with the task focused
|
||||||
- **Undo**: An Undo button appears for a few seconds after a task is deleted, cleared or moved to another day. `Cmd/Ctrl+Z` does the same. Either way the task returns to where it was
|
- **Undo**: An Undo button appears for a few seconds after a task is deleted, cleared or moved to another day. `Cmd/Ctrl+Z` does the same. Either way the task returns to where it was
|
||||||
- **Move a task to Tomorrow**: Click the arrow on the task, or press `Alt+→`. From Tomorrow, the arrow points back and `Alt+←` returns it to Today
|
- **Move a task to Tomorrow**: Click the arrow on the task, or press `Alt+→`. From Tomorrow, the arrow points back and `Alt+←` returns it to Today
|
||||||
|
|||||||
+17
-13
@@ -94,12 +94,9 @@
|
|||||||
|
|
||||||
let editingId = $state(null);
|
let editingId = $state(null);
|
||||||
let editingText = $state('');
|
let editingText = $state('');
|
||||||
// A drag ends with a click event, which would otherwise drop the row you
|
|
||||||
// just moved straight into edit mode.
|
|
||||||
let suppressClick = false;
|
|
||||||
|
|
||||||
function startEditing(task) {
|
function startEditing(task) {
|
||||||
if (suppressClick || draggedId) return;
|
if (draggedId) return;
|
||||||
editingId = task.id;
|
editingId = task.id;
|
||||||
editingText = task.text;
|
editingText = task.text;
|
||||||
}
|
}
|
||||||
@@ -478,10 +475,6 @@
|
|||||||
|
|
||||||
if (!wasActive) return;
|
if (!wasActive) return;
|
||||||
|
|
||||||
// Swallow the click the browser fires after this drag.
|
|
||||||
suppressClick = true;
|
|
||||||
setTimeout(() => { suppressClick = false; }, 0);
|
|
||||||
|
|
||||||
// Clearing the inline transform while the settling class supplies a
|
// Clearing the inline transform while the settling class supplies a
|
||||||
// transition eases the card into its slot. Nothing else on the list moves,
|
// transition eases the card into its slot. Nothing else on the list moves,
|
||||||
// because nothing else changed.
|
// because nothing else changed.
|
||||||
@@ -769,11 +762,21 @@
|
|||||||
aria-label="Edit {task.text}"
|
aria-label="Edit {task.text}"
|
||||||
/>
|
/>
|
||||||
{:else}
|
{:else}
|
||||||
<button class="task-text" onclick={() => startEditing(task)} title="Click to edit">
|
<span class="task-text">{task.text}</span>
|
||||||
{task.text}
|
|
||||||
</button>
|
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
|
<div class="row-actions">
|
||||||
|
<button
|
||||||
|
class="row-btn edit-btn"
|
||||||
|
onclick={() => startEditing(task)}
|
||||||
|
title="Edit"
|
||||||
|
aria-label="Edit {task.text}"
|
||||||
|
>
|
||||||
|
<svg viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M17 3a2.828 2.828 0 1 1 4 4L7.5 20.5 2 22l1.5-5.5L17 3z" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
|
||||||
<button
|
<button
|
||||||
class="row-btn defer-btn"
|
class="row-btn defer-btn"
|
||||||
onclick={() => deferTask(task.id)}
|
onclick={() => deferTask(task.id)}
|
||||||
@@ -803,8 +806,9 @@
|
|||||||
<path d="M19,6V20A2,2 0 0,1 17,22H7A2,2 0 0,1 5,20V6M8,6V4A2,2 0 0,1 10,2H14A2,2 0 0,1 16,4V6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
<path d="M19,6V20A2,2 0 0,1 17,22H7A2,2 0 0,1 5,20V6M8,6V4A2,2 0 0,1 10,2H14A2,2 0 0,1 16,4V6" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
<line x1="10" y1="11" x2="10" y2="17" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
<line x1="10" y1="11" x2="10" y2="17" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
<line x1="14" y1="11" x2="14" y2="17" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
<line x1="14" y1="11" x2="14" y2="17" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
|
</div>
|
||||||
</li>
|
</li>
|
||||||
{/each}
|
{/each}
|
||||||
</ul>
|
</ul>
|
||||||
|
|||||||
+27
-12
@@ -280,6 +280,9 @@ html.dark .day-option.selected {
|
|||||||
|
|
||||||
.task-item {
|
.task-item {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
/* The row is a drag handle, so pressing and moving across it should carry
|
||||||
|
the card rather than highlight words. */
|
||||||
|
user-select: none;
|
||||||
align-items: flex-start;
|
align-items: flex-start;
|
||||||
gap: 16px;
|
gap: 16px;
|
||||||
padding: 16px 20px;
|
padding: 16px 20px;
|
||||||
@@ -385,16 +388,9 @@ html.dark .task-item.dragging {
|
|||||||
.task-text {
|
.task-text {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
text-align: left;
|
|
||||||
background: transparent;
|
|
||||||
border: none;
|
|
||||||
padding-inline: 0;
|
|
||||||
/* Pads the 24px line box out to the 32px first-line band the row buttons
|
/* Pads the 24px line box out to the 32px first-line band the row buttons
|
||||||
set, so the text centres against the checkbox. Declared as a longhand
|
set, so the text centres against the checkbox. */
|
||||||
because a `padding: 0` shorthand here would reset it. */
|
|
||||||
padding-block: 4px;
|
padding-block: 4px;
|
||||||
font-family: inherit;
|
|
||||||
cursor: text;
|
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
/* 24px line box, the same height as the checkbox, so the two align on the
|
/* 24px line box, the same height as the checkbox, so the two align on the
|
||||||
first line without nudging either. */
|
first line without nudging either. */
|
||||||
@@ -414,6 +410,8 @@ html.dark .task-item.dragging {
|
|||||||
.task-edit {
|
.task-edit {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
min-width: 0;
|
min-width: 0;
|
||||||
|
/* The one place text stays selectable, so it can still be copied out. */
|
||||||
|
user-select: text;
|
||||||
font-family: inherit;
|
font-family: inherit;
|
||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
@@ -426,6 +424,15 @@ html.dark .task-item.dragging {
|
|||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* One group rather than three loose children, so the gaps between the actions
|
||||||
|
do not multiply across the row on a narrow screen. */
|
||||||
|
.row-actions {
|
||||||
|
display: flex;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: 2px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
.row-btn {
|
.row-btn {
|
||||||
width: 32px;
|
width: 32px;
|
||||||
height: 32px;
|
height: 32px;
|
||||||
@@ -443,6 +450,11 @@ html.dark .task-item.dragging {
|
|||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.edit-btn:hover {
|
||||||
|
background-color: var(--hover);
|
||||||
|
color: var(--accent);
|
||||||
|
}
|
||||||
|
|
||||||
.defer-btn:hover {
|
.defer-btn:hover {
|
||||||
background-color: var(--hover);
|
background-color: var(--hover);
|
||||||
color: var(--accent);
|
color: var(--accent);
|
||||||
@@ -617,9 +629,13 @@ html.dark .data-status.error {
|
|||||||
/* Smaller drawn box, same 44px target from the overlay below, and the
|
/* Smaller drawn box, same 44px target from the overlay below, and the
|
||||||
margin keeps it in the 32px first-line band. */
|
margin keeps it in the 32px first-line band. */
|
||||||
.row-btn {
|
.row-btn {
|
||||||
width: 28px;
|
width: 26px;
|
||||||
height: 28px;
|
height: 26px;
|
||||||
margin-block: 2px;
|
margin-block: 3px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.row-actions {
|
||||||
|
gap: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.checkbox::after,
|
.checkbox::after,
|
||||||
@@ -777,7 +793,6 @@ html.dark .data-status.error {
|
|||||||
longer exists, while five newer controls had no focus ring at all. */
|
longer exists, while five newer controls had no focus ring at all. */
|
||||||
.checkbox:focus-visible,
|
.checkbox:focus-visible,
|
||||||
.row-btn:focus-visible,
|
.row-btn:focus-visible,
|
||||||
.task-text:focus-visible,
|
|
||||||
.task-edit:focus-visible,
|
.task-edit:focus-visible,
|
||||||
.theme-toggle:focus-visible,
|
.theme-toggle:focus-visible,
|
||||||
.day-option:focus-visible,
|
.day-option:focus-visible,
|
||||||
|
|||||||
Reference in New Issue
Block a user