refactor(frontend): shared reader chrome to shadcn/radix (header, nav Sheet, bookmarks)
This commit is contained in:
@@ -3,6 +3,8 @@ import { Check, Pencil, Plus, X } from "lucide-react";
|
||||
import { useState } from "react";
|
||||
import { api } from "../api/client";
|
||||
import type { Book } from "../api/types";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { toast } from "./Toaster";
|
||||
|
||||
type Locator = Record<string, unknown>;
|
||||
@@ -55,8 +57,8 @@ export function BookmarksTab({
|
||||
return (
|
||||
<>
|
||||
<div className="mb-2 flex items-center gap-1.5">
|
||||
<input
|
||||
className="min-w-0 flex-1 rounded-md border border-stone-700 bg-stone-900 px-2 py-1 text-sm text-stone-100 placeholder:text-stone-500"
|
||||
<Input
|
||||
className="min-w-0 flex-1"
|
||||
placeholder="备注(可空)"
|
||||
maxLength={500}
|
||||
value={note}
|
||||
@@ -65,26 +67,28 @@ export function BookmarksTab({
|
||||
if (e.key === "Enter" && !add.isPending) add.mutate();
|
||||
}}
|
||||
/>
|
||||
<button
|
||||
className="rd-btn inline-flex shrink-0 items-center gap-1"
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon-xs"
|
||||
className="shrink-0"
|
||||
aria-label="加书签"
|
||||
disabled={add.isPending}
|
||||
onClick={() => add.mutate()}
|
||||
>
|
||||
<Plus size={14} /> 加
|
||||
</button>
|
||||
<Plus size={14} />
|
||||
</Button>
|
||||
</div>
|
||||
<ul className="space-y-0.5">
|
||||
{q.isPending && <li className="p-2 text-xs text-stone-500">加载中…</li>}
|
||||
{q.isPending && <li className="p-2 text-xs text-muted-foreground">加载中…</li>}
|
||||
{!q.isPending && items.length === 0 && (
|
||||
<li className="p-2 text-xs text-stone-500">还没有书签,读到想记的位置点「加」</li>
|
||||
<li className="p-2 text-xs text-muted-foreground">还没有书签,读到想记的位置点「加」</li>
|
||||
)}
|
||||
{items.map((b) => (
|
||||
<li key={b.id}>
|
||||
{editId === b.id ? (
|
||||
<div className="flex items-center gap-1">
|
||||
<input
|
||||
className="min-w-0 flex-1 rounded-md border border-stone-700 bg-stone-900 px-2 py-1 text-sm text-stone-100"
|
||||
<Input
|
||||
className="min-w-0 flex-1"
|
||||
maxLength={500}
|
||||
value={editVal}
|
||||
onChange={(e) => setEditVal(e.target.value)}
|
||||
@@ -92,34 +96,40 @@ export function BookmarksTab({
|
||||
if (e.key === "Enter" && !patch.isPending) patch.mutate({ id: b.id, note: editVal.trim() });
|
||||
}}
|
||||
/>
|
||||
<button
|
||||
className="rd-btn inline-flex shrink-0 items-center"
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon-xs"
|
||||
className="shrink-0"
|
||||
aria-label="保存备注"
|
||||
disabled={patch.isPending}
|
||||
onClick={() => patch.mutate({ id: b.id, note: editVal.trim() })}
|
||||
>
|
||||
<Check size={14} />
|
||||
</button>
|
||||
<button
|
||||
className="rd-btn inline-flex shrink-0 items-center"
|
||||
</Button>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon-xs"
|
||||
className="shrink-0"
|
||||
aria-label="取消编辑"
|
||||
onClick={() => setEditId(null)}
|
||||
>
|
||||
<X size={14} />
|
||||
</button>
|
||||
</Button>
|
||||
</div>
|
||||
) : (
|
||||
<div className="group flex items-center">
|
||||
<button
|
||||
className="rd-row min-w-0 flex-1 truncate text-left"
|
||||
className="min-w-0 flex-1 truncate rounded-md px-2.5 py-1.5 text-left text-sm transition-colors hover:bg-accent hover:text-accent-foreground"
|
||||
title={b.note || undefined}
|
||||
onClick={() => seek(b.locator)}
|
||||
>
|
||||
<span className="tabular-nums opacity-70">{Math.round(b.percent * 100)}%</span>{" "}
|
||||
{b.note || <span className="opacity-50">{b.created_at.slice(0, 10)}</span>}
|
||||
</button>
|
||||
<button
|
||||
className="rd-btn m-0.5 shrink-0 opacity-0 transition-opacity group-hover:opacity-100 focus-visible:opacity-100"
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon-xs"
|
||||
className="m-0.5 shrink-0 opacity-0 transition-opacity group-hover:opacity-100 focus-visible:opacity-100"
|
||||
aria-label="改备注"
|
||||
onClick={() => {
|
||||
setEditId(b.id);
|
||||
@@ -127,14 +137,16 @@ export function BookmarksTab({
|
||||
}}
|
||||
>
|
||||
<Pencil size={14} />
|
||||
</button>
|
||||
<button
|
||||
className="rd-btn m-0.5 shrink-0 opacity-0 transition-opacity group-hover:opacity-100 focus-visible:opacity-100"
|
||||
</Button>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="icon-xs"
|
||||
className="m-0.5 shrink-0 opacity-0 transition-opacity group-hover:opacity-100 focus-visible:opacity-100"
|
||||
aria-label="删除书签"
|
||||
onClick={() => del.mutate(b.id)}
|
||||
>
|
||||
<X size={14} />
|
||||
</button>
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
</li>
|
||||
|
||||
Reference in New Issue
Block a user