Fix activity chart bar tooltips clipping and positioning.

Anchor tooltips above each bar with high z-index and allow overflow so hover labels stay visible.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Alireza Hassani
2026-08-28 23:59:47 +03:30
co-authored by Cursor
parent e324ae5763
commit 65012717d0
4 changed files with 47 additions and 19 deletions
@@ -8,6 +8,7 @@
padding: 24px; padding: 24px;
height: 100%; height: 100%;
box-sizing: border-box; box-sizing: border-box;
overflow: visible;
} }
.header { .header {
@@ -80,6 +81,8 @@
gap: 8px; gap: 8px;
direction: ltr; direction: ltr;
unicode-bidi: isolate; unicode-bidi: isolate;
padding-top: 28px;
overflow: visible;
} }
.yAxis { .yAxis {
@@ -106,11 +109,12 @@
position: relative; position: relative;
flex: 1; flex: 1;
min-width: 0; min-width: 0;
overflow: hidden; overflow: visible;
} }
.chartWrapScroll { .chartWrapScroll {
overflow-x: auto; overflow-x: auto;
overflow-y: visible;
} }
.chartGrid { .chartGrid {
@@ -184,6 +188,12 @@
align-items: flex-end; align-items: flex-end;
justify-content: center; justify-content: center;
height: 100%; height: 100%;
z-index: 1;
}
.barWrap:hover,
.barWrap:focus-within {
z-index: 1000;
} }
.barWrap:hover .barTooltip, .barWrap:hover .barTooltip,
@@ -208,16 +218,17 @@
opacity: 0; opacity: 0;
visibility: hidden; visibility: hidden;
transition: opacity 0.12s ease, visibility 0.12s; transition: opacity 0.12s ease, visibility 0.12s;
background: rgba(255, 255, 255, 0.96); background: rgba(255, 255, 255, 0.98);
backdrop-filter: blur(10px); backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
border: 1px solid var(--glass-border); border: 1px solid var(--glass-border);
border-radius: 6px; border-radius: 6px;
box-shadow: 0 4px 12px rgba(31, 38, 135, 0.12); box-shadow: 0 6px 18px rgba(31, 38, 135, 0.18);
z-index: 4; z-index: 10000;
} }
.bar { .bar {
position: relative;
flex: 1 1 0; flex: 1 1 0;
width: 100%; width: 100%;
max-width: 8px; max-width: 8px;
@@ -257,8 +257,9 @@ export function DailyActivityChart({
style={{ style={{
height: Math.max(primaryHeight, item.primary > 0 ? 4 : 0), height: Math.max(primaryHeight, item.primary > 0 ? 4 : 0),
}} }}
/> >
<span className={styles.barTooltip}>{primaryTip}</span> <span className={styles.barTooltip}>{primaryTip}</span>
</div>
</div> </div>
{showSecondary ? ( {showSecondary ? (
<div className={styles.barWrap}> <div className={styles.barWrap}>
@@ -267,8 +268,9 @@ export function DailyActivityChart({
style={{ style={{
height: Math.max(secondaryHeight, item.secondary > 0 ? 4 : 0), height: Math.max(secondaryHeight, item.secondary > 0 ? 4 : 0),
}} }}
/> >
<span className={styles.barTooltip}>{secondaryTip}</span> <span className={styles.barTooltip}>{secondaryTip}</span>
</div>
</div> </div>
) : null} ) : null}
</div> </div>
@@ -307,8 +309,9 @@ export function DailyActivityChart({
style={{ style={{
height: Math.max(primaryHeight, item.count > 0 ? 4 : 0), height: Math.max(primaryHeight, item.count > 0 ? 4 : 0),
}} }}
/> >
<span className={styles.barTooltip}>{primaryTip}</span> <span className={styles.barTooltip}>{primaryTip}</span>
</div>
</div> </div>
{showSecondary ? ( {showSecondary ? (
<div className={styles.barWrap}> <div className={styles.barWrap}>
@@ -317,8 +320,9 @@ export function DailyActivityChart({
style={{ style={{
height: Math.max(secondaryHeight, secondaryCount > 0 ? 4 : 0), height: Math.max(secondaryHeight, secondaryCount > 0 ? 4 : 0),
}} }}
/> >
<span className={styles.barTooltip}>{secondaryTip}</span> <span className={styles.barTooltip}>{secondaryTip}</span>
</div>
</div> </div>
) : null} ) : null}
</div> </div>
@@ -6,6 +6,7 @@
border-radius: var(--radius); border-radius: var(--radius);
box-shadow: var(--glass-shadow); box-shadow: var(--glass-shadow);
padding: 24px; padding: 24px;
overflow: visible;
} }
.header { .header {
@@ -78,6 +79,8 @@
gap: 8px; gap: 8px;
direction: ltr; direction: ltr;
unicode-bidi: isolate; unicode-bidi: isolate;
padding-top: 28px;
overflow: visible;
} }
.yAxis { .yAxis {
@@ -105,6 +108,7 @@
flex: 1; flex: 1;
min-width: 0; min-width: 0;
overflow-x: auto; overflow-x: auto;
overflow-y: visible;
} }
.chartGrid { .chartGrid {
@@ -155,6 +159,12 @@
display: flex; display: flex;
align-items: flex-end; align-items: flex-end;
height: 100%; height: 100%;
z-index: 1;
}
.barWrap:hover,
.barWrap:focus-within {
z-index: 1000;
} }
.barWrap:hover .barTooltip, .barWrap:hover .barTooltip,
@@ -179,16 +189,17 @@
opacity: 0; opacity: 0;
visibility: hidden; visibility: hidden;
transition: opacity 0.12s ease, visibility 0.12s; transition: opacity 0.12s ease, visibility 0.12s;
background: rgba(255, 255, 255, 0.96); background: rgba(255, 255, 255, 0.98);
backdrop-filter: blur(10px); backdrop-filter: blur(10px);
-webkit-backdrop-filter: blur(10px); -webkit-backdrop-filter: blur(10px);
border: 1px solid var(--glass-border); border: 1px solid var(--glass-border);
border-radius: 6px; border-radius: 6px;
box-shadow: 0 4px 12px rgba(31, 38, 135, 0.12); box-shadow: 0 6px 18px rgba(31, 38, 135, 0.18);
z-index: 4; z-index: 10000;
} }
.bar { .bar {
position: relative;
width: 12px; width: 12px;
border-radius: 4px 4px 2px 2px; border-radius: 4px 4px 2px 2px;
transition: height 0.3s ease; transition: height 0.3s ease;
@@ -145,15 +145,17 @@ export function ProductActivityChart() {
<div <div
className={`${styles.bar} ${styles.barAdded}`} className={`${styles.bar} ${styles.barAdded}`}
style={{ height: Math.max(addedHeight, item.added > 0 ? 4 : 0) }} style={{ height: Math.max(addedHeight, item.added > 0 ? 4 : 0) }}
/> >
<span className={styles.barTooltip}>{addedTip}</span> <span className={styles.barTooltip}>{addedTip}</span>
</div>
</div> </div>
<div className={styles.barWrap}> <div className={styles.barWrap}>
<div <div
className={`${styles.bar} ${styles.barUpdated}`} className={`${styles.bar} ${styles.barUpdated}`}
style={{ height: Math.max(updatedHeight, item.updated > 0 ? 4 : 0) }} style={{ height: Math.max(updatedHeight, item.updated > 0 ? 4 : 0) }}
/> >
<span className={styles.barTooltip}>{updatedTip}</span> <span className={styles.barTooltip}>{updatedTip}</span>
</div>
</div> </div>
</div> </div>
<span className={styles.label} dir="ltr"> <span className={styles.label} dir="ltr">