From 1695eae2266f0af044ae8f3ed2fae41c4e921874 Mon Sep 17 00:00:00 2001 From: Claudio Date: Sun, 10 May 2026 21:43:33 +0200 Subject: [PATCH] ui(sidebar): wrap edit form in collapsible, drop Header X button MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mirror the Metadata collapsible: an 'Edit' wrapper around filename, title, notes, rating, color, and flag so the editable form is hidden with one click. Default expanded. Drop the clear-selection X from the panel Header — Esc still clears selection and grid clicks do too. The X felt out of place once the panel restructured around two equal collapsible groups (Edit / Metadata) below a plain title bar. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../src/components/layout/RightSidebar.tsx | 25 +++++-------------- .../src/components/sidebar/PhotoInfoPanel.tsx | 24 +++++++++++++++--- 2 files changed, 27 insertions(+), 22 deletions(-) diff --git a/frontend/src/components/layout/RightSidebar.tsx b/frontend/src/components/layout/RightSidebar.tsx index a7703d1..943a365 100644 --- a/frontend/src/components/layout/RightSidebar.tsx +++ b/frontend/src/components/layout/RightSidebar.tsx @@ -31,7 +31,7 @@ import { formatApiError } from '../../lib/apiError' * rating / color / discard / pick across the entire selection. */ export function RightSidebar() { - const { selectedPhotos, activePhotoId, clearSelection } = usePhotoStore() + const { selectedPhotos, activePhotoId } = usePhotoStore() const queryClient = useQueryClient() const { @@ -182,9 +182,10 @@ export function RightSidebar() { }, }) - // Unified header rendered in every branch so the collapse button is - // always reachable regardless of selection state. Title and the - // clear-selection X adapt to what's selected. + // Unified header rendered in every branch so the panel always has + // a title strip regardless of selection state. The title adapts to + // what's selected; selection is cleared via Esc or by clicking + // empty space in the grid. const headerTitle = selectedPhotos.length === 0 ? 'Metadata' @@ -193,24 +194,10 @@ export function RightSidebar() { : `${selectedPhotos.length} Photos Selected` const Header = () => ( -
+

{headerTitle}

-
- {selectedPhotos.length > 0 && ( - - )} -
) diff --git a/frontend/src/components/sidebar/PhotoInfoPanel.tsx b/frontend/src/components/sidebar/PhotoInfoPanel.tsx index d9f3e74..f3452a4 100644 --- a/frontend/src/components/sidebar/PhotoInfoPanel.tsx +++ b/frontend/src/components/sidebar/PhotoInfoPanel.tsx @@ -143,7 +143,7 @@ export function PhotoInfoPanel({ photoId, darkTheme = false }: PhotoInfoPanelPro const queryClient = useQueryClient() const [expandedSections, setExpandedSections] = useState>( - new Set(['metadata', 'basic', 'camera', 'location', 'tags']) + new Set(['edit', 'metadata', 'basic', 'camera', 'location', 'tags']) ) const toggleSection = (section: string) => { const next = new Set(expandedSections) @@ -390,8 +390,24 @@ export function PhotoInfoPanel({ photoId, darkTheme = false }: PhotoInfoPanelPro isPlaceholderData && 'opacity-70' )} > - {/* Edit fields */} -
+ {/* Edit fields — collapsible group so the user can hide the + * editable form (filename, title, notes, rating, color, flag) + * the same way they can hide the readonly metadata block below. */} + toggleSection('edit')} + className="border-b border-border" + > + + Edit + {expandedSections.has('edit') ? ( + + ) : ( + + )} + + +
+
+
{/* Read-only metadata — collapsed/expanded as one block so the user * can hide everything below the editable form with a single click.