1
0
forked from wrenn/wrenn

Polish dashboard frontend: spacing, copy, resilience

- Increase content padding (p-7→p-8) and table cell padding (px-4→px-5,
  py-3→py-4 for data rows) across capsules, keys, and snapshots pages
- Improve animation performance: wrenn-glow uses opacity instead of
  box-shadow (compositor-only, no paint cost)
- Add prefers-reduced-motion media query covering inline style animations
- Fix OAuth error display on login page (read ?error= param on mount)
- Harden clipboard copy with try-catch and toast fallback
- Improve empty state copy, dialog microcopy, and error messages
- Add retry button to error banners on keys page
- Replace "All systems operational" footer bar with a clean 1px divider
- Fix text truncation on long capsule/snapshot names (min-w-0 + truncate)
This commit is contained in:
2026-03-24 12:33:18 +06:00
parent 71564b202e
commit b786a825d4
9 changed files with 304 additions and 256 deletions

View File

@ -61,12 +61,12 @@
<!-- Header -->
<div class="mb-7">
<Dialog.Title
class="font-serif text-[24px] tracking-[-0.02em] text-[var(--color-text-bright)]"
class="font-serif text-page tracking-[-0.02em] text-[var(--color-text-bright)]"
>
{title}
</Dialog.Title>
<Dialog.Description
class="mt-1 text-[13px] text-[var(--color-text-secondary)]"
class="mt-1 text-ui text-[var(--color-text-secondary)]"
>
{subtitle}
</Dialog.Description>
@ -75,7 +75,7 @@
<!-- GitHub OAuth -->
<button
type="button"
class="flex w-full items-center justify-center gap-2.5 rounded-[var(--radius-button)] border border-[var(--color-border-mid)] bg-[var(--color-bg-2)] px-4 py-2.5 text-[13px] font-medium text-[var(--color-text-bright)] transition-all duration-150 hover:border-[var(--color-accent)] hover:text-[var(--color-text-bright)]"
class="flex w-full items-center justify-center gap-2.5 rounded-[var(--radius-button)] border border-[var(--color-border-mid)] bg-[var(--color-bg-2)] px-4 py-2.5 text-ui font-medium text-[var(--color-text-bright)] transition-all duration-150 hover:border-[var(--color-accent)] hover:text-[var(--color-text-bright)]"
>
<IconGithub size={16} />
Continue with GitHub
@ -85,7 +85,7 @@
<div class="my-5 flex items-center gap-3">
<div class="h-px flex-1 bg-[var(--color-border)]"></div>
<span
class="font-mono text-[10px] uppercase tracking-[0.1em] text-[var(--color-text-muted)]"
class="font-mono text-badge uppercase tracking-[0.1em] text-[var(--color-text-muted)]"
>or</span
>
<div class="h-px flex-1 bg-[var(--color-border)]"></div>
@ -105,7 +105,7 @@
bind:value={name}
placeholder="Full name"
autocomplete="name"
class="w-full rounded-[var(--radius-input)] border border-[var(--color-border)] bg-[var(--color-bg-2)] py-2.5 pl-9 pr-3 text-[13px] text-[var(--color-text-bright)] outline-none transition-all duration-150 placeholder:text-[var(--color-text-muted)] focus:border-[var(--color-accent)]"
class="w-full rounded-[var(--radius-input)] border border-[var(--color-border)] bg-[var(--color-bg-2)] py-2.5 pl-9 pr-3 text-ui text-[var(--color-text-bright)] outline-none transition-all duration-150 placeholder:text-[var(--color-text-muted)] focus:border-[var(--color-accent)]"
/>
</div>
{/if}
@ -121,7 +121,7 @@
bind:value={email}
placeholder="Email address"
autocomplete="email"
class="w-full rounded-[var(--radius-input)] border border-[var(--color-border)] bg-[var(--color-bg-2)] py-2.5 pl-9 pr-3 text-[13px] text-[var(--color-text-bright)] outline-none transition-all duration-150 placeholder:text-[var(--color-text-muted)] focus:border-[var(--color-accent)]"
class="w-full rounded-[var(--radius-input)] border border-[var(--color-border)] bg-[var(--color-bg-2)] py-2.5 pl-9 pr-3 text-ui text-[var(--color-text-bright)] outline-none transition-all duration-150 placeholder:text-[var(--color-text-muted)] focus:border-[var(--color-accent)]"
/>
</div>
@ -136,7 +136,7 @@
bind:value={password}
placeholder="Password"
autocomplete={mode === 'signin' ? 'current-password' : 'new-password'}
class="w-full rounded-[var(--radius-input)] border border-[var(--color-border)] bg-[var(--color-bg-2)] py-2.5 pl-9 pr-10 text-[13px] text-[var(--color-text-bright)] outline-none transition-all duration-150 placeholder:text-[var(--color-text-muted)] focus:border-[var(--color-accent)]"
class="w-full rounded-[var(--radius-input)] border border-[var(--color-border)] bg-[var(--color-bg-2)] py-2.5 pl-9 pr-10 text-ui text-[var(--color-text-bright)] outline-none transition-all duration-150 placeholder:text-[var(--color-text-muted)] focus:border-[var(--color-accent)]"
/>
<button
type="button"
@ -156,7 +156,7 @@
<div class="flex justify-end">
<button
type="button"
class="text-[12px] text-[var(--color-text-secondary)] transition-colors duration-150 hover:text-[var(--color-accent-mid)]"
class="text-meta text-[var(--color-text-secondary)] transition-colors duration-150 hover:text-[var(--color-accent-mid)]"
>
Forgot password?
</button>
@ -165,14 +165,14 @@
<button
type="submit"
class="!mt-5 w-full rounded-[var(--radius-button)] bg-[var(--color-accent)] px-4 py-2.5 text-[13px] font-semibold text-white transition-all duration-150 hover:brightness-115 hover:-translate-y-px active:translate-y-0"
class="!mt-5 w-full rounded-[var(--radius-button)] bg-[var(--color-accent)] px-4 py-2.5 text-ui font-semibold text-white transition-all duration-150 hover:brightness-115 hover:-translate-y-px active:translate-y-0"
>
{submitLabel}
</button>
</form>
<!-- Switch mode -->
<p class="mt-5 text-center text-[12px] text-[var(--color-text-secondary)]">
<p class="mt-5 text-center text-meta text-[var(--color-text-secondary)]">
{switchText}
<button
type="button"

View File

@ -74,7 +74,7 @@
alt="Wrenn"
class="h-7 w-7 shrink-0 rounded-[var(--radius-logo)]"
/>
<span class="font-brand text-[15px] text-[var(--color-text-bright)]">Wrenn</span>
<span class="font-brand text-[1.286rem] text-[var(--color-text-bright)]">Wrenn</span>
</div>
{/if}
<button
@ -95,18 +95,18 @@
: 'gap-2 px-2.5'}"
>
<div
class="flex h-6 w-6 shrink-0 items-center justify-center rounded-[var(--radius-avatar)] bg-[var(--color-bg-4)] text-[10px] font-bold uppercase text-[var(--color-text-secondary)]"
class="flex h-6 w-6 shrink-0 items-center justify-center rounded-[var(--radius-avatar)] bg-[var(--color-bg-4)] text-badge font-bold uppercase text-[var(--color-text-secondary)]"
>
{currentTeam[0]}
</div>
{#if !collapsed}
<div class="min-w-0 flex-1 overflow-hidden whitespace-nowrap">
<div
class="text-[11px] font-semibold uppercase tracking-[0.06em] text-[var(--color-text-tertiary)]"
class="text-label font-semibold uppercase tracking-[0.06em] text-[var(--color-text-tertiary)]"
>
Team
</div>
<div class="truncate text-[13px] text-[var(--color-text-primary)]">
<div class="truncate text-ui text-[var(--color-text-primary)]">
{currentTeam}
</div>
</div>
@ -126,20 +126,20 @@
style="animation: popoverSlideIn 150ms ease"
>
<div
class="mb-1 px-2.5 py-1 text-[11px] font-semibold uppercase tracking-[0.06em] text-[var(--color-text-tertiary)]"
class="mb-1 px-2.5 py-1 text-label font-semibold uppercase tracking-[0.06em] text-[var(--color-text-tertiary)]"
>
Teams
</div>
{#each teams as team}
<button
class="flex w-full items-center gap-2.5 rounded-[var(--radius-input)] px-2.5 py-2 text-[13px] transition-colors duration-150 hover:bg-[var(--color-bg-3)] {team ===
class="flex w-full items-center gap-2.5 rounded-[var(--radius-input)] px-2.5 py-2 text-ui transition-colors duration-150 hover:bg-[var(--color-bg-3)] {team ===
currentTeam
? 'bg-[var(--color-accent-glow)]'
: ''}"
onclick={() => (teamPopoverOpen = false)}
>
<div
class="flex h-5 w-5 items-center justify-center rounded-[var(--radius-avatar)] text-[9px] font-bold uppercase text-white {team ===
class="flex h-5 w-5 items-center justify-center rounded-[var(--radius-avatar)] text-badge font-bold uppercase text-white {team ===
currentTeam
? 'bg-[var(--color-accent)]'
: 'bg-[var(--color-bg-5)]'}"
@ -157,7 +157,7 @@
{/each}
<div class="mt-0.5 border-t border-[var(--color-border)] pt-0.5">
<button
class="flex w-full items-center gap-2.5 rounded-[var(--radius-input)] px-2.5 py-2 text-[13px] text-[var(--color-text-secondary)] transition-colors duration-150 hover:bg-[var(--color-bg-3)] hover:text-[var(--color-text-primary)]"
class="flex w-full items-center gap-2.5 rounded-[var(--radius-input)] px-2.5 py-2 text-ui text-[var(--color-text-secondary)] transition-colors duration-150 hover:bg-[var(--color-bg-3)] hover:text-[var(--color-text-primary)]"
>
<IconPlus size={14} />
Create team
@ -186,7 +186,7 @@
title={collapsed ? 'Docs' : undefined}
>
<IconDocs size={16} class="shrink-0 opacity-50 transition-opacity duration-150 group-hover:opacity-100" />
{#if !collapsed}<span class="text-[13px]">Docs</span>{/if}
{#if !collapsed}<span class="text-ui">Docs</span>{/if}
</a>
<a
href="/dashboard/notifications"
@ -194,7 +194,7 @@
title={collapsed ? 'Notifications' : undefined}
>
<IconBell size={16} class="shrink-0 opacity-50 transition-opacity duration-150 group-hover:opacity-100" />
{#if !collapsed}<span class="text-[13px]">Notifications</span>{/if}
{#if !collapsed}<span class="text-ui">Notifications</span>{/if}
</a>
<a
href="/dashboard/settings"
@ -202,7 +202,7 @@
title={collapsed ? 'Settings' : undefined}
>
<IconSettings size={16} class="shrink-0 opacity-50 transition-opacity duration-150 group-hover:opacity-100" />
{#if !collapsed}<span class="text-[13px]">Settings</span>{/if}
{#if !collapsed}<span class="text-ui">Settings</span>{/if}
</a>
</div>
@ -214,11 +214,11 @@
>
{#if !collapsed}
<div
class="flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-[var(--color-bg-4)] text-[10px] font-bold uppercase text-[var(--color-text-secondary)]"
class="flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-[var(--color-bg-4)] text-badge font-bold uppercase text-[var(--color-text-secondary)]"
>
{userName[0] ?? ''}
</div>
<span class="flex-1 truncate text-[13px] text-[var(--color-text-secondary)]">
<span class="flex-1 truncate text-ui text-[var(--color-text-secondary)]">
{userName}
</span>
{/if}
@ -242,7 +242,7 @@
{/if}
{:else}
<div
class="mb-1 px-2.5 py-1.5 text-[11px] font-semibold uppercase tracking-[0.06em] text-[var(--color-text-tertiary)]"
class="mb-1 px-2.5 py-1.5 text-label font-semibold uppercase tracking-[0.06em] text-[var(--color-text-tertiary)]"
>
{label}
</div>
@ -263,7 +263,7 @@
{/if}
<item.icon size={16} class="shrink-0 text-[var(--color-accent-bright)]" />
{#if !collapsed}
<span class="text-[13px] font-medium text-[var(--color-accent-bright)]">
<span class="text-ui font-medium text-[var(--color-accent-bright)]">
{item.label}
</span>
{/if}
@ -282,7 +282,7 @@
/>
{#if !collapsed}
<span
class="text-[13px] text-[var(--color-text-primary)] transition-colors duration-150 group-hover:text-[var(--color-text-bright)]"
class="text-ui text-[var(--color-text-primary)] transition-colors duration-150 group-hover:text-[var(--color-text-bright)]"
>
{item.label}
</span>

View File

@ -5,7 +5,7 @@
<div class="pointer-events-none fixed bottom-6 right-6 z-[100] flex flex-col-reverse gap-2">
{#each toast.list as t (t.id)}
<div
class="pointer-events-auto flex min-w-[280px] max-w-[400px] items-start gap-3 rounded-[var(--radius-card)] border bg-[var(--color-bg-2)] px-4 py-3 text-[13px] {t.type === 'error'
class="pointer-events-auto flex min-w-[280px] max-w-[400px] items-start gap-3 rounded-[var(--radius-card)] border bg-[var(--color-bg-2)] px-4 py-3 text-ui {t.type === 'error'
? 'border-[var(--color-red)]/30 text-[var(--color-red)]'
: 'border-[var(--color-accent)]/30 text-[var(--color-accent-bright)]'}"
style="animation: fadeUp 0.2s ease both"