フィードバック
Reading Progress
ページのスクロール量に応じて進捗を表示する固定バー。ブログ記事の読了状況確認に便利。
インストール
npx shadcn add https://d-ui.daigo-suhara.com/registry/reading-progress.jsonサンプル
スクロール進捗バー(固定表示)のプレビュー:
primary
40%
blue
50%
green
60%
purple
70%
orange
80%
pink
90%
使い方
import { ReadingProgress } from "@/components/ui/reading-progress"
export default function BlogLayout({ children }) {
return (
<>
<ReadingProgress color="purple" />
<main>{children}</main>
</>
)
}プロパティ
color任意"primary" | "blue" | "green" | "purple" | "orange" | "pink"バーの色
デフォルト:
"primary"height任意numberバーの高さ(px)
デフォルト:
3position任意"top" | "bottom"バーの表示位置
デフォルト:
"top"className必須string追加のCSSクラス
| 名前 | 型 | デフォルト | 説明 | |
|---|---|---|---|---|
| 任意 | color | "primary" | "blue" | "green" | "purple" | "orange" | "pink" | "primary" | バーの色 |
| 任意 | height | number | 3 | バーの高さ(px) |
| 任意 | position | "top" | "bottom" | "top" | バーの表示位置 |
| 必須 | className | string | — | 追加のCSSクラス |
ソースコード
"use client";
import * as React from "react";
import { cn } from "@/lib/utils";
interface ReadingProgressProps {
color?: "primary" | "blue" | "green" | "purple" | "orange" | "pink";
height?: number;
position?: "top" | "bottom";
className?: string;
}
const colorMap: Record<string, string> = {
primary: "bg-primary",
blue: "bg-blue-500",
green: "bg-emerald-500",
purple: "bg-violet-500",
orange: "bg-orange-500",
pink: "bg-pink-500",
};
export function ReadingProgress({
color = "primary",
height = 3,
position = "top",
className,
}: ReadingProgressProps) {
const [progress, setProgress] = React.useState(0);
React.useEffect(() => {
const update = () => {
const scrollTop = window.scrollY;
const docHeight =
document.documentElement.scrollHeight - window.innerHeight;
setProgress(docHeight > 0 ? (scrollTop / docHeight) * 100 : 0);
};
window.addEventListener("scroll", update, { passive: true });
return () => window.removeEventListener("scroll", update);
}, []);
return (
<div
className={cn(
"fixed left-0 right-0 z-50",
position === "top" ? "top-0" : "bottom-0",
className
)}
style={{ height }}
>
<div
className={cn("h-full transition-[width] duration-75", colorMap[color])}
style={{ width: `${progress}%` }}
/>
</div>
);
}