mirror of
https://github.com/Memo-2023/mana-monorepo.git
synced 2026-05-14 23:21:08 +02:00
style(mana/web): migrate photos/times/contacts module helpers to theme tokens (P5)
photos/PhotoCard + PhotoDetailModal: bare var() refs → hsl(var()), broken fallbacks dropped. The lightbox backdrop stays explicit near-black — photo viewing chrome is intentionally theme-neutral. times/FocusCard: phase color (focus=red, break=green, idle=muted) reads theme tokens via wrapped hsl() strings so the SVG ring tracks variants. The bogus --color-input fallback is gone. times/EntryItem: was referencing the long-removed shadcn aliases without the --color- prefix (--border, --card, --foreground, --muted-foreground, --primary, --input). Re-prefixed; --input → --background since we have no separate input token. The delete button's text-red-500 / hover bg are now --color-error so they track theme variants. contacts/ContactPage: avatar + self-badge color-mix fallback chains collapse to plain hsl(var(--color-primary) / 0.12). The cycles pink #ec4899 birthday accent on the contact row stays literal — it's a deliberate brand color, not theme intent. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
d2e44c8b65
commit
a7fbd29a67
5 changed files with 58 additions and 53 deletions
|
|
@ -422,8 +422,8 @@
|
|||
width: 2rem;
|
||||
height: 2rem;
|
||||
border-radius: 9999px;
|
||||
background: color-mix(in srgb, var(--color-primary, #8b5cf6) 12%, transparent);
|
||||
color: var(--color-primary, #8b5cf6);
|
||||
background: hsl(var(--color-primary) / 0.12);
|
||||
color: hsl(var(--color-primary));
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
|
@ -499,8 +499,8 @@
|
|||
font-weight: 600;
|
||||
padding: 0.0625rem 0.375rem;
|
||||
border-radius: 9999px;
|
||||
background: color-mix(in srgb, var(--color-primary, #8b5cf6) 12%, transparent);
|
||||
color: var(--color-primary, #8b5cf6);
|
||||
background: hsl(var(--color-primary) / 0.12);
|
||||
color: hsl(var(--color-primary));
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
|
|
@ -521,8 +521,8 @@
|
|||
width: 4.5rem;
|
||||
height: 4.5rem;
|
||||
border-radius: 9999px;
|
||||
background: color-mix(in srgb, var(--color-primary, #8b5cf6) 12%, transparent);
|
||||
color: var(--color-primary, #8b5cf6);
|
||||
background: hsl(var(--color-primary) / 0.12);
|
||||
color: hsl(var(--color-primary));
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
|
|
|
|||
|
|
@ -64,8 +64,8 @@
|
|||
position: relative;
|
||||
aspect-ratio: 1;
|
||||
overflow: hidden;
|
||||
border-radius: var(--radius-md, 0.5rem);
|
||||
background-color: var(--color-muted, #f1f5f9);
|
||||
border-radius: 0.5rem;
|
||||
background-color: hsl(var(--color-muted));
|
||||
cursor: pointer;
|
||||
border: none;
|
||||
padding: 0;
|
||||
|
|
@ -76,18 +76,14 @@
|
|||
|
||||
.photo-card:hover {
|
||||
transform: scale(1.02);
|
||||
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.2);
|
||||
box-shadow: 0 10px 20px hsl(0 0% 0% / 0.2);
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.placeholder {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: linear-gradient(
|
||||
135deg,
|
||||
var(--color-muted, #f1f5f9) 0%,
|
||||
var(--color-accent, #e2e8f0) 100%
|
||||
);
|
||||
background: linear-gradient(135deg, hsl(var(--color-muted)) 0%, hsl(var(--color-accent)) 100%);
|
||||
animation: pulse 2s ease-in-out infinite;
|
||||
}
|
||||
|
||||
|
|
@ -119,13 +115,13 @@
|
|||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: var(--color-muted-foreground, #64748b);
|
||||
color: hsl(var(--color-muted-foreground));
|
||||
}
|
||||
|
||||
.photo-overlay {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
background: linear-gradient(to top, rgba(0, 0, 0, 0.5) 0%, transparent 40%);
|
||||
background: linear-gradient(to top, hsl(0 0% 0% / 0.5) 0%, transparent 40%);
|
||||
opacity: 0;
|
||||
transition: opacity 150ms;
|
||||
display: flex;
|
||||
|
|
@ -141,8 +137,8 @@
|
|||
.favorite-btn {
|
||||
padding: 0.5rem;
|
||||
border-radius: 50%;
|
||||
background: rgba(255, 255, 255, 0.9);
|
||||
color: var(--color-muted-foreground, #64748b);
|
||||
background: hsl(0 0% 100% / 0.9);
|
||||
color: hsl(var(--color-muted-foreground));
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
transition: all 150ms;
|
||||
|
|
@ -152,6 +148,6 @@
|
|||
transform: scale(1.1);
|
||||
}
|
||||
.favorite-btn.favorited {
|
||||
color: #ef4444;
|
||||
color: hsl(var(--color-error));
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -157,10 +157,12 @@
|
|||
</div>
|
||||
|
||||
<style>
|
||||
/* Lightbox backdrop is intentionally near-black regardless of theme — photos
|
||||
need a neutral viewing chrome. */
|
||||
.lightbox-backdrop {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
background: rgba(0, 0, 0, 0.95);
|
||||
background: hsl(0 0% 0% / 0.95);
|
||||
z-index: 50;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
|
@ -180,7 +182,7 @@
|
|||
left: 1rem;
|
||||
padding: 0.5rem;
|
||||
border-radius: 50%;
|
||||
background: rgba(255, 255, 255, 0.1);
|
||||
background: hsl(0 0% 100% / 0.1);
|
||||
color: white;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
|
|
@ -189,7 +191,7 @@
|
|||
}
|
||||
|
||||
.close-btn:hover {
|
||||
background: rgba(255, 255, 255, 0.2);
|
||||
background: hsl(0 0% 100% / 0.2);
|
||||
}
|
||||
|
||||
.lightbox-main {
|
||||
|
|
@ -208,8 +210,8 @@
|
|||
|
||||
.info-panel {
|
||||
width: 320px;
|
||||
background: var(--color-card, #ffffff);
|
||||
color: var(--color-foreground, #0f172a);
|
||||
background: hsl(var(--color-card));
|
||||
color: hsl(var(--color-foreground));
|
||||
overflow-y: auto;
|
||||
padding: 1.5rem;
|
||||
}
|
||||
|
|
@ -220,7 +222,7 @@
|
|||
align-items: center;
|
||||
margin-bottom: 1.5rem;
|
||||
padding-bottom: 1rem;
|
||||
border-bottom: 1px solid var(--color-border, #e2e8f0);
|
||||
border-bottom: 1px solid hsl(var(--color-border));
|
||||
}
|
||||
|
||||
.info-actions {
|
||||
|
|
@ -235,10 +237,10 @@
|
|||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
padding: 0.75rem 1rem;
|
||||
border: 1px solid var(--color-border, #e2e8f0);
|
||||
border: 1px solid hsl(var(--color-border));
|
||||
border-radius: 0.5rem;
|
||||
background: var(--color-background, #ffffff);
|
||||
color: var(--color-foreground, #0f172a);
|
||||
background: hsl(var(--color-background));
|
||||
color: hsl(var(--color-foreground));
|
||||
cursor: pointer;
|
||||
transition: all 150ms;
|
||||
text-decoration: none;
|
||||
|
|
@ -246,11 +248,11 @@
|
|||
}
|
||||
|
||||
.action-btn:hover {
|
||||
background: var(--color-accent, #f1f5f9);
|
||||
background: hsl(var(--color-accent));
|
||||
}
|
||||
.action-btn.favorited {
|
||||
color: #ef4444;
|
||||
border-color: #ef4444;
|
||||
color: hsl(var(--color-error));
|
||||
border-color: hsl(var(--color-error));
|
||||
}
|
||||
|
||||
.info-section {
|
||||
|
|
@ -259,7 +261,7 @@
|
|||
|
||||
.info-label {
|
||||
font-size: 0.75rem;
|
||||
color: var(--color-muted-foreground, #64748b);
|
||||
color: hsl(var(--color-muted-foreground));
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 0.05em;
|
||||
margin-bottom: 0.25rem;
|
||||
|
|
@ -273,7 +275,7 @@
|
|||
padding: 0.25rem;
|
||||
border-radius: 50%;
|
||||
background: transparent;
|
||||
color: var(--color-foreground, #0f172a);
|
||||
color: hsl(var(--color-foreground));
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -103,8 +103,8 @@
|
|||
</script>
|
||||
|
||||
<div
|
||||
class="entry-item rounded-xl border border-[hsl(var(--border))] bg-[hsl(var(--card))] transition-all {isExpanded
|
||||
? 'ring-1 ring-[hsl(var(--primary)/0.3)]'
|
||||
class="entry-item rounded-xl border border-[hsl(var(--color-border))] bg-[hsl(var(--color-card))] transition-all {isExpanded
|
||||
? 'ring-1 ring-[hsl(var(--color-primary)/0.3)]'
|
||||
: ''}"
|
||||
>
|
||||
<!-- Compact row (always visible) -->
|
||||
|
|
@ -115,13 +115,13 @@
|
|||
{#if project}
|
||||
<div class="project-dot" style="background-color: {project.color}"></div>
|
||||
{:else}
|
||||
<div class="project-dot" style="background-color: #9ca3af"></div>
|
||||
<div class="project-dot" style="background-color: hsl(var(--color-muted-foreground))"></div>
|
||||
{/if}
|
||||
<div class="min-w-0 flex-1">
|
||||
<p class="truncate text-sm font-medium text-[hsl(var(--foreground))]">
|
||||
<p class="truncate text-sm font-medium text-[hsl(var(--color-foreground))]">
|
||||
{entry.description || $_('timer.noDescription')}
|
||||
</p>
|
||||
<p class="text-xs text-[hsl(var(--muted-foreground))]">
|
||||
<p class="text-xs text-[hsl(var(--color-muted-foreground))]">
|
||||
{project?.name || $_('project.internal')}
|
||||
{#if client}· {client.name}{/if}
|
||||
{#if startTimeStr && endTimeStr}
|
||||
|
|
@ -130,25 +130,25 @@
|
|||
</p>
|
||||
</div>
|
||||
<div class="text-right shrink-0">
|
||||
<p class="duration-display text-sm font-medium text-[hsl(var(--foreground))]">
|
||||
<p class="duration-display text-sm font-medium text-[hsl(var(--color-foreground))]">
|
||||
{formatDurationCompact(entry.duration)}
|
||||
</p>
|
||||
{#if entry.isBillable}
|
||||
<span class="text-xs text-[hsl(var(--primary))]">$</span>
|
||||
<span class="text-xs text-[hsl(var(--color-primary))]">$</span>
|
||||
{/if}
|
||||
</div>
|
||||
</button>
|
||||
|
||||
<!-- Expanded edit form -->
|
||||
{#if isExpanded}
|
||||
<div class="border-t border-[hsl(var(--border))] px-4 py-3 space-y-3">
|
||||
<div class="border-t border-[hsl(var(--color-border))] px-4 py-3 space-y-3">
|
||||
<!-- Description -->
|
||||
<input
|
||||
type="text"
|
||||
value={editDescription}
|
||||
oninput={(e) => handleDescriptionChange((e.target as HTMLInputElement).value)}
|
||||
placeholder={$_('entry.description')}
|
||||
class="w-full rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--input))] px-3 py-2 text-sm text-[hsl(var(--foreground))] focus:border-[hsl(var(--primary))] focus:outline-none"
|
||||
class="w-full rounded-lg border border-[hsl(var(--color-border))] bg-[hsl(var(--color-background))] px-3 py-2 text-sm text-[hsl(var(--color-foreground))] focus:border-[hsl(var(--color-primary))] focus:outline-none"
|
||||
/>
|
||||
|
||||
<!-- Project + Duration row -->
|
||||
|
|
@ -156,7 +156,7 @@
|
|||
<select
|
||||
value={editProjectId}
|
||||
onchange={(e) => handleProjectChange((e.target as HTMLSelectElement).value)}
|
||||
class="flex-1 rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--input))] px-3 py-2 text-sm text-[hsl(var(--foreground))]"
|
||||
class="flex-1 rounded-lg border border-[hsl(var(--color-border))] bg-[hsl(var(--color-background))] px-3 py-2 text-sm text-[hsl(var(--color-foreground))]"
|
||||
>
|
||||
<option value="">{$_('project.internal')}</option>
|
||||
{#each allProjects.value.filter((p) => !p.isArchived) as proj}
|
||||
|
|
@ -171,9 +171,9 @@
|
|||
oninput={(e) =>
|
||||
handleDurationChange(parseInt((e.target as HTMLInputElement).value) || 0)}
|
||||
min="0"
|
||||
class="w-20 rounded-lg border border-[hsl(var(--border))] bg-[hsl(var(--input))] px-3 py-2 text-center text-sm text-[hsl(var(--foreground))]"
|
||||
class="w-20 rounded-lg border border-[hsl(var(--color-border))] bg-[hsl(var(--color-background))] px-3 py-2 text-center text-sm text-[hsl(var(--color-foreground))]"
|
||||
/>
|
||||
<span class="text-xs text-[hsl(var(--muted-foreground))]">min</span>
|
||||
<span class="text-xs text-[hsl(var(--color-muted-foreground))]">min</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
@ -182,8 +182,8 @@
|
|||
<button
|
||||
onclick={handleBillableToggle}
|
||||
class="flex items-center gap-2 rounded-lg px-3 py-1.5 text-xs transition-colors {editIsBillable
|
||||
? 'bg-[hsl(var(--primary)/0.1)] text-[hsl(var(--primary))]'
|
||||
: 'text-[hsl(var(--muted-foreground))] hover:text-[hsl(var(--foreground))]'}"
|
||||
? 'bg-[hsl(var(--color-primary)/0.1)] text-[hsl(var(--color-primary))]'
|
||||
: 'text-[hsl(var(--color-muted-foreground))] hover:text-[hsl(var(--color-foreground))]'}"
|
||||
>
|
||||
<CurrencyDollar size={14} />
|
||||
{editIsBillable ? $_('entry.billable') : $_('entry.notBillable')}
|
||||
|
|
@ -191,7 +191,7 @@
|
|||
|
||||
<button
|
||||
onclick={handleDelete}
|
||||
class="rounded-lg px-3 py-1.5 text-xs text-red-500 transition-colors hover:bg-red-500/10"
|
||||
class="rounded-lg px-3 py-1.5 text-xs text-[hsl(var(--color-error))] transition-colors hover:bg-[hsl(var(--color-error)/0.1)]"
|
||||
>
|
||||
{$_('common.delete')}
|
||||
</button>
|
||||
|
|
|
|||
|
|
@ -32,8 +32,15 @@
|
|||
focusStore.phase === 'focus' ? 'Fokus' : focusStore.phase === 'break' ? 'Pause' : 'Bereit'
|
||||
);
|
||||
|
||||
// Focus = error/red, break = success/green, idle = muted — read from theme tokens
|
||||
// so the ring tracks light/dark + variants. SVG strokes need a real color value,
|
||||
// so we wrap with hsl().
|
||||
const phaseColor = $derived(
|
||||
focusStore.phase === 'focus' ? '#ef4444' : focusStore.phase === 'break' ? '#22c55e' : '#6b7280'
|
||||
focusStore.phase === 'focus'
|
||||
? 'hsl(var(--color-error))'
|
||||
: focusStore.phase === 'break'
|
||||
? 'hsl(var(--color-success))'
|
||||
: 'hsl(var(--color-muted-foreground))'
|
||||
);
|
||||
|
||||
// SVG ring
|
||||
|
|
@ -179,7 +186,7 @@
|
|||
padding: 0.625rem 0.75rem;
|
||||
border: 1px solid hsl(var(--color-border));
|
||||
border-radius: 0.5rem;
|
||||
background: hsl(var(--color-input, var(--color-background)));
|
||||
background: hsl(var(--color-background));
|
||||
color: hsl(var(--color-foreground));
|
||||
font-size: 0.875rem;
|
||||
outline: none;
|
||||
|
|
@ -206,7 +213,7 @@
|
|||
padding: 0.625rem;
|
||||
border: none;
|
||||
border-radius: 0.75rem;
|
||||
background: #ef4444;
|
||||
background: hsl(var(--color-error));
|
||||
color: white;
|
||||
font-size: 0.9375rem;
|
||||
font-weight: 600;
|
||||
|
|
@ -322,8 +329,8 @@
|
|||
opacity: 0.9;
|
||||
}
|
||||
.control-btn.danger:hover {
|
||||
color: #ef4444;
|
||||
border-color: #ef4444;
|
||||
color: hsl(var(--color-error));
|
||||
border-color: hsl(var(--color-error));
|
||||
}
|
||||
|
||||
/* Compact mode */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue