Skip to content

Commit ed9b710

Browse files
committed
fix: position slider correctly with inset-0 inside relative container
- Use native title attribute for tooltip (simpler, no wrapper) - Slider positioned inside the bar container which has relative - Add overflow-visible to allow triangles to extend beyond bar - Remove barHeight prop - not needed with inset-0
1 parent 379d6a4 commit ed9b710

File tree

3 files changed

+108
-122
lines changed

3 files changed

+108
-122
lines changed

src/browser/components/RightSidebar/CostsTab.tsx

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -188,8 +188,9 @@ const CostsTabComponent: React.FC<CostsTabProps> = ({ workspaceId }) => {
188188
{` (${totalPercentage.toFixed(1)}%)`}
189189
</span>
190190
</div>
191-
<div className="relative w-full py-1">
192-
<div className="bg-border-light flex h-1.5 w-full rounded-[3px]">
191+
<div className="relative w-full py-2">
192+
{/* Bar container - relative for slider positioning */}
193+
<div className="bg-border-light relative flex h-1.5 w-full overflow-visible rounded-[3px]">
193194
{cachedPercentage > 0 && (
194195
<div
195196
className="h-full transition-[width] duration-300"
@@ -231,18 +232,17 @@ const CostsTabComponent: React.FC<CostsTabProps> = ({ workspaceId }) => {
231232
}}
232233
/>
233234
)}
235+
{/* Threshold slider overlay - inside bar for proper positioning */}
236+
{maxTokens && (
237+
<ThresholdSlider
238+
threshold={autoCompactThreshold}
239+
enabled={autoCompactEnabled}
240+
onThresholdChange={setAutoCompactThreshold}
241+
onEnabledChange={setAutoCompactEnabled}
242+
orientation="horizontal"
243+
/>
244+
)}
234245
</div>
235-
{/* Threshold slider overlay - only show when model limits are known */}
236-
{maxTokens && (
237-
<ThresholdSlider
238-
threshold={autoCompactThreshold}
239-
enabled={autoCompactEnabled}
240-
onThresholdChange={setAutoCompactThreshold}
241-
onEnabledChange={setAutoCompactEnabled}
242-
orientation="horizontal"
243-
barHeight={6}
244-
/>
245-
)}
246246
</div>
247247
</div>
248248
{showWarning && (

src/browser/components/RightSidebar/ThresholdSlider.tsx

Lines changed: 94 additions & 108 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import {
33
AUTO_COMPACTION_THRESHOLD_MIN,
44
AUTO_COMPACTION_THRESHOLD_MAX,
55
} from "@/common/constants/ui";
6-
import { TooltipWrapper, Tooltip } from "../Tooltip";
76

87
interface ThresholdSliderProps {
98
/** Current threshold percentage (50-90, or 100 for disabled) */
@@ -16,8 +15,6 @@ interface ThresholdSliderProps {
1615
onEnabledChange: (enabled: boolean) => void;
1716
/** Orientation of the slider */
1817
orientation: "horizontal" | "vertical";
19-
/** Height of the bar for vertical positioning (horizontal orientation only) */
20-
barHeight?: number;
2118
}
2219

2320
// Threshold at which we consider auto-compaction disabled (dragged all the way right/down)
@@ -29,7 +26,6 @@ export const ThresholdSlider: React.FC<ThresholdSliderProps> = ({
2926
onThresholdChange,
3027
onEnabledChange,
3128
orientation,
32-
barHeight = 6,
3329
}) => {
3430
const containerRef = useRef<HTMLDivElement>(null);
3531
const [isDragging, setIsDragging] = useState(false);
@@ -80,6 +76,7 @@ export const ThresholdSlider: React.FC<ThresholdSliderProps> = ({
8076
const handleMouseDown = useCallback(
8177
(e: React.MouseEvent) => {
8278
e.preventDefault();
79+
e.stopPropagation();
8380
setIsDragging(true);
8481
updateThreshold(e.clientX, e.clientY);
8582

@@ -100,140 +97,129 @@ export const ThresholdSlider: React.FC<ThresholdSliderProps> = ({
10097
[updateThreshold]
10198
);
10299

103-
// Tooltip shows live feedback during drag
104-
const tooltipContent = isDragging
100+
// Tooltip text
101+
const tooltipText = isDragging
105102
? dragValue !== null && dragValue >= DISABLE_THRESHOLD
106103
? "Release to disable auto-compact"
107104
: `Auto-compact at ${dragValue ?? threshold}%`
108105
: enabled
109106
? `Auto-compact at ${threshold}% · Drag to adjust`
110107
: "Auto-compact disabled · Drag left to enable";
111108

109+
const lineColor = enabled ? "var(--color-plan-mode)" : "var(--color-muted)";
110+
112111
if (orientation === "horizontal") {
113-
// Render as a positioned overlay - the parent should have position:relative
112+
// Absolute overlay covering the bar area
114113
return (
115-
<TooltipWrapper inline>
116-
<div
117-
ref={containerRef}
118-
className="absolute cursor-ew-resize"
119-
style={{
120-
left: 0,
121-
right: 0,
122-
top: "50%",
123-
transform: "translateY(-50%)",
124-
height: barHeight + 16, // bar + 8px padding each side for easier grabbing
125-
}}
126-
onMouseDown={handleMouseDown}
127-
>
128-
{/* Vertical line indicator with grab handle */}
129-
<div
130-
className="pointer-events-none absolute flex flex-col items-center"
131-
style={{
132-
left: `${position}%`,
133-
transform: "translateX(-50%)",
134-
top: 0,
135-
bottom: 0,
136-
}}
137-
>
138-
{/* Top handle - small triangle */}
139-
<div
140-
className={`h-0 w-0 shrink-0 transition-opacity ${
141-
isDragging ? "opacity-100" : "opacity-70"
142-
}`}
143-
style={{
144-
borderLeft: "4px solid transparent",
145-
borderRight: "4px solid transparent",
146-
borderTop: `5px solid ${enabled ? "var(--color-plan-mode)" : "var(--color-muted)"}`,
147-
}}
148-
/>
149-
{/* The line itself */}
150-
<div
151-
className={`flex-1 transition-opacity ${isDragging ? "opacity-100" : "opacity-70"}`}
152-
style={{
153-
width: 2,
154-
background: enabled ? "var(--color-plan-mode)" : "var(--color-muted)",
155-
}}
156-
/>
157-
{/* Bottom handle - small triangle pointing up */}
158-
<div
159-
className={`h-0 w-0 shrink-0 transition-opacity ${
160-
isDragging ? "opacity-100" : "opacity-70"
161-
}`}
162-
style={{
163-
borderLeft: "4px solid transparent",
164-
borderRight: "4px solid transparent",
165-
borderBottom: `5px solid ${enabled ? "var(--color-plan-mode)" : "var(--color-muted)"}`,
166-
}}
167-
/>
168-
</div>
169-
</div>
170-
<Tooltip align="center" width="auto">
171-
{tooltipContent}
172-
</Tooltip>
173-
</TooltipWrapper>
174-
);
175-
}
176-
177-
// Vertical orientation
178-
return (
179-
<TooltipWrapper inline>
180114
<div
181115
ref={containerRef}
182-
className="absolute cursor-ns-resize"
183-
style={{
184-
top: 0,
185-
bottom: 0,
186-
left: "50%",
187-
transform: "translateX(-50%)",
188-
width: 20, // wider hit area
189-
}}
116+
className="absolute inset-0 cursor-ew-resize"
117+
style={{ zIndex: 10 }}
190118
onMouseDown={handleMouseDown}
119+
title={tooltipText}
191120
>
192-
{/* Horizontal line indicator with grab handles */}
121+
{/* Vertical line indicator with triangles */}
193122
<div
194-
className="pointer-events-none absolute flex items-center"
123+
className="pointer-events-none absolute"
195124
style={{
196-
top: `${position}%`,
197-
transform: "translateY(-50%)",
198-
left: 0,
199-
right: 0,
125+
left: `${position}%`,
126+
top: -4,
127+
bottom: -4,
128+
transform: "translateX(-50%)",
129+
display: "flex",
130+
flexDirection: "column",
131+
alignItems: "center",
200132
}}
201133
>
202-
{/* Left handle - small triangle */}
134+
{/* Top triangle */}
203135
<div
204-
className={`h-0 w-0 shrink-0 transition-opacity ${
205-
isDragging ? "opacity-100" : "opacity-70"
206-
}`}
207136
style={{
208-
borderTop: "4px solid transparent",
209-
borderBottom: "4px solid transparent",
210-
borderLeft: `5px solid ${enabled ? "var(--color-plan-mode)" : "var(--color-muted)"}`,
137+
width: 0,
138+
height: 0,
139+
borderLeft: "4px solid transparent",
140+
borderRight: "4px solid transparent",
141+
borderTop: `5px solid ${lineColor}`,
142+
opacity: isDragging ? 1 : 0.8,
211143
}}
212144
/>
213-
{/* The line itself */}
145+
{/* Line */}
214146
<div
215-
className={`flex-1 transition-opacity ${isDragging ? "opacity-100" : "opacity-70"}`}
216147
style={{
217-
height: 2,
218-
background: enabled ? "var(--color-plan-mode)" : "var(--color-muted)",
148+
flex: 1,
149+
width: 2,
150+
background: lineColor,
151+
opacity: isDragging ? 1 : 0.8,
219152
}}
220153
/>
221-
{/* Right handle - small triangle pointing left */}
154+
{/* Bottom triangle */}
222155
<div
223-
className={`h-0 w-0 shrink-0 transition-opacity ${
224-
isDragging ? "opacity-100" : "opacity-70"
225-
}`}
226156
style={{
227-
borderTop: "4px solid transparent",
228-
borderBottom: "4px solid transparent",
229-
borderRight: `5px solid ${enabled ? "var(--color-plan-mode)" : "var(--color-muted)"}`,
157+
width: 0,
158+
height: 0,
159+
borderLeft: "4px solid transparent",
160+
borderRight: "4px solid transparent",
161+
borderBottom: `5px solid ${lineColor}`,
162+
opacity: isDragging ? 1 : 0.8,
230163
}}
231164
/>
232165
</div>
233166
</div>
234-
<Tooltip align="center" width="auto">
235-
{tooltipContent}
236-
</Tooltip>
237-
</TooltipWrapper>
167+
);
168+
}
169+
170+
// Vertical orientation - absolute overlay
171+
return (
172+
<div
173+
ref={containerRef}
174+
className="absolute inset-0 cursor-ns-resize"
175+
style={{ zIndex: 10 }}
176+
onMouseDown={handleMouseDown}
177+
title={tooltipText}
178+
>
179+
{/* Horizontal line indicator with triangles */}
180+
<div
181+
className="pointer-events-none absolute"
182+
style={{
183+
top: `${position}%`,
184+
left: -3,
185+
right: -3,
186+
transform: "translateY(-50%)",
187+
display: "flex",
188+
alignItems: "center",
189+
}}
190+
>
191+
{/* Left triangle */}
192+
<div
193+
style={{
194+
width: 0,
195+
height: 0,
196+
borderTop: "4px solid transparent",
197+
borderBottom: "4px solid transparent",
198+
borderLeft: `5px solid ${lineColor}`,
199+
opacity: isDragging ? 1 : 0.8,
200+
}}
201+
/>
202+
{/* Line */}
203+
<div
204+
style={{
205+
flex: 1,
206+
height: 2,
207+
background: lineColor,
208+
opacity: isDragging ? 1 : 0.8,
209+
}}
210+
/>
211+
{/* Right triangle */}
212+
<div
213+
style={{
214+
width: 0,
215+
height: 0,
216+
borderTop: "4px solid transparent",
217+
borderBottom: "4px solid transparent",
218+
borderRight: `5px solid ${lineColor}`,
219+
opacity: isDragging ? 1 : 0.8,
220+
}}
221+
/>
222+
</div>
223+
</div>
238224
);
239225
};

src/browser/components/RightSidebar/VerticalTokenMeter.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ const VerticalTokenMeterComponent: React.FC<VerticalTokenMeterProps> = ({
4242
</div>
4343
)}
4444
<div
45-
className="relative flex min-h-0 w-full flex-1 flex-col items-center"
45+
className="relative flex min-h-0 w-full flex-1 flex-col items-center overflow-visible"
4646
data-wrapper="meter-wrapper"
4747
>
4848
{/* Threshold slider overlay - positioned over the entire meter area */}

0 commit comments

Comments
 (0)