refactor: unify floating toolbar sizing and show graph title
This commit is contained in:
@@ -0,0 +1,22 @@
|
||||
"use client";
|
||||
|
||||
import { createContext, useContext, useMemo, useState, type Dispatch, type ReactNode, type SetStateAction } from "react";
|
||||
import type { Board } from "@/lib/workspace";
|
||||
|
||||
type ActiveBoard = Pick<Board, "id" | "workspace_id" | "title"> | null;
|
||||
const ActiveBoardContext = createContext<{
|
||||
board: ActiveBoard;
|
||||
setBoard: Dispatch<SetStateAction<ActiveBoard>>;
|
||||
} | null>(null);
|
||||
|
||||
export function ActiveBoardProvider({ children }: { children: ReactNode }) {
|
||||
const [board, setBoard] = useState<ActiveBoard>(null);
|
||||
const value = useMemo(() => ({ board, setBoard }), [board]);
|
||||
return <ActiveBoardContext.Provider value={value}>{children}</ActiveBoardContext.Provider>;
|
||||
}
|
||||
|
||||
export function useActiveBoard() {
|
||||
const context = useContext(ActiveBoardContext);
|
||||
if (!context) throw new Error("useActiveBoard requires ActiveBoardProvider");
|
||||
return context;
|
||||
}
|
||||
@@ -6,11 +6,13 @@ import { api, errorText } from "@/lib/api";
|
||||
import { readDemoBoards } from "@/lib/demo-workspace";
|
||||
import type { Board } from "@/lib/workspace";
|
||||
import styles from "./workspace.module.css";
|
||||
import { useActiveBoard } from "./active-board";
|
||||
import GraphCanvas from "@/components/canvas/graph-canvas";
|
||||
|
||||
export default function GraphPage({ workspaceId, boardId }: { workspaceId: string; boardId: string }) {
|
||||
const demo = useSearchParams().get("demo") === "1";
|
||||
const router = useRouter();
|
||||
const { setBoard: setActiveBoard } = useActiveBoard();
|
||||
const [board, setBoard] = useState<Board | null>(null);
|
||||
const [error, setError] = useState("");
|
||||
|
||||
@@ -45,6 +47,13 @@ export default function GraphPage({ workspaceId, boardId }: { workspaceId: strin
|
||||
return () => { active = false; controller.abort(); };
|
||||
}, [workspaceId, boardId, demo, router]);
|
||||
|
||||
useEffect(() => {
|
||||
if (board?.id === boardId && board.workspace_id === workspaceId) {
|
||||
setActiveBoard({ id: board.id, workspace_id: board.workspace_id, title: board.title });
|
||||
}
|
||||
return () => setActiveBoard(null);
|
||||
}, [board, boardId, workspaceId, setActiveBoard]);
|
||||
|
||||
return (
|
||||
<main className={styles.graph} aria-label={board ? board.title + " · 无限图谱" : "无限图谱"} aria-busy={!board && !error}>
|
||||
{board ? <GraphCanvas key={workspaceId + ":" + boardId} board={board} /> : <div className={styles.graphSurface} aria-label="正在读取画布" />}
|
||||
|
||||
@@ -94,7 +94,7 @@
|
||||
.newWorkspace { color: #2383e2; }
|
||||
.logout { color: #78746d; font-size: 12px; }
|
||||
.separator { height: 1px; margin: 6px 7px; background: #eeece8; }
|
||||
.floating { position: fixed; left: 12px; top: 12px; z-index: 40; display: flex; gap: 6px; padding: 6px; background: #fffefa; border: 1px solid #e7e2db; border-radius: 8px; box-shadow: 0 3px 14px #3c312b0d; color: #85817b; }
|
||||
.floating { position: fixed; left: 12px; top: 12px; max-width: calc(100vw - 24px); z-index: 40; }
|
||||
.floatingError { position: absolute; left: 0; top: 42px; width: 240px; padding: 10px; background: white; border: 1px solid #e7e2db; border-radius: 8px; color: #b14b3c; font-size: 12px; }
|
||||
.settingsPanel { color: #37352f; border-color: #e6e2dc; border-radius: 12px; }
|
||||
.settingsForm { display: flex; flex-direction: column; gap: 16px; padding-top: 4px; }
|
||||
@@ -112,11 +112,15 @@
|
||||
@media (max-width: 600px) { .shell { --sidebar-width: 240px; } }
|
||||
@media (prefers-reduced-motion: reduce) { .accountPopup:popover-open { animation: none; } }
|
||||
|
||||
.logoLink { display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto; width: 28px; height: 24px; padding: 4px 6px; border-radius: 5px; }
|
||||
.logoLink img { display: block; width: 16px; height: 16px; }
|
||||
.logoLink { display: inline-flex; align-items: center; justify-content: center; flex: 0 0 auto; box-sizing: border-box; width: var(--toolbar-control-width, 28px); height: var(--toolbar-control-height, 24px); padding: 4px 6px; border-radius: 5px; }
|
||||
.logoLink img { display: block; width: var(--toolbar-icon-size, 16px); height: var(--toolbar-icon-size, 16px); }
|
||||
.logoLink:hover { background: #e9e7e3; }
|
||||
.logoLink:focus-visible { outline: 2px solid #9d7d66; outline-offset: 2px; }
|
||||
|
||||
.floatingAvatarButton { display: grid; place-items: center; width: 28px; height: 24px; border-radius: 5px; }
|
||||
.floatingAvatarButton { display: grid; place-items: center; flex: 0 0 auto; box-sizing: border-box; width: var(--toolbar-control-width, 28px); height: var(--toolbar-control-height, 24px); border-radius: 5px; }
|
||||
.floatingAvatarButton:hover { background: #e9e7e3; }
|
||||
.accountPopup[data-floating="true"] { inset: 56px auto auto 12px; max-height: calc(100dvh - 70px); transform-origin: top left; }
|
||||
|
||||
.floatingAvatarButton .avatar { flex-basis: var(--toolbar-icon-size, 16px); width: var(--toolbar-icon-size, 16px); height: var(--toolbar-icon-size, 16px); font-size: 9px; }
|
||||
.floatingTitle { flex: 1 1 auto; min-width: 0; max-width: 240px; margin: 0 4px; color: #37352f; font-size: 12px; line-height: 24px; font-weight: 500; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
|
||||
@media (max-width: 700px) { .floatingTitle { max-width: 180px; } }
|
||||
|
||||
Reference in New Issue
Block a user