Fix CustomSelect panel to left-align by default, right-align only when it would overflow the viewport
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Sonnet 4.6
parent
90789b5f47
commit
d2952cddd2
+8
-2
@@ -475,8 +475,8 @@
|
|||||||
.cs-panel {
|
.cs-panel {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: calc(100% + 4px);
|
top: calc(100% + 4px);
|
||||||
right: 0; /* right edge flushes with button's right edge */
|
left: 0; /* left edge flushes with button's left edge by default */
|
||||||
left: auto;
|
right: auto;
|
||||||
z-index: 1000;
|
z-index: 1000;
|
||||||
background: #fffcf2;
|
background: #fffcf2;
|
||||||
border: 1.5px solid #c9b08a;
|
border: 1.5px solid #c9b08a;
|
||||||
@@ -487,6 +487,12 @@
|
|||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Flip panel to right-align when left-align would overflow the viewport */
|
||||||
|
.cs-panel.cs-panel--right {
|
||||||
|
left: auto;
|
||||||
|
right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Each option row */
|
/* Each option row */
|
||||||
.cs-option {
|
.cs-option {
|
||||||
display: block;
|
display: block;
|
||||||
|
|||||||
+13
-2
@@ -41,7 +41,9 @@ const html = htm.bind(h);
|
|||||||
// -------------------------------------------------------------------
|
// -------------------------------------------------------------------
|
||||||
export function CustomSelect({ value, options, onChange, hideLabel, hidingLabel, buttonLabel, isOn, noHide, groupedLeft, isLastChild, grpClass }) {
|
export function CustomSelect({ value, options, onChange, hideLabel, hidingLabel, buttonLabel, isOn, noHide, groupedLeft, isLastChild, grpClass }) {
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
const wrapRef = useRef(null);
|
const [flipRight, setFlipRight] = useState(false);
|
||||||
|
const wrapRef = useRef(null);
|
||||||
|
const panelRef = useRef(null);
|
||||||
|
|
||||||
// Close on outside click or Escape
|
// Close on outside click or Escape
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@@ -60,6 +62,15 @@ export function CustomSelect({ value, options, onChange, hideLabel, hidingLabel,
|
|||||||
};
|
};
|
||||||
}, [open]);
|
}, [open]);
|
||||||
|
|
||||||
|
// After the panel renders, check if it overflows the right viewport edge.
|
||||||
|
// If so, flip it to right-align; otherwise keep it left-aligned.
|
||||||
|
useEffect(() => {
|
||||||
|
if (!open) { setFlipRight(false); return; }
|
||||||
|
if (!panelRef.current) return;
|
||||||
|
const rect = panelRef.current.getBoundingClientRect();
|
||||||
|
setFlipRight(rect.right > window.innerWidth - 8);
|
||||||
|
}, [open]);
|
||||||
|
|
||||||
// Build the label shown on the button
|
// Build the label shown on the button
|
||||||
const activeOpt = options.find(o => o.value === value);
|
const activeOpt = options.find(o => o.value === value);
|
||||||
const btnLabel = buttonLabel || (isOn
|
const btnLabel = buttonLabel || (isOn
|
||||||
@@ -85,7 +96,7 @@ export function CustomSelect({ value, options, onChange, hideLabel, hidingLabel,
|
|||||||
<span class="cs-arrow"></span>
|
<span class="cs-arrow"></span>
|
||||||
</button>
|
</button>
|
||||||
${open && html`
|
${open && html`
|
||||||
<div class="cs-panel" role="listbox">
|
<div class=${`cs-panel${flipRight ? ' cs-panel--right' : ''}`} ref=${panelRef} role="listbox">
|
||||||
${isOn && !noHide && html`
|
${isOn && !noHide && html`
|
||||||
<span
|
<span
|
||||||
class="cs-option"
|
class="cs-option"
|
||||||
|
|||||||
Reference in New Issue
Block a user