Skip to content

fix(ui): replace MUI date picker with existing date picker menu#30027

Open
shah-harshit wants to merge 2 commits into
mainfrom
ui/replace-mui-date-picker
Open

fix(ui): replace MUI date picker with existing date picker menu#30027
shah-harshit wants to merge 2 commits into
mainfrom
ui/replace-mui-date-picker

Conversation

@shah-harshit

@shah-harshit shah-harshit commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Describe your changes:

Replaced the remaining OSS MUI date picker usages in profiler tab filters, dimensionality, and incident manager with the existing AntD-backed DatePickerMenu.

Incident manager retains preset ranges, places the custom range option last, supports clearing the active filter, preserves the previous placeholder, and keeps the trigger height and clear icon alignment stable. The obsolete MuiDatePickerMenu component, interface, and tests are removed.

Type of change:

  • Bug fix
  • Improvement
  • New feature
  • Breaking change
  • Documentation

High-level design:

All three consumers now use the existing AntD-backed DatePickerMenu directly. The shared picker accepts optional placeholder and clear callbacks so incident manager can retain its URL-filter behavior without introducing a wrapper or changing core-ui components.

Tests:

Use cases covered

  • Profiler and dimensionality filters render the existing date picker menu and propagate preset/custom ranges.
  • Incident manager renders presets followed by custom range selection.
  • Empty incident filters show the disabled-color placeholder.
  • Selected filters keep a fixed trigger height and vertically centered clear control.
  • Clearing a selected range invokes the existing URL filter reset.

Unit tests

  • Updated unit tests for changed logic.
  • Focused Jest suites: 3 passed, 60 tests passed.

Backend integration tests

  • Not applicable (no backend API changes).

Ingestion integration tests

  • Not applicable (no ingestion changes).

Playwright (UI) tests

  • Not applicable (covered by focused unit tests; no E2E added).

Verification performed

  • UI checkstyle sequence on changed TypeScript files.
  • Changed-file TypeScript check.
  • git diff --check.

UI screen recording / screenshots:

Not attached.

Checklist:

  • I have read the CONTRIBUTING document.
  • My PR title is Fixes :
  • My PR is linked to a GitHub issue via Fixes # above.
  • I have commented on my code, particularly in hard-to-understand areas.
  • For JSON Schema changes: I updated the migration scripts or explained why it is not needed.
  • For UI changes: I attached a screen recording and/or screenshots above.
  • I have added tests (unit / integration / Playwright as applicable) and listed them above.

Greptile Summary

This PR replaces the MUI date picker usage with the shared DatePickerMenu path. The main changes are:

  • Profiler, dimensionality, and incident manager filters now render through DatePickerMenu.
  • The shared picker supports clear actions, placeholders, trigger labels, and selected custom range labels.
  • Date picker tests were updated for the new component behavior.

Confidence Score: 4/5

This is close, but the dimensionality date filter should be fixed before merging.

  • Preset selection now follows the rolling window behavior.
  • Custom ranges are passed through directly in the profiler and incident manager paths.
  • The dimensionality path still re-bounds custom range timestamps in UTC, which can return rows outside the selected local dates.

openmetadata-ui/src/main/resources/ui/src/components/DataQuality/IncidentManager/DimensionalityTab/DimensionalityTab.tsx

Important Files Changed

Filename Overview
openmetadata-ui/src/main/resources/ui/src/components/common/DatePickerMenu/DatePickerMenu.component.tsx Adds clear, placeholder, and trigger label behavior to the shared date picker.
openmetadata-ui/src/main/resources/ui/src/components/DataQuality/IncidentManager/DimensionalityTab/DimensionalityTab.tsx Switches the dimensionality date filter to DatePickerMenu, but custom ranges can be bounded twice.
openmetadata-ui/src/main/resources/ui/src/components/Database/Profiler/DataObservability/TabFilters/TabFilters.tsx Switches profiler tab filters to the shared date picker.
openmetadata-ui/src/main/resources/ui/src/components/IncidentManager/IncidentManager.component.tsx Switches incident manager filtering to the shared date picker with clear and placeholder support.

Reviews (4): Last reviewed commit: "fix(ui): use existing date picker menu" | Re-trigger Greptile

Greptile also left 1 inline comment on this PR.

Context used (3)

  • Context used - CLAUDE.md (source)
  • Context used - openmetadata-ui-core-components/CLAUDE.md (source)
  • Context used - AGENTS.md (source)

@shah-harshit shah-harshit requested review from a team, chirag-madlani and karanh37 as code owners July 14, 2026 07:54
@shah-harshit shah-harshit added UI UI specific issues safe to test Add this label to run secure Github workflows on PRs skip-pr-checks Bypass PR metadata validation check labels Jul 14, 2026
@shah-harshit shah-harshit self-assigned this Jul 14, 2026
@github-actions

Copy link
Copy Markdown
Contributor

❌ PR checklist incomplete

This PR cannot be merged until the following are addressed on its linked issue:

  • No GitHub issue is linked. Link an issue in the Development section of the PR (or add Fixes #12345 to the description). For a same-org cross-repo issue, add Fixes open-metadata/<repo>#123 to the description.

The fields live on the linked issue in the Shipping project (open the issue → right sidebar → Projects). After you set them, re-run this check (or push a commit) — issue/project changes do not re-trigger it automatically.

Maintainers can bypass this check by adding the skip-pr-checks label.

Comment thread openmetadata-ui/src/main/resources/ui/src/utils/DatePickerMenuUtils.tsx Outdated
Comment thread openmetadata-ui/src/main/resources/ui/src/utils/DatePickerMenuUtils.tsx Outdated
Comment on lines +206 to +220
<Button
color="secondary"
iconLeading={CalendarIcon}
size="md"
{...buttonProps}>
{triggerContent}
{allowClear && value && (
<span
data-testid={clearButtonTestId}
role="button"
tabIndex={0}
onClick={(event) => {
event.stopPropagation();
setValue(null);
onClear?.();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Quality: Clear action is an interactive span nested inside a Button

The clear affordance renders a <span role="button" tabIndex={0}> inside the trigger <Button> (a native button). Nesting interactive/clickable content inside a button is invalid HTML and can produce inconsistent focus/keyboard behavior across browsers and screen readers. Consider rendering the clear control as a sibling of the trigger button rather than a descendant, or using a non-button trigger container.

Was this helpful? React with 👍 / 👎

@github-actions

github-actions Bot commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Jest test Coverage

UI tests summary

Lines Statements Branches Functions
Coverage: 64%
64.5% (75481/117018) 48.43% (45023/92950) 49.12% (13608/27698)

@shah-harshit shah-harshit force-pushed the ui/replace-mui-date-picker branch from 299b0c7 to 6609d05 Compare July 14, 2026 09:39
Comment thread openmetadata-ui/src/main/resources/ui/src/utils/DatePickerMenuUtils.tsx Outdated
Comment on lines +250 to +264
<Button
color="secondary"
data-testid="date-range-picker"
iconTrailing={
<DropDownIcon
className="align-middle"
height={16}
width={16}
/>
}
size="sm">
<span>{selectedDateRangeLabel}</span>
{dateRangeKey && (
<span
data-testid="clear-date-picker"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Quality: Clear control is an interactive span nested inside a Button

The clear affordance is a <span role="button" tabIndex={0}> nested inside the <Button> that serves as the dropdown trigger, producing nested interactive elements (invalid HTML/ARIA) and a clickable icon with no accessible name. Consider rendering the clear control as a sibling of the trigger button rather than a child, and add an aria-label (e.g. t('label.clear')) to the XClose control.

Add an accessible name; ideally also move it out of the Button to avoid nested interactive elements.:

<span
  aria-label={t('label.clear')}
  data-testid="clear-date-picker"
  role="button"
  tabIndex={0}
  onClick={...}
  onKeyDown={...}>
  <XClose className="tw:size-4" />
</span>
  • Apply fix

Check the box to apply the fix or reply for a change | Was this helpful? React with 👍 / 👎

@sonarqubecloud

Copy link
Copy Markdown

@shah-harshit shah-harshit changed the title Replace MUI date picker with core picker fix(ui): replace MUI date picker with existing date picker menu Jul 14, 2026
@@ -280,7 +287,7 @@ const DimensionalityTab = () => {
<p className="tw:m-0 tw:text-sm tw:font-medium tw:whitespace-nowrap tw:text-primary">

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.

P1 Custom range rebounded This picker now emits custom range timestamps that are already bounded from the selected Luxon dates. The dimensionality handler still runs those values through getStartOfDayInMillis and getEndOfDayInMillis, which truncates them again in UTC. For a UTC+05:30 user selecting Mar 4, the picker can pass Mar 3 18:30Z as the local-day start, and this caller then moves it to Mar 3 00:00Z. The dimensionality query can include data from the previous day instead of the selected local range.

{`${t('label.date')}:`}
</span>
<MuiDatePickerMenu
<DatePickerMenu

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Bug: TabFilters date label goes stale on external URL changes

DatePickerMenu seeds selectedTimeRange/selectedTimeRangeKey from defaultOptions only at mount (useState initializer). In TabFilters.tsx the defaultDateRange={dateRangeObject} is derived from location.search, but no key prop forces a remount, so when the URL date params change through means other than this picker (e.g. browser back/forward), the trigger label keeps showing the previous range while the fetched data reflects the new URL. The prior MUI picker was controlled via value and did not have this drift. IncidentManager already works around it with a key prop keyed on the range; apply the same pattern to TabFilters (and confirm DimensionalityTab, which uses a constant default, is unaffected).

Force a remount when the URL-derived range changes so the trigger label stays in sync, matching the IncidentManager pattern.:

<DatePickerMenu
  showSelectedCustomRange
  defaultDateRange={dateRangeObject}
  handleDateRangeChange={handleDateRangeChange}
  key={`${dateRangeObject.key}-${dateRangeObject.startTs}-${dateRangeObject.endTs}`}
  size="small"
/>
  • Apply fix

Check the box to apply the fix or reply for a change | Was this helpful? React with 👍 / 👎

@gitar-bot

gitar-bot Bot commented Jul 14, 2026

Copy link
Copy Markdown
Code Review 👍 Approved with suggestions 2 resolved / 5 findings

Replaces MUI date pickers with the standard AntD-backed DatePickerMenu across profiler and incident manager components. Resolve nested interactive elements in the clear control and ensure the date label syncs correctly with external URL changes.

💡 Quality: Clear action is an interactive span nested inside a Button

📄 openmetadata-ui-core-components/src/main/resources/ui/src/components/application/date-picker/date-range-picker.tsx:206-220

The clear affordance renders a <span role="button" tabIndex={0}> inside the trigger <Button> (a native button). Nesting interactive/clickable content inside a button is invalid HTML and can produce inconsistent focus/keyboard behavior across browsers and screen readers. Consider rendering the clear control as a sibling of the trigger button rather than a descendant, or using a non-button trigger container.

💡 Quality: Clear control is an interactive span nested inside a Button

📄 openmetadata-ui/src/main/resources/ui/src/components/IncidentManager/IncidentManager.component.tsx:250-264

The clear affordance is a <span role="button" tabIndex={0}> nested inside the <Button> that serves as the dropdown trigger, producing nested interactive elements (invalid HTML/ARIA) and a clickable icon with no accessible name. Consider rendering the clear control as a sibling of the trigger button rather than a child, and add an aria-label (e.g. t('label.clear')) to the XClose control.

Add an accessible name; ideally also move it out of the Button to avoid nested interactive elements.
<span
  aria-label={t('label.clear')}
  data-testid="clear-date-picker"
  role="button"
  tabIndex={0}
  onClick={...}
  onKeyDown={...}>
  <XClose className="tw:size-4" />
</span>
💡 Bug: TabFilters date label goes stale on external URL changes

📄 openmetadata-ui/src/main/resources/ui/src/components/Database/Profiler/DataObservability/TabFilters/TabFilters.tsx:213-218 📄 openmetadata-ui/src/main/resources/ui/src/components/common/DatePickerMenu/DatePickerMenu.component.tsx:124-130

DatePickerMenu seeds selectedTimeRange/selectedTimeRangeKey from defaultOptions only at mount (useState initializer). In TabFilters.tsx the defaultDateRange={dateRangeObject} is derived from location.search, but no key prop forces a remount, so when the URL date params change through means other than this picker (e.g. browser back/forward), the trigger label keeps showing the previous range while the fetched data reflects the new URL. The prior MUI picker was controlled via value and did not have this drift. IncidentManager already works around it with a key prop keyed on the range; apply the same pattern to TabFilters (and confirm DimensionalityTab, which uses a constant default, is unaffected).

Force a remount when the URL-derived range changes so the trigger label stays in sync, matching the IncidentManager pattern.
<DatePickerMenu
  showSelectedCustomRange
  defaultDateRange={dateRangeObject}
  handleDateRangeChange={handleDateRangeChange}
  key={`${dateRangeObject.key}-${dateRangeObject.startTs}-${dateRangeObject.endTs}`}
  size="small"
/>
✅ 2 resolved
Bug: Controlled picker without onChange breaks custom range selection

📄 openmetadata-ui-core-components/src/main/resources/ui/src/components/application/date-picker/date-range-picker.tsx:93-97 📄 openmetadata-ui-core-components/src/main/resources/ui/src/components/application/date-picker/date-range-picker.tsx:186-189 📄 openmetadata-ui-core-components/src/main/resources/ui/src/components/application/date-picker/date-range-picker.tsx:203-204 📄 openmetadata-ui-core-components/src/main/resources/ui/src/components/application/date-picker/date-range-picker.tsx:284-296 📄 openmetadata-ui/src/main/resources/ui/src/components/Database/Profiler/DataObservability/TabFilters/TabFilters.tsx:269-279 📄 openmetadata-ui/src/main/resources/ui/src/components/IncidentManager/IncidentManager.component.tsx:227-239 📄 openmetadata-ui/src/main/resources/ui/src/components/DataQuality/IncidentManager/DimensionalityTab/DimensionalityTab.tsx:344-354
All three consumers pass value={dateRangePickerValue} but never pass onChange. Inside DateRangePicker, useControlledState(valueProp, defaultValue||null, onChange) treats a non-undefined valueProp (even null) as controlled, so the returned setValue only fires onChange (undefined here) and never updates the displayed value. As a result, AriaDateRangePicker value={value} onChange={setValue} can never reflect dates the user picks in the calendar, and clicking Apply calls handleApplyonApply?.(value,...) with the stale controlled value. Preset selection still works only because applyOnPresetSelect routes through onApply to the parent, but the custom-range flow the PR claims to preserve is broken. Fix by having the picker keep an internal draft state seeded/synced from value (so calendar edits and Apply use the edited value), or require consumers to supply onChange.

Bug: Date-range trigger button renders blank when no range selected

📄 openmetadata-ui/src/main/resources/ui/src/components/IncidentManager/IncidentManager.component.tsx:260-261
When no date filter is applied, dateRangeKey is undefined, so selectedDateRangeLabel is undefined and the trigger renders <span>{undefined}</span> — an empty label showing only the dropdown chevron. The removed core DateRangePicker handled this via its placeholder/triggerLabel fallback, so this migration is a UX regression for the default (unfiltered) state. Provide a fallback label, e.g. <span>{selectedDateRangeLabel ?? t('label.date-range')}</span>.

🤖 Prompt for agents
Code Review: Replaces MUI date pickers with the standard AntD-backed DatePickerMenu across profiler and incident manager components. Resolve nested interactive elements in the clear control and ensure the date label syncs correctly with external URL changes.

1. 💡 Quality: Clear action is an interactive span nested inside a Button
   Files: openmetadata-ui-core-components/src/main/resources/ui/src/components/application/date-picker/date-range-picker.tsx:206-220

   The clear affordance renders a `<span role="button" tabIndex={0}>` inside the trigger `<Button>` (a native button). Nesting interactive/clickable content inside a button is invalid HTML and can produce inconsistent focus/keyboard behavior across browsers and screen readers. Consider rendering the clear control as a sibling of the trigger button rather than a descendant, or using a non-button trigger container.

2. 💡 Quality: Clear control is an interactive span nested inside a Button
   Files: openmetadata-ui/src/main/resources/ui/src/components/IncidentManager/IncidentManager.component.tsx:250-264

   The clear affordance is a `<span role="button" tabIndex={0}>` nested inside the `<Button>` that serves as the dropdown trigger, producing nested interactive elements (invalid HTML/ARIA) and a clickable icon with no accessible name. Consider rendering the clear control as a sibling of the trigger button rather than a child, and add an `aria-label` (e.g. `t('label.clear')`) to the `XClose` control.

   Fix (Add an accessible name; ideally also move it out of the Button to avoid nested interactive elements.):
   <span
     aria-label={t('label.clear')}
     data-testid="clear-date-picker"
     role="button"
     tabIndex={0}
     onClick={...}
     onKeyDown={...}>
     <XClose className="tw:size-4" />
   </span>

3. 💡 Bug: TabFilters date label goes stale on external URL changes
   Files: openmetadata-ui/src/main/resources/ui/src/components/Database/Profiler/DataObservability/TabFilters/TabFilters.tsx:213-218, openmetadata-ui/src/main/resources/ui/src/components/common/DatePickerMenu/DatePickerMenu.component.tsx:124-130

   `DatePickerMenu` seeds `selectedTimeRange`/`selectedTimeRangeKey` from `defaultOptions` only at mount (useState initializer). In TabFilters.tsx the `defaultDateRange={dateRangeObject}` is derived from `location.search`, but no `key` prop forces a remount, so when the URL date params change through means other than this picker (e.g. browser back/forward), the trigger label keeps showing the previous range while the fetched data reflects the new URL. The prior MUI picker was controlled via `value` and did not have this drift. IncidentManager already works around it with a `key` prop keyed on the range; apply the same pattern to TabFilters (and confirm DimensionalityTab, which uses a constant default, is unaffected).

   Fix (Force a remount when the URL-derived range changes so the trigger label stays in sync, matching the IncidentManager pattern.):
   <DatePickerMenu
     showSelectedCustomRange
     defaultDateRange={dateRangeObject}
     handleDateRangeChange={handleDateRangeChange}
     key={`${dateRangeObject.key}-${dateRangeObject.startTs}-${dateRangeObject.endTs}`}
     size="small"
   />

Options

Display: compact → Showing less information.

Comment with these commands to change the behavior for this request:

Compact
gitar display:verbose         

Was this helpful? React with 👍 / 👎 | Gitar

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

Labels

safe to test Add this label to run secure Github workflows on PRs skip-pr-checks Bypass PR metadata validation check UI UI specific issues

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant