diff --git a/frontend/public/locales/en-GB/translation.toml b/frontend/public/locales/en-GB/translation.toml
index 4f81d64a3..5d9f08467 100644
--- a/frontend/public/locales/en-GB/translation.toml
+++ b/frontend/public/locales/en-GB/translation.toml
@@ -736,6 +736,11 @@ tags = "signature,autograph"
title = "Sign"
desc = "Adds signature to PDF by drawing, text or image"
+[home.annotate]
+tags = "annotate,highlight,draw"
+title = "Annotate"
+desc = "Highlight, draw, add notes and shapes in the viewer"
+
[home.flatten]
tags = "simplify,remove,interactive"
title = "Flatten"
@@ -4013,23 +4018,92 @@ deleteSelected = "Delete Selected Pages"
closePdf = "Close PDF"
exportAll = "Export PDF"
downloadSelected = "Download Selected Files"
-downloadAll = "Download All"
-saveAll = "Save All"
+annotations = "Annotations"
+exportSelected = "Export Selected Pages"
+saveChanges = "Save Changes"
toggleTheme = "Toggle Theme"
-toggleBookmarks = "Toggle Bookmarks"
language = "Language"
+toggleAnnotations = "Toggle Annotations Visibility"
search = "Search PDF"
panMode = "Pan Mode"
rotateLeft = "Rotate Left"
rotateRight = "Rotate Right"
toggleSidebar = "Toggle Sidebar"
-exportSelected = "Export Selected Pages"
-toggleAnnotations = "Toggle Annotations Visibility"
-annotationMode = "Toggle Annotation Mode"
+toggleBookmarks = "Toggle Bookmarks"
print = "Print PDF"
-draw = "Draw"
-save = "Save"
-saveChanges = "Save Changes"
+downloadAll = "Download All"
+saveAll = "Save All"
+
+[textAlign]
+left = "Left"
+center = "Center"
+right = "Right"
+
+[annotation]
+title = "Annotate"
+desc = "Use highlight, pen, text, and notes. Changes stay liveāno flattening required."
+highlight = "Highlight"
+pen = "Pen"
+text = "Text box"
+note = "Note"
+rectangle = "Rectangle"
+ellipse = "Ellipse"
+select = "Select"
+exit = "Exit annotation mode"
+strokeWidth = "Width"
+opacity = "Opacity"
+strokeOpacity = "Stroke Opacity"
+fillOpacity = "Fill Opacity"
+fontSize = "Font size"
+chooseColor = "Choose colour"
+color = "Colour"
+strokeColor = "Stroke Colour"
+fillColor = "Fill Colour"
+underline = "Underline"
+strikeout = "Strikeout"
+squiggly = "Squiggly"
+inkHighlighter = "Freehand Highlighter"
+freehandHighlighter = "Freehand Highlighter"
+square = "Square"
+circle = "Circle"
+polygon = "Polygon"
+line = "Line"
+stamp = "Add Image"
+textMarkup = "Text Markup"
+drawing = "Drawing"
+shapes = "Shapes"
+notesStamps = "Notes & Stamps"
+settings = "Settings"
+borderOn = "Border: On"
+borderOff = "Border: Off"
+editInk = "Edit Pen"
+editLine = "Edit Line"
+editNote = "Edit Note"
+editText = "Edit Text Box"
+editTextMarkup = "Edit Text Markup"
+editSelected = "Edit Annotation"
+editSquare = "Edit Square"
+editCircle = "Edit Circle"
+editPolygon = "Edit Polygon"
+unsupportedType = "This annotation type is not fully supported for editing."
+textAlignment = "Text Alignment"
+noteIcon = "Note Icon"
+imagePreview = "Preview"
+contents = "Text"
+backgroundColor = "Background colour"
+clearBackground = "Remove background"
+noBackground = "No background"
+stampSettings = "Stamp Settings"
+savingCopy = "Preparing download..."
+saveFailed = "Unable to save copy"
+saveReady = "Download ready"
+selectAndMove = "Select and Edit"
+editSelectDescription = "Click an existing annotation to edit its colour, opacity, text, or size."
+editStampHint = "To change the image, delete this stamp and add a new one."
+editSwitchToSelect = "Switch to Select & Edit to edit this annotation."
+undo = "Undo"
+redo = "Redo"
+applyChanges = "Apply Changes"
[search]
title = "Search PDF"
diff --git a/frontend/src/core/components/AppProviders.tsx b/frontend/src/core/components/AppProviders.tsx
index 5fa8d7cb9..f40bd7954 100644
--- a/frontend/src/core/components/AppProviders.tsx
+++ b/frontend/src/core/components/AppProviders.tsx
@@ -12,6 +12,7 @@ import { AppConfigProvider, AppConfigProviderProps, AppConfigRetryOptions } from
import { RightRailProvider } from "@app/contexts/RightRailContext";
import { ViewerProvider } from "@app/contexts/ViewerContext";
import { SignatureProvider } from "@app/contexts/SignatureContext";
+import { AnnotationProvider } from "@app/contexts/AnnotationContext";
import { TourOrchestrationProvider } from "@app/contexts/TourOrchestrationContext";
import { AdminTourOrchestrationProvider } from "@app/contexts/AdminTourOrchestrationContext";
import { PageEditorProvider } from "@app/contexts/PageEditorContext";
@@ -95,13 +96,15 @@ export function AppProviders({ children, appConfigRetryOptions, appConfigProvide
-
-
-
- {children}
-
-
-
+
+
+
+
+ {children}
+
+
+
+
diff --git a/frontend/src/core/components/annotation/shared/ColorPicker.tsx b/frontend/src/core/components/annotation/shared/ColorPicker.tsx
index 04ae501bb..21656b1f2 100644
--- a/frontend/src/core/components/annotation/shared/ColorPicker.tsx
+++ b/frontend/src/core/components/annotation/shared/ColorPicker.tsx
@@ -1,5 +1,5 @@
import React from 'react';
-import { Modal, Stack, ColorPicker as MantineColorPicker, Group, Button, ColorSwatch } from '@mantine/core';
+import { Modal, Stack, ColorPicker as MantineColorPicker, Group, Button, ColorSwatch, Slider, Text } from '@mantine/core';
import { useTranslation } from 'react-i18next';
interface ColorPickerProps {
@@ -8,6 +8,10 @@ interface ColorPickerProps {
selectedColor: string;
onColorChange: (color: string) => void;
title?: string;
+ opacity?: number;
+ onOpacityChange?: (opacity: number) => void;
+ showOpacity?: boolean;
+ opacityLabel?: string;
}
export const ColorPicker: React.FC = ({
@@ -15,10 +19,15 @@ export const ColorPicker: React.FC = ({
onClose,
selectedColor,
onColorChange,
- title
+ title,
+ opacity,
+ onOpacityChange,
+ showOpacity = false,
+ opacityLabel,
}) => {
const { t } = useTranslation();
const resolvedTitle = title ?? t('colorPicker.title', 'Choose colour');
+ const resolvedOpacityLabel = opacityLabel ?? t('annotation.opacity', 'Opacity');
return (
= ({
size="lg"
fullWidth
/>
+ {showOpacity && onOpacityChange && opacity !== undefined && (
+
+ {resolvedOpacityLabel}
+
+
+ )}