fix(DateRangePicker): auto-flip popup when it would overflow viewport#232
Merged
Conversation
Adds an `align` prop ('start' | 'end' | 'auto', default 'auto') that
controls the horizontal alignment of the desktop calendar popup. Under
'auto' we measure the trigger after open and flip from left-aligned to
right-aligned when the popup would otherwise spill past the right edge
of the viewport.
Fixes the picker being clipped off the page when the trigger sits in a
right-aligned slot (e.g. a page header's actions area).
There was a problem hiding this comment.
Pull request overview
Adds an align prop ('start' | 'end' | 'auto', default 'auto') to DateRangePicker to prevent the desktop calendar popup from overflowing the right edge of the viewport when the trigger sits in a right-aligned slot. Auto mode measures the trigger via useLayoutEffect and flips to right-edge alignment when needed.
Changes:
- New
alignprop with'auto'default; resolved alignment tracked in state. useLayoutEffectmeasures the trigger and flips to'end'when the estimated popup width (840px with presets, 640px without) would overflow.- Popup container conditionally uses
right-0orleft-0.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| src/components/DateRangePicker/DateRangePicker.tsx | Adds align prop, auto-flip layout effect, and conditional right-0/left-0 class on popup. |
| package.json | Version bump from 0.5.0 to 0.6.1. |
Comments suppressed due to low confidence (1)
src/components/DateRangePicker/DateRangePicker.tsx:430
- Popup width is hardcoded (200px sidebar + ~640px calendar panel). If the calendar's actual rendered width changes (e.g., due to font scaling, locale-specific month/weekday labels, or future style adjustments to padding/columns), the flip threshold will drift out of sync with reality. Consider measuring the popup's actual width via
calendarRef.current.getBoundingClientRect()after it mounts to make the heuristic robust to layout changes.
// Approximate popup width: preset sidebar (200px) + dual calendar panel
// (~640px including padding). Slight overestimate is fine — we just want
// to flip when 'start' alignment would clearly overflow.
const estimatedPopupWidth = showPresets ? 840 : 640;
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+417
to
+436
| React.useLayoutEffect(() => { | ||
| if (isMobileVariant || !isCalendarOpen) return; | ||
| if (align === 'start' || align === 'end') { | ||
| setResolvedAlign(align); | ||
| return; | ||
| } | ||
| if (typeof window === 'undefined') return; | ||
| const trigger = triggerRef.current; | ||
| if (!trigger) return; | ||
| const rect = trigger.getBoundingClientRect(); | ||
| // Approximate popup width: preset sidebar (200px) + dual calendar panel | ||
| // (~640px including padding). Slight overestimate is fine — we just want | ||
| // to flip when 'start' alignment would clearly overflow. | ||
| const estimatedPopupWidth = showPresets ? 840 : 640; | ||
| const margin = 8; | ||
| const overflowsRight = | ||
| rect.left + estimatedPopupWidth > window.innerWidth - margin; | ||
| const fitsLeftAligned = rect.right - estimatedPopupWidth >= margin; | ||
| setResolvedAlign(overflowsRight && fitsLeftAligned ? 'end' : 'start'); | ||
| }, [align, isCalendarOpen, isMobileVariant, showPresets]); |
| { | ||
| "name": "@mieweb/ui", | ||
| "version": "0.5.0", | ||
| "version": "0.6.1", |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds an
alignprop toDateRangePickerand auto-flips the popup when the default left-aligned position would overflow the viewport.Why
The desktop calendar popup is always rendered with
absolute top-full left-0, so when the trigger sits in a right-aligned slot (e.g. a page header's actions area) the popup spills past the right edge of the viewport and gets clipped.What changed
align?: 'start' | 'end' | 'auto'prop onDateRangePicker, default'auto'.'start': original behavior — popup left edge at trigger left edge.'end': popup right edge at trigger right edge.'auto': starts at'start'and, after open, measures the trigger and flips to'end'when the popup would overflow the viewport on the right.useLayoutEffectandtriggerRef.getBoundingClientRect()so it runs before paint, no visible jump.showPresets).Backward compatibility
Default switches from "always left" to "auto", but auto only flips when the original behavior would actually overflow. Existing usages on the left side of layouts render identically. Consumers can pin to the old behavior with
align="start".Tested