Repository navigation
fix(library): let long shelf names breathe in the Move To menu - #240
Conversation
The portaled menu was pinned to its trigger's width, and the Move To
trigger is a compact fit-content pill — so shelf names were crushed into
a ~90px column, and a name with no break opportunity ("Crime/Detective")
walked straight out of the menu and over the modal behind it.
The portaled menu now sizes to its content: min-width keeps it at least
as wide as the trigger, max-width keeps it inside the viewport and off
the far edge of the screen. Option labels break long tokens instead of
escaping the box, and the trigger truncates its own label so a chosen
shelf name can't push the pill past the modal.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Claude finished @MaryWylde's task in 2m 52s —— View job Claude's review of #240Todo list
SummaryThis is a well-scoped, well-reasoned CSS/layout fix. The two root causes described in the PR body check out against the code:
Two low-severity, non-blocking edge cases left as inline comments for awareness (not requested as blocking changes):
Testing note: the PR body already flags that this was verified against compiled CSS in headless Chromium rather than the live authenticated modal — that gap is called out by the author, not something I could close either (no browser tooling available in this session). |
| // behind the dropdown. Break it instead. | ||
| .optionLabel { | ||
| min-width: 0; | ||
| overflow-wrap: anywhere; |
There was a problem hiding this comment.
overflow-wrap: anywhere is applied to .optionLabel, which is also used inside .subMenu for sub-option labels (Dropdown.tsx ~L210-215). But .subMenu sets white-space: nowrap (line 198), which is inherited by .optionLabel and takes precedence over overflow-wrap — white-space: nowrap suppresses all soft-wrap opportunities, including the emergency breaks overflow-wrap: anywhere would otherwise insert. So a long, unbreakable sub-option label would still overflow the sub-menu rather than wrap.
Not triggered by today's only sub-option consumer (Shelf.tsx's Private/Public privacy options are short), so this won't reproduce right now — but it means the fix is silently inert for sub-menus, which contradicts the stated intent ("Shelf and library names can be a single long token ... Break it instead") since sub-option labels can be arbitrary CMS-driven text too. Worth an explicit white-space: normal; (or removing nowrap from .subMenu and relying on min-width: 100% + overflow-wrap) so this doesn't resurface as a real bug once a long sub-option label ships.
| // left of the viewport's right edge, and capped so a long shelf | ||
| // name can't stretch the menu across the whole screen. | ||
| minWidth: menuPos.width, | ||
| maxWidth: `min(320px, calc(100vw - ${menuPos.left + 8}px))`, |
There was a problem hiding this comment.
Two edge cases in this calc(), both low-severity but worth noting:
- If the trigger sits close enough to the right edge that
100vw - (menuPos.left + 8)goes negative (e.g. a resize/scroll that leaves less than 8px of room), CSS clamps a negativemax-widthto0, which would make the portaled menu effectively invisible rather than just tight against the edge. minWidth: menuPos.width(line 118) and thismaxWidthare independent — per spec,min-widthwins overmax-widthwhen they conflict. So if the trigger itself is wider than the room available (e.g. a very long selected shelf name has grown the compact pill before the ellipsis truncation kicks in, or the trigger just happens to sit near a narrow viewport edge), the menu can still be forced wider than the viewport allows, reproducing a version of the original overflow bug.
Neither is likely with the current compact "Move To" pill in a centered modal, so this may not be worth guarding for now — flagging in case the portal variant gets reused somewhere with a wider trigger or edge-anchored placement.
Description
Long shelf names broke the Move To dropdown in the object overview modal. Two things were compounding:
width: menuPos.widthinline, and the Move To trigger is a compactwidth: fit-contentpill (~90px) — so every shelf name was crushed into a one-or-two-words-per-line column.Crime/Detectivehas no break opportunity in Chrome, and.menuisoverflow: visible, so it painted straight over the modal content behind it.What changed:
.menuPortalis nowwidth: max-content, with inlineminWidth(never narrower than the trigger) andmaxWidth: min(320px, calc(100vw - left - 8px))(never past the viewport's right edge, never stretched across the screen)..optionLabelon option and sub-option labels —overflow-wrap: anywhere, so an unbreakable name wraps inside the menu instead of over the page..moveToTriggergetsmax-width: 100%— otherwise, once a shelf is picked the pill's label becomes that shelf's name andfit-contentpushes it past the modal edge.The library switcher (
variant="library") is untouched: it isn't portaled, and it already truncates names via.libraryIdentity > p.Verified in headless Chromium against the compiled CSS — normal names sit on one line inside the box, and a 70-character space-free name wraps rather than overflowing.
🔗 Related Issue
n/a — reported directly with a screenshot of the Move To menu.
✅ Checklist
🤖 Generated with Claude Code