Introducing PrimeReact v11-alpha 🎉Discover Now

useCompare

Hook that manages compare slider state, pointer interactions, and clip-path positioning.

basic-demo

Usage#

import { useCompare } from '@primereact/headless/compare';
const compare = useCompare({ defaultValue: 50 });
 
<div {...compare.rootProps}>
    <div {...compare.getItemProps('after')}></div>
    <div {...compare.getItemProps('before')}></div>
    <div {...compare.handleProps}>
        <div {...compare.getIndicatorProps()}></div>
    </div>
    <input {...compare.inputProps} />
</div>;

useCompare manages pointer tracking, clip-path computation, and keyboard input for a before/after comparison. See Primitive for a component-based API.

Features#

  • Built on useSlider — inherits drag, keyboard, step, and min/max behavior from the slider primitive
  • Clip-path layout — getItemProps('before' | 'after') returns the CSS for each layer so templates stay declarative
  • Hover mode — slideOnHover moves the divider as the pointer glides across the component, no drag required
  • Horizontal and vertical — flip the layout with a single orientation prop
  • Reactive state — state.value and state.isDragging drive overlays, tooltips, and custom cursors

Working with callbacks#

Controlled value#

Use value with onValueChange when the split must be driven by external state — for example, to persist it or sync multiple compares.

const [value, setValue] = React.useState(50);
 
const compare = useCompare({
    value,
    onValueChange: (e) => setValue(e.value)
});

Hover-driven comparison#

Enable slideOnHover for hero-section comparisons where pointer movement alone should reveal the other image.

const compare = useCompare({ slideOnHover: true });

Vertical layout#

Switch orientation to 'vertical' for top/bottom comparisons.

const compare = useCompare({ orientation: 'vertical' });

Custom readouts from state#

Mirror the current split or drag state into your own UI.

const compare = useCompare({ defaultValue: 50 });
 
<span>{compare.state.value}%</span>;
{
    compare.state.isDragging && <span>Dragging...</span>;
}

Styling with data attributes#

Prop objects include orientation and state-dependent data attributes.

[data-orientation='horizontal'] {
    cursor: ew-resize;
}
 
[data-orientation='vertical'] {
    cursor: ns-resize;
}
 
[data-dragging] {
    cursor: grabbing;
}

API#

useCompare#

NameTypeDefault
slideOnHoverboolean—
Whether slider moves on hover.
tabIndexnumber—
The tab index of the hidden input.
ariaLabelstring—
Establishes a string value that labels the component.
ariaLabelledbystring—
Establishes relationships between the component and label(s) where its value should be one or more element IDs.
onFocus(event: FocusEvent<HTMLInputElement>) => void—
Callback fired when the hidden input is focused.
onBlur(event: FocusEvent<HTMLInputElement>) => void—
Callback fired when the hidden input loses focus.
valuenumber | number[]—
Value of the component.
defaultValuenumber | number[]—
The default value for the input when not controlled by `value` .
minnumber0
Mininum boundary value.
maxnumber100
Maximum boundary value.
orientation"horizontal" | "vertical"horizontal
Orientation of the slider.
stepnumber1
Step factor to increment/decrement the value.
onValueChange(event: useSliderChangeEvent) => void—
Callback fired when the ToggleButton's pressed state changes.
onValueChangeEnd(event: useSliderChangeEvent) => void—
Callback fired when the pointer interaction ends.
disabledbooleanfalse
Whether the component is disabled.
readOnlybooleanfalse
Whether the component is read-only.
invalidbooleanfalse
When present, it specifies that the element should be invalid.

Accessibility#

Arrow keys move the comparison slider, Home/End jump to the edges, and dragging is accessible via pointer or touch. See Primitive for full WAI-ARIA compliance details.