Archived
feat: floating bookmarks
add floating bookmarks
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
import { useState } from "react";
|
||||
import { useTranslation } from "react-i18n-lite";
|
||||
import type { BookmarkRailItem } from "@/utils/bookmarkRailLayout";
|
||||
import { truncateRailPreview } from "@/utils/bookmarkRailLayout";
|
||||
import { normalizeHighlightColor } from "@/constants/bookmarkHighlightColors";
|
||||
import { BookmarkIcon } from "./BookmarkIcon";
|
||||
|
||||
interface BookmarkReaderRailProps {
|
||||
items: BookmarkRailItem[];
|
||||
onGoToBookmark: (epubCfi: string) => void;
|
||||
}
|
||||
|
||||
function RailMarker({
|
||||
item,
|
||||
onGoToBookmark,
|
||||
}: {
|
||||
item: BookmarkRailItem;
|
||||
onGoToBookmark: (epubCfi: string) => void;
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
const [hovered, setHovered] = useState(false);
|
||||
const color = normalizeHighlightColor(item.marker.highlight_color);
|
||||
const previewText = truncateRailPreview(item.marker.location_text || "");
|
||||
const notePreview = item.marker.content
|
||||
? truncateRailPreview(item.marker.content, 80)
|
||||
: "";
|
||||
|
||||
const ariaLabel = previewText
|
||||
? t("reader.bookmarkRailPreview", { text: previewText })
|
||||
: t("reader.bookmarkRailGoTo");
|
||||
|
||||
return (
|
||||
<li className="reader-bookmark-marker-wrap">
|
||||
<button
|
||||
type="button"
|
||||
className="reader-bookmark-marker"
|
||||
onClick={() => onGoToBookmark(item.marker.epub_cfi)}
|
||||
onMouseEnter={() => setHovered(true)}
|
||||
onMouseLeave={() => setHovered(false)}
|
||||
onFocus={() => setHovered(true)}
|
||||
onBlur={() => setHovered(false)}
|
||||
aria-label={ariaLabel}
|
||||
title={previewText || undefined}
|
||||
>
|
||||
<BookmarkIcon size={28} color={color} className="reader-bookmark-marker-icon" />
|
||||
</button>
|
||||
{hovered && previewText && (
|
||||
<div
|
||||
className="reader-bookmark-preview"
|
||||
style={{ borderLeftColor: color }}
|
||||
role="tooltip"
|
||||
>
|
||||
<p className="reader-bookmark-preview-passage">{previewText}</p>
|
||||
{notePreview && (
|
||||
<p className="reader-bookmark-preview-note">{notePreview}</p>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</li>
|
||||
);
|
||||
}
|
||||
|
||||
export function BookmarkReaderRail({ items, onGoToBookmark }: BookmarkReaderRailProps) {
|
||||
if (items.length === 0) return null;
|
||||
|
||||
return (
|
||||
<ul className="reader-bookmark-strip" aria-label="Bookmarks">
|
||||
{items.map((item) => (
|
||||
<RailMarker key={item.marker.id} item={item} onGoToBookmark={onGoToBookmark} />
|
||||
))}
|
||||
</ul>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user