ComponentsNavigation
Ridge Progress
A thin band across the top of the page with a mountain ridge in silhouette that fills with water as you read, a marker that climbs the ridgeline and a flag that waves once at the summit.
Default
This example uses generated pictures from this site: art.ts. Copy that file from the repository, or use your own images in its place.
"use client";
import { RidgeProgress } from "@/components/miyuki-ui/ridge-progress";
import { landscape } from "@/registry/lib/art";
const sections = [
{
title: "The trailhead at 05:10",
text: [
"The Makkari trail starts beside a shrine at 380 metres, in birch forest that is still dark when the first cars pull in. Sign the register in the box by the gate and write the time you expect to be back.",
"The first hour climbs steadily through the trees. Keep your layers thin; you will be warm long before you are high.",
],
image: landscape("yotei-trailhead", { width: 1200, height: 560, mood: "dawn" }),
},
{
title: "Fifth station",
text: [
"Above the fifth station the birches thin out and the path turns into a staircase of roots and loose stone. This is where most people stop for breakfast, and where the view of the Shiribetsu valley first opens behind you.",
"In early summer there is still snow in the gullies here. Stay on the ridge rather than cutting across it.",
],
},
{
title: "The crater rim",
text: [
"At 1,600 metres you step out onto the rim. The crater is 700 metres across and drops 200 metres to a floor that keeps its snow into July. The wind arrives all at once.",
"Turn left and follow the rim clockwise. The path is marked with yellow paint on the rocks, and in cloud you will be glad of it.",
],
image: landscape("yotei-rim", { width: 1200, height: 560, mood: "snow" }),
},
{
title: "Summit, 1,898 metres",
text: [
"The true summit is a heap of dark rock on the south-west side of the rim, with a small marker and room for about six people. On a clear day you can see the sea on both sides of Hokkaidō.",
"Allow three hours back down. The descent is harder on the knees than the climb was on the lungs.",
],
},
];
export default function RidgeProgressDemo() {
return (
<>
<RidgeProgress seed="yotei" />
<article className="mx-auto w-full max-w-2xl px-5 pt-16 pb-24 sm:px-8">
<p className="text-[13px] text-muted-foreground">Route notes · Mount Yōtei</p>
<h1 className="mt-2 font-display text-4xl leading-[1.05] font-semibold tracking-[-0.03em] text-balance sm:text-5xl">
Yōtei in a day, by the Makkari trail
</h1>
<p className="mt-4 text-lg leading-relaxed text-muted-foreground">
1,520 metres of ascent, nine hours on foot, and the best view in Hokkaidō if the cloud lifts.
</p>
<div className="mt-12 space-y-12">
{sections.map((section) => (
<section key={section.title}>
<h2 className="font-display text-2xl leading-tight font-semibold tracking-[-0.02em]">{section.title}</h2>
{section.text.map((text) => (
<p key={text.slice(0, 24)} className="mt-3 text-base leading-relaxed text-foreground/85">
{text}
</p>
))}
{section.image && (
<img src={section.image} alt="" className="mt-6 aspect-[15/7] w-full rounded-xl object-cover" />
)}
</section>
))}
</div>
</article>
</>
);
}In a scrolling panel
"use client";
import { useRef } from "react";
import { RidgeProgress } from "@/components/miyuki-ui/ridge-progress";
const days = [
{
title: "Magome, 08:30",
text: "The post town sits on a slope, so the walk begins by climbing its one stone street past the water wheel and the last of the inns. Fill your bottle at the trough by the noticeboard.",
},
{
title: "Magome Pass, 801 metres",
text: "Forty minutes of cedar and old paving bring you to the pass and a tea house where the keeper still lights the hearth for walkers. From here the path drops gently all the way to Tsumago.",
},
{
title: "The Odaki and Medaki falls",
text: "Two falls a few minutes apart, the larger one loud enough to hear from the bridge. In February the spray freezes on the rocks and the steps beside them need care.",
},
{
title: "Tsumago, 12:10",
text: "The street has no wires and no cars, and the shutters are the same dark wood as two hundred years ago. Send your bag ahead from Magome and you can walk this with nothing but a camera.",
},
];
export default function RidgeProgressPanelDemo() {
const panel = useRef<HTMLDivElement>(null);
return (
<div className="mx-auto w-full max-w-xl px-4 py-6 sm:py-8">
<div
ref={panel}
className="h-[440px] overflow-y-auto overscroll-contain rounded-2xl border border-border bg-background shadow-sm"
>
<RidgeProgress container={panel} seed="kiso" />
<article className="px-5 pt-6 pb-10 sm:px-7">
<p className="text-[13px] text-muted-foreground">Route notes · Kiso valley</p>
<h2 className="mt-1.5 font-display text-2xl leading-tight font-semibold tracking-[-0.02em] text-balance">
Magome to Tsumago on the old road
</h2>
<div className="mt-6 space-y-7">
{days.map((day) => (
<section key={day.title}>
<h3 className="text-base font-semibold">{day.title}</h3>
<p className="mt-1.5 text-[15px] leading-relaxed text-foreground/85">{day.text}</p>
</section>
))}
</div>
</article>
</div>
</div>
);
}Install
npx shadcn@latest add @miyuki-ui/ridge-progressThis needs the @miyuki-ui registry in your components.json. See Using the shadcn CLI.
Props
RidgeProgress
Prop
Type