Skip to content

Commit 8223dab

Browse files
authored
Merge pull request #3789 from AnnMarieW/fix-datepickers-resize-detector
fix styling issues caused by ResizeDetector wrapper
2 parents bb2d0f0 + 24f846a commit 8223dab

3 files changed

Lines changed: 263 additions & 264 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ This project adheres to [Semantic Versioning](https://semver.org/).
2020
- [#3740](https://github.com/plotly/dash/pull/3740) Fix cannot tab into dropdowns in Safari
2121
- [#2462](https://github.com/plotly/dash/issues/2462) Allow `MATCH` in `Input`/`State` when the callback's `Output` has no wildcards (fixed-id Output, no Output, or `ALL`-only wildcard Output). `ALLSMALLER` still requires a corresponding `MATCH` in an Output.
2222
- [#3759](https://github.com/plotly/dash/pull/3759) Fix the issue where `Patch` objects cannot be updated via `set_props()` in `websocket` callback. Fix [#3742](https://github.com/plotly/dash/issues/3742)
23+
- [#3789](https://github.com/plotly/dash/pull/3789) Fixed extra wrapper in `DatePickerRange` and `DatePickerSingle` causing styling and layout issues.
2324

2425
## [4.2.0rc3] - 2026-05-12
2526

components/dash-core-components/src/fragments/DatePickerRange.tsx

Lines changed: 147 additions & 148 deletions
Original file line numberDiff line numberDiff line change
@@ -357,159 +357,158 @@ const DatePickerRange = ({
357357
);
358358

359359
return (
360-
<ResizeDetector onResize={handleResize} targets={[containerRef]}>
361-
<div className="dash-datepicker" ref={containerRef}>
362-
<Popover.Root
363-
open={!disabled && isCalendarOpen}
364-
onOpenChange={disabled ? undefined : setIsCalendarOpen}
365-
>
366-
<Popover.Trigger asChild disabled={disabled}>
367-
<div
368-
id={accessibleId + '-wrapper'}
369-
className={classNames}
370-
style={style}
371-
aria-labelledby={`${accessibleId} ${accessibleId}-end-date ${start_date_id} ${end_date_id}`}
372-
aria-haspopup="dialog"
373-
aria-expanded={isCalendarOpen}
374-
aria-disabled={disabled}
375-
onClick={e => {
376-
e.preventDefault();
377-
if (!isCalendarOpen && !disabled) {
378-
setIsCalendarOpen(true);
379-
}
380-
}}
381-
>
382-
<AutosizeInput
383-
ref={startAutosizeRef}
384-
inputRef={node => {
385-
startInputRef.current = node;
386-
}}
387-
type="text"
388-
id={start_date_id || accessibleId}
389-
inputClassName="dash-datepicker-input dash-datepicker-start-date"
390-
value={startInputValue}
391-
onChange={e =>
392-
setStartInputValue(e.target?.value)
393-
}
394-
onKeyDown={handleStartInputKeyDown}
395-
onFocus={() => {
396-
if (isCalendarOpen) {
397-
sendStartInputAsDate();
398-
}
399-
}}
400-
placeholder={start_date_placeholder_text}
401-
disabled={disabled}
402-
dir={direction}
403-
aria-label={start_date_placeholder_text}
404-
/>
405-
<ArrowIcon className="dash-datepicker-range-arrow" />
406-
<AutosizeInput
407-
ref={endAutosizeRef}
408-
inputRef={node => {
409-
endInputRef.current = node;
410-
}}
411-
type="text"
412-
id={end_date_id || accessibleId + '-end-date'}
413-
inputClassName="dash-datepicker-input dash-datepicker-end-date"
414-
value={endInputValue}
415-
onChange={e =>
416-
setEndInputValue(e.target?.value)
417-
}
418-
onKeyDown={handleEndInputKeyDown}
419-
onFocus={() => {
420-
if (isCalendarOpen) {
421-
sendEndInputAsDate();
422-
}
423-
}}
424-
placeholder={end_date_placeholder_text}
425-
disabled={disabled}
426-
dir={direction}
427-
aria-label={end_date_placeholder_text}
428-
/>
429-
{clearable && !disabled && (
430-
<a
431-
className="dash-datepicker-clear"
432-
onClick={clearSelection}
433-
aria-label="Clear Dates"
434-
>
435-
<Cross1Icon />
436-
</a>
437-
)}
438-
<CaretDownIcon className="dash-datepicker-caret-icon" />
439-
</div>
440-
</Popover.Trigger>
441-
442-
<Popover.Portal
443-
container={hasPortal ? undefined : containerRef.current}
360+
<div className="dash-datepicker" ref={containerRef}>
361+
<ResizeDetector onResize={handleResize} targets={[containerRef]}/>
362+
<Popover.Root
363+
open={!disabled && isCalendarOpen}
364+
onOpenChange={disabled ? undefined : setIsCalendarOpen}
365+
>
366+
<Popover.Trigger asChild disabled={disabled}>
367+
<div
368+
id={accessibleId + '-wrapper'}
369+
className={classNames}
370+
style={style}
371+
aria-labelledby={`${accessibleId} ${accessibleId}-end-date ${start_date_id} ${end_date_id}`}
372+
aria-haspopup="dialog"
373+
aria-expanded={isCalendarOpen}
374+
aria-disabled={disabled}
375+
onClick={e => {
376+
e.preventDefault();
377+
if (!isCalendarOpen && !disabled) {
378+
setIsCalendarOpen(true);
379+
}
380+
}}
444381
>
445-
<Popover.Content
446-
className={`dash-datepicker-content${
447-
hasPortal ? ' dash-datepicker-portal' : ''
448-
}${
449-
with_full_screen_portal
450-
? ' dash-datepicker-fullscreen'
451-
: ''
452-
}`}
453-
style={portalStyle}
454-
align={hasPortal ? 'center' : 'start'}
455-
sideOffset={hasPortal ? 0 : 5}
456-
avoidCollisions={!hasPortal}
457-
onInteractOutside={
458-
with_full_screen_portal
459-
? e => e.preventDefault()
460-
: undefined
382+
<AutosizeInput
383+
ref={startAutosizeRef}
384+
inputRef={node => {
385+
startInputRef.current = node;
386+
}}
387+
type="text"
388+
id={start_date_id || accessibleId}
389+
inputClassName="dash-datepicker-input dash-datepicker-start-date"
390+
value={startInputValue}
391+
onChange={e =>
392+
setStartInputValue(e.target?.value)
461393
}
462-
onOpenAutoFocus={e => e.preventDefault()}
463-
onCloseAutoFocus={e => {
464-
e.preventDefault();
465-
// Only focus if focus is not already on one of the inputs
466-
const inputs: (Element | null)[] = [
467-
startInputRef.current,
468-
endInputRef.current,
469-
];
470-
if (inputs.includes(document.activeElement)) {
471-
return;
394+
onKeyDown={handleStartInputKeyDown}
395+
onFocus={() => {
396+
if (isCalendarOpen) {
397+
sendStartInputAsDate();
472398
}
473-
474-
// Keeps focus on the component when the calendar closes
475-
if (!startInputValue) {
476-
startInputRef.current?.focus();
477-
} else {
478-
endInputRef.current?.focus();
399+
}}
400+
placeholder={start_date_placeholder_text}
401+
disabled={disabled}
402+
dir={direction}
403+
aria-label={start_date_placeholder_text}
404+
/>
405+
<ArrowIcon className="dash-datepicker-range-arrow" />
406+
<AutosizeInput
407+
ref={endAutosizeRef}
408+
inputRef={node => {
409+
endInputRef.current = node;
410+
}}
411+
type="text"
412+
id={end_date_id || accessibleId + '-end-date'}
413+
inputClassName="dash-datepicker-input dash-datepicker-end-date"
414+
value={endInputValue}
415+
onChange={e =>
416+
setEndInputValue(e.target?.value)
417+
}
418+
onKeyDown={handleEndInputKeyDown}
419+
onFocus={() => {
420+
if (isCalendarOpen) {
421+
sendEndInputAsDate();
479422
}
480423
}}
481-
>
482-
{with_full_screen_portal && (
483-
<button
484-
className="dash-datepicker-close-button"
485-
onClick={() => setIsCalendarOpen(false)}
486-
aria-label="Close calendar"
487-
>
488-
<Cross1Icon />
489-
</button>
490-
)}
491-
<Calendar
492-
ref={calendarRef}
493-
initialVisibleDate={initialCalendarDate}
494-
selectionStart={internalStartDate}
495-
selectionEnd={internalEndDate}
496-
minDateAllowed={minDate}
497-
maxDateAllowed={maxDate}
498-
disabledDates={disabledDates}
499-
firstDayOfWeek={first_day_of_week}
500-
showOutsideDays={show_outside_days}
501-
monthFormat={month_format}
502-
numberOfMonthsShown={number_of_months_shown}
503-
calendarOrientation={calendar_orientation}
504-
daySize={day_size}
505-
direction={direction}
506-
onSelectionChange={handleSelectionChange}
507-
/>
508-
</Popover.Content>
509-
</Popover.Portal>
510-
</Popover.Root>
511-
</div>
512-
</ResizeDetector>
424+
placeholder={end_date_placeholder_text}
425+
disabled={disabled}
426+
dir={direction}
427+
aria-label={end_date_placeholder_text}
428+
/>
429+
{clearable && !disabled && (
430+
<a
431+
className="dash-datepicker-clear"
432+
onClick={clearSelection}
433+
aria-label="Clear Dates"
434+
>
435+
<Cross1Icon />
436+
</a>
437+
)}
438+
<CaretDownIcon className="dash-datepicker-caret-icon" />
439+
</div>
440+
</Popover.Trigger>
441+
442+
<Popover.Portal
443+
container={hasPortal ? undefined : containerRef.current}
444+
>
445+
<Popover.Content
446+
className={`dash-datepicker-content${
447+
hasPortal ? ' dash-datepicker-portal' : ''
448+
}${
449+
with_full_screen_portal
450+
? ' dash-datepicker-fullscreen'
451+
: ''
452+
}`}
453+
style={portalStyle}
454+
align={hasPortal ? 'center' : 'start'}
455+
sideOffset={hasPortal ? 0 : 5}
456+
avoidCollisions={!hasPortal}
457+
onInteractOutside={
458+
with_full_screen_portal
459+
? e => e.preventDefault()
460+
: undefined
461+
}
462+
onOpenAutoFocus={e => e.preventDefault()}
463+
onCloseAutoFocus={e => {
464+
e.preventDefault();
465+
// Only focus if focus is not already on one of the inputs
466+
const inputs: (Element | null)[] = [
467+
startInputRef.current,
468+
endInputRef.current,
469+
];
470+
if (inputs.includes(document.activeElement)) {
471+
return;
472+
}
473+
474+
// Keeps focus on the component when the calendar closes
475+
if (!startInputValue) {
476+
startInputRef.current?.focus();
477+
} else {
478+
endInputRef.current?.focus();
479+
}
480+
}}
481+
>
482+
{with_full_screen_portal && (
483+
<button
484+
className="dash-datepicker-close-button"
485+
onClick={() => setIsCalendarOpen(false)}
486+
aria-label="Close calendar"
487+
>
488+
<Cross1Icon />
489+
</button>
490+
)}
491+
<Calendar
492+
ref={calendarRef}
493+
initialVisibleDate={initialCalendarDate}
494+
selectionStart={internalStartDate}
495+
selectionEnd={internalEndDate}
496+
minDateAllowed={minDate}
497+
maxDateAllowed={maxDate}
498+
disabledDates={disabledDates}
499+
firstDayOfWeek={first_day_of_week}
500+
showOutsideDays={show_outside_days}
501+
monthFormat={month_format}
502+
numberOfMonthsShown={number_of_months_shown}
503+
calendarOrientation={calendar_orientation}
504+
daySize={day_size}
505+
direction={direction}
506+
onSelectionChange={handleSelectionChange}
507+
/>
508+
</Popover.Content>
509+
</Popover.Portal>
510+
</Popover.Root>
511+
</div>
513512
);
514513
};
515514

0 commit comments

Comments
 (0)