Skip to the solution
HardMachine Coding14 min read

Build a Dual Range (price) Slider

1.1k views

The problem

Question presented to candidate: "On our product listing page we need a price filter: one track, two handles, a minimum and a maximum. Users drag either handle, or type exact numbers in two boxes. The handles must never cross, values snap to a step, and the product count updates as they move. Build the slider component and a small page that uses it."

Requirements:

  • One track from min to max (0 to 1000 here) with two handles; values snap to step (10).
  • The low handle can never pass the high handle; a minimum gap (minGap, 50) is kept between them.
  • The selected part of the track is highlighted.
  • Two number boxes show the values and accept typed input, committed on Enter or blur, then snapped and clamped.
  • Both handles work with the keyboard (arrows, Home, End) and are announced with names and dollar values.
  • The component is controlled: the parent owns [min, max] and filters a (local, in-memory) product list by it.

What a strong answer should cover:

  • The build choice: two stacked native input type="range" elements (free keyboard and ARIA support) versus a custom pointer-event slider (full control), and the CSS that makes stacking work: pointer-events: none on the inputs, auto on the thumbs.
  • Pure helpers for snapping, clamping and value-to-percent mapping.
  • Why a clamped handle can stay visually crossed in some frameworks, and how to put it back.
  • The stacking problem when both thumbs sit at one end, and the z-index rule that fixes it.
  • A draft state for the number boxes so typing does not move the handles keystroke by keystroke.
  • What jsdom can and cannot verify, and testing the drag in a real browser.

Clarifying questions expected:

  • "Can the two handles meet, or is a minimum gap required?"
  • "Should the product list update while dragging, or only on release?"
  • "Is the scale linear, or do we need a logarithmic scale for wide price ranges?"

Code / implementation expected: Yes. A working two-handle slider with clamping, snapping, number boxes, keyboard support and a filtered result count.

  • React
  • Slider
  • Pointer

Try it yourself

Sketch your approach before you read the solution. That is what the interview tests.

Stuck? Get a hint.

A short nudge toward the approach. It will not give the answer away.

Solution

The solution is hidden so you can try first

14 min read ยท 9 sections

React solution

Every file of the working solution. Open it in the playground to run and change it.

ReactComplete solution
import { useState } from "react";
import DualRangeSlider from "./src/components/DualRangeSlider";
import { PRODUCTS } from "./src/data/products";

export default function App() {
  // [min, max] owned by the parent
  const [range, setRange] = useState([100, 700]);
  const matches = PRODUCTS.filter(
    (p) => p.price >= range[0] && p.price <= range[1],
  ); // derived, not state

  return (
    <main className="page">
      <section className="card">
        <h1>Filter by price</h1>
        <DualRangeSlider
          value={range}
          onChange={setRange}
          min={0}
          max={1000}
          step={10}
          minGap={50}
        />
        <p className="summary" data-testid="summary" aria-live="polite">
          {matches.length} of {PRODUCTS.length} products between ${range[0]} and
          ${range[1]}
        </p>
      </section>
    </main>
  );
}

Discussion

Other approaches, follow-ups and how it went in real interviews.

Sign in to join the discussion.

No comments yet. Share how you would answer it.

Question 81 of 107 in Machine coding

Keep your momentum going.

Mark this question solved to track your progress, then take the next one while it is fresh.

Up nextHard

Build Nested Checkboxes (tri-state)

Continue