diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index debef591f..ee76c59d4 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -148,6 +148,7 @@ jobs: packages/ui/components/Viewer.consumer.test.tsx packages/ui/components/Viewer.documentHeader.test.tsx packages/ui/components/Viewer.codeBlockHighlightSwap.test.tsx + packages/ui/components/ImageAnnotator/ImageAnnotator.layout.test.tsx packages/ui/components/ImageAnnotator/ImageAnnotator.shortcuts.test.tsx packages/ui/utils/undoHistory.dom.test.ts packages/ui/utils/codeBlockMark.test.ts diff --git a/packages/core/guide-viewer-manifest.ts b/packages/core/guide-viewer-manifest.ts index 7cd073456..354b9dfe1 100644 --- a/packages/core/guide-viewer-manifest.ts +++ b/packages/core/guide-viewer-manifest.ts @@ -6,9 +6,9 @@ import type { GuideViewerAssets } from "./guide-format"; export const GUIDE_VIEWER_MANIFEST: Omit = { js: "viewer.C8JgNbZu.js", - css: "viewer.KIp-iPxY.css", + css: "viewer.5vsvVEy8.css", jsIntegrity: "sha384-dqRkZ2N5WNwLIuwa+1kdrvswkOVHpkBxrrJ5mTU4YrUWzO/8fRS5MRTlDGV9t7eB", - cssIntegrity: "sha384-Ty9hGpag8KIAGMDPg7ImsB4L5RabqvonNVjrj/CnYqSJDqIgPRBwjEMoK9/EvgXm", + cssIntegrity: "sha384-uZahMrNIsNY6GuwrTxGzVOzNxXVnS0hyzrgM2eoyvmz/KTA+grYszKx2LZKJAd/1", langs: { "astro": "chunks/astro.BykyiR6i.js", "c": "chunks/c.BIGW1oBm.js", diff --git a/packages/ui/components/ImageAnnotator/ImageAnnotator.layout.test.tsx b/packages/ui/components/ImageAnnotator/ImageAnnotator.layout.test.tsx new file mode 100644 index 000000000..baf62964f --- /dev/null +++ b/packages/ui/components/ImageAnnotator/ImageAnnotator.layout.test.tsx @@ -0,0 +1,62 @@ +import { afterEach, describe, expect, test } from 'bun:test'; +import React, { act } from 'react'; +import { createRoot, type Root } from 'react-dom/client'; +import { ImageAnnotator } from './index'; + +const hasDom = typeof document !== 'undefined'; +let root: Root | null = null; +let host: HTMLDivElement | null = null; + +afterEach(async () => { + if (root) await act(async () => root?.unmount()); + root = null; + host?.remove(); + host = null; +}); + +describe.if(hasDom)('ImageAnnotator compact toolbar layout', () => { + test('bounds the content-fit toolbar and keeps Save outside its horizontal scroller', async () => { + host = document.createElement('div'); + document.body.append(host); + root = createRoot(host); + + await act(async () => { + root?.render( + {}} + onClose={() => {}} + />, + ); + }); + + const overlay = host.querySelector('[data-popover-layer]'); + const stage = host.querySelector('[data-pn-image-annotator-stage]'); + const toolbar = host.querySelector('[data-pn-image-annotator-toolbar]'); + const scroller = host.querySelector('[data-pn-image-toolbar-scroll]'); + const save = host.querySelector('button[title="Save (Esc)"]'); + + expect(overlay?.classList.contains('pn-visible-viewport-overlay')).toBe(true); + expect(stage?.classList.contains('max-w-full')).toBe(true); + expect(toolbar?.classList.contains('w-fit')).toBe(true); + expect(toolbar?.classList.contains('max-w-full')).toBe(true); + expect(scroller?.classList.contains('min-w-0')).toBe(true); + expect(scroller?.classList.contains('overflow-x-auto')).toBe(true); + expect(scroller?.contains(save ?? null)).toBe(false); + + for (const title of [ + 'Pen (1)', + 'Arrow (2)', + 'Circle (3)', + 'Smaller stroke', + 'Larger stroke', + 'Undo (Cmd+Z)', + 'Redo (Cmd+Shift+Z)', + 'Clear all', + ]) { + const control = host.querySelector(`button[title="${title}"]`); + expect(scroller?.contains(control ?? null)).toBe(true); + } + }); +}); diff --git a/packages/ui/components/ImageAnnotator/Toolbar.tsx b/packages/ui/components/ImageAnnotator/Toolbar.tsx index 91b5af547..01db5ec26 100644 --- a/packages/ui/components/ImageAnnotator/Toolbar.tsx +++ b/packages/ui/components/ImageAnnotator/Toolbar.tsx @@ -104,7 +104,15 @@ export const Toolbar: React.FC = ({ const canIncrease = currentSizeIndex < STROKE_SIZES.length - 1; return ( -
+
+
+
{/* Tools */}
{TOOLS.map(({ id, icon: Icon, label }) => ( @@ -228,15 +236,17 @@ export const Toolbar: React.FC = ({ > +
+
-
+
{/* Save */} diff --git a/packages/ui/components/ImageAnnotator/index.tsx b/packages/ui/components/ImageAnnotator/index.tsx index 0243a3170..d6ae2b0f6 100644 --- a/packages/ui/components/ImageAnnotator/index.tsx +++ b/packages/ui/components/ImageAnnotator/index.tsx @@ -185,12 +185,16 @@ export const ImageAnnotator: React.FC = ({ return (
{/* Canvas with image and toolbar */} -
e.stopPropagation()}> +
e.stopPropagation()} + > {/* Toolbar - above image */}