Compare slider
ProTwo versions of the same thing side by side, with a divider the person drags to see more of one or the other: what a checkpoint restore would put back against what is there now, a prose rewrite against the original, a dashboard before and after a change. The before side is at the start of the line (the left in left-to-right text) and after at the end; both are drawn at the full width and the divider crops the before one, so the same point lines up on both.
The divider is a real slider: Left and Right arrows move it 1%, with Shift (or Page Up and Page Down) 10%, and Home and End show all of the after side or all of the before side. The value is read aloud as the two labels and how much of the width each one has. Both labels are always printed, and the app says in caption what is being compared and where each side came from. Nothing animates except the divider following the pointer or the keys.
Both sides stay in the page for assistive tech while any of them shows, so a screen reader can read each in full. A side the divider has cropped away entirely (Home or End, or split at 0 or 100) is inert and aria-hidden, so keyboard focus can't land on a control nobody can see; both labels stay printed and are still read. Treat the contents as something to look at: a control inside a partly cropped half can't be seen or reached by pointer. split makes it controlled; leave it out and defaultSplit is the start.
Version 5.2.0· other versions
This page is for 5.2.0, the current release. An earlier release’s page is the Markdown that release published, so the docs match the version you have installed (candor-lock.json records it).
- 5.1.0
- 5.0.0
- 4.5.0
- 4.4.0
- 4.3.0
- 4.2.0
- 4.1.0
- 4.0.2
- 4.0.1
- 4.0.0
- 3.0.0
- 2.10.0
- 2.9.0
- 2.8.0
- 2.7.0
- 2.6.2
- 2.6.1
- 2.6.0
- 2.5.1
- 2.5.0
- 2.4.0
- 2.3.0
- 2.2.0
- 2.1.0
- 2.0.0
Not in the docs of 1.3.0, 1.4.0, 1.5.0, 1.5.1, 1.6.0, 1.7.0, 1.8.0, 1.8.1, 1.9.0 and 1.9.1: the page came later, or had another name then.
Docs pages weren’t kept for 1.0.0, 1.0.1, 1.1.0, 1.1.1, 1.2.0 and 1.2.1: they are kept from 1.3.0 on, and before that only llms.txt was published.
Preview
Loading the preview
Install
First time? Get started sets up the registry and theme. Or with shadcn directly: npx shadcn@latest add @candor/compare-slider
Brings in: bidi, locale, tokens, utils · npm: lucide-react@^1.67.0
Usage
"use client"
import { CompareSlider } from "@/components/candor/compare-slider"
/*
* A checkpoint restore preview: what the file says now against what it said at the checkpoint. The app supplies both
* sides and says in the caption where they were read from; the slider only lines them up.
*/
export default function Example() {
return (
<CompareSlider
className="max-w-xl"
before={{
label: "As it is now",
content: (
<div className="flex flex-col gap-1 text-sm">
<p className="font-medium">Acme renewal: notes</p>
<p>Renewal date moved to 1 March.</p>
<p>Keel sent the revised quote to Dana Whitfield on Tuesday.</p>
<p>Open question: does Acme still want the 3-year term?</p>
</div>
),
}}
after={{
label: "After restore",
content: (
<div className="flex flex-col gap-1 text-sm">
<p className="font-medium">Acme renewal: notes</p>
<p>Renewal date is 1 February.</p>
<p>Quote not yet sent.</p>
<p>Open question: does Acme still want the 3-year term?</p>
</div>
),
}}
caption="Notes.md in the Acme workspace now, against its copy in checkpoint 3 (Tuesday 09:12), read from Keel’s workspace."
/>
)
}<CompareSlider>
| Prop | Type | Default | Description |
|---|---|---|---|
| beforerequired | ComparePane | — | The side at the start of the line: the older, or "as it is now". |
| afterrequired | ComparePane | — | The side at the end of the line: the newer, or "after restore". |
| caption | React.ReactNode | undefined | — | What is being compared and where the data came from: "Notes.md at checkpoint 3 against today, read from the build agent's workspace." Printed under the comparison. |
| split | number | undefined | — | How much of the width the `before` side shows, 0 to 100. Makes the slider controlled: the divider is where this says, and moves only when the app changes it. |
| defaultSplit | number | undefined | 50 | Where the divider starts when `split` isn't given: 50, the middle, favouring neither side. |
| onSplitChange | ((split: number) => void) | undefined | — | Called with the new position (0 to 100) as the person drags or presses a key. |
| className | string | undefined | — | Extra classes for the outer element. |
Strings
The fixed words, in English by default. Change any of them under compareSlider in <LocaleProvider strings={{ … }}>; the table is exported as compareSliderStrings.
| Key | English |
|---|---|
| divider | Divider between the two sides |
| valueText | {before} {split}%, {after} {rest}% |
Types
- ComparePane
- One side of a CompareSlider.
{ /** Always shown above its side, for as long as the comparison is on screen: "As it is now", "After restore". Neither label is styled as the better one. */ label: string; /** What this side shows, as React nodes. It is drawn at the full width of the comparison and cropped by the divider, never scaled, so the two sides line up. */ content: React.ReactNode; }