diff --git a/src/components/library/molecules/Dropdown/Dropdown.module.scss b/src/components/library/molecules/Dropdown/Dropdown.module.scss
index 6ae6fdc6..283cac88 100644
--- a/src/components/library/molecules/Dropdown/Dropdown.module.scss
+++ b/src/components/library/molecules/Dropdown/Dropdown.module.scss
@@ -42,6 +42,12 @@
.text {
flex: 1;
+ // The trigger is a fixed-height row, so a long selected label has to
+ // truncate — wrapping would spill out of the bottom of the control.
+ min-width: 0;
+ overflow: hidden;
+ white-space: nowrap;
+ text-overflow: ellipsis;
text-align: left;
}
@@ -98,6 +104,12 @@
position: fixed;
right: auto;
z-index: 1500;
+ // `.menu` is `width: 100%`, which under `position: fixed` resolves against
+ // the viewport. Size to the longest option instead; the inline min-width
+ // keeps the menu at least as wide as the trigger (compact pill triggers
+ // would otherwise crush option labels into a one-word-per-line column) and
+ // the inline max-width keeps it inside the viewport.
+ width: max-content;
}
.optionWrapper {
@@ -138,6 +150,14 @@
}
}
+// Shelf and library names can be a single long token ("Crime/Detective"), and
+// the menu is `overflow: visible` so an unbroken one paints over whatever sits
+// behind the dropdown. Break it instead.
+.optionLabel {
+ min-width: 0;
+ overflow-wrap: anywhere;
+}
+
.subArrow {
flex-shrink: 0;
transform: rotate(0deg);
diff --git a/src/components/library/molecules/Dropdown/Dropdown.tsx b/src/components/library/molecules/Dropdown/Dropdown.tsx
index 80330446..647272b1 100644
--- a/src/components/library/molecules/Dropdown/Dropdown.tsx
+++ b/src/components/library/molecules/Dropdown/Dropdown.tsx
@@ -112,7 +112,11 @@ export function Dropdown(props: DropdownProps): JSX.Element {
? {
top: menuPos.top,
left: menuPos.left,
- width: menuPos.width,
+ // Never narrower than the trigger, never wider than the room
+ // 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))`,
transform:
menuPos.placement === 'top' ? 'translateY(-100%)' : undefined,
}
@@ -167,7 +171,12 @@ export function Dropdown(props: DropdownProps): JSX.Element {
>
) : (
- {option.label}
+
+ {option.label}
+
)}
{hasSubOptions ? (
handleSubSelect(sub.value))}
aria-label={`Select ${sub.label}`}
>
-
+
{sub.label}
{value === sub.value && (
diff --git a/src/components/library/organisms/ObjectOverviewModal/ObjectOverviewModal.module.scss b/src/components/library/organisms/ObjectOverviewModal/ObjectOverviewModal.module.scss
index 6469c808..4bdc0fb5 100644
--- a/src/components/library/organisms/ObjectOverviewModal/ObjectOverviewModal.module.scss
+++ b/src/components/library/organisms/ObjectOverviewModal/ObjectOverviewModal.module.scss
@@ -363,6 +363,9 @@
// the Shelf settings-trigger override). Compact pill, not a full-width field.
.moveToTrigger {
width: fit-content !important;
+ // The pill hugs its label, so a long shelf name would push it past the
+ // modal's edge; cap it and let the trigger's own ellipsis do the rest.
+ max-width: 100%;
padding: 7px 12px !important;
background: var(--white) !important;
border: 1px solid var(--beige) !important;