Scroll to top
Scroll to top is a neobrutalist React component from Cruise UI. A square button in a bottom corner that appears on long pages and takes you, and your keyboard focus, back to the top. Install it with npx shadcn@latest add @cruiseui/scroll-top.
Install
Terminal
npx shadcn@latest add @cruiseui/scroll-topFirst time? Installation shows the one-off components.json setup (the @cruiseui registry) and how to turn the theme on.
Example
Corners
Scroll down this page: a labelled button appears bottom-left after 300px.
"use client";
import { CruiseScrollTop } from "@/components/cruise/scroll-top";
export default function ScrollTopExample() {
return (
<div className="flex flex-col gap-3">
<p>Scroll down this page: a labelled button appears bottom-left after 300px.</p>
{/* Once per page. Put <div id="top" tabIndex={-1} /> first in <body>. */}
<CruiseScrollTop position="bottom-left" showAfter={300} label="Top" />
</div>
);
}
<body>
<div id="top" tabindex="-1"></div>
…
<button type="button" class="brutal scroll-top" data-position="bottom-right" aria-label="Back to top">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3" aria-hidden="true"><path d="m5 12 7-7 7 7"/><path d="M12 19V5"/></svg>
</button>
<script>
const toTop = document.querySelector(".scroll-top");
let ticking = false;
addEventListener("scroll", () => {
if (ticking) return;
ticking = true;
requestAnimationFrame(() => { toTop.toggleAttribute("data-visible", scrollY > 600); ticking = false; });
}, { passive: true });
toTop.addEventListener("click", () => {
const reduce = matchMedia("(prefers-reduced-motion: reduce)").matches;
scrollTo({ top: 0, behavior: reduce ? "instant" : "smooth" });
document.getElementById("top").focus({ preventScroll: true });
});
</script>
</body>Needs theme.css. Interactive parts (menus, tabs, drawers) also need the script in the spec for that component.
When to use it
When to use
Long pages: docs, feeds, component galleries.
When not to
Short pages that fit in two screens, or as a replacement for good navigation.
Props
CruiseScrollTop
| Prop | Type | Default | Description |
|---|---|---|---|
position? | "bottom-left" | "bottom-right" | "bottom-right" | — |
offset? | number | 16 | Distance from the screen edges, in px (the safe area is added). |
showAfter? | number | 600 | Pixels scrolled before it appears. |
label? | string | — | Optional text next to the icon, e.g. "Top" (the name stays "Back to top"). |
targetId? | string | "top" | id of the element that gets focus at the top (give it tabIndex={-1}). |
className? | string | — | — |
Usage
- Put <div id="top" tabIndex={-1} /> first in <body> (or pass targetId), so focus has somewhere to land.
- Use one per page. It moves up above a toast stack in the same corner.
Accessibility
- A real <button> named "Back to top" (also when it shows the "Top" text).
- After scrolling up, focus moves to the #top target, so the next Tab starts at the top of the page.
- Hidden from the tab order until it appears; no smooth scroll or slide under reduced motion.