Skip to content

fix(ui): prevent blank table hover overlays - #196

Open
danish9039 wants to merge 3 commits into
kserve:masterfrom
danish9039:agent/kserve-link-hover-tooltip
Open

fix(ui): prevent blank table hover overlays#196
danish9039 wants to merge 3 commits into
kserve:masterfrom
danish9039:agent/kserve-link-hover-tooltip

Conversation

@danish9039

@danish9039 danish9039 commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Problem

The endpoint tables exposed two related blank-overlay defects:

  1. Hovering an Endpoint or Inference Graph name created an empty white card. Repeated hovers accumulated additional cards above or below the link.
  2. After correcting the name links, hovering the Endpoint Created at value still created the same kind of empty white card.

Both defects made the table appear unstable and obscured nearby content. The Endpoint name also needed to remain clickable after repeated hovers so that the details page could open without a manual refresh.

Root Causes

Name links

The Endpoint and Inference Graph name columns configured the shared LinkValue with popoverField: 'metadata.name'. That setting activated the shared libPopover directive for text that was already visible as the link label.

In the affected production image, each hover attached an empty popover component instead of useful content. A Material tooltip experiment also rendered an empty message in the production image, so replacing one overlay mechanism with another did not solve the underlying behavior.

Creation time

The Endpoint Created at column uses the shared DateTimeValue, which is important because it provides relative-time rendering, sorting, date filtering, empty-date filtering, and date-specific filter help.

The pinned shared lib-date-time component always attaches its popover trigger and provides no supported input for disabling it. In the affected production image, the Local and UTC popover content was empty, but the trigger still created a visible blank card.

Replacing DateTimeValue locally would duplicate shared behavior and risk changing sorting and filtering semantics. Updating the shared library would affect multiple Kubeflow interfaces and is outside the narrow ownership of this correction.

Changes

  • Remove popoverField from the Endpoint name-link descriptor.
  • Remove the same field from the Inference Graph name-link descriptor.
  • Preserve LinkType.Internal, link text, truncation, and destination construction.
  • Disable pointer-event capture only on the Endpoint index page creation-time popover trigger:
    app-index .mat-column-age lib-date-time > .truncate.
  • Keep the original DateTimeValue descriptor and its metadata.creationTimestamp field unchanged.
  • Add descriptor tests for the name links and the preserved creation-time value type.
  • Add rendered Cypress coverage for repeated name and creation-time hover cycles.
  • Resolve the creation-time hover target through document.elementFromPoint so the test follows browser pointer hit testing instead of dispatching an event to the wrong parent element.
  • Link the scoped workaround to [notebooks-v1] Date-time popover renders empty content and accumulates overlays kubeflow/notebooks#1252 for upstream tracking and eventual removal.
  • Verify creation-time sorting, exact-date filtering, empty-date filtering, and details navigation.
  • Assert that the hover path creates no lib-popover, .popover-card, or .mat-tooltip element.
  • Assert that the Endpoint Server-Sent Events fixture does not enter an unexpected request or polling path.

Why This Scope Is Appropriate

The stylesheet selector is restricted to app-index, the Endpoint table's age column, and the inner trigger of lib-date-time. It does not affect event tables or other consumers of the shared date component.

Only hover-event capture on the broken, empty trigger is disabled. Header sorting, table filtering, relative-time updates, empty timestamps, and normal row content remain handled by the existing shared component.

The production behavior change is five stylesheet lines. The additional TypeScript changes are tests that preserve the existing behavior while preventing recurrence.

User Impact

Repeated hovering over Endpoint names, Inference Graph names, or Endpoint creation times no longer creates blank blocks. Endpoint names remain normal internal links and open the details page without a manual refresh.

No useful hover information is removed because the affected production image rendered empty overlay content.

Review Follow-up

Claude Code correctly found that the original creation-time test dispatched mouseenter to lib-date-time, while the shared [libPopover] directive is attached to the inner .truncate element. Because native mouseenter does not bubble, the original no-overlay assertion could pass without exercising the broken directive.

The revised test computes the center of the creation-time element and calls document.elementFromPoint to obtain the element that a physical pointer can reach. When the stylesheet rule is removed, the pointer reaches .truncate, creates the empty shared popover, and the test fails. With the rule restored, the pointer reaches the non-triggering parent and the test passes.

The shared defect is tracked at kubeflow/notebooks#1252.

Verification

Source and automated checks

  • git diff --check
  • npm run format:check
  • Focused Prettier verification for the changed Cypress specification
  • npm run lint-check
  • npm test -- --runInBand: 29 suites and 144 tests passed
  • npm run build: production build completed
  • npm run e2e:cypress:ci: 8 specifications and 63 tests passed
  • Independent architecture and adversarial reviews completed
  • Claude Code follow-up review identified a vacuous creation-time hover target and missing upstream tracking reference; both findings are addressed
  • Regression proof: with the stylesheet rule removed, the revised Cypress check selects the real .truncate pointer target and fails because a blank lib-popover remains in the document
  • Restored-rule proof: the same focused specification passes all 9 tests

Fresh production image and live KinD check

  • Image: local/models-web-app:hover-overlay-fix-v2
  • Resource-limited KinD node: 2 CPUs and 3 GiB memory
  • Ten physical Chrome pointer hovers over the Endpoint name: zero popovers, popover cards, or tooltips
  • Ten physical Chrome pointer hovers over the Endpoint creation time: zero popovers, popover cards, or tooltips
  • Creation-time computed style: pointer-events: none
  • Endpoint click after repeated hovering:
    • Parent dashboard route reached /_/kserve-endpoints/details/kubeflow-user/sklearn-iris?ns=kubeflow-user
    • Iframe route reached /kserve-endpoints/details/kubeflow-user/sklearn-iris?ns=kubeflow-user
  • Network capture included the list Server-Sent Events request, details Server-Sent Events request, inference-service details request, and revision request; all watched responses were HTTP 200
  • Browser diagnostics: zero exceptions and zero watched responses at or above HTTP 400

Assisted-by: OpenAI Codex (GPT-5)

@danish9039
danish9039 force-pushed the agent/kserve-link-hover-tooltip branch from a7c9765 to 664836a Compare July 14, 2026 11:42
@danish9039 danish9039 changed the title fix(ui): prevent repeated blank name hover overlays fix(ui): prevent blank table hover overlays Jul 14, 2026
@juliusvonkohout
juliusvonkohout requested a review from Copilot July 15, 2026 19:30

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR eliminates blank hover overlay artifacts in the Endpoints and Inference Graph tables by removing link-popover configuration from name columns and suppressing pointer-event capture on the shared date-time popover trigger for the Endpoints “Created at” cell, with added unit and Cypress regression coverage.

Changes:

  • Remove popoverField from Endpoint and Inference Graph name link descriptors to prevent empty hover overlays.
  • Add a narrowly scoped global CSS rule to disable pointer events on the Endpoints “Created at” lib-date-time > .truncate trigger.
  • Add/extend Jest and Cypress tests to prevent recurrence and verify navigation, sorting/filtering, and repeated-hover behavior.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
frontend/src/styles.scss Adds scoped CSS workaround disabling pointer events on the broken date-time popover trigger.
frontend/src/app/pages/inference-graph/config.ts Removes popoverField from the Inference Graph name link column.
frontend/src/app/pages/index/config.ts Removes popoverField from the Endpoints name link column (preserves DateTimeValue for Created at).
frontend/src/app/pages/inference-graph/inference-graph.component.spec.ts Adds unit assertions to ensure name links do not configure hover overlays.
frontend/src/app/pages/index/index.component.spec.ts Adds unit assertions for no-hover-overlay name links and preserves shared date-time semantics.
frontend/cypress/e2e/inference-graph.cy.ts Adds Cypress coverage for repeated hover cycles and name-link navigation.
frontend/cypress/e2e/index-page.cy.ts Adds Cypress coverage for repeated hover cycles and correct pointer target selection via elementFromPoint.
frontend/mocks/kubeflow.ts Updates the Jest kubeflow mock to include tooltipField and adjust popoverField handling for tests.

Comment on lines +139 to +141
expect(nameColumn?.value.linkType).toBe(LinkType.Internal);
expect(nameColumn?.value.tooltipField).toBe('');
expect(nameColumn?.value.popoverField).toBe('');

@danish9039 danish9039 Jul 16, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The pinned LinkValue contract defaults both fields to empty strings, so this exact assertion intentionally verifies production behavior.

Comment on lines 274 to +276
expect(nameColumn?.value.linkType).toBe(LinkType.Internal);
expect(nameColumn?.value.tooltipField).toBe('');
expect(nameColumn?.value.popoverField).toBe('');

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The pinned LinkValue contract guarantees empty strings here, so the strict assertion detects drift from the production object.

Comment on lines 242 to 246
export class LinkValue {
field: string;
popoverField?: string;
popoverField: string;
tooltipField: string;
truncate?: boolean;

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The mock intentionally mirrors the pinned LinkValue string properties and empty-string defaults used by its length checks.

Comment on lines +183 to +186
cy.get(creationTimestampSelector).then(creationTimestampElements => {
const creationTimestampElement = creationTimestampElements[0];
const boundingRectangle =
creationTimestampElement.getBoundingClientRect();

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Cypress cy.get already retries and fails clearly when the selector matches nothing, so this callback cannot receive an empty collection.

@danish9039
danish9039 marked this pull request as ready for review July 16, 2026 08:34
@danish9039

danish9039 commented Jul 16, 2026

Copy link
Copy Markdown
Contributor Author

@juliusvonkohout

waiting for kubeflow/notebooks#1255 to get merged

/hold

@danish9039
danish9039 marked this pull request as draft July 16, 2026 13:09
@danish9039
danish9039 marked this pull request as ready for review August 3, 2026 13:58
Signed-off-by: danish9039 <danishsiddiqui040@gmail.com>
Assisted-by: OpenAI Codex (GPT-5)
Signed-off-by: danish9039 <danishsiddiqui040@gmail.com>
Assisted-by: OpenAI Codex (GPT-5)
Signed-off-by: danish9039 <danishsiddiqui040@gmail.com>
Assisted-by: OpenAI Codex (GPT-5)
@danish9039
danish9039 force-pushed the agent/kserve-link-hover-tooltip branch from 791b44c to fd0fe62 Compare August 5, 2026 19:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants