From 85d88e59f314e8341c0f5f569e5224e270e110b0 Mon Sep 17 00:00:00 2001 From: Calixte Denizet Date: Wed, 18 Mar 2026 16:53:08 +0100 Subject: [PATCH] Add a new badge close to the Manage button in the sidebar. --- l10n/en-US/viewer.ftl | 4 ++++ web/app.js | 1 + web/app_options.js | 5 +++++ web/pdf_thumbnail_viewer.js | 11 +++++++++++ web/pdf_viewer.css | 22 ++++++++++++++++++++++ 5 files changed, 43 insertions(+) diff --git a/l10n/en-US/viewer.ftl b/l10n/en-US/viewer.ftl index d86048686..c281f1d10 100644 --- a/l10n/en-US/viewer.ftl +++ b/l10n/en-US/viewer.ftl @@ -779,3 +779,7 @@ pdfjs-views-manager-paste-button-before = # $page (Number) - the page number after which the paste button is. pdfjs-views-manager-paste-button-after = .title = Paste after page { $page } + +# Badge used to promote a new feature in the UI, keep it as short as possible. +# It's spelled uppercase for English, but it can be translated as usual. +pdfjs-new-badge-content = NEW diff --git a/web/app.js b/web/app.js index 211dc0ab6..81f677963 100644 --- a/web/app.js +++ b/web/app.js @@ -600,6 +600,7 @@ const PDFViewerApplication = { pageColors, abortSignal, enableSplitMerge, + enableNewBadge: AppOptions.get("enableNewBadge"), statusBar: viewsManager.viewsManagerStatusBar, undoBar: viewsManager.viewsManagerUndoBar, manageMenu: viewsManager.manageMenu, diff --git a/web/app_options.js b/web/app_options.js index 63278d0da..181b06eec 100644 --- a/web/app_options.js +++ b/web/app_options.js @@ -250,6 +250,11 @@ const defaultOptions = { value: true, kind: OptionKind.VIEWER + OptionKind.PREFERENCE, }, + enableNewBadge: { + /** @type {boolean} */ + value: typeof PDFJSDev === "undefined" || PDFJSDev.test("MOZCENTRAL"), + kind: OptionKind.VIEWER + OptionKind.PREFERENCE, + }, enableOptimizedPartialRendering: { /** @type {boolean} */ value: false, diff --git a/web/pdf_thumbnail_viewer.js b/web/pdf_thumbnail_viewer.js index 3bdf11f8b..a6ea0e65c 100644 --- a/web/pdf_thumbnail_viewer.js +++ b/web/pdf_thumbnail_viewer.js @@ -64,6 +64,8 @@ const SPACE_FOR_DRAG_MARKER_WHEN_NO_NEXT_ELEMENT = 15; * mode. * @property {AbortSignal} [abortSignal] - The AbortSignal for the window * events. + * @property {boolean} [enableNewBadge] - Enables the "new" badge for the split + * and merge features. * @property {boolean} [enableSplitMerge] - Enables split and merge features. * The default value is `false`. * @property {Object} [statusBar] - The status bar elements to manage the status @@ -170,6 +172,7 @@ class PDFThumbnailViewer { pageColors, abortSignal, enableSplitMerge, + enableNewBadge, statusBar, undoBar, manageMenu, @@ -205,6 +208,14 @@ class PDFThumbnailViewer { delete: del, exportSelected, } = manageMenu; + + if (enableNewBadge) { + const newSpan = document.createElement("span"); + newSpan.setAttribute("data-l10n-id", "pdfjs-new-badge-content"); + newSpan.classList.add("newBadge"); + button.parentElement.before(newSpan); + } + this.eventBus.on( "pagesloaded", () => { diff --git a/web/pdf_viewer.css b/web/pdf_viewer.css index fbc9187b6..48e0b857e 100644 --- a/web/pdf_viewer.css +++ b/web/pdf_viewer.css @@ -36,6 +36,9 @@ --loading-icon-delay: 400ms; --focus-ring-color: light-dark(#0060df, #0df); --focus-ring-outline: 2px solid var(--focus-ring-color); + --new-badge-bg: light-dark(#070, #37b847); + --new-badge-color: light-dark(#fff, #15141a); + --new-badge-border-color: light-dark(#fbfbfe / 40%, #15141a / 40%); @media screen and (forced-colors: active) { --pdfViewer-padding-bottom: 9px; @@ -43,9 +46,28 @@ --page-border: 1px solid CanvasText; --spreadHorizontalWrapped-margin-LR: 3.5px; --focus-ring-color: CanvasText; + --new-badge-bg: AccentColor; + --new-badge-color: ButtonFace; + --new-badge-border-color: CanvasText; } } +.newBadge { + background-color: var(--new-badge-bg); + color: var(--new-badge-color); + border-radius: 4px; + border: 1px solid var(--new-badge-border-color); + padding-inline: 4px; + margin-inline: 4px; + font: menu; + font-size: 12px; + font-style: normal; + font-weight: 400; + line-height: normal; + flex: 0 0 fit-content; + user-select: none; +} + [data-main-rotation="90"] { transform: rotate(90deg) translateY(-100%); }