Skip to content

Finish the antd Form, Select, Input and DatePicker migration and fix the navbar search bar - #35509

Merged
shah-harshit merged 45 commits into
mainfrom
shah-harshit/6884-antd-tail
Oct 17, 2026
Merged

shah-harshit merged 45 commits into
mainfrom
shah-harshit/6884-antd-tail

Conversation

@shah-harshit

@shah-harshit shah-harshit commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

Describe your changes:

Part of open-metadata/openmetadata-collate#6884 (open-metadata/openmetadata-collate#6892 Form, open-metadata/openmetadata-collate#6893 Select, open-metadata/openmetadata-collate#6894 Input, open-metadata/openmetadata-collate#7304 residual imports).

Fixes open-metadata/openmetadata-collate#7509 (classic sidebar, folded in from #35522).

Fixes #30811 (core Button onFocus/onBlur, regression tests only).

Merge after open-metadata/openmetadata-collate#7502, which moves NotificationTemplateForm off antd. That form is the last caller of the generateFormFields factory and legacy FieldProp types this PR deletes, so Collate breaks if this lands first.

This clears the OSS antd tail: Form, Select, Input and DatePicker reach zero, and every antd/* subpath import is gone. With AntDConfigProvider replaced as well, OSS has no antd import left (source and tests). With #35205 (icons, merged) on main, OSS has no antd suppressions left.

It also fixes the navbar search bar, which has drawn its input, index select and search button as separate boxes since #35280.

  • Dead code removed. getField / generateFormFields and the components only they used (FilterPattern, SanitizedInput, UserTeamSelectableListSearchInput), AsyncSelect, SchedularUtils, the legacy antd FieldProp / FieldTypes types, filterSelectOptions, getFilterOptions, listLengthValidator, NAME_FIELD_RULES and VALIDATION_MESSAGES had no callers left in OSS.
  • antd types replaced. Rule, RuleObject, DefaultOptionType and Gutter give way to local types (EntityNameValidationRule, EnumColumnOption) or go with the dead code that used them.
  • Date pickers. The audit-log export, table queries, pipeline executions, lineage time filter and KPI form use the core DateRangePicker / DatePicker. Range filters reuse the existing DqDateRangeFilter adapter. Where antd offered allowClear, a core clear button appears once a range is set. The antd generatePicker wrapper is deleted.
  • CSV grid. Enum, tier and entity-type cells use a core Select that opens with the cell. Picking a value commits it, and closing the list ends the edit (re-picking the current value fires no selection change). The entity-type cell drops its Save/Cancel buttons to match the other enum cells: the full-width core Select pushed Save past the cell edge, under the next column. Custom-property enums and the metric related-metrics / data-products cells use core Autocomplete; the latter in free-text mode, replacing antd mode="tags".
  • Classic notification alerts. The add/edit routes render AddObservabilityPage with alertType=Notification. That page already runs on react-hook-form; useAlertFormData now picks the notification fetch, save, breadcrumb and details path by alert type, and the trigger section stays hidden as before. AddNotificationPage is deleted.
  • AntDConfigProvider → useThemeCssVariables. The provider's only live job was writing the custom theme into the --ant-* CSS variables our LESS reads (@primary-color: var(--ant-primary-color), @success-color, …). The hook writes the configured primary and status colours, only when set, as ConfigProvider.config did, next to the palette the provider already wrote, so colours are unchanged. RetentionPeriod's alert drops its overrides of antd's info tints for the core brand style.
  • Popup ConfigProviders. DrawerPopupContainerProvider and the one in CreateMemoryModal are removed: no antd popup is left in those drawers or that modal.
  • Navbar search. Core Input and Select gain a borderless option that drops the field's surface and border (Select keeps its keyboard-focus outline). The search bar uses it, so it reads as one field again.
  • Core Button focus (ui-core-components: Button silently drops a bare onFocus prop #30811). onFocus/onBlur already reach react-aria's Button/Link, and have since the library landed, so nothing was dropped on main and no source change is needed. New tests in button.test.tsx lock that in.
  • Lint. Form, Select, Input, DatePicker and ConfigProvider join MIGRATED_ANTD_COMPONENTS. Suppressed antd symbols drop to 0 (main had 33 after refactor(ui): render SVG assets directly instead of antd's Icon wrapper #35205 removed the icons); one positional locator is removed.

Classic sidebar (from #35522). #35253 moved the classic left sidebar onto core NavItemBase. Its default md size and light current-item style made it look different from the pre-migration sidebar: 16px semibold labels, "Data Marketplace" wrapping, tightly packed rows, and no solid brand treatment on the current item or open groups. The sidebar now matches it again, using only core component APIs. AI mode uses a separate sidebar and is untouched.

Core (NavItemBase), additive. Existing sm and md output is unchanged:

  • New size="lg" for roomy primary navigation: 56px rows (p-3.5), 28px icons, 14px/500 labels (600 when current), rounded-xl. At lg, collapsible children keep their icon and sit flush (px-4 py-2.5, 48px rows) inside the open group.
  • New variant="solid":
    • resting items are transparent, so they sit on the sidebar surface (the default variant keeps bg-primary);
    • resting icons and labels share one mid-gray (fg-tertiary / text-tertiary, #535862), as the old sidebar did, instead of the default's lighter gray-400 icons and darker gray-700 labels;
    • the current item fills with bg-brand-solid and uses on-brand text and icon;
    • an open or child-selected group header fills with bg-brand-solid_hover, with square bottom corners when open;
    • resting items hover with a brand tint instead of gray.
  • collapsible-child indent is now per size (sm → pl-9, md → pl-10), so children line up with the parent label.

Classic LeftSidebar:

  • Drops the white tw:bg-surface that Migrate display, navigation, selection and numeric components to core #35253 added to the classic <aside>, so the rail shows the #f8f9fc page background as before.
  • Uses size="lg" variant="solid", with the old layout:
    • a 16px start inset, so items run flush to the rail end;
    • an 8px gap between rows;
    • an open group is wrapped in a 1px border-brand-subtle panel with no top border.
  • Logout renders as a NavItemBase (a link-less role="link"), so it matches Settings. react-aria activates it on Enter. In the collapsed rail it stays an icon Button.
  • Long labels still wrap rather than being cut off with "…" ("Column Bulk Operations"), so they stay readable without a tooltip.

Dark login panel. In dark mode the sign-in video panel was bg-primary (#0c0e12), while Collate's is #202a3c (open-metadata/openmetadata-collate#7475). OSS now uses the gray-modern-800 palette token (#202939, within 3 RGB units of Collate's) through --login-panel-bg in app.less, so both products' dark login pages match. Light mode and the form side are unchanged.

Still to do for open-metadata/openmetadata-collate#7304: the antd package and its stylesheet (antd-master.less, which also carries antd's global base styles and the --ant-* defaults), and the dead .ant-* rules left in LESS, TSX and Playwright.

Type of change:

  • Improvement

High-level design:

Each group is its own commit, so the PR reads commit by commit. The notification page reuses the observability form rather than porting its own antd form, because the two pages differed only in their API calls, breadcrumb and the trigger section.

The search bar fix adds a prop to core rather than overriding core styles from the caller. A borderless field is the only way to put a core input and select inside a container that already draws the border.

Tests:

Use cases covered

  • Export audit logs for a date range picked in the core range picker.
  • Filter table queries and pipeline executions by date, then clear the filter.
  • Pick a custom range or a point in time in the lineage time filter.
  • Pick KPI start and end dates; past days are unavailable.
  • Edit enum, tier, entity-type and custom-property cells in the bulk import/edit grid.
  • Create and edit a notification alert from Settings → Notifications.
  • Search from the navbar with an index picked.

Unit tests

  • CSVUtilsClassBase.test.tsx: the entity-type cell commits the picked value, and closing the list without a new pick ends the edit.
  • nav-item.test.tsx (core): child indent per size, child icon only at lg, solid current and resting item styles.
  • button.test.tsx (core): onFocus/onBlur fire on keyboard focus in/out, and onFocus fires on the link variant. Both cases fail when button.tsx is mutated to drop the handlers; file passes 36/36.
  • LeftSidebar.test.tsx: Logout asks for confirmation on click and on Enter.
  • Updated for the core components: AuditLogsPage, AddKPIPage, EditKPIPage, CSVUtilsClassBase, AddObservabilityPage (new notification-page cases: breadcrumb, no trigger section), AuthMechanismForm, SettingsRouter, AddTeamForm, AlertsUtil.
  • New: picking a metric enum value commits the row and closes the cell.
  • New: the core Input and Select borderless option.
  • Jest on everything related to the branch (--changedSince=origin/main): 1394 suites, 17,411 tests, all passing. Core Vitest for input/select: 33 passing.

Backend integration tests

  • Not applicable (no backend changes).

Playwright (UI) tests

Updated AuditLogs.spec.ts plus the auditLogs, dataInsight and importUtils helpers to drive the core pickers and options by role. fillEntityTypeDetails no longer clicks Save, because picking a value now commits the cell.

Local run on a011e859e69, with this branch's UI (Vite) against an OSS server built from this branch (MySQL + Elasticsearch), --retries=0:

Spec Result
Features/BulkImport.spec.ts (full spec) 9 passed, 0 failed
Features/DataQuality/FailureThreshold.spec.ts › Enum parameters (--repeat-each=3) 6 passed, 0 failed

CI: Playwright E2E run 38746348836 on d44af08: 4888 tests, 1 failed, 1 skipped.

Failing test Cause Fixed by
FailureThreshold.spec.ts › Enum parameters render as sentences The Operator list closes before the test checks every option. This also fails in the merge queue on main and is not caused by this PR #35529 (fixes the spec on main); passes 6/6 locally on this branch

Visual regression run 38752219375 on cb2144e6150: passed.

Three visual baselines were refreshed from CI renders: landing-page-sidebar-collapsed and metric-list-desktop in 47db1d21eab, and table-details-schema in cb2144e6150.

Manual testing performed

Branch UI on a local dev server against a local backend, compared with main: the navbar search, the audit-log export modal, the KPI date fields, and the notification alert form. Screenshots below.

UI screen recording:

Not applicable: component migration and a styling fix with no new feature flow. Before/after screenshots:

Branch on a local dev server against a local backend, compared with main at b79a00b0029 (light theme; the change doesn't touch theming).

Navbar search bar (classic mode)

main This PR
before-top after-top

Navbar search bar with natural-language search on (as in Collate)

On main, the input and the "All" select each draw their own bordered box inside the search pill. This PR makes them borderless, so the bar matches sandbox: one bordered pill, with dividers around the ✦ toggle and the search icon.

main This PR
search-before-nlp search-after-nlp

Sign-in page, dark mode (AI mode)

The video panel now uses the gray-modern-800 token, matching Collate's #202a3c, instead of bg-primary (#0c0e12). The form side is unchanged.

Before This PR
login-dark-before login-dark-after

Audit logs export: date range

main This PR
before-audit after-audit

KPI form: start date open

main This PR
before-kpi after-kpi

Settings → Notifications → Add alert

main This PR
before-notif after-notif

Classic sidebar

Before (main) After (this PR) Sandbox (reference)
sidebar-before sidebar-after sidebar-sandbox

Measured (228px rail, Govern open)

Sandbox Main (before) This PR
Label 14px / 500 16px / 600 14px / 500
Current label 600, white 600, brand 600, white
Icon 28px 20px 28px
Row height / pitch 56 / 64px 40 / 44px 56 / 64px
Label x-offset 68px 48px 68px
Rest icon / label colour #535862 / #535862 #a4a7ae / #414651 #535862 / #535862
Rail / rest-item background #f8f9fc page bg / transparent white / white #f8f9fc page bg / transparent
Current item #1570ef solid light brand #1570ef solid
Open group solid header + bordered panel plain solid header + bordered panel
Group children icons, 48px rows, label x 71 no icons, 44px icons, 48px rows, label x 71
Long child label truncated wraps wraps (kept readable)

AI mode renders the separate ai-shell sidebar and is unchanged: hashing every sidebar element gives the same result on main and on this branch, in both OSS and Collate. Collate's classic mode renders this same OSS LeftSidebar, so it is fixed with no Collate change.

Checklist:

  • I have read the CONTRIBUTING document.
  • My PR is linked to a GitHub issue above.
  • I have added tests (unit / Playwright as applicable) and listed them above.
  • Decision check: no new durable decision; the classic-reuses-AI-form rule already has its record.

RetriggerView in GreptileConfidence Score: 5/5

The PR appears safe to merge once the documented Collate prerequisite has landed.

Summary

This PR finishes replacing antd controls, shares the notification alert form, and restores the navbar search and classic sidebar styles.

  • The classic sidebar uses roomy rows and solid brand highlights.
  • The navbar search input and index selector sit cleanly inside one pill.
  • Date filters and forms use the shared core pickers.
  • CSV grid cells use core pickers and commit selected values.
  • Notification alerts use the shared observability form.
  • Theme colors stay set after the antd provider is removed.
  • Button tests cover focus and blur callbacks on keyboard focus.
  • The remaining antd-based form helpers and unused controls are removed.

Reviews (4) · Last reviewed commit: "chore(playwright): auto-refresh impact-m..." · Reviewed by Greptile

…ly types

getField/generateFormFields, FilterPattern, SanitizedInput,
UserTeamSelectableListSearchInput, AsyncSelect and SchedularUtils had no
callers left in OSS. Also replace antd Rule/RuleObject/DefaultOptionType/Gutter
types with local ones or drop the dead code that used them.
Audit log export, table queries, pipeline executions, lineage time filter and
the KPI form now use the core DateRangePicker/DatePicker (range filters through
the existing DqDateRangeFilter adapter), with a core clear button where antd
offered allowClear. Deletes the antd generatePicker wrapper and its luxon-only
helpers, and drives the pickers through their roles in Playwright.
Enum, tier and entity-type cells use a core Select that opens with the cell;
custom-property enums and metric related-metrics/data-products use core
Autocomplete (the latter in free-text mode, replacing antd mode="tags").
Drops the antd select styles and the grid's .ant-select key-handling checks.
…-form

AddNotificationPage was the last antd Form. It now reuses the observability
alert form (useAlertFormData picks the notification fetch, save, breadcrumb and
details path by alert type) and hides the trigger section notifications do
not have. Removes the antd-only NAME_FIELD_RULES and VALIDATION_MESSAGES.
…page

Rather than a second page importing another page's form, the notification
add/edit routes render AddObservabilityPage with alertType=Notification, which
hides triggers and keeps the system-alert guard. Deletes AddNotificationPage.
No antd popup is left inside the drawers or the memory modal, so
DrawerPopupContainerProvider and CreateMemoryModal's ConfigProvider no longer
do anything. AntDConfigProvider stays: it still feeds the custom theme into
antd's CSS variables, which the LESS and Collate's last antd form read.
All four reached zero, so they join MIGRATED_ANTD_COMPONENTS. Prunes the
suppression baselines (antd symbols 148 -> 113, positional locators
560 -> 559) and swaps a test's stale antd Option mock for the core items the
helper returns.
Moving the global search off antd (#35280) swapped its borderless antd
Input and Select for core ones that draw their own surface and outline, so
the bar showed three boxes inside its container. Core Input and Select gain
a borderless option (Select keeps its keyboard focus outline) and the search
bar uses it.
@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 Oct 15, 2026
@shah-harshit shah-harshit self-assigned this Oct 15, 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.

@github-actions

Copy link
Copy Markdown
Contributor

🔄 Playwright impact map auto-refreshed

This PR touched specs or UI source that changed the source→spec routing map. I regenerated .github/playwright/impact-map.generated.json and pushed the diff to this branch.

- source entries: 921 → 921
- 0 added, 0 removed, 1 changed spec-list

Entries whose spec list changed:
  openmetadata-ui/src/main/resources/ui/playwright/utils/dateTime.ts

What is this file? It is the auto-generated half of Playwright's PR planner. It routes "if source X changes, run specs Y" by walking spec imports and cross-referencing getByTestId strings. Hand-authored routing in impact-map.json always wins on conflict.

What if I want to regenerate locally instead? Run this before pushing your next change to skip the bot commit:

python3 .github/scripts/generate_playwright_impact_map.py
git add .github/playwright/impact-map.generated.json
git commit --amend --no-edit  # or a separate commit

@github-actions

github-actions Bot commented Oct 15, 2026 •

Copy link
Copy Markdown
Contributor

Jest test Coverage

UI tests summary

Lines Statements Branches Functions
Coverage: 78%
78.2% (128086/163782) 64.89% (81212/125153) 66.24% (27165/41009)

The provider's only live job was writing the custom theme into the --ant-*
CSS variables our LESS reads. useThemeCssVariables now writes the configured
primary and status colours (only when set, as ConfigProvider.config did) next
to the existing palette, so OSS has no antd import left. ConfigProvider joins
MIGRATED_ANTD_COMPONENTS; antd symbol suppressions 113 -> 112, all
@ant-design/icons. RetentionPeriod's alert drops its antd-tint overrides for the
core brand style.
Logout opens a confirmation dialog rather than navigating, so it should be
announced as a button, not a link.
Captured from visual-regression run 38743999049 on d44af08: the classic
sidebar's restored lg/solid look and the single-field navbar search.
The baseline predated #31268 and sat near its 0.03 diff-ratio allowance; the
navbar and sidebar changes here pushed it over. Captured from visual run
38747924746 on 47db1d2.
The OSS dark sign-in panel used bg-primary (#0c0e12) while Collate's uses
#202a3c; use the same colour so both products' dark login pages match.
…d-tail

# Conflicts:
#	openmetadata-ui/src/main/resources/ui/playwright/eslint-rules/tests/corpus.test.mjs
…d-tail

# Conflicts:
#	openmetadata-ui/src/main/resources/ui/playwright/e2e/VisualRegression/__snapshots__/entityDetails.spec.ts-snapshots/table-details-schema.png
#	openmetadata-ui/src/main/resources/ui/playwright/e2e/VisualRegression/__snapshots__/staticPages.spec.ts-snapshots/landing-page-sidebar-collapsed.png
Core Button passes onFocus/onBlur through to react-aria's Button/Link;
lock that in so a regression to silently dropping them is caught.
shah-harshit and others added 3 commits October 16, 2026 10:16
- Select: value/onChange instead of the deprecated selectedKey/onSelectionChange.
- Drop fragments left with a single child after removing the popup providers.
- Set over lodash uniq; lodash toString for unknown grid cell values.
- Mark the fire-and-forget query refetch with void; return Promise.resolve
  from sync onUpdate handlers instead of async without await.
- Number.NaN; merge the duplicate react import.
- DateRangeFilter: hoist the range builder so the force-close effect lists
  its real dependencies.
- Dark login panel uses the gray-modern-800 palette token, not a hex.
…s landing redesign

Captured from visual run 38852373478 on 1db2e56: main's new landing
page (#35462) with this PR's sidebar and search bar.
…d-tail

# Conflicts:
#	openmetadata-ui/src/main/resources/ui/playwright/eslint-rules/tests/corpus.test.mjs
@github-actions

Copy link
Copy Markdown
Contributor

🚦 Removed from the merge queue — manual (2026-10-16T06:22:44Z)

The entry left the queue before it was built, so no checks ran against it.

…d-tail

# Conflicts:
#	openmetadata-ui/src/main/resources/ui/eslint-rules/openmetadata-antd.test.mjs
#	openmetadata-ui/src/main/resources/ui/eslint-suppressions.json
#	openmetadata-ui/src/main/resources/ui/src/components/Database/TableQueries/TableQueries.tsx
#	openmetadata-ui/src/main/resources/ui/src/components/Pipeline/Execution/Execution.component.tsx
Comment thread openmetadata-ui/src/main/resources/ui/src/pages/KPIPage/KPIFormFields.tsx Outdated
…le enums

- KPI and audit-export date pickers staged nothing: every pick went straight
  to the form, so Cancel kept it. useStagedPickerValue holds picks until
  Apply and drops them on Cancel or close.
- A borderless Input dropped its focus outline outright; like a borderless
  Select it now keeps it for keyboard focus.
- Single-value custom-property enums used a chip Autocomplete, which refuses
  a second pick; a Select replaces the value.
Comment thread openmetadata-ui/src/main/resources/ui/src/utils/CSV/CSVUtilsClassBase.tsx Outdated
Comment thread openmetadata-ui/src/main/resources/ui/src/utils/CSV/CSVUtilsClassBase.tsx Outdated
Comment thread openmetadata-ui/src/main/resources/ui/src/utils/CSV/CSVUtilsClassBase.tsx Outdated
…single enum clear

The editor cancels on any mousedown outside it or the
bulk-edit-custom-property-select-dropdown class; the core Select and
Autocomplete popovers portal to the body without that class, so a press in
them could close the editor. A single-value enum also lost its own clear
when it moved to Select; a clear button restores it.
@github-actions

Copy link
Copy Markdown
Contributor

🚦 Removed from the merge queue — manual (2026-10-16T10:00:50Z)

The entry left the queue before it was built, so no checks ran against it.

shah-harshit and others added 2 commits October 16, 2026 15:35
…d-tail

# Conflicts:
#	openmetadata-ui/src/main/resources/ui/playwright/eslint-rules/tests/corpus.test.mjs
@github-actions

Copy link
Copy Markdown
Contributor

🔄 Playwright impact map auto-refreshed

This PR touched specs or UI source that changed the source→spec routing map. I regenerated .github/playwright/impact-map.generated.json and pushed the diff to this branch.

- source entries: 936 → 937
- 1 added, 0 removed, 11 changed spec-list

New source→spec entries:
  openmetadata-ui/src/main/resources/ui/src/components/Database/Profiler/TableProfiler/QualityTab/QualityTab.component.tsx

Entries whose spec list changed:
  openmetadata-ui/src/main/resources/ui/playwright/e2e/fixtures/pages.ts
  openmetadata-ui/src/main/resources/ui/playwright/support/entity/TableClass.ts
  openmetadata-ui/src/main/resources/ui/playwright/support/entity/service/DatabaseServiceClass.ts
  openmetadata-ui/src/main/resources/ui/playwright/utils/admin.ts
  openmetadata-ui/src/main/resources/ui/playwright/utils/apiResponse.ts
  openmetadata-ui/src/main/resources/ui/playwright/utils/common.ts
  openmetadata-ui/src/main/resources/ui/playwright/utils/entity.ts
  openmetadata-ui/src/main/resources/ui/playwright/utils/scopedLocators.ts
  openmetadata-ui/src/main/resources/ui/playwright/utils/testCases.ts
  openmetadata-ui/src/main/resources/ui/playwright/utils/waitHelpers.ts
  … and 1 more

What is this file? It is the auto-generated half of Playwright's PR planner. It routes "if source X changes, run specs Y" by walking spec imports and cross-referencing getByTestId strings. Hand-authored routing in impact-map.json always wins on conflict.

What if I want to regenerate locally instead? Run this before pushing your next change to skip the bot commit:

python3 .github/scripts/generate_playwright_impact_map.py
git add .github/playwright/impact-map.generated.json
git commit --amend --no-edit  # or a separate commit

@gitar-bot

gitar-bot Bot commented Oct 16, 2026

Copy link
Copy Markdown
Code Review ✅ Approved 4 closed / 4 findings

🟡 Medium risk · Migrating alert forms, date filters, and CSV selectors to core controls could alter alert saves, date boundaries, or bulk edits.

Finishes the antd Form, Select, Input and DatePicker migration and fixes the navbar search bar, with dead antd helpers removed and the classic sidebar restyled. Resolved this session: theme colours now clear their inline CSS variable, expanded-sidebar Logout is exposed as a link, enum popovers stay inside the custom-property editor, and a single enum can be cleared with its own clear button. No open findings.

✅ 4 closed
✅ Edge Case: Cleared theme colours keep their old inline CSS variable

📄 openmetadata-ui/src/main/resources/ui/src/hooks/useThemeCssVariables.ts:37-44
The hook only calls setProperty when a colour is set and never removes a variable once it has been written. antd's ConfigProvider.config → registerTheme rebuilt its whole :root{} style tag on every call, so a colour that was dropped fell back to the stylesheet default. AppearanceConfigSettingsPage.handleSave sends orEmpty(...), which gives '' for a status colour the user clears. After that save the old --ant-success-color/--ant-error-color stays inline on <html> until the page reloads. The fix is to call removeProperty(variable) when the colour is falsy.

✅ Quality: Expanded-sidebar Logout is now exposed as a link, not a button

📄 openmetadata-ui/src/main/resources/ui/src/components/MyData/LeftSidebar/LeftSidebar.component.tsx:107-121 📄 openmetadata-ui/src/main/resources/ui/src/components/MyData/LeftSidebar/LeftSidebar.component.tsx:150-163 📄 openmetadata-ui-core-components/src/main/resources/ui/src/components/application/app-navigation/base-components/nav-item.tsx:214-220
renderLeaf now renders the Button only when isSidebarCollapsed. In the expanded sidebar, items without redirect_url (Logout) go through NavItemBase with type="link" and href={undefined}, so react-aria Link renders a <span role="link">. Logout opens a confirmation modal; it does not navigate. Screen readers will announce it as a link, which goes against the a11y rule: <button> for actions, <a href> for navigation. The new test only checks that click and Enter open the modal, not the role. Fix: keep a Button for href-less items in both states, giving it NavItem-like styling when expanded, or let NavItemBase render a button when href is missing.

✅ Bug: Single-enum Select popover is missing the outside-click exemption class

📄 openmetadata-ui/src/main/resources/ui/src/utils/CSV/CSVUtilsClassBase.tsx:1486-1500 📄 openmetadata-ui/src/main/resources/ui/src/utils/CSV/CSVUtilsClassBase.tsx:1516-1528 📄 openmetadata-ui/src/main/resources/ui/src/utils/CSV/CSVUtilsClassBase.test.tsx:1090-1096
InlineCustomPropertiesEditor adds a document mousedown listener (around lines 1413-1428) that calls onCancel() for any press outside the trigger, the editor, or .bulk-edit-custom-property-select-dropdown. The comment there explains why: select dropdowns portal to document.body. The core Select popover is a react-aria Popover, which also portals to the body. The new single-value enum Select (lines 1486-1500) doesn't pass popoverClassName, unlike the reference picker at line 1565. In a real browser, the mousedown on an option fires first, cancels the editor and unmounts it before the option's press-up selects anything, so the swap this commit adds never lands. The new test uses fireEvent.click, which sends no mousedown, so it passes anyway. Fix: pass popoverClassName="bulk-edit-custom-property-select-dropdown" to the Select, and to the multi-value Autocomplete while you're there. Then drive the test with userEvent so the mousedown path is covered.

✅ Edge Case: Single-value enum can no longer be cleared on its own

📄 openmetadata-ui/src/main/resources/ui/src/utils/CSV/CSVUtilsClassBase.tsx:1484-1498
Before this commit, a single-value enum was a chip Autocomplete, and its chip remove button called onItemCleared to unset the property. The core Select that replaces it has no clear affordance. Its onChange only fires with a key, so the key === null ? [] : ... branch never runs. The only way left to unset one single-value enum is "Clear all", which wipes every custom property in the draft. Consider adding a per-field clear button (or an empty option) that calls handleUpdateDraft(customProperty.name, []).

Verification

Rules No rules evaluated

Functional validation Not enabled

Set up

Auto-approval Not enabled

Set up

For more verification details, comment gitar display:verbose.

Options

Display: compact → Showing compact verification results.

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

Compact
gitar display:verbose         

Was this helpful? React with 👍 / 👎 | Powered by Gitar — free for open source

@github-actions

Copy link
Copy Markdown
Contributor

⚠️ UI Checkstyle passed — lint findings in changed files

🔍 ESLint findings in this PR's files — 0 error(s), 42 warning(s)

Errors block the build. Warnings do not yet — they are rules whose backlog is still
being worked down, listed so this PR does not add to it. See docs/ui-code-quality-gate.md.

0 error(s), 42 warning(s) across 17 changed file(s).

Count Rule
23 react-hooks/exhaustive-deps
7 openmetadata-ui-patterns/no-non-adaptive-palette
7 openmetadata-imports/no-lower-layer-page-imports
3 openmetadata-imports/no-impure-pure-utils
1 openmetadata-imports/review-sequential-api-calls
1 openmetadata-imports/no-circular-imports
All findings
Location Rule Message
🟡 src/AppRoot.tsx:70:6 react-hooks/exhaustive-deps React Hook useEffect has missing dependencies: 'fetchApplicationConfig' and 'initializeAuthState'. Either include them or remove the dependency array.
🟡 src/components/DataInsight/PageViewsByEntitiesChart.tsx:115:6 react-hooks/exhaustive-deps React Hook useEffect has a missing dependency: 'fetchPageViewsByEntities'. Either include it or remove the dependency array.
🟡 src/components/Database/ColumnDetailPanel/ColumnDetailPanel.component.tsx:636:6 react-hooks/exhaustive-deps React Hook useEffect has a missing dependency: 'activeColumn'. Either include it or remove the dependency array.
🟡 src/components/Database/ColumnDetailPanel/ColumnDetailPanel.component.tsx:755:24 openmetadata-ui-patterns/no-non-adaptive-palette Raw palette class "tw:text-gray-400" is static — it does not flip in dark mode. Use the theme-adapting "utility-" variant (tw:text-utility-gray-400) or a semant
🟡 src/components/Database/ColumnDetailPanel/ColumnDetailPanel.component.tsx:814:17 openmetadata-ui-patterns/no-non-adaptive-palette Raw palette class "tw:text-gray-400" is static — it does not flip in dark mode. Use the theme-adapting "utility-" variant (tw:text-utility-gray-400) or a semant
🟡 src/components/Database/ColumnDetailPanel/ColumnDetailPanel.component.tsx:825:27 openmetadata-ui-patterns/no-non-adaptive-palette Raw palette class "tw:text-gray-400" is static — it does not flip in dark mode. Use the theme-adapting "utility-" variant (tw:text-utility-gray-400) or a semant
🟡 src/components/Database/ColumnDetailPanel/ColumnDetailPanel.component.tsx:875:19 openmetadata-ui-patterns/no-non-adaptive-palette Raw palette class "tw:text-gray-400" is static — it does not flip in dark mode. Use the theme-adapting "utility-" variant (tw:text-utility-gray-400) or a semant
🟡 src/components/Database/TableQueries/TableQueries.tsx:180:6 react-hooks/exhaustive-deps React Hook useEffect has a missing dependency: 'fetchResourcePermission'. Either include it or remove the dependency array.
🟡 src/components/Database/TableQueries/TableQueries.tsx:205:24 openmetadata-imports/review-sequential-api-calls Review these sequential API requests. If they are independent, start them together with Promise.all/Promise.allSettled; keep sequencing only when data-dependent
🟡 src/components/Database/TableQueries/TableQueries.tsx:475:6 react-hooks/exhaustive-deps React Hook useEffect has missing dependencies: 'fetchFilteredQueries', 'isTableDeleted', and 'searchParams.queryFrom'. Either include them or remove the depende
🟡 src/components/Entity/EntityLineage/LineageTimeFilter.component.tsx:231:44 openmetadata-ui-patterns/no-non-adaptive-palette Raw palette class "tw:text-brand-600" is static — it does not flip in dark mode. Use the theme-adapting "utility-" variant (tw:text-utility-brand-600) or a sema
🟡 src/components/GlobalSearchBar/GlobalSearchBar.tsx:127:5 react-hooks/exhaustive-deps React Hook useMemo has an unnecessary dependency: 'i18n.language'. Either exclude it or remove the dependency array.
🟡 src/components/GlobalSearchBar/GlobalSearchBar.tsx:139:6 react-hooks/exhaustive-deps React Hook useCallback has a missing dependency: 'navigate'. Either include it or remove the dependency array.
🟡 src/components/GlobalSearchBar/GlobalSearchBar.tsx:148:28 react-hooks/exhaustive-deps React Hook useCallback received a function whose dependencies are unknown. Pass an inline function instead.
🟡 src/components/GlobalSearchBar/GlobalSearchBar.tsx:209:6 react-hooks/exhaustive-deps React Hook useEffect has a missing dependency: 'initNLP'. Either include it or remove the dependency array.
🟡 src/components/Pipeline/Execution/Execution.component.tsx:101:6 react-hooks/exhaustive-deps React Hook useEffect has a missing dependency: 'fetchPipelineStatus'. Either include it or remove the dependency array.
🟡 src/components/observability/Alerts/AlertAiFormFieldsPureUtils.ts:26:1 openmetadata-imports/no-impure-pure-utils Pure utilities must not depend on React, UI, state, hooks, pages, or REST clients. Move orchestration/rendering out or move shared types to a lower layer.
🟡 src/components/observability/Alerts/AlertAiFormFieldsPureUtils.ts:26:1 openmetadata-imports/no-lower-layer-page-imports Pages are route-level composition modules. Move the shared implementation/type to a lower layer instead of importing a page from here.
🟡 src/components/observability/Alerts/AlertAiFormFieldsPureUtils.ts:32:1 openmetadata-imports/no-impure-pure-utils Pure utilities must not depend on React, UI, state, hooks, pages, or REST clients. Move orchestration/rendering out or move shared types to a lower layer.
🟡 src/components/observability/Alerts/AlertAiFormFieldsPureUtils.ts:33:1 openmetadata-imports/no-impure-pure-utils Pure utilities must not depend on React, UI, state, hooks, pages, or REST clients. Move orchestration/rendering out or move shared types to a lower layer.
🟡 src/components/observability/Alerts/AlertAiFormFieldsValidationUtils.test.ts:16:1 openmetadata-imports/no-lower-layer-page-imports Pages are route-level composition modules. Move the shared implementation/type to a lower layer instead of importing a page from here.
🟡 src/components/observability/Alerts/AlertAiFormFieldsValidationUtils.ts:22:1 openmetadata-imports/no-lower-layer-page-imports Pages are route-level composition modules. Move the shared implementation/type to a lower layer instead of importing a page from here.
🟡 src/hooks/useGridEditController.ts:156:6 react-hooks/exhaustive-deps React Hook useCallback has an unnecessary dependency: 'selectedRange'. Either exclude it or remove the dependency array.
🟡 src/hooks/useGridEditController.ts:194:6 react-hooks/exhaustive-deps React Hook useCallback has an unnecessary dependency: 'selectedRange'. Either exclude it or remove the dependency array.
🟡 src/hooks/useGridEditController.ts:635:6 react-hooks/exhaustive-deps React Hook useCallback has a missing dependency: 'gridContainer'. Either include it or remove the dependency array.
🟡 src/hooks/useGridEditController.ts:669:6 react-hooks/exhaustive-deps React Hook useCallback has missing dependencies: 'getCellsInRange' and 'gridContainer'. Either include them or remove the dependency array.
🟡 src/hooks/useGridEditController.ts:688:6 react-hooks/exhaustive-deps React Hook useEffect has a missing dependency: 'gridContainer'. Either include it or remove the dependency array.
🟡 src/hooks/useGridEditController.ts:796:6 react-hooks/exhaustive-deps React Hook useEffect has missing dependencies: 'focusCell', 'getCellIndices', and 'setSelectedRange'. Either include them or remove the dependency array.
🟡 src/hooks/useGridEditController.ts:892:6 react-hooks/exhaustive-deps React Hook useEffect has missing dependencies: 'getCellIndices', 'handleCopy', 'handlePaste', and 'setSelectedRange'. Either include them or remove the dependen
🟡 src/hooks/useGridEditController.ts:955:5 react-hooks/exhaustive-deps React Hook useCallback has a missing dependency: 'setSelectedRange'. Either include it or remove the dependency array.
🟡 src/hooks/useGridEditController.ts:968:5 react-hooks/exhaustive-deps React Hook useCallback has a missing dependency: 'setSelectedRange'. Either include it or remove the dependency array.
🟡 src/hooks/useGridEditController.ts:1031:6 react-hooks/exhaustive-deps React Hook useCallback has a missing dependency: 'setSelectedRange'. Either include it or remove the dependency array.
🟡 src/hooks/useGridEditController.ts:1058:6 react-hooks/exhaustive-deps React Hook useEffect has a missing dependency: 'dataSource'. Either include it or remove the dependency array.
🟡 src/hooks/useGridEditController.ts:1058:7 react-hooks/exhaustive-deps React Hook useEffect has a complex expression in the dependency array. Extract it to a separate variable so it can be statically checked.
🟡 src/pages/AuditLogsPage/AuditLogsPage.tsx:549:39 openmetadata-ui-patterns/no-non-adaptive-palette Raw palette class "tw:text-brand-600" is static — it does not flip in dark mode. Use the theme-adapting "utility-" variant (tw:text-utility-brand-600) or a sema
🟡 src/pages/AuditLogsPage/AuditLogsPage.tsx:633:25 openmetadata-ui-patterns/no-non-adaptive-palette Raw palette class "tw:text-gray-400" is static — it does not flip in dark mode. Use the theme-adapting "utility-" variant (tw:text-utility-gray-400) or a semant
🟡 src/pages/TeamsPage/AddTeamForm.tsx:144:6 react-hooks/exhaustive-deps React Hook useEffect has a missing dependency: 'fetchAllTeams'. Either include it or remove the dependency array.
🟡 src/utils/Alerts/AlertsUtil.test.tsx:39:1 openmetadata-imports/no-lower-layer-page-imports Pages are route-level composition modules. Move the shared implementation/type to a lower layer instead of importing a page from here.
🟡 src/utils/Alerts/AlertsUtilPure.ts:41:1 openmetadata-imports/no-lower-layer-page-imports Pages are route-level composition modules. Move the shared implementation/type to a lower layer instead of importing a page from here.
🟡 src/utils/CSV/CSVUtilsClassBase.tsx:95:1 openmetadata-imports/no-lower-layer-page-imports Pages are route-level composition modules. Move the shared implementation/type to a lower layer instead of importing a page from here.
🟡 src/utils/CSV/CSVUtilsClassBase.tsx:113:1 openmetadata-imports/no-circular-imports This runtime import participates in a circular dependency. Extract the shared type/constant/utility or invert the dependency.
🟡 src/utils/SearchSettingsUtils.ts:27:1 openmetadata-imports/no-lower-layer-page-imports Pages are route-level composition modules. Move the shared implementation/type to a lower layer instead of importing a page from here.

Fix locally (fast - only checks files changed in this branch):

make ui-checkstyle-changed

@sonarqubecloud

Copy link
Copy Markdown

@github-actions

Copy link
Copy Markdown
Contributor

🚦 Removed from the merge queue — failed_checks (2026-10-16T19:01:35Z)

Blocked the queue: playwright-summary

Failed Playwright tests:

  • Pages/Glossary.spec.ts › Term should stay approved when changes made by reviewer

This branch was successfully deployed

1 active deployment
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.

ui-core-components: Button silently drops a bare onFocus prop

3 participants