refactor(themes): align installed cards with the workshop layout

Installed theme cards now use the same visual hierarchy as workshop cards: status and API badges at the top, version on the preview, an author strip over the artwork, a compact title and description, and a footer with status plus compact actions. This removes the oversized primary button and duplicate version/author rows.
This commit is contained in:
HorizonCode committed 2026-11-03 23:13:44 +01:00
1 parent 47c022642f
commit 760bd9a283
1 file changed
+67 -37
+67 -37
View File
@@ -4012,17 +4012,37 @@
<div
class="pointer-events-none absolute inset-0 bg-gradient-to-t from-theme-950/75 via-transparent to-transparent"
></div>
<div
class="absolute top-1.5 left-1.5 flex max-w-[calc(100%-4.5rem)] flex-wrap items-center gap-1"
>
{#if isActive}
<Badge class="absolute top-1.5 left-1.5 text-[9px]">In use</Badge>
<Badge class="text-[9px]">In use</Badge>
{/if}
{#if theme.name !== 'Default' && theme.folder_name !== 'default' && theme.apiVersion}
<Badge
variant="secondary"
class="absolute top-1.5 right-1.5 bg-black/50 px-1.5 py-0 text-[9px] backdrop-blur-sm"
class="bg-black/50 px-1.5 py-0 text-[9px] backdrop-blur-sm"
>
API {theme.apiVersion.startsWith('2') ? '2.0' : '1.0'}
</Badge>
{/if}
</div>
<div class="absolute top-1.5 right-1.5 flex items-center gap-1">
{#if theme.nsfw}
<Badge
variant="destructive"
class="px-1.5 py-0 text-[9px]"
title="Adult content"
>
18+
</Badge>
{/if}
<span
class="rounded-md bg-black/60 px-1.5 py-0.5 text-[9px] font-medium text-white/90 backdrop-blur-sm"
>
v{theme.version}
</span>
</div>
{#if theme.nsfw && !revealedNsfw.includes(theme.name)}
<button
type="button"
@@ -4038,56 +4058,65 @@
{:else if theme.nsfw}
<button
type="button"
class="absolute bottom-1.5 left-1.5 z-10 flex items-center gap-1 rounded-full bg-black/60 px-1.5 py-0.5 text-[8px] font-medium text-white/80 backdrop-blur-sm hover:bg-black/75 hover:text-white"
class="absolute right-1.5 bottom-10 z-10 flex items-center gap-1 rounded-full bg-black/60 px-1.5 py-0.5 text-[8px] font-medium text-white/80 backdrop-blur-sm hover:bg-black/75 hover:text-white"
onclick={() => toggleNsfwPreview(theme.name)}
>
<ThemeIcon name="eye-off" set={iconSet} class="size-3" />
Hide preview
</button>
{/if}
{#if theme.nsfw}
<Badge
variant="destructive"
class="absolute right-1.5 bottom-1.5 px-1.5 py-0 text-[9px]"
title="Adult content"
<div
class="absolute right-2 bottom-2 left-2 flex items-center justify-between gap-2"
>
18+
</Badge>
{/if}
</div>
<div class="flex flex-1 flex-col gap-1.5 p-2.5">
<div class="flex items-start justify-between gap-1.5">
<div class="min-w-0">
<div class="flex min-w-0 items-center gap-1.5">
<span
class="block truncate text-[13px] leading-tight font-semibold"
class="flex size-5 shrink-0 items-center justify-center rounded-full border border-white/20 bg-theme-800 text-[9px] font-bold text-white/80 uppercase"
>
{theme.author.trim().charAt(0) || '?'}
</span>
<span
class="truncate text-[11px] font-semibold text-white/95 drop-shadow-sm"
>
{theme.author || 'Unknown author'}
</span>
</div>
<span
class="shrink-0 text-[9px] {theme.updateAvailable
? 'text-primary'
: 'text-muted-foreground/90'}"
>
{theme.updateAvailable ? 'Update available' : 'Installed'}
</span>
</div>
</div>
<div class="flex flex-1 flex-col gap-2 p-3">
<h3 class="truncate text-[13px] font-bold text-theme-50">
{theme.name}
</span>
<span
class="mt-0.5 block truncate text-[10px] text-muted-foreground"
>
by {theme.author}
</span>
</div>
<span
class="shrink-0 rounded-full bg-theme-800/50 px-1.5 py-0.5 text-[9px] whitespace-nowrap tabular-nums text-muted-foreground"
>
{#if theme.updateAvailable && theme.availableVersion}
v{theme.version} <span class="text-primary">→</span>
v{theme.availableVersion}
{:else}
v{theme.version}
{/if}
</span>
</div>
</h3>
{#if theme.description}
<p
class="min-h-8 line-clamp-2 text-[10px] leading-snug text-muted-foreground"
class="line-clamp-2 text-[10px] leading-relaxed text-muted-foreground"
>
{theme.description}
</p>
<div class="mt-auto flex items-center gap-1 pt-0.5">
{/if}
<div
class="mt-auto flex items-center justify-between gap-2 border-t border-theme-800/40 pt-2.5"
>
<span class="min-w-0 truncate text-[9px] text-muted-foreground">
{#if theme.updateAvailable && theme.availableVersion}
<span class="text-primary"
>v{theme.availableVersion} available</span
>
{:else if isActive}
Active theme
{:else}
Installed
{/if}
</span>
<div class="flex shrink-0 items-center gap-1">
<Button
class="relative h-8 min-w-0 flex-1 overflow-hidden px-2 text-xs {theme.status ===
class="relative h-7 min-w-0 max-w-44 overflow-hidden px-2.5 text-xs {theme.status ===
'downloading' || theme.status === 'extracting'
? 'disabled:bg-primary disabled:opacity-100'
: ''}"
@@ -4229,6 +4258,7 @@
</div>
</div>
</div>
</div>
{/each}
</div>
{/key}