refactor(web): use shadcn reasoning slider

This commit is contained in:
fdc310
2026-08-01 22:15:43 +08:00
parent f83a163b15
commit c48c345b13
5 changed files with 255 additions and 123 deletions
@@ -1,86 +0,0 @@
.control {
position: relative;
height: 2.5rem;
margin-top: 0.75rem;
}
.track,
.fill {
position: absolute;
top: 50%;
left: 0;
height: 2rem;
transform: translateY(-50%);
border-radius: 1rem;
}
.track {
width: 100%;
background: var(--muted);
}
.fill {
background: var(--primary);
}
.tick {
position: absolute;
top: 50%;
width: 0.3rem;
height: 0.3rem;
transform: translate(-50%, -50%);
border-radius: 50%;
background: color-mix(in oklch, var(--muted-foreground) 46%, transparent);
pointer-events: none;
}
.tickActive {
background: color-mix(in oklch, var(--primary-foreground) 42%, transparent);
}
.input {
position: absolute;
inset: 0;
width: 100%;
height: 100%;
margin: 0;
appearance: none;
background: transparent;
cursor: pointer;
}
.input::-webkit-slider-runnable-track {
height: 2rem;
background: transparent;
}
.input::-webkit-slider-thumb {
width: 2.125rem;
height: 2.125rem;
margin-top: -0.0625rem;
appearance: none;
border: 1px solid var(--border);
border-radius: 50%;
background: var(--background);
box-shadow: 0 1px 4px color-mix(in oklch, var(--foreground) 20%, transparent);
}
.input::-moz-range-track {
height: 2rem;
background: transparent;
}
.input::-moz-range-thumb {
width: 2.125rem;
height: 2.125rem;
border: 1px solid var(--border);
border-radius: 50%;
background: var(--background);
box-shadow: 0 1px 4px color-mix(in oklch, var(--foreground) 20%, transparent);
}
.input:focus-visible {
outline: 2px solid var(--ring);
outline-offset: 2px;
border-radius: 1rem;
}
@@ -7,7 +7,7 @@ import {
PopoverContent,
PopoverTrigger,
} from '@/components/ui/popover';
import styles from './ReasoningLevelPicker.module.css';
import { Slider } from '@/components/ui/slider';
export const REASONING_LEVELS: ReasoningLevel[] = [
'provider_default',
@@ -55,8 +55,6 @@ export default function ReasoningLevelPicker({
const currentLabel = t(REASONING_LEVEL_LABEL_KEYS[safeValue]);
const isExplicit = safeValue !== 'provider_default';
const currentIndex = Math.max(0, safeLevels.indexOf(safeValue));
const denominator = Math.max(1, safeLevels.length - 1);
const progress = currentIndex / denominator;
return (
<Popover>
@@ -83,40 +81,16 @@ export default function ReasoningLevelPicker({
<span>{currentLabel}</span>
<ChevronRight className="size-3.5" />
</div>
<div className={styles.control}>
<div className={styles.track} />
<div
className={styles.fill}
style={{
width: `calc(17px + (100% - 34px) * ${progress})`,
}}
/>
{safeLevels.map((level, index) => {
const tickProgress = index / denominator;
return (
<span
key={level}
className={`${styles.tick} ${index <= currentIndex ? styles.tickActive : ''}`}
style={{
left: `calc(17px + (100% - 34px) * ${tickProgress})`,
}}
/>
);
})}
<input
className={styles.input}
type="range"
min={0}
max={Math.max(0, safeLevels.length - 1)}
step={1}
value={currentIndex}
aria-label={t('models.reasoningLevel')}
aria-valuetext={currentLabel}
onChange={(event) =>
onChange(safeLevels[Number(event.target.value)])
}
/>
</div>
<Slider
className="mt-5"
min={0}
max={Math.max(0, safeLevels.length - 1)}
step={1}
value={[currentIndex]}
aria-label={t('models.reasoningLevel')}
aria-valuetext={currentLabel}
onValueChange={([index]) => onChange(safeLevels[index])}
/>
</PopoverContent>
</Popover>
);