Skip to content

[DateRangePicker] Fix broken active range position underline in single input range fields#23166

Merged
LukasTy merged 5 commits into
mui:masterfrom
LukasTy:claude/range-activebar-visual-bug-f97d0f
Jul 22, 2026
Merged

[DateRangePicker] Fix broken active range position underline in single input range fields#23166
LukasTy merged 5 commits into
mui:masterfrom
LukasTy:claude/range-activebar-visual-bug-f97d0f

Conversation

@LukasTy

@LukasTy LukasTy commented Jul 17, 2026

Copy link
Copy Markdown
Member

Summary

The active range position underline (activeBar) that marks the range side currently being selected in a single input range field is visually broken -- it renders but is invisible.

Root cause

The bar's width is computed in resolveSectionElementWidth (PickersInputBase.tsx), which is gated on if (sectionElement.content.id). When the activeBar was introduced in #16938 every section's content object carried an id (${id}-${section.type}), so that guard was effectively always true. #19523 later removed that id from the section content props as redundant, which silently turned the guard into a permanent short-circuit: resolveSectionElementWidth now always returns 0, so activeBarWidth is always 0 and the bar renders at width: 0px.

display still toggles and left still positions correctly -- only the width was zeroed, which is why the bar was invisible rather than mispositioned.

Fix

Guard on content['data-range-position'] instead of the removed content.id. It is the typed 'start' | 'end' signal that is still present on every range section and already drives isSingleInputRange in the same file, so it is the natural, intent-revealing replacement.

Testing

There were previously zero tests referencing the activeBar, which is why the regression slipped through. This adds two browser-only tests (DateRangePicker.test.tsx): one asserting the bar has a non-zero width once a single-input desktop range picker is open, and one asserting the bar's left shifts to the end date sections after the start date is selected (which advances the picker to the end position). They are skipIf(isJSDOM) because offsetWidth / offsetLeft are always 0 in jsdom. Verified the width test fails on the old guard and passes with the fix.

Visual comparison

Before After
Screenshot 2026-07-20 at 15 51 11 Screenshot 2026-07-20 at 15 51 34

…ange fields

The single input range field's active range underline (`activeBar`) rendered at
`width: 0px` (invisible) because its width computation was gated on
`sectionElement.content.id`, which was removed from section content props in
mui#19523. Guard on `data-range-position` instead,
which is still present and already identifies range sections. Adds a browser
regression test (offsetWidth is 0 in jsdom, so it is browser-only).

Co-Authored-By: Claude Opus 4.8 <[email protected]>
@LukasTy LukasTy added type: regression A bug, but worse, it used to behave as expected. scope: pickers Changes related to the date/time pickers. component: DateRangePicker The React component labels Jul 17, 2026
@LukasTy LukasTy changed the title [fields] Fix broken active range position underline in single input range fields [DateRangePicker] Fix broken active range position underline in single input range fields Jul 17, 2026
@code-infra-dashboard

code-infra-dashboard Bot commented Jul 17, 2026

Copy link
Copy Markdown

Deploy preview

https://deploy-preview-23166--material-ui-x.netlify.app/
QR code for https://deploy-preview-23166--material-ui-x.netlify.app/

Bundle size

Bundle Parsed size Gzip size
@mui/x-data-grid 0B(0.00%) 0B(0.00%)
@mui/x-data-grid-pro 0B(0.00%) 0B(0.00%)
@mui/x-data-grid-premium 0B(0.00%) 0B(0.00%)
@mui/x-charts 0B(0.00%) 0B(0.00%)
@mui/x-charts-pro 0B(0.00%) 0B(0.00%)
@mui/x-charts-premium 0B(0.00%) 0B(0.00%)
@mui/x-date-pickers 🔺+29B(+0.01%) ▼-3B(-0.01%)
@mui/x-date-pickers-pro 🔺+29B(+0.01%) ▼-2B(0.00%)
@mui/x-tree-view 0B(0.00%) 0B(0.00%)
@mui/x-tree-view-pro 0B(0.00%) 0B(0.00%)
@mui/x-scheduler 0B(0.00%) 0B(0.00%)
@mui/x-scheduler-premium 0B(0.00%) 0B(0.00%)
@mui/x-chat 0B(0.00%) 0B(0.00%)
@mui/x-license 0B(0.00%) 0B(0.00%)

Details of bundle changes


Check out the code infra dashboard for more information about this PR.

@LukasTy LukasTy added needs cherry-pick The PR should be cherry-picked to master after merge. v8.x labels Jul 17, 2026
@LukasTy LukasTy self-assigned this Jul 17, 2026
LukasTy and others added 3 commits July 17, 2026 17:19
Adds a browser regression test verifying the active bar's `left` shifts from the
start sections to the end sections when the end date is being edited, covering
the bar's positioning alongside the existing width check.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
…rolled prop

Rewrites the active bar movement test to select the start date through the
calendar (the real user flow that advances the picker to the end position),
instead of flipping the controlled `rangePosition` prop with `setProps`.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
The regression origin is documented in the PR description, so the inline comment
only needs to state what the guard does.

Co-Authored-By: Claude Opus 4.8 <[email protected]>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a regression where the active range-position underline (activeBar) in single-input DateRangePicker fields renders with width: 0, making it invisible. It updates the width-measurement guard in PickersInputBase to rely on the still-present data-range-position attribute and adds browser-only coverage to prevent future regressions.

Changes:

  • Fix activeBar width measurement by guarding on content['data-range-position'] instead of the removed content.id.
  • Add browser-only DateRangePicker tests to assert activeBar has non-zero width and moves from start to end after selecting the start date.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
packages/x-date-pickers/src/PickersTextField/PickersInputBase/PickersInputBase.tsx Updates the activeBar measurement guard to correctly detect range sections via data-range-position.
packages/x-date-pickers-pro/src/DateRangePicker/DateRangePicker.test.tsx Adds browser-only tests validating activeBar width and left offset behavior in single-input range fields.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@LukasTy
LukasTy marked this pull request as ready for review July 17, 2026 20:34
@LukasTy
LukasTy requested a review from noraleonte July 20, 2026 12:56

@flaviendelangle flaviendelangle left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PR review

Correct, minimal regression fix: the activeBar width guard keyed off content.id, which PR #19523 silently removed, permanently zeroing the width. Switching the guard to content['data-range-position'] restores it and reads as intent. The values data-range-position can hold ('start' | 'end' | undefined) make the truthiness guard safe, and the whole measurement path is already gated behind isSingleInputRange, so there's no non-range regression. Nothing merge-blocking; one optional consistency note.

Bugs (0)

No findings.

Tests (0)

No findings.

The two new browser tests correctly pin the regression (non-zero offsetWidth) and its positioning (bar shifts right after advancing to the end position). it.skipIf(isJSDOM) is right since offsetWidth/offsetLeft are 0 in jsdom. getPickerDay('3') matches the established exact-name gridcell pattern and resolves uniquely in the January 2018 grid.

Simplifications (1)

1. ℹ️ Guard predicate differs in style from the sibling isSingleInputRange check

Location: packages/x-date-pickers/src/PickersTextField/PickersInputBase/PickersInputBase.tsx:271

// new guard
if (sectionElement.content['data-range-position']) { ... }
// sibling check, same field, line ~443
const isSingleInputRange = elements.some(
  (element) => element.content['data-range-position'] !== undefined,
);

Both read the same property but one uses truthiness and the other an explicit !== undefined. They're functionally identical here (the value is only ever 'start', 'end', or undefined), so this is purely optional — matching !== undefined would make the two range-detection checks visibly consistent and immune to a future value change. Not worth blocking on.

Failure scenario: No runtime effect today; only a minor readability/consistency cost for a future maintainer comparing the two checks.

Fix: Optionally write if (sectionElement.content['data-range-position'] !== undefined) to mirror isSingleInputRange.

Docs (0)

No findings.

Verdict

Approve — a correct, well-scoped regression fix with adequate browser test coverage; the only note is an optional style-consistency nit.


🤖 Review generated with Claude Code

Use an explicit `!== undefined` in the active bar width guard so it reads the
same way as the `isSingleInputRange` check on the same property. Functionally
identical, since `data-range-position` is normalized to `undefined` when unset.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
@LukasTy
LukasTy merged commit d29fc6b into mui:master Jul 22, 2026
21 of 22 checks passed
@github-actions

Copy link
Copy Markdown
Contributor

Cherry-pick PRs will be created targeting branches: v8.x

@LukasTy
LukasTy deleted the claude/range-activebar-visual-bug-f97d0f branch July 22, 2026 12:45
@github-actions

Copy link
Copy Markdown
Contributor

Cherry-pick PRs will be created targeting branches: v8.x, v8.x

@github-actions

Copy link
Copy Markdown
Contributor

Cherry-pick PRs will be created targeting branches: v8.x

@github-actions

Copy link
Copy Markdown
Contributor

Cherry-pick PRs will be created targeting branches: v8.x, v8.x

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

component: DateRangePicker The React component needs cherry-pick The PR should be cherry-picked to master after merge. scope: pickers Changes related to the date/time pickers. type: regression A bug, but worse, it used to behave as expected. v8.x

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants