Skip to content

Fix: draw component borders with outline instead of ring (Safari border rendering at non-100% zoom) - #30190

Merged
chirag-madlani merged 6 commits into
mainfrom
fix-ring-border-issue
Jul 21, 2026
Merged

Fix: draw component borders with outline instead of ring (Safari border rendering at non-100% zoom)#30190
chirag-madlani merged 6 commits into
mainfrom
fix-ring-border-issue

Conversation

@aniketkatkar97

@aniketkatkar97 aniketkatkar97 commented Jul 17, 2026

Copy link
Copy Markdown
Member

Fixes #30188

What's the problem

In Safari, component borders thin out — and at some zoom levels vanish entirely — at any zoom other than 100%. It looks Safari-only, but isn't quite.

The design system never drew these borders with a real border. It used Tailwind's ring-*, which compiles to a box-shadow, and WebKit does not pixel-snap box-shadows. At a fractional device pixel ratio (Safari reports devicePixelRatio: 1.7 at 85% zoom on Retina) a 1px ring cannot occupy a whole number of device pixels, so it is antialiased across two columns and renders washed out or not at all. border and outline are snapped and never degrade.

Chromium degrades rings too — it just never falls far enough to notice, which is why only Safari gets reported. Peak border darkness sampled from rendered pixels across a 50–150% zoom sweep (42 = full strength for the token, 0 = invisible):

border ring outline
WebKit @1x 42..42 0..42 (vanishes) 42..42
Chromium @1x 42..42 21..42 (dims ~50%) 42..42
WebKit @2x 42..42 42..42 42..42

What changed

ring-* is replaced with outline (or border) as the border primitive across the design system — ~120 sites in 85 files — with no intended visual change at 100% zoom.

Why outline and not border: a border occupies layout. On controls whose height is content-driven it would add 2px and make them grow on focus (1px → 2px). outline is layout-neutral, and an inset outline is pixel-identical to the ring it replaces.

Three patterns, by situation:

Situation Treatment
Element's outline is free tw:outline-1 tw:-outline-offset-1 tw:outline-<token>
Element's outline is already the focus ring (buttons, checkbox, radio, toggle, tags, tabs, slider) border moves to an ::after overlay (borderAfter in utils/tailwindClasses) — an element gets exactly one outline, and these must show border and focus ring simultaneously
Suppressors (ring-0) outline-0 / after:outline-0must flip with the core change, or the suppressor becomes a no-op and borders reappear

Offsets matter: ring-inset-outline-offset-1; no ring-inset → offset 0 (a non-inset ring draws outward). Getting this wrong shifts an edge by 1px.

Verification

  • Pre-flight: every ring colour compile-checked to confirm its outline-* counterpart dereferences to the same value — 41 tokens, zero mismatches. ring-* and outline-* use different theme namespaces, so this was not a given.
  • Pixel parity (ring vs ::after outline, identical geometry): WebKit @2x differs by 1 pixel at delta 1/255 — visually identical at working zoom. WebKit @1.7 differs at max delta 42 — that difference is the bug being fixed.
  • Confirmed in real Safari that an inset outline and a real border are indistinguishable at every zoom, while the ring is not.
  • Core + app tsc, ESLint, Prettier all clean. The two ring-coupled tests in DataQualityDashboard.test.tsx pass unmodified.

Rings deliberately left in place

Each would be a visual change to convert, so they aren't:

  • ring-offset-* halos (color-picker-field, icon-picker-field) — ring-offset-color fills the gap; outline-offset leaves it transparent. Not reproducible. Also 2–3 rings compete for one outline there.
  • Avatar consumers (OwnerReveal, OwnerStackOverflow) — Avatar already uses an outline; a second would clobber it. Wants Avatar's contrastBorder API instead.
  • ring-secondary with no ring-width (AgentCard, RunHistoryDrawer) — renders nothing today; converting would make an invisible border appear.
  • ring-0 on Card (OntologyExplorer, DataQualityDashboard) — Card uses a real border and never had a ring, so it is already inert. Converting would kill Card's focus outline.

Docs

docs/colors.md §2.3.1 documents the rule, the measurements, the ring→outline translation table, and the gotchas that make this easy to get wrong: outline-hidden erases an outline border; unlayered LESS outline: none beats Tailwind utilities regardless of specificity; transition-shadow does not animate an outline; and overriding a Button's border needs after:outline-*, since outline-* silently sets its focus colour instead. Summarised in both CLAUDE.md files and added to the anti-pattern cheat sheet so the pattern isn't reintroduced.

Reviewer notes

  • Visual parity is the acceptance test. At 100% nothing should look different. Worth a pass over button variants (× hover/disabled/focus), checkbox/radio/toggle, tabs, badges, table cards and dropdowns — in light and dark.
  • Focus indicators must survive on every ::after component — that's the whole reason for the overlay approach and the main regression risk.
  • Then the actual fix: Safari at 85% zoom / dpr 1.7, borders hold.
  • ::before was already taken on button.tsx / social-button.tsx (inner gradient), hence ::after.

Before:

Screenshot 2026-07-17 at 5 52 37 PM Screenshot 2026-07-17 at 5 56 06 PM Screenshot 2026-07-17 at 5 57 54 PM

After:

Screenshot 2026-07-17 at 5 52 41 PM Screenshot 2026-07-17 at 5 56 17 PM Screenshot 2026-07-17 at 5 58 11 PM

Greptile Summary

This PR replaces ring-based component edges with pixel-snapped outlines or borders.

  • Migrates design-system borders away from box-shadow rings.
  • Preserves separate focus indicators with pseudo-element overlays.
  • Updates suppressors, transitions, documentation, and application consumers.
  • Removes the obsolete 2xl company-avatar ring class.

Confidence Score: 5/5

This looks safe to merge.

  • The latest avatar update removes the obsolete ring class without adding another edge.
  • No blocking issue remains in the updated code.

Important Files Changed

Filename Overview
openmetadata-ui-core-components/src/main/resources/ui/src/components/base/avatar/base-components/avatar-company-icon.tsx Removes the obsolete 2xl ring utility while retaining the shared outline edge.
openmetadata-ui-core-components/src/main/resources/ui/src/utils/tailwindClasses.ts Adds shared pseudo-element outline classes for components that reserve their own outline for focus.

Reviews (5): Last reviewed commit: "Merge branch 'main' into fix-ring-border..." | Re-trigger Greptile

Context used (3)

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

Copilot AI review requested due to automatic review settings July 17, 2026 14:08

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@github-actions github-actions Bot added safe to test Add this label to run secure Github workflows on PRs UI UI specific issues labels Jul 17, 2026
@github-actions

github-actions Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Jest test Coverage

UI tests summary

Lines Statements Branches Functions
Coverage: 65%
65.21% (75824/116265) 48.96% (45167/92240) 49.84% (13677/27441)

…drop dead ring class, fix import order

- OwnerStackOverflow: drop tw:outline-hidden — it set outline-style:none and
  erased the outline that now draws the tooltip border (all browsers).
- avatar-company-icon: remove dead unprefixed ring-[1.67px] from the 2xl size.
  It generates no CSS under prefix(tw), but contradicts the no-rings rule and
  would spring to life if the prefix bug is fixed.
- ManageMenuButton: run organize-imports so the added borderAfter import is
  sorted, fixing the UI Checkstyle lint-src failure.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 17, 2026 16:13

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@gitar-bot

gitar-bot Bot commented Jul 17, 2026

Copy link
Copy Markdown
Code Review ✅ Approved 1 resolved / 1 findings

Replaces Tailwind ring utilities with outline styles to resolve Safari rendering issues at non-100% zoom levels. The fix also addresses an issue where outline-hidden erroneously erased tooltip borders.

✅ 1 resolved
Bug: outline-hidden erases the new outline border on owners tooltip

📄 openmetadata-ui/src/main/resources/ui/src/components/common/OwnerLabel/OwnerStackOverflow.component.tsx:124
The tooltip class was converted from tw:ring-1 tw:ring-secondary_alt tw:outline-hidden to tw:outline-1 tw:outline-secondary_alt tw:outline-hidden. Now that the border is drawn with outline, the retained tw:outline-hidden sets outline-style: none and erases that border entirely (in every browser, not just Safari) — exactly the gotcha documented in this PR's own colors.md §2.3.1 and CLAUDE.md. The sibling conversion in nav-account-card.tsx correctly dropped outline-hidden; this site did not. Remove tw:outline-hidden so the 1px border renders.

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

Copilot AI review requested due to automatic review settings July 20, 2026 13:14
@open-metadata open-metadata deleted a comment from github-actions Bot Jul 20, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

Copilot AI review requested due to automatic review settings July 21, 2026 04:50

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@sonarqubecloud

Copy link
Copy Markdown

@github-actions

Copy link
Copy Markdown
Contributor

🔴 Playwright Results — 1 test failure(s)

✅ 4549 passed · ❌ 1 failed · 🟡 20 flaky · ⏭️ 99 skipped

Shard Passed Failed Flaky Skipped
🟡 Shard 1 436 0 4 16
✅ Shard 2 11 0 0 0
🟡 Shard 3 827 0 6 8
🟡 Shard 4 821 0 2 18
🔴 Shard 5 836 1 2 9
✅ Shard 6 788 0 0 46
🟡 Shard 7 830 0 6 2

Genuine Failures (failed on all attempts)

Pages/CustomProperties.spec.ts › Set & Update all CP types on chart (shard 5)
�[31mTest timeout of 300000ms exceeded.�[39m
🟡 20 flaky test(s) (passed on retry)
  • Features/TagsSuggestion.spec.ts › should decline suggested tags for a container column (shard 1, 1 retry)
  • Pages/Lineage/LineageRightPanel.spec.ts › Verify custom properties tab IS visible for supported type: chart (shard 1, 1 retry)
  • Pages/SearchSettings.spec.ts › Latest preview config wins when a superseded request resolves late (shard 1, 1 retry)
  • Flow/SearchRBAC.spec.ts › a fully denied user sees neither asset type when browsing (shard 1, 1 retry)
  • Features/BulkEditEntity.spec.ts › Glossary (shard 3, 1 retry)
  • Features/ContextCenterArticles.spec.ts › Article listing search filters, clears, and shows empty state (shard 3, 1 retry)
  • Features/ContextCenterArticles.spec.ts › Article list cards, recently viewed widget, and pagination work (shard 3, 1 retry)
  • Features/ContextCenterArticles.spec.ts › Article edits and navigation-flushed titles persist (shard 3, 1 retry)
  • Features/ContextCenterArticles.spec.ts › description: switching articles does not bleed unsaved content into next article (shard 3, 1 retry)
  • Features/ContextCenterMemories.spec.ts › adding a linked asset in edit mode shows entity badge on the row (shard 3, 1 retry)
  • Features/Glossary/LargeGlossaryPerformance.spec.ts › should handle drag and drop for term reordering (shard 4, 1 retry)
  • Features/SearchExport.spec.ts › Export queues a background job and downloads from the jobs tray (shard 4, 1 retry)
  • Flow/ExploreDiscovery.spec.ts › Should not display soft deleted assets in search suggestions (shard 5, 1 retry)
  • Pages/CustomProperties.spec.ts › Should clear search and show all properties for metric in right panel (shard 5, 1 retry)
  • Pages/Lineage/LineageFilters.spec.ts › Verify Impact Analysis service filter selection (shard 7, 1 retry)
  • Pages/Lineage/LineageRightPanel.spec.ts › Verify custom properties tab is NOT visible for pipelineService in platform lineage (shard 7, 1 retry)
  • Pages/Lineage/LineageRightPanel.spec.ts › Verify custom properties tab is NOT visible for apiService in platform lineage (shard 7, 1 retry)
  • Pages/ServiceEntity.spec.ts › Domain Add, Update and Remove (shard 7, 1 retry)
  • Pages/TestSuite.spec.ts › Logical TestSuite (shard 7, 1 retry)
  • Pages/UserDetails.spec.ts › Create team with domain and verify visibility of inherited domain in user profile after team removal (shard 7, 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

@chirag-madlani
chirag-madlani merged commit 29c6ca5 into main Jul 21, 2026
59 of 61 checks passed
@chirag-madlani
chirag-madlani deleted the fix-ring-border-issue branch July 21, 2026 09:00
@gitar-bot

gitar-bot Bot commented Jul 21, 2026

Copy link
Copy Markdown
Code Review ✅ Approved 1 resolved / 1 findings

Replaces Tailwind ring utilities with outline styles to resolve Safari rendering issues at non-100% zoom levels. The fix also addresses an issue where outline-hidden erroneously erased tooltip borders.

✅ 1 resolved
Bug: outline-hidden erases the new outline border on owners tooltip

📄 openmetadata-ui/src/main/resources/ui/src/components/common/OwnerLabel/OwnerStackOverflow.component.tsx:124
The tooltip class was converted from tw:ring-1 tw:ring-secondary_alt tw:outline-hidden to tw:outline-1 tw:outline-secondary_alt tw:outline-hidden. Now that the border is drawn with outline, the retained tw:outline-hidden sets outline-style: none and erases that border entirely (in every browser, not just Safari) — exactly the gotcha documented in this PR's own colors.md §2.3.1 and CLAUDE.md. The sibling conversion in nav-account-card.tsx correctly dropped outline-hidden; this site did not. Remove tw:outline-hidden so the 1px border renders.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Component borders thin out or disappear in Safari at non-100% zoom (ring/box-shadow is not pixel-snapped by WebKit)

3 participants