Content-first redesign covering showcase stagger animation and ghost badges, gallery source tag filtering, modal two-panel hierarchy, series reader immersive mode, and settings tab structure. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
8.6 KiB
UI/UX Improvements Design
Date: 2026-03-19 Approach: Content-First Redesign — every UI element is evaluated against the principle that content leads, chrome follows. The black/transparent brand is preserved throughout.
Design Principles
- Content leads, chrome follows. No UI element competes with image/video for attention. Overlays, badges, and controls recede by default and surface when needed.
- Black and transparent is the brand. No light surfaces. Depth through opacity layers and subtle borders, not color changes.
- Motion has a purpose. Transitions communicate state, not decoration. Fast and snappy.
- Density is a choice. Settings is dense. Showcase is sparse. Each page gets appropriate density.
- No orphaned interactions. Every action gets in-context feedback — not a toast, but a brief fade label right where the action happened.
1. Showcase
Goal: Discovery feeling — energetic, surprising, content-first.
Changes
Staggered entry animation.
On page load and shuffle, images stagger in with a subtle fade + translate-up per column (150–200ms per item, offset by column index). Creates the feeling of content surfacing, not a grid appearing. Animation is CSS-based with a JS-assigned --stagger-index custom property on each item.
Tag overlays replaced with ghost badge.
Each showcase item gets a single small semi-transparent pill badge in the bottom-right corner showing tag count (e.g. #3). No text, no emoji, no color — just faint opacity. On desktop: visible only on hover. On touch: always visible. Clicking the image opens the modal where full tags are accessible.
Navbar hint refinement.
"Press R to shuffle" moves from a permanently rendered hint to a tooltip-style label that appears only when hovering over the .nav-hint text itself. The element remains in the DOM (for accessibility) but is visually hidden at rest via opacity: 0, transitioning to opacity: 1 on hover. Reduces permanent chrome without hiding the affordance.
No structural changes
Masonry layout, modal integration, shuffle API, and column logic all unchanged.
2. Gallery & Tag Overlays
Goal: Keep tag chips visible on gallery items for navigation but reduce visual noise.
Changes
Source tags filtered from gallery items.
_gallery_item.html currently filters out archive kind tags. Extend the filter to also exclude source kind tags. One-line template change.
Before: selectattr('kind', 'ne', 'archive')
After: rejectattr('kind', 'in', ['archive', 'source'])
Date label refinement.
.image-date span gets reduced opacity at rest (e.g. 0.5), full opacity on hover. Stops competing with the image at a glance.
Video play indicator refinement. Play overlay gets a minimal centered circle + triangle treatment. Refined sizing and opacity — reads clearly without dominating the thumbnail.
Selection mode visual consistency. Selection checkbox overlay on items uses semi-transparent treatment with accent color on selected state. Consistent with the overall dark visual language.
No changes
Timeline sidebar, infinite scroll, bulk editor functionality, gallery header all unchanged.
3. Image Modal
Goal: Clear hierarchy — image dominates, metadata lives quietly alongside it.
Layout
Formal two-panel split.
- Left ~65%: image viewer (already roughly this, formalized with explicit layout)
- Right ~35%: metadata sidebar — fixed width, scrollable if content overflows, subtle left border as divider
Right Panel — Section Order
The modal currently contains only three content areas: series info/add-to-series, tag chips, and the tag input form. No hidden metadata fields (filename, dimensions, etc.) exist. The redesign reorganizes these same elements:
-
Series block (top, conditional) Only rendered when the image is in a series OR series exist to add it to.
- If in a series: compact single-row — page number input, "of", series name link, Save button
- If not in a series: "Add to Series" collapsed behind a toggle button (not always expanded)
-
Tags block Current tag chips. Each chip shows a remove
×on hover only — not always visible. Reduces visual noise at rest. -
Add tag input (bottom of tag block) Autocomplete unchanged. Input sits flush below the tag list, not separated by excessive spacing.
Feedback
All actions (tag added, tag removed, page number saved) display a brief in-context fade label next to the triggering element. Appears immediately, fades out after 1.5s. No toast notifications.
No changes
Navigation arrows (prev/next), ESC to close, video playback, API calls all unchanged.
4. Series Reader
Goal: Immersive reading experience — UI surfaces when needed, recedes while reading.
Changes
Scroll progress bar.
A 1–2px full-width bar fixed at the very top of the viewport. Fills from left to right as you scroll through the series. Uses --btn-primary accent color. Always visible, extremely unobtrusive.
Auto-hiding header. Reader header fades out 2–3 seconds after scrolling begins. Reappears instantly on scroll-stop, mouse move, or any keyboard interaction. Implemented with a CSS opacity transition + JS scroll/mousemove listeners and a debounced timeout.
Active thumbnail tracking in sidebar.
As the user scrolls the main reading area, the currently-visible page is detected (IntersectionObserver on .reader-page elements). The matching thumbnail in the sidebar gets:
- Left border accent (
--btn-primary) - Slightly elevated opacity
- Smooth scroll-into-view within the sidebar
Single global page indicator.
Remove the per-image page / total .page-indicator div from each .reader-page. Replace with one fixed-position label in the bottom-right corner of the viewport, updated by the same IntersectionObserver that drives the sidebar tracking.
No changes
Jump-to-page select, back button, image lazy loading, sidebar toggle button all unchanged.
5. Settings Page
Goal: Reduce scrolling, surface important controls, push rarely-used tools out of the way.
Tab Structure
Three tabs replacing the current flat scroll layout:
| Tab | Contents |
|---|---|
| Overview | System stats, Import Queue Status, active batch progress, import trigger buttons |
| Import | Import filter settings, filter scan/delete tools, duplicate detection |
| Maintenance | Thumbnail regeneration, artist tag reapply, orphaned tag cleanup, Celery worker status |
Tab Implementation
- Pure frontend — JS show/hide, no server changes
- Active tab persisted in URL hash (
/settings#import) for deep-linking and refresh persistence - On page load, read hash and activate matching tab (default: Overview)
- Tab bar uses same filter pill visual language as the tag list page for consistency
Visual Hierarchy Within Tabs
- Overview tab: Full-width cards, prominent stat values, clear action buttons
- Import tab: Two-column grid — left column: import filter settings form; right column: filter scan/delete tools and duplicate detection
- Maintenance tab: Visually subdued cards — slightly lower contrast to signal lower priority. Single column: thumbnail regeneration (all + missing), artist tag reapply, orphaned tag cleanup, Celery worker status
Inline styles removed
All style="..." attributes on settings elements replaced with proper CSS classes.
No changes
All existing API endpoints, form logic, and functionality unchanged. Layout and organization only.
Files Affected
| File | Change |
|---|---|
app/templates/_gallery_item.html |
Filter source tags; refine date label and video overlay |
app/templates/showcase.html |
Stagger animation; ghost badge; navbar hint refinement |
app/templates/_gallery_modal.html |
Two-panel layout; section hierarchy; conditional series block |
app/templates/reader.html |
Progress bar; auto-hide header; single page indicator |
app/templates/settings.html |
Tab structure; section reorganization; remove inline styles |
app/static/style.css |
New classes for all of the above |
app/static/js/showcase.js |
Stagger animation logic; ghost badge rendering |
app/static/js/view-modal.js |
In-context feedback; series block toggle |
app/static/js/reader.js |
Progress bar; header auto-hide; active thumbnail tracking — new file (reader logic currently inline in reader.html; extract to this file) |
Out of Scope
- No new API endpoints
- No database changes
- No changes to import pipeline, Celery tasks, or tag logic
- No changes to the gallery infinite scroll or timeline sidebar
- No changes to bulk select functionality