feat(web): adopt cyberspace terminal aesthetic + dithered images
Rebrand light/dark themes to the cyberspace.online look: warm cream-on-black palette (light/dark are exact inverses), self-hosted JetBrains Mono + VT323, square corners, border-driven surfaces with no soft shadows. Adds a terminal design-system CSS layer (DOS double-border modals with hatched corner, fg focus, inversion-on-hover), a theme-aware <RasterImage> (Atkinson-dithered canvas with img fallback), and unifies desktop icons, taskbar, window controls, pills and links under one idiom. Pins window titlebars to a fixed height and switches chat auto-scroll off scrollIntoView to avoid titlebar reflow. VERSION 0.15.1 -> 0.16.0
This commit is contained in:
@@ -80,25 +80,30 @@
|
||||
|
||||
<button
|
||||
type="button"
|
||||
class="group absolute flex flex-col items-center gap-1 rounded-lg p-1.5 pointer-events-auto select-none focus-visible:outline-2 focus-visible:outline-ring {dragging
|
||||
? 'z-50 cursor-grabbing bg-accent/40'
|
||||
: 'cursor-pointer hover:bg-accent/30'}"
|
||||
class="group absolute flex flex-col items-center gap-1.5 p-1.5 pointer-events-auto select-none transition-transform focus-visible:outline-2 focus-visible:outline-ring {dragging
|
||||
? 'z-50 cursor-grabbing'
|
||||
: 'cursor-pointer hover:-translate-y-0.5'}"
|
||||
style="left: {left}px; top: {top}px; width: {GRID.cell}px;"
|
||||
onpointerdown={onPointerDown}
|
||||
onkeydown={onKeydown}
|
||||
title={app.title}
|
||||
>
|
||||
<span
|
||||
class="relative flex size-10 items-center justify-center rounded-xl border bg-card/80 text-foreground shadow-sm backdrop-blur"
|
||||
class="relative flex size-11 items-center justify-center border transition-all {dragging
|
||||
? 'border-foreground bg-foreground text-background shadow-[4px_4px_0_0_var(--foreground)]'
|
||||
: 'border-border bg-card text-foreground group-hover:border-foreground group-hover:bg-foreground group-hover:text-background'}"
|
||||
>
|
||||
<app.icon class="size-5" />
|
||||
<app.icon class="size-5 transition-colors" />
|
||||
{#if badge > 0}
|
||||
<span
|
||||
class="absolute -right-1.5 -top-1.5 flex h-4 min-w-4 items-center justify-center rounded-full bg-destructive px-1 text-[10px] font-semibold text-destructive-foreground"
|
||||
class="absolute -right-1.5 -top-1.5 flex h-4 min-w-4 items-center justify-center border border-background bg-destructive px-1 text-[10px] font-semibold text-destructive-foreground"
|
||||
>
|
||||
{badge > 99 ? '99+' : badge}
|
||||
</span>
|
||||
{/if}
|
||||
</span>
|
||||
<span class="max-w-full truncate text-[11px] text-foreground/90">{app.title}</span>
|
||||
<span
|
||||
class="max-w-full truncate text-[10px] uppercase tracking-wider text-muted-foreground transition-colors group-hover:text-foreground"
|
||||
>{app.title}</span
|
||||
>
|
||||
</button>
|
||||
|
||||
@@ -53,10 +53,10 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="flex h-11 shrink-0 items-center gap-1.5 border-t bg-muted/30 px-2">
|
||||
<div class="flex h-11 shrink-0 items-center gap-1.5 border-t border-border bg-background px-2">
|
||||
<button
|
||||
type="button"
|
||||
class="flex shrink-0 items-center justify-center rounded-md p-1.5 text-muted-foreground hover:bg-muted hover:text-foreground"
|
||||
class="flex shrink-0 items-center justify-center border border-border p-1.5 text-muted-foreground transition-colors hover:border-foreground hover:bg-foreground hover:text-background"
|
||||
onclick={toggleShowDesktop}
|
||||
title="Show desktop"
|
||||
>
|
||||
@@ -65,7 +65,7 @@
|
||||
|
||||
<div class="h-6 w-px shrink-0 bg-border"></div>
|
||||
|
||||
<div class="flex min-w-0 flex-1 items-center gap-1 overflow-x-auto">
|
||||
<div class="flex min-w-0 flex-1 items-center gap-1 overflow-x-auto py-1.5">
|
||||
{#each buttons as win (win.id)}
|
||||
{@const Icon = iconFor(win.id)}
|
||||
{@const badge = badgeFor(win.id)}
|
||||
@@ -73,12 +73,12 @@
|
||||
<button
|
||||
type="button"
|
||||
data-taskbar-btn={win.id}
|
||||
class="flex h-8 max-w-56 items-center gap-1.5 rounded-md border px-2 font-mono text-xs transition-colors {$wmState.focusedId ===
|
||||
class="flex h-8 max-w-56 items-center gap-1.5 border px-2 font-mono text-xs transition-colors {$wmState.focusedId ===
|
||||
win.id && win.stage !== 'minimized'
|
||||
? 'border-primary/50 bg-primary/10 text-foreground'
|
||||
: 'border-transparent bg-card/60 text-muted-foreground hover:bg-muted'} {win.stage ===
|
||||
? 'border-foreground bg-foreground text-background'
|
||||
: 'border-border bg-background text-muted-foreground hover:border-foreground hover:bg-foreground hover:text-background'} {win.stage ===
|
||||
'minimized'
|
||||
? 'opacity-60'
|
||||
? 'opacity-50'
|
||||
: ''}"
|
||||
onclick={() => toggle(win.id, win)}
|
||||
title={win.title}
|
||||
@@ -87,7 +87,7 @@
|
||||
<span class="min-w-0 truncate">{truncateMiddle(win.title, 26)}</span>
|
||||
{#if badge > 0}
|
||||
<span
|
||||
class="flex h-3.5 min-w-3.5 shrink-0 items-center justify-center rounded-full bg-destructive px-1 text-[9px] font-semibold text-destructive-foreground"
|
||||
class="flex h-3.5 min-w-3.5 shrink-0 items-center justify-center border border-background bg-destructive px-1 text-[9px] font-semibold text-destructive-foreground"
|
||||
>
|
||||
{badge > 99 ? '99+' : badge}
|
||||
</span>
|
||||
@@ -95,7 +95,7 @@
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="absolute -top-1.5 -right-1.5 hidden size-4 items-center justify-center rounded-full bg-muted-foreground/80 text-background hover:bg-destructive group-hover/tb:flex"
|
||||
class="win-ctrl absolute -top-1.5 -right-1.5 hidden size-4 group-hover/tb:flex"
|
||||
onclick={(e) => {
|
||||
e.stopPropagation()
|
||||
wm.close(win.id)
|
||||
@@ -113,7 +113,7 @@
|
||||
<div class="flex shrink-0 items-center gap-0.5">
|
||||
<button
|
||||
type="button"
|
||||
class="flex items-center justify-center rounded-md p-1.5 text-muted-foreground hover:bg-muted hover:text-foreground"
|
||||
class="flex items-center justify-center border border-border p-1.5 text-muted-foreground transition-colors hover:border-foreground hover:bg-foreground hover:text-background"
|
||||
onclick={() => toggleTheme()}
|
||||
title="Cycle theme ({THEME_LABELS[getTheme()]})"
|
||||
aria-label="Cycle theme, currently {THEME_LABELS[getTheme()]}"
|
||||
@@ -122,12 +122,12 @@
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
class="flex items-center justify-center rounded-md p-1.5 text-muted-foreground hover:bg-muted hover:text-foreground"
|
||||
class="flex items-center justify-center border border-border p-1.5 text-muted-foreground transition-colors hover:border-foreground hover:bg-foreground hover:text-background"
|
||||
onclick={() => openAppWindow('settings')}
|
||||
title="Settings"
|
||||
>
|
||||
<SettingsIcon class="size-4" />
|
||||
</button>
|
||||
<span class="px-1.5 text-[11px] text-muted-foreground select-none">{VERSION}</span>
|
||||
<span class="px-1.5 font-mono text-[11px] text-muted-foreground select-none">{VERSION}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -67,18 +67,18 @@
|
||||
<section use:dk.window={{ id }} class="min-w-0" aria-label={win.title}>
|
||||
<header
|
||||
data-wm-drag
|
||||
class="flex shrink-0 cursor-move items-center justify-between gap-2 border-b bg-muted/40 px-3 py-1.5"
|
||||
class="flex h-9 shrink-0 cursor-move items-center justify-between gap-2 overflow-hidden border-b border-border bg-background px-3"
|
||||
>
|
||||
<span
|
||||
data-wm-title
|
||||
class="flex min-w-0 flex-1 items-center self-stretch truncate font-mono text-xs font-medium"
|
||||
class="min-w-0 flex-1 truncate font-mono text-xs font-medium"
|
||||
>{win.title}</span
|
||||
>
|
||||
<div class="flex shrink-0 items-center gap-0.5">
|
||||
<div class="flex shrink-0 items-center gap-1">
|
||||
<button
|
||||
type="button"
|
||||
data-wm-minimize
|
||||
class="flex items-center justify-center rounded p-1 text-muted-foreground hover:bg-muted hover:text-foreground"
|
||||
class="win-ctrl flex size-6"
|
||||
aria-label="Minimize {win.title}"
|
||||
>
|
||||
<MinusIcon class="size-3.5" />
|
||||
@@ -86,7 +86,7 @@
|
||||
<button
|
||||
type="button"
|
||||
data-wm-maximize
|
||||
class="flex items-center justify-center rounded p-1 text-muted-foreground hover:bg-muted hover:text-foreground"
|
||||
class="win-ctrl flex size-6"
|
||||
aria-label="Maximize {win.title}"
|
||||
>
|
||||
<Maximize2Icon class="size-3.5" />
|
||||
@@ -94,7 +94,7 @@
|
||||
<button
|
||||
type="button"
|
||||
data-wm-close
|
||||
class="flex items-center justify-center rounded p-1 text-muted-foreground hover:bg-destructive/10 hover:text-destructive"
|
||||
class="win-ctrl flex size-6"
|
||||
aria-label="Close {win.title}"
|
||||
>
|
||||
<XIcon class="size-3.5" />
|
||||
|
||||
Reference in New Issue
Block a user