fix(manacore/web): align notes and finance ListViews with workbench design system

Match todo/calendar/contacts patterns: hardcoded colors with dark mode
overrides, consistent button styles (transparent bg, hover states),
same padding/spacing/border-radius as existing ListViews.

Buttons are now clearly recognizable: primary (purple bg), ghost
(transparent with hover), danger (red on hover), filter tabs
(active state with colored bg).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Till JS 2026-04-03 14:08:01 +02:00
parent b63829ae4c
commit 09eef96ed8
2 changed files with 365 additions and 267 deletions

View file

@ -1,6 +1,6 @@
<!--
Finance — Workbench ListView
Always-visible quick-add at top, monthly summary, recent transactions.
Always-visible quick-add, monthly summary, recent transactions.
-->
<script lang="ts">
import {
@ -44,37 +44,30 @@
let income = $derived(getMonthTotal(txs, month, 'income'));
let expenses = $derived(getMonthTotal(txs, month, 'expense'));
let balance = $derived(getMonthBalance(txs, month));
let catMap = $derived(new Map(categories.map((c) => [c.id, c])));
let recentTxs = $derived(monthTxs.slice(0, 10));
let grouped = $derived(groupByDate(recentTxs));
// Always-visible quick add
// Quick add state
let addType = $state<TransactionType>('expense');
let addAmount = $state('');
let addDesc = $state('');
let addCatId = $state<string | null>(null);
let showCats = $state(false);
let filteredCats = $derived(categories.filter((c) => c.type === addType));
async function handleAdd(e: Event) {
e.preventDefault();
const amount = parseFloat(addAmount.replace(',', '.'));
if (!amount || !addDesc.trim()) return;
await financeStore.addTransaction({
type: addType,
amount,
description: addDesc.trim(),
categoryId: addCatId,
});
addAmount = '';
addDesc = '';
addCatId = null;
showCats = false;
}
function handleKeydown(e: KeyboardEvent) {
@ -85,13 +78,13 @@
}
</script>
<div class="finance-list-view">
<!-- Always-visible Quick Add -->
<form class="quick-add" onsubmit={handleAdd}>
<div class="type-toggle">
<div class="app-view">
<!-- Quick Add -->
<form class="quick-add-form" onsubmit={handleAdd}>
<div class="type-tabs">
<button
type="button"
class="type-btn"
class="type-tab"
class:active={addType === 'expense'}
onclick={() => {
addType = 'expense';
@ -100,7 +93,7 @@
>
<button
type="button"
class="type-btn inc"
class="type-tab inc"
class:active={addType === 'income'}
onclick={() => {
addType = 'income';
@ -117,7 +110,7 @@
bind:value={addAmount}
onkeydown={handleKeydown}
/>
<span class="currency">&euro;</span>
<span class="currency-label">&euro;</span>
<input
class="desc-input"
type="text"
@ -125,10 +118,9 @@
bind:value={addDesc}
onkeydown={handleKeydown}
/>
<button type="submit" class="submit-btn" disabled={!addAmount || !addDesc.trim()}>+</button>
<button type="submit" class="add-btn" disabled={!addAmount || !addDesc.trim()}>+</button>
</div>
<!-- Category chips -->
<div class="cat-row">
<div class="cat-chips">
{#each filteredCats as cat (cat.id)}
<button
type="button"
@ -141,98 +133,119 @@
</div>
</form>
<!-- Monthly Summary -->
<div class="month-summary">
<div class="summary-item">
<span class="summary-value income">+{formatCurrency(income)}</span>
<span class="summary-label">Einnahmen</span>
<!-- Summary -->
<div class="summary">
<div class="summary-col">
<span class="s-value income">+{formatCurrency(income)}</span>
<span class="s-label">Einnahmen</span>
</div>
<div class="summary-item">
<span class="summary-value expense">-{formatCurrency(expenses)}</span>
<span class="summary-label">Ausgaben</span>
<div class="summary-col">
<span class="s-value expense">-{formatCurrency(expenses)}</span>
<span class="s-label">Ausgaben</span>
</div>
<div class="summary-item">
<span class="summary-value" class:income={balance >= 0} class:expense={balance < 0}>
<div class="summary-col">
<span class="s-value" class:income={balance >= 0} class:expense={balance < 0}>
{balance >= 0 ? '+' : ''}{formatCurrency(balance)}
</span>
<span class="summary-label">Bilanz</span>
<span class="s-label">Bilanz</span>
</div>
</div>
<!-- Recent Transactions -->
{#if recentTxs.length > 0}
<div class="tx-list">
{#each [...grouped.entries()] as [date, dayTxs] (date)}
<div class="day-label">{formatDateLabel(date)}</div>
{#each dayTxs as tx (tx.id)}
{@const cat = tx.categoryId ? catMap.get(tx.categoryId) : null}
<div class="tx-row">
<span class="tx-emoji">{cat?.emoji ?? '\ud83d\udcb3'}</span>
<div class="tx-info">
<span class="tx-desc">{tx.description}</span>
{#if cat}<span class="tx-cat">{cat.name}</span>{/if}
</div>
<span
class="tx-amount"
class:income={tx.type === 'income'}
class:expense={tx.type === 'expense'}
>
{tx.type === 'income' ? '+' : '-'}{formatCurrency(tx.amount)}
</span>
<!-- Transactions -->
<div class="tx-list">
{#each [...grouped.entries()] as [date, dayTxs] (date)}
<div class="day-label">{formatDateLabel(date)}</div>
{#each dayTxs as tx (tx.id)}
{@const cat = tx.categoryId ? catMap.get(tx.categoryId) : null}
<div class="tx-item">
<span class="tx-emoji">{cat?.emoji ?? '\ud83d\udcb3'}</span>
<div class="tx-info">
<span class="tx-desc">{tx.description}</span>
{#if cat}<span class="tx-cat">{cat.name}</span>{/if}
</div>
{/each}
<span
class="tx-amount"
class:income={tx.type === 'income'}
class:expense={tx.type === 'expense'}
>
{tx.type === 'income' ? '+' : '-'}{formatCurrency(tx.amount)}
</span>
</div>
{/each}
</div>
{:else}
<div class="empty">Noch keine Transaktionen diesen Monat.</div>
{/if}
{/each}
{#if recentTxs.length === 0}
<p class="empty">Noch keine Transaktionen diesen Monat.</p>
{/if}
</div>
</div>
<style>
.finance-list-view {
.app-view {
display: flex;
flex-direction: column;
gap: 0.5rem;
padding: 0.5rem;
gap: 0.625rem;
padding: 1rem;
height: 100%;
}
/* ── Quick Add (always visible) ─────────────── */
.quick-add {
/* ── Quick Add Form ─────────────────────────── */
.quick-add-form {
display: flex;
flex-direction: column;
gap: 0.375rem;
padding: 0.5rem;
border-radius: 0.625rem;
background: var(--color-surface, rgba(255, 255, 255, 0.04));
border: 1px solid var(--color-border, rgba(255, 255, 255, 0.1));
border-radius: 0.375rem;
border: 1px solid rgba(0, 0, 0, 0.08);
background: transparent;
}
:global(.dark) .quick-add-form {
border-color: rgba(255, 255, 255, 0.08);
}
.type-toggle {
.type-tabs {
display: flex;
gap: 0.25rem;
}
.type-btn {
.type-tab {
flex: 1;
padding: 0.3rem;
border-radius: 0.375rem;
padding: 0.25rem;
border-radius: 0.25rem;
font-size: 0.6875rem;
font-weight: 600;
background: transparent;
color: var(--color-muted-foreground);
border: 1px solid var(--color-border, rgba(255, 255, 255, 0.08));
color: #9ca3af;
border: 1px solid rgba(0, 0, 0, 0.06);
cursor: pointer;
transition: all 0.15s;
}
.type-btn.active {
background: rgba(239, 68, 68, 0.12);
color: #ef4444;
border-color: rgba(239, 68, 68, 0.25);
.type-tab:hover {
color: #374151;
background: rgba(0, 0, 0, 0.03);
}
.type-btn.inc.active {
background: rgba(34, 197, 94, 0.12);
.type-tab.active {
background: rgba(239, 68, 68, 0.08);
color: #ef4444;
border-color: rgba(239, 68, 68, 0.2);
}
.type-tab.inc.active {
background: rgba(34, 197, 94, 0.08);
color: #22c55e;
border-color: rgba(34, 197, 94, 0.25);
border-color: rgba(34, 197, 94, 0.2);
}
:global(.dark) .type-tab {
border-color: rgba(255, 255, 255, 0.06);
}
:global(.dark) .type-tab:hover {
color: #e5e7eb;
background: rgba(255, 255, 255, 0.04);
}
:global(.dark) .type-tab.active {
background: rgba(239, 68, 68, 0.12);
}
:global(.dark) .type-tab.inc.active {
background: rgba(34, 197, 94, 0.12);
}
.input-row {
@ -245,8 +258,8 @@
width: 4.5rem;
background: transparent;
border: none;
border-bottom: 2px solid var(--color-border, rgba(255, 255, 255, 0.15));
color: var(--color-foreground);
border-bottom: 1.5px solid rgba(0, 0, 0, 0.1);
color: #374151;
font-size: 1rem;
font-weight: 700;
padding: 0.25rem 0;
@ -256,15 +269,22 @@
flex-shrink: 0;
}
.amount-input:focus {
border-color: var(--color-primary, #6366f1);
border-color: #6366f1;
}
.amount-input::placeholder {
color: var(--color-muted-foreground);
color: #c0bfba;
font-weight: 400;
}
:global(.dark) .amount-input {
border-color: rgba(255, 255, 255, 0.12);
color: #f3f4f6;
}
:global(.dark) .amount-input::placeholder {
color: #4b5563;
}
.currency {
color: var(--color-muted-foreground);
.currency-label {
color: #9ca3af;
font-size: 0.8125rem;
flex-shrink: 0;
}
@ -273,109 +293,132 @@
flex: 1;
background: transparent;
border: none;
border-bottom: 2px solid var(--color-border, rgba(255, 255, 255, 0.15));
color: var(--color-foreground);
border-bottom: 1.5px solid rgba(0, 0, 0, 0.1);
color: #374151;
font-size: 0.8125rem;
padding: 0.25rem 0;
outline: none;
min-width: 0;
}
.desc-input:focus {
border-color: var(--color-primary, #6366f1);
border-color: #6366f1;
}
.desc-input::placeholder {
color: var(--color-muted-foreground);
color: #c0bfba;
}
:global(.dark) .desc-input {
border-color: rgba(255, 255, 255, 0.12);
color: #f3f4f6;
}
:global(.dark) .desc-input::placeholder {
color: #4b5563;
}
.submit-btn {
width: 1.75rem;
height: 1.75rem;
border-radius: 0.375rem;
background: var(--color-primary, #6366f1);
.add-btn {
width: 1.625rem;
height: 1.625rem;
border-radius: 0.25rem;
background: #6366f1;
color: white;
border: none;
font-size: 1rem;
font-size: 0.875rem;
font-weight: 500;
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
transition: filter 0.15s;
transition: background 0.15s;
}
.submit-btn:hover:not(:disabled) {
filter: brightness(1.1);
.add-btn:hover:not(:disabled) {
background: #5558e6;
}
.submit-btn:disabled {
opacity: 0.3;
.add-btn:disabled {
opacity: 0.25;
cursor: not-allowed;
}
.cat-row {
.cat-chips {
display: flex;
flex-wrap: wrap;
gap: 0.2rem;
gap: 0.1875rem;
}
.cat-chip {
padding: 0.2rem 0.4rem;
padding: 0.1875rem 0.375rem;
border-radius: 9999px;
font-size: 0.625rem;
background: rgba(255, 255, 255, 0.04);
border: 1px solid var(--color-border, rgba(255, 255, 255, 0.08));
color: var(--color-foreground);
background: transparent;
border: 1px solid rgba(0, 0, 0, 0.08);
color: #6b7280;
cursor: pointer;
transition: all 0.15s;
}
.cat-chip:hover {
background: rgba(255, 255, 255, 0.08);
background: rgba(0, 0, 0, 0.03);
color: #374151;
}
.cat-chip.selected {
border-color: var(--color-primary, #6366f1);
background: rgba(99, 102, 241, 0.12);
border-color: #6366f1;
background: rgba(99, 102, 241, 0.08);
color: #6366f1;
}
:global(.dark) .cat-chip {
border-color: rgba(255, 255, 255, 0.08);
color: #9ca3af;
}
:global(.dark) .cat-chip:hover {
background: rgba(255, 255, 255, 0.04);
color: #e5e7eb;
}
:global(.dark) .cat-chip.selected {
border-color: #6366f1;
background: rgba(99, 102, 241, 0.15);
color: #818cf8;
}
/* ── Summary ─────────────────────────────────── */
.month-summary {
.summary {
display: flex;
gap: 0.25rem;
}
.summary-item {
.summary-col {
flex: 1;
display: flex;
flex-direction: column;
align-items: center;
padding: 0.375rem 0.25rem;
border-radius: 0.5rem;
background: var(--color-surface, rgba(255, 255, 255, 0.04));
border: 1px solid var(--color-border, rgba(255, 255, 255, 0.06));
border-radius: 0.375rem;
background: rgba(0, 0, 0, 0.02);
}
:global(.dark) .summary-col {
background: rgba(255, 255, 255, 0.03);
}
.summary-value {
.s-value {
font-size: 0.75rem;
font-weight: 700;
font-variant-numeric: tabular-nums;
}
.summary-value.income {
.s-value.income {
color: #22c55e;
}
.summary-value.expense {
.s-value.expense {
color: #ef4444;
}
.summary-label {
.s-label {
font-size: 0.5625rem;
color: var(--color-muted-foreground);
color: #9ca3af;
text-transform: uppercase;
letter-spacing: 0.03em;
}
/* ── Transaction List ────────────────────────── */
.tx-list {
display: flex;
flex-direction: column;
gap: 0.125rem;
flex: 1;
overflow-y: auto;
}
.day-label {
@ -383,15 +426,16 @@
font-weight: 600;
text-transform: uppercase;
letter-spacing: 0.05em;
color: var(--color-muted-foreground);
padding: 0.25rem 0 0.125rem;
color: #9ca3af;
padding: 0.375rem 0 0.125rem;
}
.tx-row {
.tx-item {
display: flex;
align-items: center;
gap: 0.375rem;
padding: 0.25rem 0.125rem;
padding: 0.3rem 0.25rem;
border-radius: 0.25rem;
}
.tx-emoji {
@ -401,22 +445,24 @@
.tx-info {
flex: 1;
display: flex;
flex-direction: column;
min-width: 0;
}
.tx-desc {
font-size: 0.75rem;
color: var(--color-foreground);
color: #374151;
display: block;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
:global(.dark) .tx-desc {
color: #e5e7eb;
}
.tx-cat {
font-size: 0.625rem;
color: var(--color-muted-foreground);
color: #9ca3af;
}
.tx-amount {
@ -433,9 +479,9 @@
}
.empty {
padding: 2rem 0;
text-align: center;
color: var(--color-muted-foreground);
font-size: 0.8125rem;
padding: 1.5rem 0;
color: #9ca3af;
}
</style>

View file

@ -1,6 +1,6 @@
<!--
Notes — Workbench ListView
Compact single-line input at top, click any note to edit inline.
Single-line quick-create, click any note to edit inline.
-->
<script lang="ts">
import { useAllNotes, searchNotes, getPreview, formatRelativeTime } from './queries';
@ -21,13 +21,9 @@
});
let searchQuery = $state('');
// Inline editing — clicking a note opens it right there
let editingId = $state<string | null>(null);
let editTitle = $state('');
let editContent = $state('');
// Quick create — single input line
let newTitle = $state('');
let filtered = $derived(searchNotes(notes, searchQuery));
@ -37,15 +33,11 @@
e.preventDefault();
const note = await notesStore.createNote({ title: newTitle.trim() });
newTitle = '';
// Immediately open the new note for editing
startEdit(note);
}
function startEdit(note: Note) {
// Save previous edit if any
if (editingId && editingId !== note.id) {
saveEdit();
}
if (editingId && editingId !== note.id) saveEdit();
editingId = note.id;
editTitle = note.title;
editContent = note.content;
@ -60,12 +52,6 @@
editingId = null;
}
function handleEditKeydown(e: KeyboardEvent) {
if (e.key === 'Escape') {
saveEdit();
}
}
async function handleDelete(id: string) {
await notesStore.deleteNote(id);
if (editingId === id) editingId = null;
@ -77,30 +63,35 @@
}
</script>
<div class="notes-lv">
<!-- Quick create input -->
<div class="quick-create">
<span class="create-icon">+</span>
<div class="app-view">
<!-- Quick create -->
<form onsubmit={(e) => e.preventDefault()} class="quick-add">
<span class="add-icon">+</span>
<input
class="create-input"
class="add-input"
type="text"
placeholder="Neue Notiz... (Enter)"
bind:value={newTitle}
onkeydown={handleQuickCreate}
/>
</div>
</form>
<!-- Search (only when many notes) -->
<!-- Search -->
{#if notes.length > 5}
<input class="search" type="text" placeholder="Suchen..." bind:value={searchQuery} />
<input class="search-input" type="text" placeholder="Suchen..." bind:value={searchQuery} />
{/if}
<!-- Note List -->
<div class="list">
<!-- Note list -->
<div class="note-list">
{#each filtered as note (note.id)}
{#if editingId === note.id}
<!-- Inline editor -->
<div class="card editing" onkeydown={handleEditKeydown}>
<div
class="note-item editing"
onkeydown={(e) => {
if (e.key === 'Escape') saveEdit();
}}
>
<input
class="ed-title"
type="text"
@ -110,189 +101,241 @@
/>
<textarea class="ed-content" bind:value={editContent} placeholder="Inhalt..." rows="4"
></textarea>
<div class="ed-footer">
<button class="ed-action danger" onclick={() => handleDelete(note.id)}>Löschen</button>
<button class="ed-action" onclick={() => handleTogglePin(new Event('click'), note.id)}>
<div class="ed-actions">
<button class="ed-btn danger" onclick={() => handleDelete(note.id)}>Löschen</button>
<button class="ed-btn" onclick={() => handleTogglePin(new Event('click'), note.id)}>
{note.isPinned ? 'Lösen' : 'Pinnen'}
</button>
<button class="ed-action primary" onclick={saveEdit}>Fertig</button>
<button class="ed-btn primary" onclick={saveEdit}>Fertig</button>
</div>
</div>
{:else}
<!-- Note row -->
<button
class="card"
class:pinned={note.isPinned}
style:border-left-color={note.color ?? 'transparent'}
onclick={() => startEdit(note)}
>
<div class="card-top">
<span class="card-title">{note.title || 'Unbenannt'}</span>
{#if note.isPinned}<span class="pin">&#x1f4cc;</span>{/if}
</div>
{#if note.content}
<div class="card-preview">{getPreview(note.content, 60)}</div>
<button class="note-item" onclick={() => startEdit(note)}>
{#if note.color}
<span class="color-dot" style="background: {note.color}"></span>
{/if}
<div class="card-meta">{formatRelativeTime(note.updatedAt)}</div>
<div class="note-content">
<div class="note-top">
<span class="note-title">{note.title || 'Unbenannt'}</span>
{#if note.isPinned}<span class="pin">&#x1f4cc;</span>{/if}
</div>
{#if note.content}
<p class="note-preview">{getPreview(note.content, 60)}</p>
{/if}
<span class="note-meta">{formatRelativeTime(note.updatedAt)}</span>
</div>
</button>
{/if}
{/each}
{#if filtered.length === 0 && notes.length > 0}
<p class="empty">Keine Treffer</p>
{/if}
</div>
{#if notes.length === 0}
<div class="empty">Tippe oben, um eine Notiz zu erstellen.</div>
<p class="empty">Tippe oben, um eine Notiz zu erstellen.</p>
{/if}
</div>
<style>
.notes-lv {
.app-view {
display: flex;
flex-direction: column;
gap: 0.375rem;
padding: 0.5rem;
gap: 0.625rem;
padding: 1rem;
height: 100%;
}
/* ── Quick Create ──────────────────────────── */
.quick-create {
/* ── Quick Add (matches todo pattern) ────────── */
.quick-add {
display: flex;
align-items: center;
gap: 0.375rem;
gap: 0.5rem;
padding: 0.375rem 0.5rem;
border-radius: 0.5rem;
background: var(--color-surface, rgba(255, 255, 255, 0.04));
border: 1px solid var(--color-border, rgba(255, 255, 255, 0.1));
transition: border-color 0.15s;
border-radius: 0.375rem;
border: 1px solid rgba(0, 0, 0, 0.08);
background: transparent;
}
.quick-create:focus-within {
border-color: var(--color-primary, #6366f1);
:global(.dark) .quick-add {
border-color: rgba(255, 255, 255, 0.08);
}
.create-icon {
color: var(--color-muted-foreground);
.add-icon {
color: #d1d5db;
font-size: 0.875rem;
font-weight: 500;
flex-shrink: 0;
opacity: 0.5;
display: flex;
align-items: center;
}
:global(.dark) .add-icon {
color: #4b5563;
}
.create-input {
.add-input {
flex: 1;
background: transparent;
border: none;
color: var(--color-foreground);
font-size: 0.8125rem;
background: transparent;
outline: none;
padding: 0;
font-size: 0.8125rem;
color: #374151;
}
.create-input::placeholder {
color: var(--color-muted-foreground);
.add-input::placeholder {
color: #c0bfba;
}
:global(.dark) .add-input {
color: #f3f4f6;
}
:global(.dark) .add-input::placeholder {
color: #4b5563;
}
/* ── Search ─────────────────────────────────── */
.search {
background: var(--color-surface, rgba(255, 255, 255, 0.04));
border: 1px solid var(--color-border, rgba(255, 255, 255, 0.08));
border-radius: 0.375rem;
color: var(--color-foreground);
font-size: 0.75rem;
.search-input {
padding: 0.3rem 0.5rem;
border-radius: 0.375rem;
border: 1px solid rgba(0, 0, 0, 0.08);
background: transparent;
font-size: 0.75rem;
color: #374151;
outline: none;
}
.search:focus {
border-color: var(--color-primary, #6366f1);
.search-input:focus {
border-color: #6366f1;
}
.search::placeholder {
color: var(--color-muted-foreground);
.search-input::placeholder {
color: #c0bfba;
}
:global(.dark) .search-input {
border-color: rgba(255, 255, 255, 0.08);
color: #f3f4f6;
}
:global(.dark) .search-input::placeholder {
color: #4b5563;
}
/* ── Note Cards ─────────────────────────────── */
.list {
display: flex;
flex-direction: column;
gap: 0.1875rem;
/* ── Note List ──────────────────────────────── */
.note-list {
flex: 1;
overflow-y: auto;
}
.card {
.note-item {
display: flex;
flex-direction: column;
gap: 0.0625rem;
padding: 0.375rem 0.5rem;
border-radius: 0.375rem;
background: var(--color-surface, rgba(255, 255, 255, 0.03));
border: 1px solid transparent;
border-left: 3px solid transparent;
cursor: pointer;
text-align: left;
align-items: flex-start;
gap: 0.5rem;
width: 100%;
transition: background 0.12s;
padding: 0.375rem 0.25rem;
border: none;
background: transparent;
text-align: left;
border-radius: 0.25rem;
cursor: pointer;
transition: background 0.15s;
}
.card:hover {
background: var(--color-muted, rgba(255, 255, 255, 0.06));
.note-item:hover {
background: rgba(0, 0, 0, 0.03);
}
.card.pinned {
background: rgba(99, 102, 241, 0.04);
:global(.dark) .note-item:hover {
background: rgba(255, 255, 255, 0.04);
}
.card-top {
.color-dot {
width: 6px;
height: 6px;
border-radius: 9999px;
flex-shrink: 0;
margin-top: 0.375rem;
}
.note-content {
min-width: 0;
flex: 1;
}
.note-top {
display: flex;
align-items: center;
gap: 0.25rem;
}
.card-title {
.note-title {
font-size: 0.8125rem;
font-weight: 600;
color: var(--color-foreground);
flex: 1;
font-weight: 500;
color: #374151;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
flex: 1;
}
:global(.dark) .note-title {
color: #e5e7eb;
}
.pin {
font-size: 0.625rem;
font-size: 0.5625rem;
flex-shrink: 0;
}
.card-preview {
.note-preview {
font-size: 0.6875rem;
color: var(--color-muted-foreground);
color: #9ca3af;
margin: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.card-meta {
.note-meta {
font-size: 0.625rem;
color: var(--color-muted-foreground);
opacity: 0.6;
color: #c0bfba;
}
:global(.dark) .note-meta {
color: #4b5563;
}
/* ── Inline Editor ──────────────────────────── */
.card.editing {
.note-item.editing {
cursor: default;
background: var(--color-surface, rgba(255, 255, 255, 0.06));
border: 1px solid var(--color-primary, #6366f1);
border-left: 3px solid var(--color-primary, #6366f1);
padding: 0.5rem;
flex-direction: column;
gap: 0.25rem;
padding: 0.5rem;
border: 1px solid rgba(99, 102, 241, 0.3);
border-radius: 0.375rem;
background: rgba(99, 102, 241, 0.03);
}
.note-item.editing:hover {
background: rgba(99, 102, 241, 0.03);
}
:global(.dark) .note-item.editing {
border-color: rgba(99, 102, 241, 0.4);
background: rgba(99, 102, 241, 0.06);
}
.ed-title {
width: 100%;
background: transparent;
border: none;
color: var(--color-foreground);
font-size: 0.875rem;
color: #374151;
font-size: 0.8125rem;
font-weight: 600;
padding: 0;
outline: none;
}
.ed-title::placeholder {
color: var(--color-muted-foreground);
color: #c0bfba;
}
:global(.dark) .ed-title {
color: #f3f4f6;
}
.ed-content {
width: 100%;
background: transparent;
border: none;
color: var(--color-foreground);
font-size: 0.8125rem;
color: #374151;
font-size: 0.75rem;
padding: 0;
outline: none;
resize: vertical;
@ -301,17 +344,20 @@
line-height: 1.5;
}
.ed-content::placeholder {
color: var(--color-muted-foreground);
color: #c0bfba;
}
:global(.dark) .ed-content {
color: #e5e7eb;
}
.ed-footer {
.ed-actions {
display: flex;
gap: 0.25rem;
justify-content: flex-end;
padding-top: 0.25rem;
padding-top: 0.125rem;
}
.ed-action {
.ed-btn {
padding: 0.25rem 0.5rem;
border-radius: 0.25rem;
font-size: 0.6875rem;
@ -319,29 +365,35 @@
cursor: pointer;
border: none;
background: transparent;
color: var(--color-muted-foreground);
transition: all 0.12s;
color: #9ca3af;
transition: all 0.15s;
}
.ed-action:hover {
background: var(--color-muted, rgba(255, 255, 255, 0.08));
.ed-btn:hover {
background: rgba(0, 0, 0, 0.04);
color: #374151;
}
.ed-action.primary {
background: var(--color-primary, #6366f1);
:global(.dark) .ed-btn:hover {
background: rgba(255, 255, 255, 0.06);
color: #e5e7eb;
}
.ed-btn.primary {
background: #6366f1;
color: white;
}
.ed-action.primary:hover {
filter: brightness(1.1);
.ed-btn.primary:hover {
background: #5558e6;
}
.ed-action.danger:hover {
color: var(--color-destructive, #ef4444);
background: rgba(239, 68, 68, 0.1);
.ed-btn.danger:hover {
color: #ef4444;
background: rgba(239, 68, 68, 0.08);
}
.empty {
padding: 2rem 0;
text-align: center;
color: var(--color-muted-foreground);
font-size: 0.75rem;
padding: 1.5rem 0;
opacity: 0.7;
font-size: 0.8125rem;
color: #9ca3af;
}
</style>