Skip to content

Commit c9bdfc2

Browse files
committed
Improves timeline chart tooltip interactions
- Shows tooltip when hovering over slider and footer SHA
1 parent bf6f0f3 commit c9bdfc2

File tree

2 files changed

+50
-22
lines changed

2 files changed

+50
-22
lines changed

src/webviews/apps/plus/timeline/components/chart.ts

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -220,13 +220,20 @@ export class GlTimelineChart extends GlElement {
220220
}
221221

222222
private renderFooter() {
223+
const sha = this._shaHovered ?? this._shaSelected;
224+
223225
return html`<footer>
224226
<gl-chart-slider
225227
.data=${this._dataReversed}
226228
?shift=${this._shiftKeyPressed}
227229
@gl-slider-change=${this.onSliderChanged}
230+
@mouseover=${this.onSliderMouseOver}
231+
@mouseout=${this.onSliderMouseOut}
228232
></gl-chart-slider>
229-
${renderCommitSha(this._shaHovered ?? this._shaSelected, 16)}${this.renderActions()}
233+
<span @mouseover=${this.onFooterShaMouseOver} @mouseout=${this.onFooterShaMouseOut}
234+
>${renderCommitSha(sha, 16)}</span
235+
>
236+
${this.renderActions()}
230237
</footer>`;
231238
}
232239

@@ -295,6 +302,16 @@ export class GlTimelineChart extends GlElement {
295302
this._shiftKeyPressed = e.shiftKey;
296303
};
297304

305+
private onFooterShaMouseOver() {
306+
if (!this._shaSelected) return;
307+
308+
this.showTooltip(this._data?.find(c => c.sha === this._shaSelected));
309+
}
310+
311+
private onFooterShaMouseOut() {
312+
this.hideTooltip();
313+
}
314+
298315
private readonly onResize = (e: CustomEvent<{ entries: ResizeObserverEntry[] }>) => {
299316
if (!this._chart) return;
300317

@@ -325,14 +342,25 @@ export class GlTimelineChart extends GlElement {
325342
private onSliderChanged(e: CustomEvent<SliderChangeEventDetail>) {
326343
this.revealDate(e.detail.date, { focus: true, select: true });
327344

328-
const sha = this._commitsByTimestamp.get(e.detail.date.getTime())?.sha;
345+
const commit = this._commitsByTimestamp.get(e.detail.date.getTime());
346+
const sha = commit?.sha;
329347
this._shaHovered = undefined;
330348
this._shaSelected = sha;
331349

350+
this.showTooltip(commit);
351+
332352
if (sha == null) return;
333353
this.emit('gl-commit-select', { id: sha, shift: e.detail.shift });
334354
}
335355

356+
private onSliderMouseOver(_e: MouseEvent) {
357+
this.showTooltip(this.slider?.value);
358+
}
359+
360+
private onSliderMouseOut(_e: MouseEvent) {
361+
this.hideTooltip();
362+
}
363+
336364
private readonly onZoom = (domain: [Date, Date]) => {
337365
this.zoomedRange = domain[0] <= this.range[0] && domain[1] >= this.range[1] ? undefined : domain;
338366
};
@@ -415,6 +443,16 @@ export class GlTimelineChart extends GlElement {
415443
}
416444
}
417445

446+
private showTooltip(datum: TimelineDatum | undefined) {
447+
if (datum == null) return;
448+
449+
this._chart?.tooltip.show({ x: new Date(datum.date) });
450+
}
451+
452+
private hideTooltip() {
453+
this._chart?.tooltip.hide();
454+
}
455+
418456
zoom(factor: number): void {
419457
if (factor === 0) {
420458
this.resetZoom();

src/webviews/apps/plus/timeline/components/slider.ts

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,5 @@
1-
import type SlRange from '@shoelace-style/shoelace/dist/components/range/range.js';
2-
import type { PropertyValues } from 'lit';
31
import { css, html } from 'lit';
4-
import { customElement, property, query, state } from 'lit/decorators.js';
5-
import { isUncommitted, isUncommittedStaged, shortenRevision } from '../../../../../git/utils/revision.utils';
2+
import { customElement, property, state } from 'lit/decorators.js';
63
import type { TimelineDatum } from '../../../../plus/timeline/protocol';
74
import { GlElement } from '../../../shared/components/element';
85
import '@shoelace-style/shoelace/dist/components/range/range.js';
@@ -30,10 +27,11 @@ export class GlChartSlider extends GlElement {
3027
--track-active-offset: 100%;
3128
--track-color-active: var(--gl-track-color-active, var(--sl-color-neutral-200));
3229
}
33-
`;
3430
35-
@query('#slider')
36-
private slider!: SlRange;
31+
sl-range::part(thumb) {
32+
cursor: pointer;
33+
}
34+
`;
3735

3836
@state()
3937
private _value: number = 0;
@@ -68,18 +66,8 @@ export class GlChartSlider extends GlElement {
6866
}
6967
}
7068

71-
protected override firstUpdated(_changedProperties: PropertyValues): void {
72-
this.slider.tooltipFormatter = (value: number) => {
73-
const sha = this.data?.[value]?.sha;
74-
if (sha == null) return '';
75-
76-
if (!sha) return 'Working Changes';
77-
if (isUncommitted(sha)) {
78-
return isUncommittedStaged(sha) ? 'Staged Changes' : 'Working Changes';
79-
}
80-
81-
return `Commit ${shortenRevision(sha)}`;
82-
};
69+
get value() {
70+
return this.data?.[this._value];
8371
}
8472

8573
override render() {
@@ -89,8 +77,10 @@ export class GlChartSlider extends GlElement {
8977
.min=${this._min}
9078
.max=${this._max}
9179
.value=${this._value}
80+
tooltip="none"
9281
@sl-change=${this.handleSliderInput}
9382
@sl-input=${this.handleSliderInput}
83+
@click=${this.handleSliderInput}
9484
></sl-range>
9585
</div>`;
9686
}
@@ -110,7 +100,7 @@ export class GlChartSlider extends GlElement {
110100
this._value = index;
111101
}
112102

113-
private handleSliderInput(e: CustomEvent<void>) {
103+
private handleSliderInput(e: MouseEvent | CustomEvent<void>) {
114104
if (!this.data?.length) return;
115105

116106
const index = parseInt((e.target as HTMLInputElement).value);

0 commit comments

Comments
 (0)