Horizontal Scroll
A free horizontal scroll section that glides panels sideways as you scroll.
- Rotterdam
- Mid-Atlantic
- Newark
Rotterdam
Booking PW-40118
Booking
Lock a lane in ninety seconds
Live carrier rates, equipment and cutoffs land on one screen. Your desk books the sailing while the quote is still valid, and the paperwork files itself behind it.
12 Aug
Rotterdam RTM
23 Aug
Newark EWR
Sailings this week
- per FEU, held 48 hours
- $2,480
- median time to book
- 9 min
- carriers quoting this lane
- 412
Rotterdam, Maasvlakte II · Booked 12 Aug 09:41 CEST
- Rotterdam
- Mid-Atlantic
- Newark
Mid-Atlantic
Booking PW-40118
In transit
Every box on one moving line
Vessel position, reefer temperature and berth congestion stream into the same timeline, so a six hour delay reaches your customer before it reaches your inbox.
Speed over ground, last 24 hours
- speed over ground
- 17.4 kn
- reefer set point
- -18.2°C
- ETA drift
- +6 h
- door to door on this lane
- 11 days
- current ETA drift
- +6 h
- between position updates
- 4 min
41.2°N 38.7°W · Day 6 of 11 · Northline Atlantic
- Rotterdam
- Mid-Atlantic
- Newark
Newark
Booking PW-40118
Delivered
Signed at the gate, invoiced by lunch
Proof of delivery closes the leg and releases the invoice the same hour. Finance sees the cash days earlier, and the lane's real cost feeds straight into the next quote.
Closing the leg
- Gate out, Newark23 Aug 09:12
- Proof of delivery signed23 Aug 11:48
- Invoice issued to Aveline Foods23 Aug 11:49
- Payment cleared27 Aug 08:30
- gate out to cash
- 4.1 days
- PODs captured first time
- 99.2%
- of invoices queried
- 1.4%
Newark, PNCT berth 4 · Delivered 23 Aug 11:48 EDT
Horizontal Scroll is a free scroll section for Next.js and React that sticks to the viewport and slides between two and six panels sideways as the page scrolls, built with Motion and styled with Tailwind. You pass your panels as plain children, one per direct child, and the component builds the flex row track, the sticky frame, the scrub and the reduced motion fallback for you.
The section is pinned with CSS position: sticky inside a track that reserves the scroll distance, so scrolling stays native: wheel, keyboard and touch all carry you straight through and past the section, and nothing shifts. The pinned layout is part of the server-rendered page, so a reload or the Back button returns you to the same point in the scene. With prefers-reduced-motion enabled, or with JavaScript unavailable, the panels render as a static vertical stack, fully visible in order.
Install
Add the @te registry to your components.json once:
{
"registries": {
"@te": "https://templateempire.io/r/{name}.json"
}
}Then install the component:
npx shadcn@latest add @te/scroll-horizontalUsage
import { ScrollHorizontal } from "@/components/scroll-horizontal";
export default function Page() {
return (
<ScrollHorizontal>
<div>
<h2>Scene one</h2>
<p>The section pins and scroll turns sideways.</p>
</div>
<div>
<h2>Scene two</h2>
<p>Each panel glides across, tied to the scrub.</p>
</div>
<div>
<h2>Scene three</h2>
<p>Scroll on and the pin releases.</p>
</div>
</ScrollHorizontal>
);
}Props
| Prop | Type | Default | Description |
|---|---|---|---|
| children | ReactNode | required | Panel content. Pass 2 to 6 direct children; each direct child is rendered inside its own [data-panel] wrapper as one panel, in DOM order. |
| className | string | undefined | Additional classes merged onto the section root. |
Customisation
Horizontal Scroll declares no tokens of its own: the section and each panel surface use the semantic background token, and everything inside a panel is your own markup, styled however you like. To retheme the section, restyle your panel content directly or override the semantic tokens it consumes from :root or any ancestor:
:root {
--background: var(--color-neutral-900);
--foreground: var(--color-neutral-50);
}Frequently asked questions
- Is Horizontal Scroll free for commercial use?
- Yes. Horizontal Scroll is MIT licensed, so you can use it in personal and commercial projects without attribution.
- Does Horizontal Scroll trap scrolling or hurt accessibility?
- No. The sideways travel is scrubbed from native vertical scroll and never intercepts it, so mouse wheel, trackpad, touch and keyboard keys such as arrows, space and PageDown all move through and past the section uninterrupted, with no snap points. The track reserves the full scroll distance up front, so pinning causes no layout shift, and the scrub animates a single transform on the row of panels. Every panel stays visible and Tab reachable in both modes, focusing content in an offscreen panel scrolls the page to that panel so its focus ring is in view, and with reduced motion enabled the panels render as a static vertical stack with nothing listening to scroll.
- Why does the section scroll past instead of sticking?
- The pin is CSS position: sticky, which needs a clear path to the page's scroller. If any ancestor between the section and the page sets overflow to hidden, auto or scroll, sticky stops working there; use overflow: clip on that ancestor instead, which clips the same way without creating a scroll container. The section also stays stacked where a panel's own content is taller than the viewport, because pinned content below a panel's fold could never be scrolled to.
- How do I change the number of panels or their content?
- Pass between two and six direct children to the component; each direct child becomes one panel in DOM order, and the scroll distance scales with the panel count automatically. Panels are plain containers, so headings, text, images and layout inside each one are entirely your own markup and Tailwind classes, and heading levels stay under your control.