fix: align sidebar counts in a single right column
The previous count-alignment fix used invisible group-hover:visible for
hover-only buttons, but invisible still reserves layout space. Folder
rows had a permanent kebab slot that non-folder rows didn't, and active
heap rows had a Target indicator before the count — both shifted their
counts left of the rest. The result was visually misaligned counts.
- LeftSidebar folder kebab + HeapsPanel kebab/set-active: switch to
hidden group-hover:block so the slot occupies zero width in the
resting state. Counts now sit at the same right edge across folder,
non-folder, and heap rows.
- HeapsPanel: drop the standalone Target indicator from active heap
rows. Active state is signaled by the bold name (font-semibold)
already, and removing the indicator lets the heap count column line
up with everything else.
- Both kebab wrappers also use hidden group-hover:block on the wrapper
div so the menu trigger truly takes 0 width when not hovered.
On hover the kebab appears to the right of the count and pushes it
slightly left, as the user requested ("on hover we can push them to
make space for the burger").
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -338,17 +338,13 @@ export function HeapsPanel() {
|
||||
</span>
|
||||
)}
|
||||
|
||||
{/* Right-aligned cluster. Active indicator + count are
|
||||
* always visible; set-active and kebab appear on hover
|
||||
* to the RIGHT of the count, displacing it slightly so
|
||||
* the count column lines up with the rest of the
|
||||
* sidebar in the resting state. */}
|
||||
{isActive && (
|
||||
<Target
|
||||
className="h-3 w-3 flex-shrink-0 text-primary"
|
||||
aria-label="Active heap (T target)"
|
||||
/>
|
||||
)}
|
||||
{/* Right cluster. Count is the rightmost element in the
|
||||
* resting state — set-active and kebab use display:none
|
||||
* (not invisible) so they reserve no width until hover,
|
||||
* keeping the count column aligned with the rest of the
|
||||
* sidebar. The active heap is signaled by font-semibold
|
||||
* on the name above; the standalone Target indicator
|
||||
* was making heap counts sit left of the others. */}
|
||||
{heap.photo_count > 0 ? (
|
||||
<span className="flex h-5 min-w-[24px] flex-shrink-0 items-center justify-center rounded bg-surface-offset px-1.5 text-xs tabular-nums text-text-muted">
|
||||
{heap.photo_count}
|
||||
@@ -362,7 +358,7 @@ export function HeapsPanel() {
|
||||
e.stopPropagation()
|
||||
setActiveMutation.mutate(heap.id)
|
||||
}}
|
||||
className="invisible flex-shrink-0 rounded p-0.5 text-text-muted hover:bg-surface-offset hover:text-text group-hover:visible"
|
||||
className="hidden flex-shrink-0 rounded p-0.5 text-text-muted hover:bg-surface-offset hover:text-text group-hover:block"
|
||||
title="Set as active heap (T target)"
|
||||
aria-label="Set as active heap"
|
||||
>
|
||||
@@ -372,16 +368,18 @@ export function HeapsPanel() {
|
||||
|
||||
{/* Kebab menu — collects rename / duplicate / convert /
|
||||
* delete so the row stays compact. */}
|
||||
<div className="relative flex-shrink-0">
|
||||
<div
|
||||
className={clsx(
|
||||
'relative flex-shrink-0',
|
||||
isMenuOpen ? 'block' : 'hidden group-hover:block'
|
||||
)}
|
||||
>
|
||||
<button
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
setOpenMenuId(isMenuOpen ? null : heap.id)
|
||||
}}
|
||||
className={clsx(
|
||||
'rounded p-0.5 text-text-muted hover:bg-surface-offset hover:text-text',
|
||||
isMenuOpen ? 'visible' : 'invisible group-hover:visible'
|
||||
)}
|
||||
className="rounded p-0.5 text-text-muted hover:bg-surface-offset hover:text-text"
|
||||
title="More actions"
|
||||
aria-label="More heap actions"
|
||||
aria-haspopup="menu"
|
||||
|
||||
@@ -537,24 +537,28 @@ export function LeftSidebar() {
|
||||
<span className="h-5 min-w-[24px] flex-shrink-0" aria-hidden="true" />
|
||||
)}
|
||||
|
||||
{/* Folder kebab menu — only on folder rows. Hidden until hover
|
||||
* (or when its menu is open) so the count column stays aligned
|
||||
* in the resting state. */}
|
||||
{/* Folder kebab menu — only on folder rows. Hidden (display:none)
|
||||
* until hover so it reserves NO width in the resting state and
|
||||
* the count column stays aligned across folder + non-folder
|
||||
* rows. On hover it appears to the right, pushing the count
|
||||
* left to make room. */}
|
||||
{item.id.startsWith('folder-') &&
|
||||
(() => {
|
||||
const folderId = item.id.slice('folder-'.length)
|
||||
const isMenuOpen = openMenuId === item.id
|
||||
return (
|
||||
<div className="relative flex-shrink-0">
|
||||
<div
|
||||
className={clsx(
|
||||
'relative flex-shrink-0',
|
||||
isMenuOpen ? 'block' : 'hidden group-hover:block'
|
||||
)}
|
||||
>
|
||||
<button
|
||||
onClick={(e) => {
|
||||
e.stopPropagation()
|
||||
setOpenMenuId(isMenuOpen ? null : item.id)
|
||||
}}
|
||||
className={clsx(
|
||||
'rounded p-0.5 text-text-muted hover:bg-surface-offset hover:text-text',
|
||||
isMenuOpen ? 'visible' : 'invisible group-hover:visible'
|
||||
)}
|
||||
className="rounded p-0.5 text-text-muted hover:bg-surface-offset hover:text-text"
|
||||
title="More actions"
|
||||
aria-label="More folder actions"
|
||||
aria-haspopup="menu"
|
||||
|
||||
Reference in New Issue
Block a user