mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-15 21:19:40 +02:00
feat(todo): improve task UI with priority checkboxes, drag styling, and route fix
- Integrate priority indicator into checkbox (color fill + border weight + dashed for low + ! for urgent) for better a11y - Reduce notepad border-radius and enable rounding on mobile - Fix reorder route being shadowed by :id param route - Improve drag & drop styling: remove container highlight, add lifted effect on dragged item Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
23ea63a1d3
commit
5a3ee5c7cb
4 changed files with 77 additions and 39 deletions
|
|
@ -58,6 +58,12 @@ export class TaskController {
|
|||
return { tasks };
|
||||
}
|
||||
|
||||
@Put('reorder')
|
||||
async reorder(@CurrentUser() user: CurrentUserData, @Body() dto: ReorderTasksDto) {
|
||||
const tasks = await this.taskService.reorder(user.userId, dto.taskIds, dto.projectId);
|
||||
return { tasks };
|
||||
}
|
||||
|
||||
@Get(':id')
|
||||
async findOne(@CurrentUser() user: CurrentUserData, @Param('id') id: string) {
|
||||
const task = await this.taskService.findByIdOrThrow(id, user.userId);
|
||||
|
|
@ -119,10 +125,4 @@ export class TaskController {
|
|||
const task = await this.taskService.findByIdOrThrow(id, user.userId);
|
||||
return { task };
|
||||
}
|
||||
|
||||
@Put('reorder')
|
||||
async reorder(@CurrentUser() user: CurrentUserData, @Body() dto: ReorderTasksDto) {
|
||||
const tasks = await this.taskService.reorder(user.userId, dto.taskIds, dto.projectId);
|
||||
return { tasks };
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -372,11 +372,12 @@
|
|||
</svg>
|
||||
</div>
|
||||
|
||||
<!-- Checkbox -->
|
||||
<!-- Checkbox with priority fill -->
|
||||
<button
|
||||
class="task-checkbox"
|
||||
class="task-checkbox priority-{task.priority || 'medium'}"
|
||||
class:checked={task.isCompleted}
|
||||
class:animating={isAnimatingComplete}
|
||||
style="--priority-color: {priorityColors[task.priority] || priorityColors.medium}"
|
||||
onclick={handleToggleClick}
|
||||
>
|
||||
{#if task.isCompleted || isAnimatingComplete}
|
||||
|
|
@ -394,15 +395,11 @@
|
|||
d="M5 13l4 4L19 7"
|
||||
/>
|
||||
</svg>
|
||||
{:else if task.priority === 'urgent'}
|
||||
<span class="priority-bang">!</span>
|
||||
{/if}
|
||||
</button>
|
||||
|
||||
<!-- Priority indicator -->
|
||||
<div
|
||||
class="priority-dot"
|
||||
style="background-color: {priorityColors[task.priority] || priorityColors.medium}"
|
||||
></div>
|
||||
|
||||
<!-- Content -->
|
||||
<div class="task-content">
|
||||
{#if isEditingTitle}
|
||||
|
|
@ -806,21 +803,13 @@
|
|||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* Priority dot */
|
||||
.priority-dot {
|
||||
width: 0.625rem;
|
||||
height: 0.625rem;
|
||||
border-radius: 9999px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
/* Checkbox */
|
||||
/* Checkbox with priority color fill */
|
||||
.task-checkbox {
|
||||
width: 1.25rem;
|
||||
height: 1.25rem;
|
||||
border-radius: 9999px;
|
||||
border: 2px solid rgba(0, 0, 0, 0.2);
|
||||
background: transparent;
|
||||
border: 2px solid var(--priority-color, rgba(0, 0, 0, 0.2));
|
||||
background: color-mix(in srgb, var(--priority-color) 15%, transparent);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
|
@ -831,22 +820,57 @@
|
|||
}
|
||||
|
||||
:global(.dark) .task-checkbox {
|
||||
border-color: rgba(255, 255, 255, 0.3);
|
||||
border-color: var(--priority-color, rgba(255, 255, 255, 0.3));
|
||||
background: color-mix(in srgb, var(--priority-color) 20%, transparent);
|
||||
}
|
||||
|
||||
.task-checkbox:hover {
|
||||
border-color: #8b5cf6;
|
||||
background: rgba(139, 92, 246, 0.1);
|
||||
background: color-mix(in srgb, var(--priority-color) 35%, transparent);
|
||||
}
|
||||
|
||||
/* Priority: low — dashed thin border */
|
||||
.task-checkbox.priority-low {
|
||||
border-style: dashed;
|
||||
border-width: 1.5px;
|
||||
}
|
||||
|
||||
/* Priority: medium — normal solid border */
|
||||
.task-checkbox.priority-medium {
|
||||
border-width: 2px;
|
||||
}
|
||||
|
||||
/* Priority: high — thick border */
|
||||
.task-checkbox.priority-high {
|
||||
border-width: 3px;
|
||||
}
|
||||
|
||||
/* Priority: urgent — thick border + exclamation mark */
|
||||
.task-checkbox.priority-urgent {
|
||||
border-width: 3px;
|
||||
}
|
||||
|
||||
.priority-bang {
|
||||
font-size: 0.6875rem;
|
||||
font-weight: 800;
|
||||
line-height: 1;
|
||||
color: var(--priority-color);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.task-checkbox.checked {
|
||||
background: #8b5cf6;
|
||||
border-color: #8b5cf6;
|
||||
border-style: solid;
|
||||
}
|
||||
|
||||
.task-checkbox.checked .priority-bang {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.task-checkbox.animating {
|
||||
background: #22c55e;
|
||||
border-color: #22c55e;
|
||||
border-style: solid;
|
||||
transform: scale(1.2);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -243,7 +243,7 @@
|
|||
items,
|
||||
flipDurationMs,
|
||||
dropTargetStyle: {},
|
||||
dropTargetClasses: ['task-drop-target'],
|
||||
dropTargetClasses: [],
|
||||
type: 'homepage-tasks',
|
||||
}}
|
||||
onconsider={handleDndConsider}
|
||||
|
|
@ -334,17 +334,31 @@
|
|||
opacity: 0.5;
|
||||
}
|
||||
|
||||
:global(.task-drop-target) {
|
||||
outline: 2px dashed #8b5cf6 !important;
|
||||
outline-offset: -2px;
|
||||
background: rgba(139, 92, 246, 0.08) !important;
|
||||
/* Dragged item styling */
|
||||
:global([aria-grabbed='true']) {
|
||||
opacity: 0.9;
|
||||
transform: scale(1.02);
|
||||
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
|
||||
border-radius: 0.5rem;
|
||||
background: rgba(255, 255, 255, 0.95);
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
:global(.task-drop-target) .empty-placeholder {
|
||||
opacity: 0;
|
||||
:global(.dark [aria-grabbed='true']) {
|
||||
background: rgba(40, 40, 40, 0.95);
|
||||
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.4);
|
||||
}
|
||||
|
||||
:global(.dark .task-drop-target) {
|
||||
background: rgba(139, 92, 246, 0.15) !important;
|
||||
/* Shadow placeholder (where dragged item will land) */
|
||||
:global(.task-list [data-is-dnd-shadow-item-hint]) {
|
||||
background: rgba(139, 92, 246, 0.06);
|
||||
border-radius: 0.375rem;
|
||||
border: 1px dashed rgba(139, 92, 246, 0.3);
|
||||
visibility: visible !important;
|
||||
}
|
||||
|
||||
:global(.dark .task-list [data-is-dnd-shadow-item-hint]) {
|
||||
background: rgba(139, 92, 246, 0.1);
|
||||
border-color: rgba(139, 92, 246, 0.4);
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -507,7 +507,7 @@
|
|||
max-width: 560px;
|
||||
margin: 0 auto;
|
||||
background: #fffef5;
|
||||
border-radius: 0.75rem;
|
||||
border-radius: 0.5rem;
|
||||
box-shadow:
|
||||
0 2px 8px rgba(0, 0, 0, 0.08),
|
||||
0 1px 2px rgba(0, 0, 0, 0.04);
|
||||
|
|
@ -529,7 +529,7 @@
|
|||
@media (max-width: 640px) {
|
||||
.notepad {
|
||||
max-width: 100%;
|
||||
border-radius: 0;
|
||||
border-radius: 0.5rem;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue