useReel
Manages horizontal scrolling reel/carousel components with snap points and navigation.
import { useRef } from 'react';import { useReel } from '@volvo-cars/react-headless';
function Reel() { const ref = useRef<HTMLDivElement>(null); const { activeIndex, totalCount, previousButtonProps, nextButtonProps, reelProps, } = useReel({ ref });
return ( <div> <div ref={ref} className="reel" {...reelProps}> <div className="reel-frame">Frame 1</div> <div className="reel-frame">Frame 2</div> <div className="reel-frame">Frame 3</div> </div> <div className="flex items-center gap-8"> <button {...previousButtonProps}>Previous</button> <span> {activeIndex + 1} / {totalCount} </span> <button {...nextButtonProps}>Next</button> </div> </div> );}Navigation
Section titled “Navigation”The hook returns previousButtonProps and nextButtonProps that should be spread onto your navigation buttons. These props include onClick handlers, disabled state, and accessibility attributes — the buttons are hidden from assistive technology since the scroll container itself is keyboard-navigable.
import { useRef } from 'react';import { useReel } from '@volvo-cars/react-headless';
function ReelWithNavigation() { const ref = useRef<HTMLDivElement>(null); const { previousButtonProps, nextButtonProps, reelProps } = useReel({ ref });
return ( <div> <div ref={ref} className="reel" {...reelProps}> <div className="reel-frame">Frame 1</div> <div className="reel-frame">Frame 2</div> <div className="reel-frame">Frame 3</div> </div> <button {...previousButtonProps}>←</button> <button {...nextButtonProps}>→</button> </div> );}Listening to changes
Section titled “Listening to changes”Use the onChange callback to react when the visible frame changes:
import { useRef } from 'react';import { useReel } from '@volvo-cars/react-headless';
function ReelWithCallback() { const ref = useRef<HTMLDivElement>(null);
const { reelProps } = useReel({ ref, onChange: ({ activeIndex, target }) => { console.log('Now viewing frame', activeIndex, target); }, });
return ( <div ref={ref} className="reel" {...reelProps}> <div className="reel-frame">Frame 1</div> <div className="reel-frame">Frame 2</div> <div className="reel-frame">Frame 3</div> </div> );}Accessibility
Section titled “Accessibility”The hook automatically sets tabIndex={0} on the reel container if it contains no focusable children, ensuring keyboard users can scroll the reel. The navigation buttons are hidden from screen readers (aria-hidden) since the scroll container is already keyboard-navigable.
useReel accepts an options object with the following properties:
ref– ref to the scrollable container element (required)onChange– callback fired when the active index changes, receives{ activeIndex, target, currentTarget }
The hook returns an object with:
activeIndex– the index of the first visible frametotalCount– the total number of frames in the reelreelProps– props to spread on the reel container (includestabIndexwhen needed)previousButtonProps– props to spread on the “previous” navigation button (includesonClick,disabled, and ARIA attributes)nextButtonProps– props to spread on the “next” navigation button (includesonClick,disabled, and ARIA attributes)