diff --git a/packages/feedback/src/screenshot/components/CropIcon.tsx b/packages/feedback/src/screenshot/components/CropIcon.tsx new file mode 100644 index 000000000000..091179d86004 --- /dev/null +++ b/packages/feedback/src/screenshot/components/CropIcon.tsx @@ -0,0 +1,23 @@ +import type { VNode, h as hType } from 'preact'; + +interface FactoryParams { + h: typeof hType; +} + +export default function CropIconFactory({ + h, // eslint-disable-line @typescript-eslint/no-unused-vars +}: FactoryParams) { + return function CropIcon(): VNode { + return ( + + + + ); + }; +} diff --git a/packages/feedback/src/screenshot/components/PenIcon.tsx b/packages/feedback/src/screenshot/components/PenIcon.tsx index ec50862c1dd4..75a0faedf480 100644 --- a/packages/feedback/src/screenshot/components/PenIcon.tsx +++ b/packages/feedback/src/screenshot/components/PenIcon.tsx @@ -9,7 +9,7 @@ export default function PenIconFactory({ }: FactoryParams) { return function PenIcon(): VNode { return ( - + ({ __html: createScreenshotInputStyles(options.styleNonce).innerText }), []); @@ -86,6 +88,7 @@ export function ScreenshotEditorFactory({ const [croppingRect, setCroppingRect] = hooks.useState({ startX: 0, startY: 0, endX: 0, endY: 0 }); const [confirmCrop, setConfirmCrop] = hooks.useState(false); const [isResizing, setIsResizing] = hooks.useState(false); + const [isCropping, setIsCropping] = hooks.useState(true); const [isAnnotating, setIsAnnotating] = hooks.useState(false); hooks.useEffect(() => { @@ -142,6 +145,10 @@ export function ScreenshotEditorFactory({ const croppingBox = constructRect(croppingRect); ctx.clearRect(0, 0, imageDimensions.width, imageDimensions.height); + if (!isCropping) { + return; + } + // draw gray overlay around the selection ctx.fillStyle = 'rgba(0, 0, 0, 0.5)'; ctx.fillRect(0, 0, imageDimensions.width, imageDimensions.height); @@ -154,7 +161,7 @@ export function ScreenshotEditorFactory({ ctx.strokeStyle = '#000000'; ctx.lineWidth = 1; ctx.strokeRect(croppingBox.x + 3, croppingBox.y + 3, croppingBox.width - 6, croppingBox.height - 6); - }, [croppingRect]); + }, [croppingRect, isCropping]); function onGrabButton(e: Event, corner: string): void { setIsAnnotating(false); @@ -398,102 +405,115 @@ export function ScreenshotEditorFactory({ return ( - {options._experiments.annotations && ( - - { - e.preventDefault(); - setIsAnnotating(!isAnnotating); - }} + + + - - - - )} - - + + {isCropping && ( + + + + + + + )} + {isCropping && ( + + { + e.preventDefault(); + if (croppingRef.current) { + setCroppingRect({ + startX: 0, + startY: 0, + endX: croppingRef.current.width / DPI, + endY: croppingRef.current.height / DPI, + }); + } + setConfirmCrop(false); + }} + class="btn btn--default" + > + {options.cancelButtonLabel} + + { + e.preventDefault(); + applyCrop(); + setConfirmCrop(false); + }} + class="btn btn--primary" + > + {options.confirmButtonLabel} + + + )} + - - - - - + + + {options._experiments.annotations && ( + + + { e.preventDefault(); - if (croppingRef.current) { - setCroppingRect({ - startX: 0, - startY: 0, - endX: croppingRef.current.width / DPI, - endY: croppingRef.current.height / DPI, - }); - } - setConfirmCrop(false); + setIsCropping(!isCropping); + setIsAnnotating(false); }} - class="btn btn--default" > - {options.cancelButtonLabel} + { e.preventDefault(); - applyCrop(); - setConfirmCrop(false); + setIsAnnotating(!isAnnotating); + setIsCropping(false); }} - class="btn btn--primary" > - {options.confirmButtonLabel} + + - - + )} ); }; diff --git a/packages/feedback/src/screenshot/components/ScreenshotInput.css.ts b/packages/feedback/src/screenshot/components/ScreenshotInput.css.ts index 5b439390d068..4a9b313cdd6b 100644 --- a/packages/feedback/src/screenshot/components/ScreenshotInput.css.ts +++ b/packages/feedback/src/screenshot/components/ScreenshotInput.css.ts @@ -11,11 +11,17 @@ export function createScreenshotInputStyles(styleNonce?: string): HTMLStyleEleme style.textContent = ` .editor { + display: flex; + flex-grow: 1; + flex-direction: column; +} +.editor__image-container { padding: 10px; padding-top: 65px; padding-bottom: 65px; - flex-grow: 1; position: relative; + height: 100%; + border-radius: var(--menu-border-radius, 6px); background-color: ${surface200}; background-image: repeating-linear-gradient( @@ -34,6 +40,13 @@ export function createScreenshotInputStyles(styleNonce?: string): HTMLStyleEleme ); } +.editor__annotation { + z-index: 1; +} +.editor__annotation--active { + z-index: 2; +} + .editor__canvas-container { width: 100%; height: 100%; @@ -49,7 +62,15 @@ export function createScreenshotInputStyles(styleNonce?: string): HTMLStyleEleme } .editor__crop-container { + custor: auto; position: absolute; + z-index: 2; +} +.editor__crop-container--inactive { + z-index: 1; +} +.editor__crop-container--move { + cursor: move; } .editor__crop-btn-group { @@ -59,6 +80,10 @@ export function createScreenshotInputStyles(styleNonce?: string): HTMLStyleEleme background: var(--button-background, var(--background)); width: 175px; position: absolute; + display: none; +} +.editor__crop-btn-group--active { + display: flex; } .editor__crop-corner { @@ -90,17 +115,28 @@ export function createScreenshotInputStyles(styleNonce?: string): HTMLStyleEleme border-top: none; } .editor__tool-container { - position: absolute; - padding: 10px 0px; - top: 0; + padding-top: 8px; + display: flex; + justify-content: space-between; } -.editor__pen-tool { - height: 30px; +.editor__tool-bar { display: flex; + gap: 8px; +} +.editor__tool { + display: flex; + padding: 8px 12px; justify-content: center; align-items: center; border: var(--button-border, var(--border)); border-radius: var(--button-border-radius, 6px); + background: var(--button-background, var(--background)); + color: var(--button-foreground, var(--foreground)); +} + +.editor__tool--active { + background: var(--button-primary-background, var(--accent-background)); + color: var(--button-primary-foreground, var(--accent-foreground)); } `;