[SPPM-324] Milestone tooltip is off screen if milestone name is long - #24700
[SPPM-324] Milestone tooltip is off screen if milestone name is long#24700bsatarnejad wants to merge 1 commit into
Conversation
|
Warning Flaky specs
🤖 Ask Copilot to investigateCopy the prompt below into a new comment on this PR to delegate the investigation to GitHub Copilot. It will look into the flakiness and open a separate pull request with you as reviewer. |
There was a problem hiding this comment.
Pull request overview
Moves project timeline tooltips to a body-level layer so long milestone names remain visible within the viewport.
Changes:
- Relocates and positions tooltip layers.
- Adds cleanup and fixed-layer styling.
- Adds relocation and lifecycle tests.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.
| File | Summary |
|---|---|
frontend/src/app/shared/components/project-timeline-graph/project-timeline-graph.component.ts |
Manages tooltip relocation and cleanup. Moderate issue (2 votes): the moved tooltip should remain aria-hidden="true" to preserve accessibility behavior. |
frontend/src/app/shared/components/project-timeline-graph/project-timeline-graph.component.spec.ts |
Tests tooltip relocation and cleanup. |
frontend/src/app/shared/components/project-timeline-graph/project-timeline-graph.component.sass |
Styles the viewport-level tooltip layer. |
Suppressed comments (2)
frontend/src/app/shared/components/project-timeline-graph/project-timeline-graph.component.spec.ts:585
- This test calls the private
liftTooltip()directly, so it does not exercise the newitemoversubscription at line 152 and would still pass if the event hookup were missing. It also never verifies the viewport-bound geometry that is central to this fix; trigger the actual timeline hover path and assert the layer's positioning (including after scrolling/resizing).
(fixture.componentInstance as unknown as { liftTooltip:() => void }).liftTooltip();
frontend/src/app/shared/components/project-timeline-graph/project-timeline-graph.component.ts:184
- The layer's fixed coordinates are calculated only while
itemoverfires. If the page is scrolled, the viewport is resized, or the grid reflows while the pointer remains over the same item, the timeline moves but this layer stays at its oldleft/topand size, so the tooltip can become detached or off-screen. Reposition the layer on the relevant scroll/resize/reflow events (and clean those listeners up on destroy), or otherwise keep its viewport anchoring current.
const rect = root.getBoundingClientRect();
this.tooltipLayer.style.left = `${rect.left}px`;
this.tooltipLayer.style.top = `${rect.top}px`;
this.tooltipLayer.style.width = `${Math.max(0, window.innerWidth - rect.left)}px`;
this.tooltipLayer.style.height = `${Math.max(0, window.innerHeight - rect.top)}px`;
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| this.tooltipLayer.className = 'op-project-timeline-graph op-project-timeline-graph--tooltip-layer'; | ||
| document.body.appendChild(this.tooltipLayer); |
afe517c to
f58f7bd
Compare
|
Caution The provided work package version does not match the core version Details:
Please make sure that:
|
myabc
left a comment
There was a problem hiding this comment.
@bsatarnejad This works, but I think the z-index approach will prove to be brittle in the long-run. We already a Primer anchored-position-based solution for this in place for the time entry widgets (frontend/src/app/features/calendar/te-calendar/te-calendar.component.ts), so I think it makes sense to re-use that (plus we "own the code", so to speak).
Since I've ended up reviewing this PR so late (sorry!), and won't have a chance to talk this through with you, I took the liberty of just pushing my alternate solution as #24893.
Ticket
https://community.openproject.org/wp/SPPM-324
What are you trying to accomplish?
The project timeline widget renders its hover tooltip via vis-timeline, which appends it inside
.vis-timeline(overflow: hidden). That element is in a dashboard grid cell (.grid--area) that both haveoverflow: hiddenand owns az-indexstacking context, so a long milestone name was cut off and could be painted behind the widget below.Move the tooltip into a body-level layer anchored to the timeline origin and stretched to the viewport edges. vis-timeline's
overflowMethod: 'cap'then keeps the tooltip within the viewport, so it stays fully visible regardless of the milestone name length or position.Screenshots