feat: tweak theme colors and streamline sidebar chrome

This commit is contained in:
2026-05-15 01:09:29 +02:00
parent c8b189d0e7
commit 598e842b2c
8 changed files with 27 additions and 156 deletions

View File

@@ -6,19 +6,19 @@
@source "../**/*.ts";
@theme {
--color-background: light-dark(#ffffff, #080808);
--color-background-sidebar: light-dark(#fafaf9, #0f0f0f);
--color-background-header: light-dark(#ffffff, #141414);
--color-background-surface: light-dark(#f5f5f4, #202020);
--color-background-button: light-dark(#ffffff, #1a1a1a);
--color-background-button-hover: light-dark(#f5f5f4, #252525);
--color-background: light-dark(#fbfcff, #0b0c10);
--color-background-sidebar: light-dark(#f8fafc, #0f1115);
--color-background-header: light-dark(#fbfcff, #0f1115);
--color-background-surface: light-dark(#f3f4f6, #17181c);
--color-background-button: light-dark(#ffffff, #131417);
--color-background-button-hover: light-dark(#f3f4f6, #1c1d22);
--color-foreground-muted: light-dark(#6b7280, #6a6b70);
--color-foreground: light-dark(#1f2937, #f8f9fa);
--color-foreground-muted: light-dark(#6b7280, #9ca3af);
--color-foreground: light-dark(#111827, #f3f4f6);
--color-accent: #0466c8;
--color-border: light-dark(rgba(0, 0, 0, 0.08), rgba(255, 255, 255, 0.08));
--color-surface-hover: light-dark(rgba(0, 0, 0, 0.04), rgba(255, 255, 255, 0.04));
--color-accent: #d97706;
--color-border: light-dark(rgba(17, 24, 39, 0.08), rgba(243, 244, 246, 0.08));
--color-surface-hover: light-dark(rgba(17, 24, 39, 0.04), rgba(243, 244, 246, 0.04));
}
:root {

View File

@@ -43,7 +43,7 @@
{{if .WatchlistIDs}}<script>initWatchlist({{.WatchlistIDs}})</script>{{end}}
{{$anime := .Anime}}
<div class="flex flex-col gap-10 lg:pr-80">
<div class="flex w-full flex-col gap-10 lg:pr-80">
<div class="flex flex-col gap-8 md:flex-row lg:gap-12">
<div class="flex w-64 shrink-0 flex-col items-center gap-6 md:w-80 md:items-start lg:w-96">
<div class="aspect-2/3 w-full overflow-hidden bg-background-surface shadow-lg">
@@ -123,20 +123,12 @@
</section>
{{end}}
{{if $anime.Background}}
<section class="mt-12">
<h2 class="mb-4 text-lg font-normal text-foreground">Background</h2>
<div class="border-l border-border pl-6 text-sm italic leading-relaxed text-foreground-muted whitespace-pre-line">
{{$anime.Background}}
</div>
</section>
{{end}}
</div>
<aside class="fixed right-0 top-0 hidden h-screen w-80 shrink-0 flex-col overflow-y-auto border-l border-border bg-background-sidebar p-10 lg:flex">
<div class="flex flex-col gap-10">
<section>
<h3 class="mb-8 text-lg font-normal text-foreground">Information</h3>
<div class="flex flex-col gap-8 text-sm">
<dl class="flex flex-col gap-8 text-sm">
{{if $anime.Studios}}
<div>
<dt class="mb-1 text-xs font-normal text-foreground-muted">Studios</dt>
@@ -233,7 +225,7 @@
<dd class="text-foreground">{{$anime.ScoredByFormatted}} users</dd>
</div>
{{end}}
</div>
</dl>
</section>
</div>
</aside>

View File

@@ -67,25 +67,12 @@
<script>
// initialize sidebar state immediately to prevent layout shift/transitions
(function() {
const isCollapsed = localStorage.getItem('sidebar-collapsed') === 'true';
// only apply collapsed state on desktop (lg+)
if (isCollapsed && window.innerWidth >= 1024) {
document.documentElement.classList.add('sidebar-collapsed');
}
})();
function toggleSidebar() {
const sidebar = document.getElementById('mobile-menu');
const isCollapsed = document.documentElement.classList.contains('sidebar-collapsed');
if (isCollapsed) {
document.documentElement.classList.remove('sidebar-collapsed');
localStorage.setItem('sidebar-collapsed', 'false');
} else {
// keep the sidebar collapsed on desktop (lg+)
if (window.innerWidth >= 1024) {
document.documentElement.classList.add('sidebar-collapsed');
localStorage.setItem('sidebar-collapsed', 'true');
}
}
})();
// Initialize sidebar state on load
document.addEventListener('DOMContentLoaded', () => {
@@ -95,17 +82,6 @@
});
});
function toggleMobileMenu() {
const menu = document.getElementById('mobile-menu');
if (menu.classList.contains('-translate-x-full')) {
menu.classList.remove('-translate-x-full');
document.getElementById('mobile-overlay').classList.remove('hidden');
} else {
menu.classList.add('-translate-x-full');
document.getElementById('mobile-overlay').classList.add('hidden');
}
}
const watchlistIds = new Set()
function initWatchlist(ids) {
@@ -253,19 +229,14 @@ if (window.showToast) showToast({ message: 'Something went wrong' })
<div class="flex min-h-screen flex-col">
{{if .User}}
<div class="flex flex-1 overflow-hidden">
<button id="mobile-overlay" class="hidden fixed inset-0 z-40 w-full cursor-default border-none bg-black/60 backdrop-blur-sm outline-none lg:hidden" onclick="toggleMobileMenu()" aria-label="Close mobile menu"></button>
<!-- Sidebar -->
<div id="mobile-menu" class="fixed inset-y-0 left-0 z-50 shrink-0 overflow-hidden transform lg:relative lg:z-auto lg:translate-x-0 w-64 transition-transform duration-300 -translate-x-full lg:block">
<div id="mobile-menu" class="shrink-0 overflow-hidden w-64">
{{block "sidebar" .}}
{{template "navigation" dict "CurrentPath" .CurrentPath}}
{{end}}
</div>
<main class="w-full flex-1 flex flex-col h-screen overflow-y-auto">
<div class="sticky top-0 z-40 w-full">
{{template "header" .}}
</div>
<div class="flex-1 p-4 md:p-8 lg:p-10">
{{template "content" .}}
</div>

View File

@@ -21,7 +21,7 @@ All components are exposed as Go templates. Import by name:
```gohtml
{{template "anime_card" dict "Anime" .Data "WithActions" true}}
{{template "navigation" dict "CurrentPath" .CurrentPath}}
{{template "header" .}}
{{/* header removed */}}
```
## Props Convention

View File

@@ -1,91 +0,0 @@
{{define "header"}}
<header class="bg-background-header flex flex-col border-b border-border relative z-50">
<div class="flex h-16 items-center justify-between px-4 md:px-6">
<div class="flex items-center gap-4">
<button onclick="toggleMobileMenu()" class="block text-foreground-muted transition-colors hover:text-foreground focus:outline-none md:hidden">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="4" x2="20" y1="12" y2="12"/><line x1="4" x2="20" y1="6" y2="6"/><line x1="4" x2="20" y1="18" y2="18"/></svg>
</button>
<button onclick="toggleSidebar()" class="hidden text-foreground-muted transition-colors hover:text-foreground focus:outline-none lg:block">
<svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="3" x2="21" y1="12" y2="12"/><line x1="3" x2="21" y1="6" y2="6"/><line x1="3" x2="21" y1="18" y2="18"/></svg>
</button>
<a href="/" class="group flex items-center gap-2.5 focus:outline-none">
<img src="/static/assets/readme-logo-light.svg" alt="MAL" class="h-8 w-8 transition-transform group-hover:scale-110" />
<span class="text-xl font-bold tracking-tight text-foreground">MyAnime<span class="text-accent">List</span></span>
</a>
</div>
<div class="hidden max-w-2xl flex-1 items-center justify-center px-4 md:flex">
<form action="/browse" method="GET" class="w-full max-w-lg">
<div class="focus-within:border-accent bg-background-surface flex h-10 w-full items-center overflow-hidden border border-border transition-colors">
<div class="pr-2 pl-4 text-foreground-muted">
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.3-4.3"/></svg>
</div>
<input type="text" name="q" placeholder="Search..." class="h-full w-full bg-transparent px-1 text-sm text-foreground focus:outline-none" />
</div>
</form>
</div>
<div class="flex items-center gap-2 relative justify-end">
<button
id="theme-toggle"
class="rounded-full p-1.5 text-foreground-muted transition-colors hover:bg-surface-hover hover:text-foreground focus:outline-none"
>
<svg class="theme-icon-dark size-5" viewBox="0 0 24 24" stroke="currentColor" fill="none" stroke-width="2">
<path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/>
</svg>
<svg class="theme-icon-light hidden size-5" viewBox="0 0 24 24" stroke="currentColor" fill="none" stroke-width="2">
<circle cx="12" cy="12" r="5"/>
<path d="M12 1v2M12 21v2M4.22 4.22l1.42 1.42M18.36 18.36l1.42 1.42M1 12h2M21 12h2M4.22 19.78l1.42-1.42M18.36 5.64l1.42-1.42"/>
</svg>
</button>
<ui-dropdown class="relative block">
<div data-trigger class="cursor-pointer">
<button class="flex items-center gap-1 rounded-full p-1 transition-colors hover:bg-surface-hover focus:outline-none">
{{with .User}}
<img
src="{{.AvatarUrl}}"
alt="{{.Username}}"
class="h-8 w-8 rounded-full object-cover"
/>
{{else}}
<div class="bg-accent flex h-8 w-8 items-center justify-center rounded-full text-sm font-semibold text-on-accent">
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M19 21v-2a4 4 0 0 0-4-4H9a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg>
</div>
{{end}}
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="text-foreground-muted"><path d="m6 9 6 6 6-6"/></svg>
</button>
</div>
<div data-content class="hidden absolute z-50 min-w-[320px] bg-background-button rounded-none shadow-2xl right-0 top-full mt-2">
<div class="flex flex-col py-1">
{{with .User}}
<a href="/logout" class="flex w-full items-center px-5 py-3.5 transition-colors focus:outline-none hover:bg-red-500/10 focus:bg-red-500/10">
<div class="flex w-full items-center justify-between text-left">
<span class="font-medium text-[15px] text-red-500">Log out</span>
</div>
</a>
{{else}}
<a href="/login" class="flex w-full items-center px-5 py-3.5 transition-colors focus:outline-none hover:bg-surface-hover focus:bg-surface-hover">
<div class="flex w-full items-center justify-between text-left">
<span class="font-medium text-[15px] text-foreground">Log in</span>
</div>
</a>
{{end}}
</div>
</div>
</ui-dropdown>
</div>
</div>
<div class="flex border-t border-border p-3 md:hidden">
<form action="/browse" method="GET" class="w-full">
<div class="focus-within:border-accent bg-background-surface flex h-10 w-full items-center overflow-hidden border border-border transition-colors">
<div class="pr-2 pl-4 text-foreground-muted">
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="11" cy="11" r="8"/><path d="m21 21-4.3-4.3"/></svg>
</div>
<input type="text" name="q" placeholder="Search..." class="h-full w-full bg-transparent px-1 text-sm text-foreground focus:outline-none" />
</div>
</form>
</div>
</header>
{{end}}

View File

@@ -8,13 +8,13 @@
"watchlist" (dict "href" "/watchlist" "label" "Watchlist")
}}
<nav class="bg-background-sidebar h-full py-6 border-r border-border">
<nav class="bg-background-sidebar h-full border-r border-border">
<div class="flex flex-col">
{{/* Home */}}
{{$isActive := eq $currentPath "/"}}
<a href="/" class="group relative flex items-center px-7 py-3 transition-colors hover:bg-surface-hover" {{if $isCollapsed}}title="Home"{{end}}>
{{if $isActive}}
<div class="bg-accent absolute top-1/2 left-0 h-8 w-0.5 -translate-y-1/2 rounded-r-sm shadow-[0_0_8px_var(--color-accent)]"></div>
<div class="bg-accent absolute top-1/2 left-0 h-12 w-0.5 -translate-y-1/2 rounded-r-sm shadow-[0_0_8px_var(--color-accent)]"></div>
{{end}}
<svg class="size-6 shrink-0 transition-colors duration-200 {{if $isActive}}text-accent{{else}}text-foreground-muted group-hover:text-foreground{{end}}" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
<path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z" />
@@ -31,7 +31,7 @@
{{$isActive := eq $currentPath "/browse"}}
<a href="/browse" class="group relative flex items-center px-7 py-3 transition-colors hover:bg-surface-hover" {{if $isCollapsed}}title="Browse"{{end}}>
{{if $isActive}}
<div class="bg-accent absolute top-1/2 left-0 h-8 w-0.5 -translate-y-1/2 rounded-r-sm shadow-[0_0_8px_var(--color-accent)]"></div>
<div class="bg-accent absolute top-1/2 left-0 h-12 w-0.5 -translate-y-1/2 rounded-r-sm shadow-[0_0_8px_var(--color-accent)]"></div>
{{end}}
<svg class="size-6 shrink-0 transition-colors duration-200 {{if $isActive}}text-accent{{else}}text-foreground-muted group-hover:text-foreground{{end}}" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
<rect x="2" y="2" width="20" height="20" rx="2" ry="2" />
@@ -54,7 +54,7 @@
{{$isActive := eq $currentPath "/discover"}}
<a href="/discover" class="group relative flex items-center px-7 py-3 transition-colors hover:bg-surface-hover" {{if $isCollapsed}}title="Discover"{{end}}>
{{if $isActive}}
<div class="bg-accent absolute top-1/2 left-0 h-8 w-0.5 -translate-y-1/2 rounded-r-sm shadow-[0_0_8px_var(--color-accent)]"></div>
<div class="bg-accent absolute top-1/2 left-0 h-12 w-0.5 -translate-y-1/2 rounded-r-sm shadow-[0_0_8px_var(--color-accent)]"></div>
{{end}}
<svg class="size-6 shrink-0 transition-colors duration-200 {{if $isActive}}text-accent{{else}}text-foreground-muted group-hover:text-foreground{{end}}" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">
<circle cx="12" cy="12" r="10" />
@@ -71,7 +71,7 @@
{{$isActive := eq $currentPath "/watchlist"}}
<a href="/watchlist" class="group relative flex items-center px-7 py-3 transition-colors hover:bg-surface-hover" {{if $isCollapsed}}title="Watchlist"{{end}}>
{{if $isActive}}
<div class="bg-accent absolute top-1/2 left-0 h-8 w-0.5 -translate-y-1/2 rounded-r-sm shadow-[0_0_8px_var(--color-accent)]"></div>
<div class="bg-accent absolute top-1/2 left-0 h-12 w-0.5 -translate-y-1/2 rounded-r-sm shadow-[0_0_8px_var(--color-accent)]"></div>
{{end}}
<svg class="size-6 shrink-0 transition-colors duration-200 {{if $isActive}}text-accent{{else}}text-foreground-muted group-hover:text-foreground{{end}}" viewBox="0 0 24 24" fill="currentColor">
<path d="M17 18.113l-3.256-2.326A2.989 2.989 0 0 0 12 15.228c-.629 0-1.232.194-1.744.559L7 18.113V4h10v14.113zM18 2H6a1 1 0 0 0-1 1v17.056c0 .209.065.412.187.581a.994.994 0 0 0 1.394.233l4.838-3.455a1 1 0 0 1 1.162 0l4.838 3.455A1 1 0 0 0 19 20.056V3a1 1 0 0 0-1-1z" />
@@ -84,4 +84,4 @@
</a>
</div>
</nav>
{{end}}
{{end}}

View File

@@ -55,9 +55,8 @@
{{define "watchlist_remove_button"}}
<div id="remove-watchlist-container-{{.ID}}" class="{{.ContainerClass}}">
<div class="{{.DividerClass}}"></div>
<button class="{{.ButtonClass}}" onclick="removeWatchlist({{.ID}}, this)">
<span class="{{.SpanClass}}">Remove from Watchlist</span>
</button>
</div>
{{end}}
{{end}}

View File

@@ -1,7 +1,7 @@
{{define "title"}}Watchlist{{end}}
{{define "content"}}
{{if .WatchlistIDs}}<script>initWatchlist({{.WatchlistIDs}})</script>{{end}}
<div id="watchlist-content" class="flex w-full flex-col gap-6 mt-6">
<div id="watchlist-content" class="flex w-full flex-col gap-6">
<h1 class="text-xl font-normal text-foreground">Watchlist</h1>
<div class="flex flex-wrap items-center justify-between gap-4">