From de8ad5fdd5ce1b9552ca8ca6e405d15c7372a4c8 Mon Sep 17 00:00:00 2001 From: Luca <102960244+Luca-Timo@users.noreply.github.com> Date: Wed, 6 May 2026 13:01:09 +0200 Subject: [PATCH] feat(gallery): icon-only menu, accent Download CTA, logo aligned (#386) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Addresses the-luap/picpeak#386 — gallery header layout cleanup. - Drop the redundant "Menu" text label; menu button is icon-only with tight padding (p-2). - Absolute-position the menu icon at the very left of the header so it no longer pushes the logo right with every other action. Logo wrapper picks up pl-12 sm:pl-14 only when a menu button is rendered, so the icon and logo don't overlap. When no menu button (controlsStyle: classic), logo is flush with .container. - New accent-coloured "Download" CTA placed immediately left of Logout. Always visible when downloads are allowed; replaces the previous primary-coloured "Download All" header button. Same CTA appears in standard, hero, and minimal headers. Intentionally NOT shown in the no-header variant (chromeless by design). - Coloured via var(--color-accent) inline so the button automatically tracks whatever palette the admin has chosen — works on plain beta today (#22c55e) and auto-upgrades to the CI accent when #400 lands. The sidebar's own Download All is untouched. Old showDownloadAll prop stays on GalleryLayout for back-compat; GalleryView now passes showDownloadAll={false} so only the new accent button renders in the header. Co-Authored-By: Claude Opus 4.6 --- .../src/components/gallery/GalleryLayout.tsx | 93 +++++++++++++++++-- .../src/components/gallery/GalleryView.tsx | 37 +++++--- 2 files changed, 107 insertions(+), 23 deletions(-) diff --git a/frontend/src/components/gallery/GalleryLayout.tsx b/frontend/src/components/gallery/GalleryLayout.tsx index 144a6871..45dcb7b3 100644 --- a/frontend/src/components/gallery/GalleryLayout.tsx +++ b/frontend/src/components/gallery/GalleryLayout.tsx @@ -40,6 +40,16 @@ interface GalleryLayoutProps { showDownloadAll?: boolean; onDownloadAll?: () => void; isDownloading?: boolean; + /** + * "Download" CTA shown immediately to the left of the Logout button in the + * standard / banner header. Same handler as Download All; the label and + * placement are intentionally simpler — single primary action right before + * Logout, the natural step at the end of a gallery visit (#386). Always + * visible when allowed (independent of sidebar state) so guests aren't + * forced to discover the download in the menu. + */ + showHeaderDownload?: boolean; + onHeaderDownload?: () => void; headerExtra?: React.ReactNode; menuButton?: React.ReactNode; headerStyle?: HeaderStyleType; @@ -54,6 +64,8 @@ export const GalleryLayout: React.FC = ({ showDownloadAll = false, onDownloadAll, isDownloading = false, + showHeaderDownload = false, + onHeaderDownload, headerExtra, menuButton, headerStyle: headerStyleProp, @@ -154,17 +166,22 @@ export const GalleryLayout: React.FC = ({
{/* Standard / Banner header - full bar with logo, event info, and actions (all layouts) */} {!isHeroHeader && !isMinimalHeader && !isNoHeader && ( -
+
+ {/* + * Menu icon is absolute-positioned at the very left of the header + * row instead of sitting inside the flex flow, so the logo's left + * edge can align with the leftmost gallery image (both anchored at + * `.container` left padding) — see #386. The icon stays vertically + * centred via top-1/2 + -translate-y-1/2. + */} + {menuButton && ( +
+ {menuButton} +
+ )}
- {/* Left side - Menu button, Logo */} -
- {/* Menu button */} - {menuButton && ( -
- {menuButton} -
- )} - + {/* Left side - Logo (menu lives in the absolute wrapper above) */} +
{/* Logo - Show custom logo or fallback to PicPeak logo */} {shouldShowLogo('header') && (
@@ -239,6 +256,27 @@ export const GalleryLayout: React.FC = ({ )} + {/* + * "Download" CTA — accent-coloured button immediately left of + * Logout, always visible when the gallery allows downloads. + * Uses var(--color-accent) inline so the same colour token + * shared with the 8-token palette (PR #400) resolves to the + * admin's chosen accent regardless of which PR merges first. + */} + {showHeaderDownload && onHeaderDownload && ( + + )} + {/* Logout button */} {showLogout && onLogout && ( )} + {/* Accent Download CTA — also rendered in the minimal header + so the action stays one click away regardless of header + style. Intentionally NOT shown in the no-header variant + where the gallery is fully chromeless by design. */} + {showHeaderDownload && onHeaderDownload && ( + + )} {showLogout && onLogout && ( )} + {/* Accent Download CTA — also rendered above the hero so the + primary download action is reachable without scrolling. + Intentionally NOT shown in the no-header variant where + the gallery is fully chromeless by design. */} + {showHeaderDownload && onHeaderDownload && ( + + )} + {/* Logout button */} {showLogout && onLogout && ( - ) : undefined} + menuButton={ + // Menu icon is shown when the event theme uses the sidebar + // controls style. The button is icon-only — the redundant + // "Menu" text label was dropped (#386). The wrapper aligns the + // icon to the very left of the header so the logo lines up + // with the leftmost gallery image. + showSidebar ? ( + + ) : undefined + } + showHeaderDownload={allowDownloads} + onHeaderDownload={handleDownloadAll} headerExtra={(() => { const items = [];