fix(todo-web): clean up list design and make onboarding tip dismissable

- Remove spiral binding holes (ring elements) from notepad container
- Remove vertical red margin line from left side
- Add X close button to onboarding tip so users can dismiss it

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Till JS 2026-03-23 21:19:14 +01:00
parent dc372ee744
commit 08a7d2a097
2 changed files with 54 additions and 67 deletions

View file

@ -1,7 +1,21 @@
import { describe, it, expect } from 'vitest';
import type { Task } from '@todo/shared';
import type { Task, Label } from '@todo/shared';
import { applyTaskFilters, type TaskFilterCriteria } from './task-filters';
const now = new Date().toISOString();
function makeLabel(overrides: Partial<Label>): Label {
return {
id: 'l',
userId: 'user-1',
name: 'Label',
color: '#000',
createdAt: now,
updatedAt: now,
...overrides,
};
}
// Helper to create a minimal task for testing
function makeTask(overrides: Partial<Task> = {}): Task {
return {
@ -33,7 +47,7 @@ describe('applyTaskFilters', () => {
title: 'Urgent meeting',
priority: 'urgent',
projectId: 'proj-b',
labels: [{ id: 'label-1', userId: 'user-1', name: 'Work', color: '#f00' }],
labels: [makeLabel({ id: 'label-1', name: 'Work', color: '#f00' })],
}),
makeTask({
id: '3',
@ -42,8 +56,8 @@ describe('applyTaskFilters', () => {
projectId: 'proj-a',
description: 'Quarterly financial report',
labels: [
{ id: 'label-1', userId: 'user-1', name: 'Work', color: '#f00' },
{ id: 'label-2', userId: 'user-1', name: 'Important', color: '#0f0' },
makeLabel({ id: 'label-1', name: 'Work', color: '#f00' }),
makeLabel({ id: 'label-2', name: 'Important', color: '#0f0' }),
],
}),
makeTask({ id: '4', title: 'Relax', priority: 'low', projectId: null }),

View file

@ -12,6 +12,7 @@
import type { Task } from '@todo/shared';
let isLoading = $state(true);
let tipDismissed = $state(false);
// Build filter criteria from viewStore (reactive)
let filterCriteria = $derived({
@ -203,14 +204,6 @@
</div>
{:else}
<div class="notepad">
<div class="notepad-holes" aria-hidden="true">
<span class="hole"></span>
<span class="hole"></span>
<span class="hole"></span>
<span class="hole"></span>
<span class="hole"></span>
<span class="hole"></span>
</div>
<div class="notepad-content">
<div class="space-y-2">
<!-- Overdue Section - only show if there are overdue tasks -->
@ -314,12 +307,27 @@
{/if}
<!-- Onboarding tip for users with 1-3 tasks -->
{#if showOnboardingTip}
{#if showOnboardingTip && !tipDismissed}
<div class="onboarding-tip">
<span class="onboarding-tip-icon">💡</span>
<span class="onboarding-tip-text">
Tipp: Nutze <code>#tags</code> und <code>!priorität</code> für bessere Organisation
</span>
<button
class="onboarding-tip-close"
onclick={() => (tipDismissed = true)}
title="Tipp ausblenden"
aria-label="Tipp ausblenden"
>
<svg class="w-4 h-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="2"
d="M6 18L18 6M6 6l12 12"
/>
</svg>
</button>
</div>
{/if}
</div>
@ -468,6 +476,23 @@
color: hsl(var(--color-muted-foreground));
}
.onboarding-tip-close {
flex-shrink: 0;
margin-left: auto;
padding: 0.25rem;
border-radius: 0.375rem;
color: hsl(var(--color-muted-foreground));
background: transparent;
border: none;
cursor: pointer;
transition: all 0.15s ease;
}
.onboarding-tip-close:hover {
color: hsl(var(--color-foreground));
background: hsl(var(--color-primary) / 0.15);
}
.onboarding-tip-text code {
padding: 0.125rem 0.375rem;
font-size: 0.8125rem;
@ -482,12 +507,11 @@
max-width: 560px;
margin: 0 auto;
background: #fffef5;
border-radius: 0.5rem 0.5rem 0.75rem 0.75rem;
border-radius: 0.75rem;
box-shadow:
0 2px 8px rgba(0, 0, 0, 0.08),
0 1px 2px rgba(0, 0, 0, 0.04);
position: relative;
padding-top: 1.25rem;
}
:global(.dark) .notepad {
@ -497,66 +521,15 @@
0 1px 2px rgba(0, 0, 0, 0.2);
}
/* Spiral binding holes */
.notepad-holes {
position: absolute;
top: -6px;
left: 10%;
right: 10%;
display: flex;
justify-content: space-evenly;
pointer-events: none;
z-index: 2;
}
.hole {
width: 14px;
height: 14px;
border-radius: 50%;
background: hsl(var(--color-background, 0 0% 100%));
border: 2px solid #c4c4c4;
box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
}
:global(.dark) .hole {
background: hsl(var(--color-background, 0 0% 7%));
border-color: #555;
}
/* Notepad content with red margin line */
.notepad-content {
position: relative;
padding: 0.75rem 1rem 1.5rem 3.25rem;
padding: 0.75rem 1rem 1.5rem 1rem;
min-height: 200px;
}
.notepad-content::before {
content: '';
position: absolute;
top: 0;
bottom: 0;
left: 2.5rem;
width: 2px;
background: #e8b4b8;
z-index: 1;
}
:global(.dark) .notepad-content::before {
background: rgba(232, 180, 184, 0.4);
}
@media (max-width: 640px) {
.notepad {
max-width: 100%;
border-radius: 0;
}
.notepad-content {
padding-left: 2.75rem;
}
.notepad-content::before {
left: 2rem;
}
}
</style>