Data Point Dropper
A 2D scatter where every sample is a focusable toggle. Click (or focus + Enter / Space) any point to "drop" it from the regression; the solid accent line refits over the remaining points and a faint dashed reference keeps the original full-dataset fit visible for direct comparison. Used for leverage and influence analysis — drop a point near the cloud's centre of mass and the remaining line barely budges; drop a point at the cloud's x-extreme and the line rotates dramatically.
Data point dropper. 11 of 11 samples kept. Full fit y = 0.16 x + 0.11. Remaining fit y = 0.16 x + 0.11.
full y = 0.16 x + 0.11drop 0/11remaining y = 0.16 x + 0.11
Customize
Display
Installation
npx shadcn@latest add https://craftbits.dev/r/data-point-dropper.jsonUsage
import { DataPointDropper } from "@craft-bits/core";
<DataPointDropper
samples={[
{ id: "a", x: -2, y: -0.6 },
{ id: "b", x: -1, y: 0.1 },
{ id: "c", x: 0, y: 0.6 },
{ id: "d", x: 1, y: 1.0 },
{ id: "e", x: 2, y: 1.7 },
]}
/>Drive the dropped-set from outside (controlled):
const [dropped, setDropped] = useState<readonly string[]>([]);
<DataPointDropper
samples={cloud}
droppedIds={dropped}
onDroppedIdsChange={setDropped}
/>Start with one point pre-dropped (uncontrolled):
<DataPointDropper
samples={cloud}
defaultDroppedIds={["leverage"]}
/>Hide the full-dataset reference for a single-fit picker:
<DataPointDropper
samples={cloud}
showFullLine={false}
/>Understanding the component
- Two analytic fits, side by side. Both the full-dataset and remaining-after-drop lines are closed-form least-squares solutions: the slope is the covariance of x and y divided by the variance of x; the intercept is
mean(y) − slope · mean(x). No gradient descent, no iteration — one pass over the points yields each line. Degenerate clouds (variance of x near zero, or fewer than two points) returnnulland the line is hidden. - Stable viewport. The math viewport is derived from the full sample cloud — not the remaining set — so dropping a high-leverage point doesn't pan the chart and the user can see the line snap relative to fixed axes. The viewport is then extended in y to keep both line endpoints inside the visible area.
- Leverage made visible. Drop a point near the cloud's centre of mass and the remaining line barely budges. Drop a point at the cloud's x-extreme — a high-leverage observation — and the remaining line rotates dramatically. That's the lesson the component teaches at a glance.
- Controlled + uncontrolled. Following Radix's
value/defaultValuepattern, passdroppedIds+onDroppedIdsChangefor controlled mode or justdefaultDroppedIdsto let the component manage its own state. - Keyboard-first interaction. Every sample circle is
role="checkbox"withtabIndex={0}andaria-checked. Tab between points, press Enter or Space to toggle — no mouse required.:focus-visiblegets a stroke ring in the accent colour. - Spring transitions. Line endpoints and per-point opacity follow with
SPRINGS.smooth.prefers-reduced-motion: reducecollapses every spring to an instant swap.
Props
| Prop | Type | Default | Description |
|---|---|---|---|
samples | readonly DataPointDropperSample[] | required | The full set of samples available to fit. Each must have a stable id. |
droppedIds | readonly string[] | — | Controlled set of dropped (excluded) sample IDs. |
defaultDroppedIds | readonly string[] | [] | Uncontrolled initial set of dropped IDs. |
onDroppedIdsChange | (next: readonly string[]) => void | — | Fires whenever the dropped-set changes (click toggle, kbd Enter/Space). |
showFullLine | boolean | true | Render the dashed regression line fit through the full dataset. |
showRemainingLine | boolean | true | Render the solid regression line fit through the remaining samples. |
transition | Transition | SPRINGS.smooth | Spring for line endpoint and point-fade transitions. |
className | string | — | Merged onto the root <div> via cn(). |
The DataPointDropperSample shape:
interface DataPointDropperSample {
id: string; // stable identifier — used for controlled droppedIds + React keys
x: number; // x coordinate in math space
y: number; // y coordinate in math space
}Accessibility
- The root
<div>isrole="figure"with a visually hiddenaria-live="polite"summary of point count, drop count, and both fitted formulas — screen readers hear the new line whenever a point is dropped or restored. - Every sample point is a focusable
role="checkbox"witharia-checkedreflecting drop state and anaria-labelreporting the sample's coordinates. - Keyboard control: Tab moves between points; Enter or Space toggles drop state.
:focus-visiblestroke ring intext-cb-accentso keyboard users always see where they are.- Motion respects
prefers-reduced-motion: reduce— every spring collapses to an instant swap.
Credits
- Extracted from:
craftingattention(app/src/lessons/primitives/viz/DataPointDropper.tsx). The source paired a click-to-place scatter sandbox with a click-anywhere-on-the-plane add interaction and a single best-fit line. The library extract reframes that as a drop-an-existing-point primitive for leverage / influence analysis — a fixed cloud in, the dropped subset out, two regression lines (full + remaining) drawn on top.