Skip to content

Commit 379d6a4

Browse files
committed
fix: make threshold slider visible with triangle handles
- Move slider outside bar div to avoid clipping - Add triangle handles at line endpoints for visual affordance - Use proper absolute positioning with centered alignment - barHeight prop for accurate vertical centering
1 parent a350950 commit 379d6a4

File tree

3 files changed

+126
-51
lines changed

3 files changed

+126
-51
lines changed

src/browser/components/RightSidebar/CostsTab.tsx

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ const CostsTabComponent: React.FC<CostsTabProps> = ({ workspaceId }) => {
189189
</span>
190190
</div>
191191
<div className="relative w-full py-1">
192-
<div className="bg-border-light relative flex h-1.5 w-full rounded-[3px]">
192+
<div className="bg-border-light flex h-1.5 w-full rounded-[3px]">
193193
{cachedPercentage > 0 && (
194194
<div
195195
className="h-full transition-[width] duration-300"
@@ -231,17 +231,18 @@ const CostsTabComponent: React.FC<CostsTabProps> = ({ workspaceId }) => {
231231
}}
232232
/>
233233
)}
234-
{/* Threshold slider overlay - only show when model limits are known */}
235-
{maxTokens && (
236-
<ThresholdSlider
237-
threshold={autoCompactThreshold}
238-
enabled={autoCompactEnabled}
239-
onThresholdChange={setAutoCompactThreshold}
240-
onEnabledChange={setAutoCompactEnabled}
241-
orientation="horizontal"
242-
/>
243-
)}
244234
</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+
)}
245246
</div>
246247
</div>
247248
{showWarning && (

src/browser/components/RightSidebar/ThresholdSlider.tsx

Lines changed: 112 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ interface ThresholdSliderProps {
1616
onEnabledChange: (enabled: boolean) => void;
1717
/** Orientation of the slider */
1818
orientation: "horizontal" | "vertical";
19+
/** Height of the bar for vertical positioning (horizontal orientation only) */
20+
barHeight?: number;
1921
}
2022

2123
// Threshold at which we consider auto-compaction disabled (dragged all the way right/down)
@@ -27,6 +29,7 @@ export const ThresholdSlider: React.FC<ThresholdSliderProps> = ({
2729
onThresholdChange,
2830
onEnabledChange,
2931
orientation,
32+
barHeight = 6,
3033
}) => {
3134
const containerRef = useRef<HTMLDivElement>(null);
3235
const [isDragging, setIsDragging] = useState(false);
@@ -107,59 +110,130 @@ export const ThresholdSlider: React.FC<ThresholdSliderProps> = ({
107110
: "Auto-compact disabled · Drag left to enable";
108111

109112
if (orientation === "horizontal") {
113+
// Render as a positioned overlay - the parent should have position:relative
110114
return (
111-
<div
112-
ref={containerRef}
113-
className="absolute inset-0 cursor-ew-resize"
114-
onMouseDown={handleMouseDown}
115-
>
116-
<TooltipWrapper inline>
117-
{/* Vertical line indicator - extends above and below the bar */}
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 */}
118129
<div
119-
className={`pointer-events-none absolute transition-opacity ${
120-
isDragging ? "opacity-100" : "opacity-60 hover:opacity-100"
121-
} ${enabled ? "bg-plan-mode" : "bg-muted"}`}
130+
className="pointer-events-none absolute flex flex-col items-center"
122131
style={{
123132
left: `${position}%`,
124133
transform: "translateX(-50%)",
125-
width: "2px",
126-
top: "-4px",
127-
bottom: "-4px",
134+
top: 0,
135+
bottom: 0,
128136
}}
129-
/>
130-
<Tooltip align="center" width="auto">
131-
{tooltipContent}
132-
</Tooltip>
133-
</TooltipWrapper>
134-
</div>
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>
135174
);
136175
}
137176

138177
// Vertical orientation
139178
return (
140-
<div
141-
ref={containerRef}
142-
className="absolute inset-0 cursor-ns-resize"
143-
onMouseDown={handleMouseDown}
144-
>
145-
<TooltipWrapper inline>
146-
{/* Horizontal line indicator - extends left and right of the bar */}
179+
<TooltipWrapper inline>
180+
<div
181+
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+
}}
190+
onMouseDown={handleMouseDown}
191+
>
192+
{/* Horizontal line indicator with grab handles */}
147193
<div
148-
className={`pointer-events-none absolute transition-opacity ${
149-
isDragging ? "opacity-100" : "opacity-60 hover:opacity-100"
150-
} ${enabled ? "bg-plan-mode" : "bg-muted"}`}
194+
className="pointer-events-none absolute flex items-center"
151195
style={{
152196
top: `${position}%`,
153197
transform: "translateY(-50%)",
154-
height: "2px",
155-
left: "-2px",
156-
right: "-2px",
198+
left: 0,
199+
right: 0,
157200
}}
158-
/>
159-
<Tooltip align="center" width="auto">
160-
{tooltipContent}
161-
</Tooltip>
162-
</TooltipWrapper>
163-
</div>
201+
>
202+
{/* Left handle - small triangle */}
203+
<div
204+
className={`h-0 w-0 shrink-0 transition-opacity ${
205+
isDragging ? "opacity-100" : "opacity-70"
206+
}`}
207+
style={{
208+
borderTop: "4px solid transparent",
209+
borderBottom: "4px solid transparent",
210+
borderLeft: `5px solid ${enabled ? "var(--color-plan-mode)" : "var(--color-muted)"}`,
211+
}}
212+
/>
213+
{/* The line itself */}
214+
<div
215+
className={`flex-1 transition-opacity ${isDragging ? "opacity-100" : "opacity-70"}`}
216+
style={{
217+
height: 2,
218+
background: enabled ? "var(--color-plan-mode)" : "var(--color-muted)",
219+
}}
220+
/>
221+
{/* Right handle - small triangle pointing left */}
222+
<div
223+
className={`h-0 w-0 shrink-0 transition-opacity ${
224+
isDragging ? "opacity-100" : "opacity-70"
225+
}`}
226+
style={{
227+
borderTop: "4px solid transparent",
228+
borderBottom: "4px solid transparent",
229+
borderRight: `5px solid ${enabled ? "var(--color-plan-mode)" : "var(--color-muted)"}`,
230+
}}
231+
/>
232+
</div>
233+
</div>
234+
<Tooltip align="center" width="auto">
235+
{tooltipContent}
236+
</Tooltip>
237+
</TooltipWrapper>
164238
);
165239
};

src/browser/components/RightSidebar/VerticalTokenMeter.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,10 @@ 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 overflow-visible"
45+
className="relative flex min-h-0 w-full flex-1 flex-col items-center"
4646
data-wrapper="meter-wrapper"
4747
>
48-
{/* Threshold slider overlay */}
48+
{/* Threshold slider overlay - positioned over the entire meter area */}
4949
{data.maxTokens && autoCompaction && (
5050
<ThresholdSlider
5151
threshold={autoCompaction.threshold}

0 commit comments

Comments
 (0)