diff --git a/apps/web/src/App.tsx b/apps/web/src/App.tsx index 57e0fc7..c459719 100644 --- a/apps/web/src/App.tsx +++ b/apps/web/src/App.tsx @@ -336,8 +336,8 @@ export function App() { uploadAndCacheSource={uploadAndCacheSource} refreshCache={refreshCache} panelRole="pinned" - isFolded={false} - onToggleFold={() => {}} + isCollapsed={false} + onToggleCollapse={() => {}} onPin={() => {}} onUnpin={sidePanel.unpin} showPinButton={false} @@ -355,8 +355,8 @@ export function App() { uploadAndCacheSource={uploadAndCacheSource} refreshCache={refreshCache} panelRole="browse" - isFolded={sidePanel.isRightPanelFolded} - onToggleFold={sidePanel.toggleFold} + isCollapsed={sidePanel.isRightPanelCollapsed} + onToggleCollapse={sidePanel.toggleCollapse} onPin={sidePanel.togglePin} onUnpin={() => {}} showPinButton={sidePanel.isWideDesktop && !!selectedCreature} @@ -371,7 +371,7 @@ export function App() { diff --git a/apps/web/src/__tests__/stat-block-fold-pin.test.tsx b/apps/web/src/__tests__/stat-block-collapse-pin.test.tsx similarity index 77% rename from apps/web/src/__tests__/stat-block-fold-pin.test.tsx rename to apps/web/src/__tests__/stat-block-collapse-pin.test.tsx index 213541b..5608abe 100644 --- a/apps/web/src/__tests__/stat-block-fold-pin.test.tsx +++ b/apps/web/src/__tests__/stat-block-collapse-pin.test.tsx @@ -45,8 +45,8 @@ interface PanelProps { creatureId?: CreatureId | null; creature?: Creature | null; panelRole?: "browse" | "pinned"; - isFolded?: boolean; - onToggleFold?: () => void; + isCollapsed?: boolean; + onToggleCollapse?: () => void; onPin?: () => void; onUnpin?: () => void; showPinButton?: boolean; @@ -64,8 +64,8 @@ function renderPanel(overrides: PanelProps = {}) { uploadAndCacheSource: vi.fn(), refreshCache: vi.fn(), panelRole: "browse" as const, - isFolded: false, - onToggleFold: vi.fn(), + isCollapsed: false, + onToggleCollapse: vi.fn(), onPin: vi.fn(), onUnpin: vi.fn(), showPinButton: false, @@ -78,18 +78,18 @@ function renderPanel(overrides: PanelProps = {}) { return props; } -describe("Stat Block Panel Fold/Unfold and Pin", () => { +describe("Stat Block Panel Collapse/Expand and Pin", () => { beforeEach(() => { mockMatchMedia(true); // desktop by default }); afterEach(cleanup); - describe("US1: Fold and Unfold", () => { - it("shows fold button instead of close button on desktop", () => { + describe("US1: Collapse and Expand", () => { + it("shows collapse button instead of close button on desktop", () => { renderPanel(); expect( - screen.getByRole("button", { name: "Fold stat block panel" }), + screen.getByRole("button", { name: "Collapse stat block panel" }), ).toBeInTheDocument(); expect( screen.queryByRole("button", { name: /close/i }), @@ -101,42 +101,42 @@ describe("Stat Block Panel Fold/Unfold and Pin", () => { expect(screen.queryByText("Stat Block")).not.toBeInTheDocument(); }); - it("renders folded tab with creature name when isFolded is true", () => { - renderPanel({ isFolded: true }); + it("renders collapsed tab with creature name when isCollapsed is true", () => { + renderPanel({ isCollapsed: true }); expect(screen.getByText("Goblin")).toBeInTheDocument(); expect( - screen.getByRole("button", { name: "Unfold stat block panel" }), + screen.getByRole("button", { name: "Expand stat block panel" }), ).toBeInTheDocument(); }); - it("calls onToggleFold when fold button is clicked", () => { + it("calls onToggleCollapse when collapse button is clicked", () => { const props = renderPanel(); fireEvent.click( - screen.getByRole("button", { name: "Fold stat block panel" }), + screen.getByRole("button", { name: "Collapse stat block panel" }), ); - expect(props.onToggleFold).toHaveBeenCalledTimes(1); + expect(props.onToggleCollapse).toHaveBeenCalledTimes(1); }); - it("calls onToggleFold when folded tab is clicked", () => { - const props = renderPanel({ isFolded: true }); + it("calls onToggleCollapse when collapsed tab is clicked", () => { + const props = renderPanel({ isCollapsed: true }); fireEvent.click( - screen.getByRole("button", { name: "Unfold stat block panel" }), + screen.getByRole("button", { name: "Expand stat block panel" }), ); - expect(props.onToggleFold).toHaveBeenCalledTimes(1); + expect(props.onToggleCollapse).toHaveBeenCalledTimes(1); }); - it("applies translate-x class when folded (right side)", () => { - renderPanel({ isFolded: true, side: "right" }); + it("applies translate-x class when collapsed (right side)", () => { + renderPanel({ isCollapsed: true, side: "right" }); const panel = screen - .getByRole("button", { name: "Unfold stat block panel" }) + .getByRole("button", { name: "Expand stat block panel" }) .closest("div"); expect(panel?.className).toContain("translate-x-[calc(100%-40px)]"); }); it("applies translate-x-0 when expanded", () => { - renderPanel({ isFolded: false }); + renderPanel({ isCollapsed: false }); const foldBtn = screen.getByRole("button", { - name: "Fold stat block panel", + name: "Collapse stat block panel", }); const panel = foldBtn.closest("div.fixed") as HTMLElement; expect(panel?.className).toContain("translate-x-0"); @@ -148,12 +148,12 @@ describe("Stat Block Panel Fold/Unfold and Pin", () => { mockMatchMedia(false); // mobile }); - it("shows fold button instead of X close button on mobile drawer", () => { + it("shows collapse button instead of X close button on mobile drawer", () => { renderPanel(); expect( - screen.getByRole("button", { name: "Fold stat block panel" }), + screen.getByRole("button", { name: "Collapse stat block panel" }), ).toBeInTheDocument(); - // No X close icon button — only backdrop dismiss and fold toggle + // No X close icon button — only backdrop dismiss and collapse toggle const buttons = screen.getAllByRole("button"); const buttonLabels = buttons.map((b) => b.getAttribute("aria-label")); expect(buttonLabels).not.toContain("Close"); @@ -175,8 +175,8 @@ describe("Stat Block Panel Fold/Unfold and Pin", () => { uploadAndCacheSource={vi.fn()} refreshCache={vi.fn()} panelRole="pinned" - isFolded={false} - onToggleFold={vi.fn()} + isCollapsed={false} + onToggleCollapse={vi.fn()} onPin={vi.fn()} onUnpin={vi.fn()} showPinButton={false} @@ -235,7 +235,7 @@ describe("Stat Block Panel Fold/Unfold and Pin", () => { it("positions browse panel on the right side", () => { renderPanel({ panelRole: "browse", side: "right" }); const foldBtn = screen.getByRole("button", { - name: "Fold stat block panel", + name: "Collapse stat block panel", }); const panel = foldBtn.closest("div.fixed") as HTMLElement; expect(panel?.className).toContain("right-0"); @@ -243,16 +243,16 @@ describe("Stat Block Panel Fold/Unfold and Pin", () => { }); }); - describe("US3: Fold independence with pinned panel", () => { - it("pinned panel has no fold button", () => { + describe("US3: Collapse independence with pinned panel", () => { + it("pinned panel has no collapse button", () => { renderPanel({ panelRole: "pinned", side: "left" }); expect( - screen.queryByRole("button", { name: /fold/i }), + screen.queryByRole("button", { name: /collapse/i }), ).not.toBeInTheDocument(); }); it("pinned panel is always expanded (no translate offset)", () => { - renderPanel({ panelRole: "pinned", side: "left", isFolded: false }); + renderPanel({ panelRole: "pinned", side: "left", isCollapsed: false }); const unpinBtn = screen.getByRole("button", { name: "Unpin creature", }); diff --git a/apps/web/src/components/stat-block-panel.tsx b/apps/web/src/components/stat-block-panel.tsx index 499a90f..a89e166 100644 --- a/apps/web/src/components/stat-block-panel.tsx +++ b/apps/web/src/components/stat-block-panel.tsx @@ -22,8 +22,8 @@ interface StatBlockPanelProps { ) => Promise; refreshCache: () => Promise; panelRole: "browse" | "pinned"; - isFolded: boolean; - onToggleFold: () => void; + isCollapsed: boolean; + onToggleCollapse: () => void; onPin: () => void; onUnpin: () => void; showPinButton: boolean; @@ -42,23 +42,23 @@ function extractSourceCode(cId: CreatureId): string { return cId.slice(0, colonIndex).toUpperCase(); } -function FoldedTab({ +function CollapsedTab({ creatureName, side, - onToggleFold, + onToggleCollapse, }: { creatureName: string; side: "left" | "right"; - onToggleFold: () => void; + onToggleCollapse: () => void; }) { return ( @@ -124,48 +124,48 @@ function PanelHeader({ } function DesktopPanel({ - isFolded, + isCollapsed, side, creatureName, panelRole, showPinButton, - onToggleFold, + onToggleCollapse, onPin, onUnpin, children, }: { - isFolded: boolean; + isCollapsed: boolean; side: "left" | "right"; creatureName: string; panelRole: "browse" | "pinned"; showPinButton: boolean; - onToggleFold: () => void; + onToggleCollapse: () => void; onPin: () => void; onUnpin: () => void; children: ReactNode; }) { const sideClasses = side === "left" ? "left-0 border-r" : "right-0 border-l"; - const foldedTranslate = + const collapsedTranslate = side === "right" ? "translate-x-[calc(100%-40px)]" : "translate-x-[calc(-100%+40px)]"; return (
- {isFolded ? ( - ) : ( <> @@ -206,7 +206,7 @@ function MobileDrawer({ size="icon-sm" onClick={onDismiss} className="text-muted-foreground" - aria-label="Fold stat block panel" + aria-label="Collapse stat block panel" > @@ -227,8 +227,8 @@ export function StatBlockPanel({ uploadAndCacheSource, refreshCache, panelRole, - isFolded, - onToggleFold, + isCollapsed, + onToggleCollapse, onPin, onUnpin, showPinButton, @@ -341,12 +341,12 @@ export function StatBlockPanel({ if (isDesktop) { return ( diff --git a/apps/web/src/hooks/use-side-panel-state.ts b/apps/web/src/hooks/use-side-panel-state.ts index 208781e..9a04709 100644 --- a/apps/web/src/hooks/use-side-panel-state.ts +++ b/apps/web/src/hooks/use-side-panel-state.ts @@ -12,7 +12,7 @@ interface SidePanelState { selectedCreatureId: CreatureId | null; bulkImportMode: boolean; sourceManagerMode: boolean; - isRightPanelFolded: boolean; + isRightPanelCollapsed: boolean; pinnedCreatureId: CreatureId | null; isWideDesktop: boolean; } @@ -22,14 +22,14 @@ interface SidePanelActions { showBulkImport: () => void; showSourceManager: () => void; dismissPanel: () => void; - toggleFold: () => void; + toggleCollapse: () => void; togglePin: () => void; unpin: () => void; } export function useSidePanelState(): SidePanelState & SidePanelActions { const [panelView, setPanelView] = useState({ mode: "closed" }); - const [isRightPanelFolded, setIsRightPanelFolded] = useState(false); + const [isRightPanelCollapsed, setIsRightPanelCollapsed] = useState(false); const [pinnedCreatureId, setPinnedCreatureId] = useState( null, ); @@ -49,25 +49,25 @@ export function useSidePanelState(): SidePanelState & SidePanelActions { const showCreature = useCallback((creatureId: CreatureId) => { setPanelView({ mode: "creature", creatureId }); - setIsRightPanelFolded(false); + setIsRightPanelCollapsed(false); }, []); const showBulkImport = useCallback(() => { setPanelView({ mode: "bulk-import" }); - setIsRightPanelFolded(false); + setIsRightPanelCollapsed(false); }, []); const showSourceManager = useCallback(() => { setPanelView({ mode: "source-manager" }); - setIsRightPanelFolded(false); + setIsRightPanelCollapsed(false); }, []); const dismissPanel = useCallback(() => { setPanelView({ mode: "closed" }); }, []); - const toggleFold = useCallback(() => { - setIsRightPanelFolded((f) => !f); + const toggleCollapse = useCallback(() => { + setIsRightPanelCollapsed((f) => !f); }, []); const togglePin = useCallback(() => { @@ -87,14 +87,14 @@ export function useSidePanelState(): SidePanelState & SidePanelActions { selectedCreatureId, bulkImportMode: panelView.mode === "bulk-import", sourceManagerMode: panelView.mode === "source-manager", - isRightPanelFolded, + isRightPanelCollapsed, pinnedCreatureId, isWideDesktop, showCreature, showBulkImport, showSourceManager, dismissPanel, - toggleFold, + toggleCollapse, togglePin, unpin, };