Skip to content

fix(ui): replace native HTML title attributes with Tooltip component - #32916

Merged
shrabantipaul-collate merged 31 commits into
mainfrom
native-html-title-usage-audit
Sep 16, 2026
Merged

shrabantipaul-collate merged 31 commits into
mainfrom
native-html-title-usage-audit

Conversation

@shrabantipaul-collate

@shrabantipaul-collate shrabantipaul-collate commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Replaces all native HTML title attributes in 18 production UI files with the Tooltip component from @openmetadata/ui-core-components, so tooltips render consistently through the design system instead of browser-native behavior
  • Non-button elements wrapped in <Tooltip title={...}> (with <span> intermediary where needed for Transi18next anchor templates)
  • Button elements keep the native <button> element and wrap it in <Tooltip title={...}> to preserve visual appearance exactly
  • <iframe title> attributes left unchanged (ARIA accessibility requirement)
  • Conditional tooltip disabled via isDisabled prop (ChipTrigger)
  • Reuses existing i18n keys — no new locale entries added or synced

Files changed (18)

File Change
BarMenu.tsx ButtonTooltip; <button> wrapped in <Tooltip>
EmptyGraphPlaceholder.tsx <a title><Tooltip> wrapping <Transi18next> in <span>
MarketplaceSearchBar.component.tsx NLP toggle <button> wrapped in <Tooltip>; <Typography title><Tooltip>
DataQualityDashboard.component.tsx Removed redundant title on <div> inside existing Tooltip
ChipTrigger.component.tsx Added <Tooltip isDisabled={!isBounded}> for truncated label
NoProfilerBanner.component.tsx <a title><Tooltip>
SingleColumnProfile.tsx <a title> (Transi18next) → <Tooltip><span>
TableProfilerChart.tsx Same Transi18next pattern
CustomPropertiesSection.tsx Same Transi18next pattern
AgentCard.component.tsx Run-dot <button> wrapped in <Tooltip>
LogViewerModal.component.tsx <span title><Tooltip>
TierTag.tsx <span title><Tooltip>
ExploreSearchInput.tsx NLP toggle <button> wrapped in <Tooltip>
ContextCenterSubNavSections.tsx Nav link <button> wrapped in <Tooltip>
ColumnGrid.component.tsx Badge <div title><Tooltip>
AdvancedSearchUtils.tsx Dropdown option <span title><Tooltip>
EntityDisplayPureUtils.tsx Filter count <span title><Tooltip>
ServiceInsightsWidgets.tsx Transi18next anchor → <Tooltip><span>

Test plan

  • Hover over bar menu format buttons — tooltip text appears
  • Hover over tier tag — FQN tooltip appears
  • Hover over agent run dots — status tooltip appears
  • Hover over NLP toggle in Explore / Marketplace search bars — tooltip appears
  • Hover over truncated chip label (bounded) — full label tooltip appears; unbounded chip shows no tooltip
  • Verify <iframe> elements in VideoPlayer and StorylaneTour retain their title attributes (ARIA)
  • UI Checkstyle passes (organize-imports → eslint → prettier — warnings only, no errors)

🤖 Generated with Claude Code

Greptile Summary

This PR replaces native title attributes with design-system tooltips and updates affected tests and lint enforcement.

  • Migrates tooltip presentation across editor, search, profiling, data-quality, service-agent, navigation, and utility UI.
  • Promotes the raw native-title lint rule to an error while retaining accessibility and test exemptions.
  • Updates Playwright and unit-test selectors that previously relied on native title attributes.
  • Two trigger-integration problems remain: direct native buttons become nested controls, and the Column Grid tooltip wrapper defeats flex truncation.
Confidence Score: 3/5

The PR is not yet safe to merge because several migrated controls render invalid nested buttons and the Column Grid migration breaks the badge truncation layout contract.

Direct native button children are deterministically wrapped in another button by Tooltip, creating duplicate interactive controls across multiple user-facing actions; the generated max-content wrapper in Column Grid also moves flex constraints off the actual flex item.

Files Needing Attention: openmetadata-ui/src/main/resources/ui/src/components/BlockEditor/BarMenu/BarMenu.tsx, openmetadata-ui/src/main/resources/ui/src/components/DataMarketplace/MarketplaceSearchBar/MarketplaceSearchBar.component.tsx, openmetadata-ui/src/main/resources/ui/src/components/ServiceAgents/components/AgentCard.component.tsx, openmetadata-ui/src/main/resources/ui/src/components/discovery/explore/ExploreHeader/ExploreSearchInput.tsx, openmetadata-ui/src/main/resources/ui/src/components/platform/ai-shell/Sidebar/ContextCenterSubNavSections.tsx, openmetadata-ui/src/main/resources/ui/src/pages/ColumnBulkOperations/ColumnGrid/ColumnGrid.component.tsx

Important Files Changed
Filename Overview
openmetadata-ui/src/main/resources/ui/src/components/BlockEditor/BarMenu/BarMenu.tsx Wraps editor formatting buttons in Tooltip, but the Tooltip implementation adds an outer button around each native button.
openmetadata-ui/src/main/resources/ui/src/pages/ColumnBulkOperations/ColumnGrid/ColumnGrid.component.tsx Adds badge tooltips whose generated max-content wrappers bypass the existing flex shrink and overflow constraints.
openmetadata-ui/src/main/resources/ui/eslint-rules/openmetadata-ui-patterns.mjs Narrows raw-title enforcement to native elements while exempting iframe, title, components, and the legacy Ant selection pattern.
openmetadata-ui/src/main/resources/ui/eslint.config.mjs Promotes raw-title enforcement to an error in production code and exempts test and mock paths.
openmetadata-ui/src/main/resources/ui/src/components/DataQuality/IncidentManager/TestCaseStatus/InlineIncidentStatus/ChipTrigger.component.tsx Replaces conditional native titles with a non-nesting Focusable-based Tooltip trigger for bounded chip labels.
openmetadata-ui/src/main/resources/ui/src/utils/AdvancedSearchUtils.tsx Replaces dropdown-label titles using Focusable so menu-item click handling remains on the parent.

Reviews (1): Last reviewed commit: "Merge branch 'main' into native-html-tit..." | Re-trigger Greptile

Greptile also left 2 inline comments on this PR.

Replaces all native HTML `title` attributes in production UI files with
the `Tooltip` component from `@openmetadata/ui-core-components` so
tooltips render consistently via the design-system instead of relying on
browser-native tooltip behavior.

- Non-button elements: wrapped in `<Tooltip title={...}>` with a `<span>`
  where required (Transi18next anchor templates, non-focusable children).
- Button elements: native `<button>` preserved and wrapped in
  `<Tooltip title={...}>` to keep visual appearance unchanged.
- `<iframe title>` attributes (ARIA accessibility requirement) left as-is.
- Removed redundant `title` on a `<div>` already inside an existing Tooltip.
- Conditional tooltip disabled via `isDisabled` prop (ChipTrigger).
- Existing i18n keys reused; no new locale keys added.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@github-actions

github-actions Bot commented Sep 8, 2026

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 github-actions Bot added the UI UI specific issues label Sep 8, 2026
@github-actions

github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Hi there 👋 Thanks for your contribution!

The OpenMetadata team will review the PR shortly! Once it has been labeled as safe to test, the CI workflows
will start executing and we'll be able to make sure everything is working as expected.

Let us know if you need any help!

@github-actions

github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

✅ Playwright Results — workflow succeeded

Validated commit 72b0d29fe5f658c078ca72a2c776c8f6439b5e1c in Playwright run 35065562126, attempt 1.

✅ 4490 passed · ❌ 0 failed · 🟡 4 flaky · ⏭️ 1 skipped · 🧰 0 lifecycle flaky

Performance

Blocking targets: ✅ met · Optimization targets: 🟡 in progress

Shard-job maxima below are not the full workflow wall time; the linked run includes build, fixture, planning, and reporting.

🕒 Full workflow signal wall (to summary) 1h 4m 27s

⏱️ Max setup 4m 43s · max shard execution 23m 5s · max shard-job elapsed before upload 26m 33s · reporting 19s

🌐 220.29 requests/attempt · 2.23 app boots/UI scenario · 36.68% common-shard skew

Optimization targets still in progress:

  • Common shard skew was 36.68% (convergence target: at most 15%).
  • Browser traffic was 220.29 requests per attempt (convergence target: fewer than 200).
  • Application boot ratio was 2.23 per UI scenario (10647 boots / 4776 scenarios; convergence target: at most 1).
Shard Passed Failed Flaky Skipped Lifecycle failed Lifecycle flaky
✅ Shard advanced-search-01 130 0 0 0 0 0
✅ Shard chromium-01 171 0 0 0 0 0
✅ Shard chromium-02 156 0 0 0 0 0
🟡 Shard chromium-03 159 0 1 0 0 0
✅ Shard chromium-04 166 0 0 0 0 0
✅ Shard chromium-05 190 0 0 1 0 0
✅ Shard chromium-06 180 0 0 0 0 0
✅ Shard chromium-07 134 0 0 0 0 0
✅ Shard chromium-08 173 0 0 0 0 0
✅ Shard chromium-09 154 0 0 0 0 0
✅ Shard chromium-10 177 0 0 0 0 0
✅ Shard chromium-11 166 0 0 0 0 0
✅ Shard chromium-12 180 0 0 0 0 0
✅ Shard chromium-13 156 0 0 0 0 0
🟡 Shard chromium-14 168 0 1 0 0 0
✅ Shard chromium-15 158 0 0 0 0 0
✅ Shard chromium-16 159 0 0 0 0 0
✅ Shard chromium-17 163 0 0 0 0 0
✅ Shard chromium-18 156 0 0 0 0 0
✅ Shard chromium-19 165 0 0 0 0 0
✅ Shard chromium-20 157 0 0 0 0 0
✅ Shard chromium-21 131 0 0 0 0 0
✅ Shard chromium-22 188 0 0 0 0 0
✅ Shard chromium-23 185 0 0 0 0 0
🟡 Shard chromium-24 141 0 1 0 0 0
✅ Shard data-asset-rules-01 65 0 0 0 0 0
✅ Shard domain-isolation-01 16 0 0 0 0 0
✅ Shard global-state-01 34 0 0 0 0 0
✅ Shard import-export-01 114 0 0 0 0 0
🟡 Shard import-export-02 35 0 1 0 0 0
✅ Shard ingestion-01 45 0 0 0 0 0
✅ Shard ingestion-02 49 0 0 0 0 0
✅ Shard reindex-01 28 0 0 0 0 0
✅ Shard search-01 12 0 0 0 0 0
✅ Shard search-rbac-01 29 0 0 0 0 0
🟡 4 flaky test(s) (passed on retry)
  • Pages/Lineage/DataAssetLineage.spec.tsColumn lineage for apiEndpoint -> container (shard chromium-03, 1 retry)
  • Flow/Tour.spec.tsTour should work from help section (shard chromium-14, 1 retry)
  • Pages/UserDetails.spec.tsCreate team with domain and verify visibility of inherited domain in user profile after team removal (shard chromium-24, 1 retry)
  • Features/BulkEditImportPermissions.spec.tsEditor with EditAll can access every bulk edit and import page (shard import-export-02, 1 retry)

📦 Download artifacts

How to debug locally
# Download playwright-test-results-<shard> artifact and unzip
npx playwright show-trace path/to/trace.zip    # view trace

@shrabantipaul-collate shrabantipaul-collate added the safe to test Add this label to run secure Github workflows on PRs label Sep 8, 2026
… tag list

The key prop must be on the outermost element returned by a map callback.
Moves key={tag.tagFQN} from the inner <div> to the wrapping <Tooltip>.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Shrabanti Paul and others added 2 commits September 8, 2026 12:04
Tests were checking for native HTML `title` attributes and using `getByTitle`
queries that no longer apply after switching to the Tooltip component.

- MarketplaceSearchBar.test: add Tooltip to ui-core-components mock; remove
  title attribute assertions on the NLQ toggle button
- ExploreSearchCard.test: replace toHaveAttribute('title') check on NLP toggle
  with toBeInTheDocument() — tooltip text is now a component-level concern
- AgentCard.test: replace getAllByTitle() queries with getAllByTestId('agent-run-dot')
- ChipTrigger.test: replace toHaveAttribute('title') assertions with
  toHaveTextContent() — the label text in the DOM is what matters, hover
  tooltip is now handled by the Tooltip component

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@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: 758 → 758
- 0 added, 0 removed, 13 changed spec-list

Entries whose spec list changed:
  openmetadata-ui/src/main/resources/ui/playwright/constant/config.ts
  openmetadata-ui/src/main/resources/ui/playwright/constant/service.ts
  openmetadata-ui/src/main/resources/ui/playwright/support/entity/service/DashboardServiceClass.ts
  openmetadata-ui/src/main/resources/ui/playwright/support/entity/service/DatabaseServiceClass.ts
  openmetadata-ui/src/main/resources/ui/playwright/support/entity/service/MessagingServiceClass.ts
  openmetadata-ui/src/main/resources/ui/playwright/support/fixtures/base.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/service.ts
  openmetadata-ui/src/main/resources/ui/playwright/utils/serviceIngestion.ts
  … and 3 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

# Conflicts:
#	openmetadata-ui/src/main/resources/ui/src/utils/AdvancedSearchUtils.tsx
@github-actions

Copy link
Copy Markdown
Contributor

🚦 Removed from the merge queue — failed_checks (2026-09-10T18:42:24Z)

Blocked the queue: playwright-summary

@github-actions

Copy link
Copy Markdown
Contributor

🚦 Removed from the merge queue — failed_checks (2026-09-11T05:24:05Z)

Blocked the queue: playwright-summary

Shrabanti Paul and others added 3 commits September 11, 2026 11:02
The native-title → Tooltip migration removed the option label's `title`, so the
service-type quick-filter tests that selected an option by `getByTitle('mysql')`
/ `getByLabel('mlflow', { exact: true })` no longer resolve. The option label is
also source-cased ('Mysql', 'Mlflow') while the searched string is lowercase, so
a case-sensitive label match would fail regardless.

Match the option row's data-testid instead — it is the lowercased service-type
key ('mysql', 'mlflow'), stable across the Tooltip migration and label-casing:

- Pagination.spec.ts (Impact Analysis pagination reset on quick-filter change,
  added by #32699 in main): getByTitle('mysql') → getByTestId('mysql').
- ImpactAnalysis.spec.ts (service type filter): getByLabel('mlflow', exact) →
  getByTestId('mlflow').

Verified against the running app: getByTestId('mysql') / getByTestId('mlflow')
resolve the option rows.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@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: 762 → 762
- 0 added, 0 removed, 3 changed spec-list

Entries whose spec list changed:
  openmetadata-ui/src/main/resources/ui/src/components/Alerts/AlertFormSourceItem/AlertFormSourceItem.tsx
  openmetadata-ui/src/main/resources/ui/src/components/Explore/QuickFilterDropdown.tsx
  openmetadata-ui/src/main/resources/ui/src/components/SearchDropdown/SearchDropdown.tsx

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

TableAliases (merged from main via #31829) rendered the truncated alias name
with a native `title={record.fqn}`, which the now-error no-raw-title-attribute
rule flags. Migrate it to <Tooltip> using a <Focusable> trigger so the hover
tooltip works without a wrapper element that would break the cell's ellipsis.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Shrabanti Paul and others added 4 commits September 11, 2026 12:57
…bute

TableAliases now surfaces the full alias FQN through the design-system Tooltip
(migrated from a native `title` for the no-raw-title-attribute rule), so the
widget test must check the react-aria tooltip overlay on hover instead of a
`title` attribute. Filter the tooltip by the expected FQN to stay robust against
the brief open/close overlap when moving between cells.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…dom)

TableAliases migrated its alias name from a native `title` to <Tooltip> +
<Focusable>, so the jest test can no longer assert `toHaveAttribute('title')`.
jsdom does not render the react-aria tooltip overlay on hover/focus, so verify
the jsdom-observable contract instead — the name carries the Focusable trigger's
tabindex="-1" (i.e. it is a tooltip trigger, not plain text). The hover overlay
itself is covered by playwright/e2e/Pages/TableAliases.spec.ts.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…td ellipsis cell)

The earlier migration wrapped the alias name in <Tooltip><Focusable>, but the
react-aria tooltip does not open on hover when nested inside an antd Table
`ellipsis` cell (verified in CI: getByRole('tooltip') never appears). Revert to a
native title carrying the full FQN — the antd ellipsis column's own overflow
tooltip is native-title-based, so this is the idiomatic affordance here — with a
justified eslint-disable for no-raw-title-attribute. Restores the original jest
and playwright assertions.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
karanh37
karanh37 previously approved these changes Sep 11, 2026
The native-title→Tooltip migration replaced `import { …, Tooltip } from
'recharts'` with the ui-core-components Tooltip, but the `<Tooltip />` inside the
PieChart is the recharts chart tooltip — so the pie chart's hover tooltip broke
(and it tripped a type error: ui-core TooltipProps requires title/children).
Import the recharts Tooltip aliased as RechartsTooltip and use it for the chart;
the ui-core Tooltip stays for the documentation tooltip.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

⚠️ UI Checkstyle passed — lint findings in changed files

🔍 ESLint findings in this PR's files — 0 error(s), 57 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), 57 warning(s) across 10 changed file(s).

Count Rule
20 react-hooks/exhaustive-deps
18 openmetadata-imports/no-impure-pure-utils
9 openmetadata-imports/no-circular-imports
7 no-restricted-imports
2 openmetadata-imports/no-internal-barrel-imports
1 openmetadata-imports/no-api-calls-in-iteration
All findings
Location Rule Message
🟡 src/components/DataQuality/DataQualityDashboard/DataQualityDashboard.component.tsx:22: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/components/DataQuality/DataQualityDashboard/DataQualityDashboard.component.tsx:23: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/components/DataQuality/DataQualityDashboard/DataQualityDashboard.component.tsx:25: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/components/DataQuality/DataQualityDashboard/DataQualityDashboard.component.tsx:30: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/components/DataQuality/DataQualityDashboard/DataQualityDashboard.component.tsx:33: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/components/Database/Profiler/TableProfiler/SingleColumnProfile.tsx:144:6 react-hooks/exhaustive-deps React Hook useMemo has missing dependencies: 'profilerDocsLink' and 't'. Either include them or remove the dependency array.
🟡 src/components/Database/Profiler/TableProfiler/SingleColumnProfile.tsx:214:6 react-hooks/exhaustive-deps React Hook useEffect has a missing dependency: 'createMetricsChartData'. Either include it or remove the dependency array.
🟡 src/components/Database/Profiler/TableProfiler/TableProfilerChart/TableProfilerChart.tsx:131:6 react-hooks/exhaustive-deps React Hook useMemo has missing dependencies: 'profilerDocsLink' and 't'. Either include them or remove the dependency array.
🟡 src/components/Database/Profiler/TableProfiler/TableProfilerChart/TableProfilerChart.tsx:152:5 react-hooks/exhaustive-deps React Hook useCallback has an unnecessary dependency: 'profileMetrics'. Either exclude it or remove the dependency array.
🟡 src/components/Database/Profiler/TableProfiler/TableProfilerChart/TableProfilerChart.tsx:190:6 react-hooks/exhaustive-deps React Hook useEffect has a missing dependency: 'fetchProfilerData'. Either include it or remove the dependency array.
🟡 src/components/Explore/EntitySummaryPanel/CustomPropertiesSection/CustomPropertiesSection.tsx:43:9 react-hooks/exhaustive-deps The 'customProperties' logical expression could make the dependencies of useMemo Hook (at line 64) change on every render. To fix this, wrap the initialization
🟡 src/components/Explore/EntitySummaryPanel/CustomPropertiesSection/CustomPropertiesSection.tsx:108:6 react-hooks/exhaustive-deps React Hook useMemo has a missing dependency: 't'. Either include it or remove the dependency array.
🟡 src/components/platform/ai-shell/Sidebar/ContextCenterSubNavSections.tsx:127:36 openmetadata-imports/no-api-calls-in-iteration Avoid issuing one API request per item. Fetch at the data owner, use a bulk endpoint, or use useQueries with an intentional concurrency policy.
🟡 src/pages/ColumnBulkOperations/ColumnGrid/ColumnGrid.component.tsx:57:1 openmetadata-imports/no-internal-barrel-imports Import the internal module directly instead of its index barrel so unrelated siblings do not enter the bundle graph.
🟡 src/pages/ColumnBulkOperations/ColumnGrid/ColumnGrid.component.tsx:59:1 openmetadata-imports/no-internal-barrel-imports Import the internal module directly instead of its index barrel so unrelated siblings do not enter the bundle graph.
🟡 src/pages/ColumnBulkOperations/ColumnGrid/ColumnGrid.component.tsx:1105:5 react-hooks/exhaustive-deps React Hook useCallback has missing dependencies: 'buildMultiOccurrenceRows', 'buildSingleOccurrenceRows', 'buildVariationRows', and 'getUniquePaths'. Either inc
🟡 src/pages/ColumnBulkOperations/ColumnGrid/ColumnGrid.component.tsx:1293:5 react-hooks/exhaustive-deps React Hook useCallback has missing dependencies: 'renderCoverageDescriptionCell' and 't'. Either include them or remove the dependency array.
🟡 src/pages/ColumnBulkOperations/ColumnGrid/ColumnGrid.component.tsx:1561:5 react-hooks/exhaustive-deps React Hook useCallback has missing dependencies: 'renderGroupColumnNameCell', 'renderOccurrenceColumnNameCell', and 'renderStructChildColumnNameCell'. Either in
🟡 src/pages/ColumnBulkOperations/ColumnGrid/ColumnGrid.component.tsx:1633:5 react-hooks/exhaustive-deps React Hook useMemo has a missing dependency: 'columnGridListing'. Either include it or remove the dependency array.
🟡 src/pages/ColumnBulkOperations/ColumnGrid/ColumnGrid.component.tsx:1812:6 react-hooks/exhaustive-deps React Hook useCallback has missing dependencies: 'buildColumnUpdatesByKey' and 'columnGridListing'. Either include them or remove the dependency array.
🟡 src/pages/ColumnBulkOperations/ColumnGrid/ColumnGrid.component.tsx:1966:5 react-hooks/exhaustive-deps React Hook useCallback has missing dependencies: 'handleBulkUpdateCompleted' and 'handleBulkUpdateFailed'. Either include them or remove the dependency array.
🟡 src/pages/ColumnBulkOperations/ColumnGrid/ColumnGrid.component.tsx:2042:6 react-hooks/exhaustive-deps React Hook useEffect has a missing dependency: 'columnGridListing'. Either include it or remove the dependency array.
🟡 src/pages/ColumnBulkOperations/ColumnGrid/ColumnGrid.component.tsx:2164:5 react-hooks/exhaustive-deps React Hook useCallback has a missing dependency: 'columnGridListing'. Either include it or remove the dependency array.
🟡 src/pages/ColumnBulkOperations/ColumnGrid/ColumnGrid.component.tsx:2273:5 react-hooks/exhaustive-deps React Hook useCallback has a missing dependency: 'columnGridListing'. Either include it or remove the dependency array.
🟡 src/pages/ColumnBulkOperations/ColumnGrid/ColumnGrid.component.tsx:2385:5 react-hooks/exhaustive-deps React Hook useMemo has a missing dependency: 'columnGridListing'. Either include it or remove the dependency array.
🟡 src/pages/ColumnBulkOperations/ColumnGrid/ColumnGrid.component.tsx:2418:5 react-hooks/exhaustive-deps React Hook useMemo has a missing dependency: 'columnGridListing'. Either include it or remove the dependency array.
🟡 src/pages/ColumnBulkOperations/ColumnGrid/ColumnGrid.component.tsx:2532:6 react-hooks/exhaustive-deps React Hook useMemo has an unnecessary dependency: 'columnGridListing.allRows'. Either exclude it or remove the dependency array.
🟡 src/pages/TableDetailsPageV1/TableAliases/TableAliases.component.tsx:94:6 react-hooks/exhaustive-deps React Hook useEffect has a missing dependency: 'filterWidgets'. Either include it or remove the dependency array.
🟡 src/utils/AdvancedSearchUtils.tsx:22:1 no-restricted-imports '@untitledui/icons' import is restricted from being used by a pattern. Import icons from @openmetadata/ui-core-components/icons, not directly from @untitledui/i
🟡 src/utils/AdvancedSearchUtils.tsx:26: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/AdvancedSearchUtils.tsx:35: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/AdvancedSearchUtils.tsx:37: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/AdvancedSearchUtils.tsx:40: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/EntityDisplayPureUtils.tsx:14: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/utils/EntityDisplayPureUtils.tsx:18: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/utils/EntityDisplayPureUtils.tsx:34:5 openmetadata-imports/no-impure-pure-utils Pure utilities must not render JSX. Move this code to a component or renderer and keep PureUtils as a .ts module.
🟡 src/utils/EntityDisplayPureUtils.tsx:40:7 openmetadata-imports/no-impure-pure-utils Pure utilities must not render JSX. Move this code to a component or renderer and keep PureUtils as a .ts module.
🟡 src/utils/EntityDisplayPureUtils.tsx:41:9 openmetadata-imports/no-impure-pure-utils Pure utilities must not render JSX. Move this code to a component or renderer and keep PureUtils as a .ts module.
🟡 src/utils/EntityDisplayPureUtils.tsx:51:5 openmetadata-imports/no-impure-pure-utils Pure utilities must not render JSX. Move this code to a component or renderer and keep PureUtils as a .ts module.
🟡 src/utils/EntityDisplayPureUtils.tsx:52:7 openmetadata-imports/no-impure-pure-utils Pure utilities must not render JSX. Move this code to a component or renderer and keep PureUtils as a .ts module.
🟡 src/utils/EntityDisplayPureUtils.tsx:62:3 openmetadata-imports/no-impure-pure-utils Pure utilities must not render JSX. Move this code to a component or renderer and keep PureUtils as a .ts module.
🟡 src/utils/EntityDisplayPureUtils.tsx:64:5 openmetadata-imports/no-impure-pure-utils Pure utilities must not render JSX. Move this code to a component or renderer and keep PureUtils as a .ts module.
🟡 src/utils/EntityDisplayPureUtils.tsx:64:54 openmetadata-imports/no-impure-pure-utils Pure utilities must not render JSX. Move this code to a component or renderer and keep PureUtils as a .ts module.
🟡 src/utils/EntityDisplayPureUtils.tsx:75:5 openmetadata-imports/no-impure-pure-utils Pure utilities must not render JSX. Move this code to a component or renderer and keep PureUtils as a .ts module.
🟡 src/utils/EntityDisplayPureUtils.tsx:77:34 openmetadata-imports/no-impure-pure-utils Pure utilities must not render JSX. Move this code to a component or renderer and keep PureUtils as a .ts module.
🟡 src/utils/EntityDisplayPureUtils.tsx:84:10 openmetadata-imports/no-impure-pure-utils Pure utilities must not render JSX. Move this code to a component or renderer and keep PureUtils as a .ts module.
🟡 src/utils/EntityDisplayPureUtils.tsx:95:7 openmetadata-imports/no-impure-pure-utils Pure utilities must not render JSX. Move this code to a component or renderer and keep PureUtils as a .ts module.
🟡 src/utils/EntityDisplayPureUtils.tsx:98:11 openmetadata-imports/no-impure-pure-utils Pure utilities must not render JSX. Move this code to a component or renderer and keep PureUtils as a .ts module.
🟡 src/utils/EntityDisplayPureUtils.tsx:123:7 openmetadata-imports/no-impure-pure-utils Pure utilities must not render JSX. Move this code to a component or renderer and keep PureUtils as a .ts module.
🟡 src/utils/EntityDisplayPureUtils.tsx:124:9 openmetadata-imports/no-impure-pure-utils Pure utilities must not render JSX. Move this code to a component or renderer and keep PureUtils as a .ts module.

… and 7 more. Run make ui-checkstyle-changed locally for the full list.


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

make ui-checkstyle-changed

Shrabanti Paul and others added 5 commits September 11, 2026 17:58
# Conflicts:
#	openmetadata-ui/src/main/resources/ui/playwright/e2e/Features/ImpactAnalysis.spec.ts
# Conflicts:
#	openmetadata-ui/src/main/resources/ui/eslint-rules/openmetadata-ui-patterns.mjs
@github-actions

Copy link
Copy Markdown
Contributor

🚦 Removed from the merge queue — failed_checks (2026-09-16T03:48:35Z)

Blocked the queue: playwright-summary

@gitar-bot

gitar-bot Bot commented Sep 16, 2026

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

Replaces native HTML title attributes across 18 UI files with the Tooltip component for consistent design-system rendering, addressing React key placement on inner divs and Tooltip's built-in excludeTriggerFromTabOrder behavior. No open issues.

✅ 2 closed
Bug: React key on inner div instead of Tooltip in tag list

📄 openmetadata-ui/src/main/resources/ui/src/pages/ColumnBulkOperations/ColumnGrid/ColumnGrid.component.tsx:237-245
Inside visibleTags.map(...) the returned element is now <Tooltip>, but key={tag.tagFQN} stayed on the inner <div>. React requires the key on the outermost element returned by the map callback, so this triggers the "unique key" warning and can cause incorrect list reconciliation when tags change. Move the key onto the <Tooltip>. Note the sibling conversions in BarMenu.tsx and AgentCard.component.tsx correctly placed key on the Tooltip.

Quality: Reimplements Tooltip's built-in excludeTriggerFromTabOrder trigger

📄 openmetadata-ui/src/main/resources/ui/src/pages/TableDetailsPageV1/TableAliases/TableAliases.component.tsx:16 📄 openmetadata-ui/src/main/resources/ui/src/pages/TableDetailsPageV1/TableAliases/TableAliases.component.tsx:79-86
The Tooltip component in ui-core-components already provides excludeTriggerFromTabOrder, which is documented for exactly this case (a non-focusable child in a grid/table cell where focus belongs to the cell, not its content). It wraps the child in a plain, non-focusable span. Reaching into react-aria-components's Focusable directly (a dependency not otherwise used in this codebase) bypasses that design-system API and, via excludeFromTabOrder (tabIndex=-1), leaves the span programmatically focusable — the exact behavior the library's own prop deliberately avoids. Prefer <Tooltip title={record.fqn} excludeTriggerFromTabOrder><span>{name}</span></Tooltip> and drop the Focusable import.

Review coverage

Rules No rules evaluated

Functional validation Not enabled · Set up

Auto-approval Not enabled · Set up

Options

Display: compact → Counting what did not apply, without listing it.

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

Comment on lines +153 to +154
<Tooltip key={item.name} title={item.name}>
<button

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 Tooltip creates nested buttons

Wrapping a native button directly in Tooltip causes the Tooltip implementation to place an AriaButton around it. This creates invalid button-inside-button markup, giving one action two focusable controls and leaving the outer button unnamed. The same pattern affects the NLP toggles, recent-run dots, and context-center navigation buttons. Use a tooltip trigger pattern that does not add another button.

Comment on lines +239 to +240
<Tooltip key={tag.tagFQN} title={fullLabel}>
<div className="tw:min-w-0 tw:flex-1 tw:basis-0 tw:overflow-hidden">

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 Tooltip breaks badge truncation

Tooltip inserts a tw:w-max wrapper outside the div carrying tw:min-w-0 tw:flex-1 tw:basis-0. That wrapper becomes the flex item, so the inner shrink and truncation rules no longer constrain the badge. Long labels can therefore consume their intrinsic width and overflow the fixed-width column. Apply the sizing rules to the actual tooltip trigger or use a shrinkable, non-focusable trigger wrapper.

@sonarqubecloud

Copy link
Copy Markdown

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 UI UI specific issues

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants