ui/pixelslider.razor.scss
// Self-contained pixel slider styling. Lives on the PixelSlider component itself, so it reliably
// styles the component's own internals (unlike a parent stylesheet, which s&box does not cascade
// into child components). Square knob + flat track for the blocky/CutePixel aesthetic.
$white: #f8f5e6;
$black: #3a404c;
.pixel-slider {
flex-grow: 1;
height: 56px;
align-items: center;
justify-content: center;
// Self-contained: a parent stylesheet does NOT cascade into this child component, so a host that
// sets pointer-events:none on its container (e.g. the replay panel) would otherwise leave the
// slider unclickable. Opt back in here so the component is always draggable wherever it's placed.
pointer-events: all;
cursor: blank-hand;
// Compact variant for tight rows (e.g. the editor grid controls): trims the generous vertical
// click-padding so the row isn't dominated by empty space above/below the 12px track. Passed as
// class="compact" on the component (merged onto this root, so it's not a cross-component cascade).
&.compact {
height: 28px;
}
.track {
// Positioned ancestor so the absolutely-placed fill/thumb anchor to THIS track
// (not the panel root) — otherwise every thumb stacks on the first row.
position: relative;
width: 100%;
height: 12px;
background-color: $black;
.fill {
position: absolute;
left: 0;
top: 0;
height: 100%;
background-color: $white;
}
// Square knob. Absolute, centered on the value position (left: %).
.thumb {
position: absolute;
top: -6px;
width: 24px;
height: 24px;
margin-left: -12px;
background-color: $white;
border: 4px solid $black;
image-rendering: pixelated;
}
}
// Opt-in hover highlight, mirroring the ReplayScrubBar timeline: hovering anywhere on the slider
// gives the track a soft glow, while the knob only lights up when it is itself hovered (its own
// grab affordance) rather than any time the pointer is on the bar.
&.glow {
&:hover .track {
box-shadow: 0 0 7px 0 rgba($white, 0.35);
}
.thumb:hover {
box-shadow: 0 0 8px 0 rgba($white, 0.5);
}
}
}