Spaces:
Running
Running
File size: 7,449 Bytes
32864b0 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 | "use client"
import { useId } from "react"
import {
PARAM_RANGE_MARKERS,
PARAM_RANGE_MAX_INDEX,
PARAM_RANGE_VALUES,
formatParamBoundLabel,
} from "@/lib/param-range"
export type ParamRangeVariant = "default" | "inline" | "promo"
interface ParamRangePickerProps {
/** Index into PARAM_RANGE_VALUES for the lower handle (0 = "< 1B"). */
minStep: number
/** Index into PARAM_RANGE_VALUES for the upper handle (max = "> 500B"). */
maxStep: number
onMinChange: (next: number) => void
onMaxChange: (next: number) => void
/**
* `default` β Variant A: bracketed range with a labelled rail and a boxed
* mono readout, suitable for use as the headline call-out at the top of a
* leaderboard.
*
* `inline` β Variant B: a single-line picker with no boxed readout, sized
* to drop into a hairline toolbar alongside Sort and Filter pickers.
*
* `promo` β Variant C: warm-background framed slider with a left accent
* rule. Use when the slider actively reframes a chart/matrix below it.
*/
variant?: ParamRangeVariant
/** Headline shown to the left of the slider (default & promo variants). */
headline?: string
/** Sub-text shown under the headline (default & promo variants). */
subline?: string
/** Callback to reset both handles to the open range. When provided, a
* Reset affordance is rendered next to the readout while the slider
* is constrained. */
onReset?: () => void
/** When defined, renders a small "Show models without known size" pill
* next to the readout. The toggle is independent of the slider β when
* off, models with no detected size are filtered out regardless of
* where the handles are. */
showUnknownSize?: boolean
onShowUnknownSizeChange?: (next: boolean) => void
className?: string
}
/**
* Themed dual-handle parameter-range picker. Shape and colour come from the
* design system: hairline rail, square outline thumbs, mono uppercase tick
* labels above the rail, and a boxed mono readout for the explicit bounds.
*
* The two `<input type="range">` elements provide native dragging + arrow-key
* a11y. The visual rail/fill/ticks/thumbs are absolutely-positioned overlays;
* the inputs themselves are kept transparent except for their thumbs (see
* `.param-range-input` in globals.css).
*/
export function ParamRangePicker({
minStep,
maxStep,
onMinChange,
onMaxChange,
variant = "default",
headline = "Parameter range",
subline = "Narrow the matrix to comparable model sizes.",
onReset,
showUnknownSize,
onShowUnknownSizeChange,
className,
}: ParamRangePickerProps) {
const minId = useId()
const maxId = useId()
const isInline = variant === "inline"
const isPromo = variant === "promo"
const minPercent = (minStep / PARAM_RANGE_MAX_INDEX) * 100
const maxPercent = (maxStep / PARAM_RANGE_MAX_INDEX) * 100
const isConstrained = minStep > 0 || maxStep < PARAM_RANGE_MAX_INDEX
const track = (
<div className="pr-track-wrap">
<div className="pr-ticks" aria-hidden>
{PARAM_RANGE_MARKERS.map((marker, idx) => {
const isFirst = idx === 0
const isLast = idx === PARAM_RANGE_MARKERS.length - 1
const active = marker.step === minStep || marker.step === maxStep
return (
<div
key={marker.label}
className={`pr-tick${active ? " on" : ""}`}
style={{
left: `${(marker.step / PARAM_RANGE_MAX_INDEX) * 100}%`,
}}
>
<span
style={{
transform: isFirst
? "translateX(0)"
: isLast
? "translateX(-100%)"
: "translateX(-50%)",
marginLeft: 0,
}}
>
{marker.label}
</span>
</div>
)
})}
</div>
<div className="pr-rail" />
<div
className="pr-fill"
style={{
left: `${minPercent}%`,
width: `${Math.max(maxPercent - minPercent, 0)}%`,
}}
/>
{/* Hidden inter-bucket micro-ticks to give the rail a metered feel */}
<div className="pr-microticks" aria-hidden>
{PARAM_RANGE_VALUES.map((_, stepIndex) => (
<span
key={`pr-micro-${stepIndex}`}
style={{ left: `${(stepIndex / PARAM_RANGE_MAX_INDEX) * 100}%` }}
/>
))}
</div>
{/* Native inputs provide a11y + drag; we hide them visually and rely
on the .param-range-input thumb styling for the visible handles. */}
<input
id={minId}
type="range"
min={0}
max={PARAM_RANGE_MAX_INDEX}
step={1}
value={minStep}
onChange={(event) => {
const next = Number(event.target.value)
onMinChange(Math.min(next, maxStep))
}}
className="param-range-input"
aria-label={`Minimum ${headline.toLowerCase()}`}
/>
<input
id={maxId}
type="range"
min={0}
max={PARAM_RANGE_MAX_INDEX}
step={1}
value={maxStep}
onChange={(event) => {
const next = Number(event.target.value)
onMaxChange(Math.max(next, minStep))
}}
className="param-range-input"
aria-label={`Maximum ${headline.toLowerCase()}`}
/>
</div>
)
const resetBtn = onReset && isConstrained ? (
<button
type="button"
onClick={onReset}
className="pr-reset"
aria-label="Reset parameter range"
>
Reset
</button>
) : null
const unknownToggle =
onShowUnknownSizeChange != null ? (
<button
type="button"
onClick={() => onShowUnknownSizeChange(!showUnknownSize)}
className={`pr-unknown-toggle${showUnknownSize ? " on" : ""}`}
aria-pressed={Boolean(showUnknownSize)}
title="Models without a reported parameter count"
>
<span className="pr-unknown-toggle-box" aria-hidden>
{showUnknownSize ? "β" : ""}
</span>
Unknown size
</button>
) : null
const readout = (
<div className="pr-readout-cell">
<div className={`pr-readout${isInline ? " inline" : ""}`}>
<span>{formatParamBoundLabel(minStep, "min")}</span>
<span className="arrow">{isInline ? "β" : "β"}</span>
<span>{formatParamBoundLabel(maxStep, "max")}</span>
</div>
{unknownToggle}
{resetBtn}
</div>
)
if (isInline) {
return (
<div className={`pr-slider inline${className ? ` ${className}` : ""}`}>
<span className="pr-label inline-label">
<strong>{headline}</strong>
</span>
{track}
{readout}
</div>
)
}
if (isPromo) {
return (
<div className={`pr-promo${className ? ` ${className}` : ""}`}>
<div className="pr-promo-head">
<span className="kicker">{headline}</span>
<p>{subline}</p>
</div>
<div className="pr-slider pr-slider-track-only">
{track}
{readout}
</div>
</div>
)
}
// Default (Variant A)
return (
<div className={`pr-slider${className ? ` ${className}` : ""}`}>
<div className="pr-label">
<strong>{headline}</strong>
{subline}
</div>
{track}
{readout}
</div>
)
}
|