From 220416ce3111546078068726b12c690bb128902f Mon Sep 17 00:00:00 2001 From: Calixte Denizet Date: Mon, 1 Jul 2024 22:37:48 +0200 Subject: [PATCH] Refactor the toolbar html & css to improve its overall accessibility (bug 1171799, bug 1855695) The first goal of this patch was to remove the tabindex because it helps to improve overall a11y. That led to move some html elements associated with the buttons which helped to position these elements relatively to their buttons. Consequently it was easy to change the toolbar height (configurable in Firefox with the pref browser.uidensity): it's the second goal of this patch. For a11y reasons we want to be able to change the height of the toolbar to make the buttons larger. --- test/integration/find_spec.mjs | 2 +- web/annotation_editor_layer_builder.css | 15 +- web/pdf_find_bar.js | 29 - web/toolbar.js | 21 +- web/viewer-geckoview.html | 4 +- web/viewer.css | 1276 +++++++++++++---------- web/viewer.html | 534 +++++----- 7 files changed, 1001 insertions(+), 880 deletions(-) diff --git a/test/integration/find_spec.mjs b/test/integration/find_spec.mjs index 4fca69c5f6412..b73f499aee2cc 100644 --- a/test/integration/find_spec.mjs +++ b/test/integration/find_spec.mjs @@ -43,7 +43,7 @@ describe("find bar", () => { await page.click("#viewFindButton"); await page.waitForSelector("#viewFindButton", { hidden: false }); await page.type("#findInput", "a"); - await page.click("#findHighlightAll"); + await page.click("#findHighlightAll + label"); await page.waitForSelector(".textLayer .highlight"); // The PDF file contains the text 'AB BA' in a monospace font on a diff --git a/web/annotation_editor_layer_builder.css b/web/annotation_editor_layer_builder.css index 8d01e4671821e..22adc6e2d3cdf 100644 --- a/web/annotation_editor_layer_builder.css +++ b/web/annotation_editor_layer_builder.css @@ -1226,18 +1226,9 @@ } #highlightParamsToolbarContainer { - height: auto; - padding-inline: 10px; - padding-block: 10px 16px; gap: 16px; - display: flex; - flex-direction: column; - box-sizing: border-box; - - .editorParamsLabel { - width: fit-content; - inset-inline-start: 0; - } + padding-inline: 10px; + padding-block-end: 12px; .colorPicker { display: flex; @@ -1261,6 +1252,7 @@ align-items: center; background: none; flex: 0 0 auto; + padding: 0; .swatch { width: 24px; @@ -1290,7 +1282,6 @@ align-self: stretch; .editorParamsLabel { - width: 100%; height: auto; align-self: stretch; } diff --git a/web/pdf_find_bar.js b/web/pdf_find_bar.js index 72147799af567..4618da60951d0 100644 --- a/web/pdf_find_bar.js +++ b/web/pdf_find_bar.js @@ -25,8 +25,6 @@ const MATCHES_COUNT_LIMIT = 1000; * is done by PDFFindController. */ class PDFFindBar { - #resizeObserver = new ResizeObserver(this.#resizeObserverCallback.bind(this)); - constructor(options, eventBus) { this.opened = false; @@ -166,13 +164,6 @@ class PDFFindBar { open() { if (!this.opened) { - // Potentially update the findbar layout, row vs column, when: - // - The width of the viewer itself changes. - // - The width of the findbar changes, by toggling the visibility - // (or localization) of find count/status messages. - this.#resizeObserver.observe(this.bar.parentNode); - this.#resizeObserver.observe(this.bar); - this.opened = true; toggleExpandedBtn(this.toggleButton, true, this.bar); } @@ -184,7 +175,6 @@ class PDFFindBar { if (!this.opened) { return; } - this.#resizeObserver.disconnect(); this.opened = false; toggleExpandedBtn(this.toggleButton, false, this.bar); @@ -199,25 +189,6 @@ class PDFFindBar { this.open(); } } - - #resizeObserverCallback(entries) { - const { bar } = this; - // The find bar has an absolute position and thus the browser extends - // its width to the maximum possible width once the find bar does not fit - // entirely within the window anymore (and its elements are automatically - // wrapped). Here we detect and fix that. - bar.classList.remove("wrapContainers"); - - const findbarHeight = bar.clientHeight; - const inputContainerHeight = bar.firstElementChild.clientHeight; - - if (findbarHeight > inputContainerHeight) { - // The findbar is taller than the input container, which means that - // the browser wrapped some of the elements. For a consistent look, - // wrap all of them to adjust the width of the find bar. - bar.classList.add("wrapContainers"); - } - } } export { PDFFindBar }; diff --git a/web/toolbar.js b/web/toolbar.js index bc4994ee09829..539f6038fdbfb 100644 --- a/web/toolbar.js +++ b/web/toolbar.js @@ -21,7 +21,7 @@ import { DEFAULT_SCALE_VALUE, MAX_SCALE, MIN_SCALE, - toggleCheckedBtn, + toggleExpandedBtn, } from "./ui_utils.js"; /** @@ -180,6 +180,9 @@ class Toolbar { for (const { element, eventName, eventDetails, telemetry } of buttons) { element.addEventListener("click", evt => { if (eventName !== null) { + if (evt.target !== element) { + return; + } eventBus.dispatch(eventName, { source: this, ...eventDetails, @@ -270,32 +273,32 @@ class Toolbar { editorStampParamsToolbar, } = this.#opts; - toggleCheckedBtn( + toggleExpandedBtn( editorFreeTextButton, mode === AnnotationEditorType.FREETEXT, editorFreeTextParamsToolbar ); - toggleCheckedBtn( + toggleExpandedBtn( editorHighlightButton, mode === AnnotationEditorType.HIGHLIGHT, editorHighlightParamsToolbar ); - toggleCheckedBtn( + toggleExpandedBtn( editorInkButton, mode === AnnotationEditorType.INK, editorInkParamsToolbar ); - toggleCheckedBtn( + toggleExpandedBtn( editorStampButton, mode === AnnotationEditorType.STAMP, editorStampParamsToolbar ); const isDisable = mode === AnnotationEditorType.DISABLE; - editorFreeTextButton.disabled = isDisable; - editorHighlightButton.disabled = isDisable; - editorInkButton.disabled = isDisable; - editorStampButton.disabled = isDisable; + editorFreeTextButton.toggleAttribute("disabled", isDisable); + editorHighlightButton.toggleAttribute("disabled", isDisable); + editorInkButton.toggleAttribute("disabled", isDisable); + editorStampButton.toggleAttribute("disabled", isDisable); } #updateUIState(resetNumPages = false) { diff --git a/web/viewer-geckoview.html b/web/viewer-geckoview.html index fe3e2583e5651..e80f528fd9016 100644 --- a/web/viewer-geckoview.html +++ b/web/viewer-geckoview.html @@ -93,13 +93,13 @@ - +
-
diff --git a/web/viewer.css b/web/viewer.css index 462e7ac4b43b1..6f06ff762abb0 100644 --- a/web/viewer.css +++ b/web/viewer.css @@ -26,9 +26,15 @@ --sidebar-transition-duration: 200ms; --sidebar-transition-timing-function: ease; + --toolbar-height: 32px; + --toolbar-horizontal-padding: 1px; + --toolbar-vertical-padding: 2px; + --icon-size: 16px; + --toolbar-icon-opacity: 0.7; --doorhanger-icon-opacity: 0.9; --editor-toolbar-base-offset: 105px; + --doorhanger-height: 8px; --main-color: rgb(12 12 13); --body-bg-color: rgb(212 212 215); @@ -213,11 +219,6 @@ } } -* { - padding: 0; - margin: 0; -} - html, body { height: 100%; @@ -225,6 +226,7 @@ body { } body { + margin: 0; background-color: var(--body-bg-color); scrollbar-color: var(--scrollbar-color) var(--scrollbar-bg-color); @@ -270,6 +272,7 @@ body { width: 100%; height: 100%; position: relative; + margin: 0; } #sidebarContainer { @@ -290,6 +293,7 @@ body { #outerContainer:is(.sidebarMoving, .sidebarOpen) #sidebarContainer { visibility: visible; } + #outerContainer.sidebarOpen #sidebarContainer { inset-inline-start: 0; } @@ -298,6 +302,9 @@ body { position: absolute; inset: 0; min-width: 350px; + margin: 0; + display: flex; + flex-direction: column; } #sidebarContent { @@ -315,6 +322,7 @@ body { inset: var(--toolbar-height) 0 0; outline: none; } + #viewerContainer:not(.pdfPresentationMode) { transition-duration: var(--sidebar-transition-duration); transition-timing-function: var(--sidebar-transition-timing-function); @@ -325,18 +333,12 @@ body { transition-property: inset-inline-start; } -.toolbar { - position: relative; - inset-inline: 0; - z-index: 9999; - cursor: default; +#sidebarContainer :is(input, button, select) { font: message-box; } -:is(.toolbar, .editorParamsToolbar, #sidebarContainer) - :is(input, button, select) { - outline: none; - font: message-box; +.toolbar { + z-index: 9999; } #toolbarContainer { @@ -349,6 +351,35 @@ body { background-color: var(--sidebar-toolbar-bg-color); box-shadow: var(--toolbarSidebar-box-shadow); border-bottom: var(--toolbarSidebar-border-bottom); + padding: var(--toolbar-vertical-padding) var(--toolbar-horizontal-padding); + justify-content: space-between; + + #toolbarSidebarLeft { + width: auto; + height: 100%; + + #viewThumbnail::before { + mask-image: var(--toolbarButton-viewThumbnail-icon); + } + + #viewOutline::before { + mask-image: var(--toolbarButton-viewOutline-icon); + transform: scaleX(var(--dir-factor)); + } + + #viewAttachments::before { + mask-image: var(--toolbarButton-viewAttachments-icon); + } + + #viewLayers::before { + mask-image: var(--toolbarButton-viewLayers-icon); + } + } + + #toolbarSidebarRight { + width: auto; + height: 100%; + } } #sidebarResizer { @@ -360,181 +391,16 @@ body { cursor: ew-resize; } -#toolbarContainer, -.editorParamsToolbar { - position: relative; - height: var(--toolbar-height); - background-color: var(--toolbar-bg-color); - box-shadow: var(--toolbar-box-shadow); - border-bottom: var(--toolbar-border-bottom); -} - -#toolbarViewer { - height: var(--toolbar-height); -} - -#loadingBar { - /* Define these variables here, and not in :root, to avoid reflowing the - entire viewer when updating progress (see issue 15958). */ - --progressBar-percent: 0%; - --progressBar-end-offset: 0; - - position: absolute; - inset-inline: 0 var(--progressBar-end-offset); - height: 4px; - background-color: var(--progressBar-bg-color); - border-bottom: 1px solid var(--toolbar-border-color); - transition-property: inset-inline-start; - transition-duration: var(--sidebar-transition-duration); - transition-timing-function: var(--sidebar-transition-timing-function); -} - #outerContainer.sidebarOpen #loadingBar { inset-inline-start: var(--sidebar-width); } -#loadingBar .progress { - position: absolute; - top: 0; - inset-inline-start: 0; - width: 100%; - transform: scaleX(var(--progressBar-percent)); - transform-origin: calc(50% - 50% * var(--dir-factor)) 0; - height: 100%; - background-color: var(--progressBar-color); - overflow: hidden; - transition: transform 200ms; -} - -@keyframes progressIndeterminate { - 0% { - transform: translateX(calc(-142px * var(--dir-factor))); - } - 100% { - transform: translateX(0); - } -} - -#loadingBar.indeterminate .progress { - transform: none; - background-color: var(--progressBar-bg-color); - transition: none; -} - -#loadingBar.indeterminate .progress .glimmer { - position: absolute; - top: 0; - inset-inline-start: 0; - height: 100%; - width: calc(100% + 150px); - background: repeating-linear-gradient( - 135deg, - var(--progressBar-blend-color) 0, - var(--progressBar-bg-color) 5px, - var(--progressBar-bg-color) 45px, - var(--progressBar-color) 55px, - var(--progressBar-color) 95px, - var(--progressBar-blend-color) 100px - ); - animation: progressIndeterminate 1s linear infinite; -} - #outerContainer.sidebarResizing :is(#sidebarContainer, #viewerContainer, #loadingBar) { /* Improve responsiveness and avoid visual glitches when the sidebar is resized. */ transition-duration: 0s; } -.editorParamsToolbar { - background-color: var(--doorhanger-bg-color); - top: var(--toolbar-height); - position: absolute; - z-index: 30000; - height: auto; - inset-inline-end: 4px; - padding: 6px 0 10px; - margin: 4px 2px; - font: message-box; - font-size: 12px; - line-height: 14px; - text-align: left; - cursor: default; -} - -.editorParamsToolbarContainer { - width: 220px; - margin-bottom: -4px; -} - -.editorParamsToolbarContainer > .editorParamsSetter { - min-height: 26px; - display: flex; - align-items: center; - justify-content: space-between; - padding-inline: 10px; -} - -.editorParamsToolbarContainer .editorParamsLabel { - padding-inline-end: 10px; - flex: none; - font: menu; - font-size: 13px; - font-style: normal; - font-weight: 400; - line-height: 150%; - color: var(--main-color); -} - -.editorParamsToolbarContainer .editorParamsColor { - width: 32px; - height: 32px; - flex: none; -} - -.editorParamsToolbarContainer .editorParamsSlider { - background-color: transparent; - width: 90px; - flex: 0 1 0; -} - -.editorParamsToolbarContainer .editorParamsSlider::-moz-range-progress { - background-color: black; -} - -/*#if !MOZCENTRAL*/ -.editorParamsToolbarContainer .editorParamsSlider::-webkit-slider-runnable-track, -/*#endif*/ -.editorParamsToolbarContainer .editorParamsSlider::-moz-range-track { - background-color: black; -} - -/*#if !MOZCENTRAL*/ -.editorParamsToolbarContainer .editorParamsSlider::-webkit-slider-thumb, -/*#endif*/ -.editorParamsToolbarContainer .editorParamsSlider::-moz-range-thumb { - background-color: white; -} - -#editorStampParamsToolbar { - inset-inline-end: calc(var(--editor-toolbar-base-offset) + 0px); -} - -#editorInkParamsToolbar { - inset-inline-end: calc(var(--editor-toolbar-base-offset) + 28px); -} - -#editorFreeTextParamsToolbar { - inset-inline-end: calc(var(--editor-toolbar-base-offset) + 56px); -} - -#editorHighlightParamsToolbar { - inset-inline-end: calc(var(--editor-toolbar-base-offset) + 84px); -} - -#editorStampAddImage::before { - mask-image: var(--editorParams-stampAddImage-icon); -} - .doorHanger, .doorHangerRight { border-radius: 2px; @@ -542,71 +408,62 @@ body { 0 1px 5px var(--doorhanger-border-color), 0 0 0 1px var(--doorhanger-border-color); border: var(--doorhanger-border-color-whcm); -} -:is(.doorHanger, .doorHangerRight)::after, -:is(.doorHanger, .doorHangerRight)::before { - bottom: 100%; - border: 8px solid rgb(0 0 0 / 0); - content: " "; - height: 0; - width: 0; - position: absolute; - pointer-events: none; - opacity: var(--doorhanger-triangle-opacity-whcm); -} -.doorHanger::after { - inset-inline-start: 10px; - margin-inline-start: -8px; - border-bottom-color: var(--toolbar-bg-color); -} -.doorHangerRight::after { - inset-inline-end: 10px; - margin-inline-end: -8px; - border-bottom-color: var(--doorhanger-bg-color); -} -:is(.doorHanger, .doorHangerRight)::before { - border-bottom-color: var(--doorhanger-border-color); - border-width: 9px; -} -.doorHanger::before { - inset-inline-start: 10px; - margin-inline-start: -9px; -} -.doorHangerRight::before { - inset-inline-end: 10px; - margin-inline-end: -9px; -} + background-color: var(--doorhanger-bg-color); -#toolbarViewerMiddle { - position: absolute; - left: 50%; - transform: translateX(-50%); + &::after, + &::before { + bottom: 100%; + border: var(--doorhanger-height) solid rgb(0 0 0 / 0); + content: ""; + height: 0; + width: 0; + position: absolute; + pointer-events: none; + opacity: var(--doorhanger-triangle-opacity-whcm); + } + + &::before { + border-bottom-color: var(--doorhanger-border-color); + border-width: calc(var(--doorhanger-height) + 1px); + } } -#toolbarViewerLeft, -#toolbarSidebarLeft { - float: var(--inline-start); +.doorHangerRight { + inset-inline-end: calc(50% - var(--doorhanger-height)); + inset-block-start: calc(100% + var(--doorhanger-height)); + + &::before, + &::after { + inset-inline-end: calc(var(--doorhanger-height) + 2px); + margin-inline-end: calc(-1px - var(--doorhanger-height)); + } + + &::after { + border-bottom-color: var(--doorhanger-bg-color); + } } -#toolbarViewerRight, -#toolbarSidebarRight { - float: var(--inline-end); + +.doorHanger { + inset-inline-start: calc(50% - var(--doorhanger-height)); + inset-block-start: calc(100% + var(--doorhanger-height)); + + &::before, + &::after { + inset-inline-start: calc(var(--doorhanger-height) + 2px); + margin-inline-start: calc(-1 * var(--doorhanger-height)); + } + + &::after { + border-bottom-color: var(--toolbar-bg-color); + } } -#toolbarViewerLeft > *, -#toolbarViewerMiddle > *, -#toolbarViewerRight > *, #toolbarSidebarLeft *, #toolbarSidebarRight * { position: relative; float: var(--inline-start); } -#toolbarViewerLeft { - padding-inline-start: 1px; -} -#toolbarViewerRight { - padding-inline-end: 1px; -} #toolbarSidebarRight { padding-inline-end: 2px; } @@ -615,11 +472,7 @@ body { margin: 2px; display: inline-block; } -.splitToolbarButton > .toolbarButton { - float: var(--inline-start); -} -.toolbarButton, .dialogButton { border: none; background: none; @@ -636,39 +489,13 @@ body { color: var(--dialog-button-hover-color); } -.toolbarButton > span { - display: inline-block; - width: 0; - height: 0; - overflow: hidden; -} - -:is(.toolbarButton, .dialogButton)[disabled] { - opacity: 0.5; -} - -.splitToolbarButton > .toolbarButton:is(:hover, :focus-visible), -.dropdownToolbarButton:hover { - background-color: var(--button-hover-color); -} -.splitToolbarButton > .toolbarButton { - position: relative; - margin: 0; -} -#toolbarSidebar .splitToolbarButton > .toolbarButton { - margin-inline-end: 2px; -} - .splitToolbarButtonSeparator { float: var(--inline-start); - margin: 4px 0; width: 1px; - height: 20px; + height: 62%; background-color: var(--separator-color); } -.toolbarButton, -.dropdownToolbarButton, .dialogButton { min-width: 16px; margin: 2px 1px; @@ -683,75 +510,7 @@ body { box-sizing: border-box; } -.toolbarButton:is(:hover, :focus-visible) { - background-color: var(--button-hover-color); -} - -.toolbarButton.toggled, -.splitToolbarButton.toggled > .toolbarButton.toggled { - background-color: var(--toggled-btn-bg-color); - color: var(--toggled-btn-color); -} - -.toolbarButton.toggled:hover, -.splitToolbarButton.toggled > .toolbarButton.toggled:hover { - outline: var(--toggled-hover-btn-outline) !important; -} - -.toolbarButton.toggled::before { - background-color: var(--toggled-btn-color); -} - -.toolbarButton.toggled:hover:active, -.splitToolbarButton.toggled > .toolbarButton.toggled:hover:active { - background-color: var(--toggled-hover-active-btn-color); -} - -.dropdownToolbarButton { - display: flex; - width: fit-content; - min-width: 140px; - padding: 0; - background-color: var(--dropdown-btn-bg-color); - border: var(--dropdown-btn-border); -} -.dropdownToolbarButton::after { - top: 6px; - inset-inline-end: 6px; - pointer-events: none; - mask-image: var(--toolbarButton-menuArrow-icon); -} - -.dropdownToolbarButton > select { - appearance: none; - width: inherit; - min-width: inherit; - height: 28px; - font-size: 12px; - color: var(--main-color); - margin: 0; - padding-block: 1px 2px; - padding-inline: 6px 38px; - border: none; - background-color: var(--dropdown-btn-bg-color); -} -.dropdownToolbarButton > select:is(:hover, :focus-visible) { - background-color: var(--button-hover-color); - color: var(--toggled-btn-color); -} -.dropdownToolbarButton > select > option { - background: var(--doorhanger-bg-color); - color: var(--main-color); -} - -.toolbarButtonSpacer { - width: 30px; - display: inline-block; - height: 1px; -} - -:is(.toolbarButton, .treeItemToggler)::before, -.dropdownToolbarButton::after { +.treeItemToggler::before { /* All matching images have a size of 16x16 * All relevant containers have a size of 28x28 */ position: absolute; @@ -764,20 +523,6 @@ body { mask-size: cover; } -.dropdownToolbarButton:is(:hover, :focus-visible, :active)::after { - background-color: var(--toolbar-icon-hover-bg-color); -} - -.toolbarButton::before { - opacity: var(--toolbar-icon-opacity); - top: 6px; - left: 6px; -} - -.toolbarButton:is(:hover, :focus-visible)::before { - background-color: var(--toolbar-icon-hover-bg-color); -} - #sidebarToggleButton::before { mask-image: var(--toolbarButton-sidebarToggle-icon); transform: scaleX(var(--dir-factor)); @@ -804,6 +549,10 @@ body { mask-image: var(--toolbarButton-zoomIn-icon); } +#presentationMode::before { + mask-image: var(--toolbarButton-presentationMode-icon); +} + #editorFreeTextButton::before { mask-image: var(--toolbarButton-editorFreeText-icon); } @@ -820,29 +569,23 @@ body { mask-image: var(--toolbarButton-editorStamp-icon); } -#printButton::before { +:is(#printButton, #secondaryPrint)::before { mask-image: var(--toolbarButton-print-icon); } -#downloadButton::before { - mask-image: var(--toolbarButton-download-icon); -} - -#viewThumbnail::before { - mask-image: var(--toolbarButton-viewThumbnail-icon); +/*#if GENERIC*/ +#secondaryOpenFile::before { + mask-image: var(--toolbarButton-openFile-icon); } -#viewOutline::before { - mask-image: var(--toolbarButton-viewOutline-icon); - transform: scaleX(var(--dir-factor)); -} +/*#endif*/ -#viewAttachments::before { - mask-image: var(--toolbarButton-viewAttachments-icon); +:is(#downloadButton, #secondaryDownload)::before { + mask-image: var(--toolbarButton-download-icon); } -#viewLayers::before { - mask-image: var(--toolbarButton-viewLayers-icon); +#viewBookmark::before { + mask-image: var(--toolbarButton-bookmark-icon); } #currentOutlineItem::before { @@ -869,11 +612,13 @@ body { .verticalToolbarSeparator { display: block; - margin: 5px 2px; width: 1px; - height: 22px; + height: 80%; + margin-inline: 2px; background-color: var(--separator-color); + box-sizing: border-box; } + .horizontalToolbarSeparator { display: block; margin: 6px 0; @@ -882,6 +627,29 @@ body { background-color: var(--doorhanger-separator-color); } +.toggleButton { + display: inline; + + &:is(:hover, :has(> input:focus-visible)) { + color: var(--toggled-btn-color); + background-color: var(--button-hover-color); + } + + &:has(> input:checked) { + color: var(--toggled-btn-color); + background-color: var(--toggled-btn-bg-color); + } + + & > input { + position: absolute; + top: 50%; + left: 50%; + opacity: 0; + width: 0; + height: 0; + } +} + .toolbarField { padding: 4px 7px; margin: 3px 0; @@ -894,14 +662,10 @@ body { font-size: 12px; line-height: 16px; outline: none; -} -.toolbarField[type="checkbox"] { - opacity: 0; - position: absolute !important; - left: 0; - margin: 10px 0 3px; - margin-inline-start: 7px; + &:focus { + border-color: #0a84ff; + } } #pageNumber { @@ -915,10 +679,11 @@ body { &::-webkit-inner-spin-button { -webkit-appearance: none; } + /*#endif*/ .loadingInput:has(> &.loading)::after { - display: block; + display: inline; visibility: visible; transition-property: visibility; @@ -927,13 +692,14 @@ body { } .loadingInput { + position: relative; + &::after { position: absolute; visibility: hidden; display: none; - top: calc(50% - 8px); - width: 16px; - height: 16px; + width: var(--icon-size); + height: var(--icon-size); content: ""; background-color: var(--toolbar-icon-bg-color); @@ -944,32 +710,12 @@ body { &.start::after { inset-inline-start: 4px; } + &.end::after { inset-inline-end: 4px; } } -.toolbarField:focus { - border-color: #0a84ff; -} - -.toolbarLabel { - min-width: 16px; - padding: 7px; - margin: 2px; - border-radius: 2px; - color: var(--main-color); - font-size: 12px; - line-height: 14px; - text-align: left; - user-select: none; - cursor: default; -} - -#numPages.toolbarLabel { - padding-inline-start: 3px; -} - #thumbnailView, #outlineView, #attachmentsView, @@ -981,6 +727,7 @@ body { overflow: auto; user-select: none; } + #thumbnailView { width: calc(100% - 60px); padding: 10px 30px 0; @@ -1013,6 +760,7 @@ a:focus > .thumbnail, .thumbnail:hover { border-color: var(--thumbnail-hover-color); } + .thumbnail.selected { border-color: var(--thumbnail-selected-color) !important; } @@ -1022,10 +770,12 @@ a:focus > .thumbnail, height: var(--thumbnail-height); opacity: 0.9; } + a:focus > .thumbnail > .thumbnailImage, .thumbnail:hover > .thumbnailImage { opacity: 0.95; } + .thumbnail.selected > .thumbnailImage { opacity: 1 !important; } @@ -1062,9 +812,11 @@ a:focus > .thumbnail > .thumbnailImage, #layersView .treeItem > a * { cursor: pointer; } + #layersView .treeItem > a > label { padding-inline-start: 4px; } + #layersView .treeItem > a > label > input { float: var(--inline-start); margin-top: 1px; @@ -1077,14 +829,17 @@ a:focus > .thumbnail > .thumbnailImage, width: 0; color: rgb(255 255 255 / 0.5); } + .treeItemToggler::before { inset-inline-end: 4px; mask-image: var(--treeitem-expanded-icon); } + .treeItemToggler.treeItemsHidden::before { mask-image: var(--treeitem-collapsed-icon); transform: scaleX(var(--dir-factor)); } + .treeItemToggler.treeItemsHidden ~ .treeItems { display: none; } @@ -1134,6 +889,7 @@ dialog { border-radius: 4px; box-shadow: 0 1px 4px rgb(0 0 0 / 0.3); } + dialog::backdrop { background-color: rgb(0 0 0 / 0.2); } @@ -1170,6 +926,7 @@ dialog :link { #passwordDialog { text-align: center; } + #passwordDialog .toolbarField { width: 200px; } @@ -1177,18 +934,22 @@ dialog :link { #documentPropertiesDialog { text-align: left; } + #documentPropertiesDialog .row > * { min-width: 100px; text-align: start; } + #documentPropertiesDialog .row > span { width: 125px; word-wrap: break-word; } + #documentPropertiesDialog .row > p { max-width: 225px; word-wrap: break-word; } + #documentPropertiesDialog .buttonRow { margin-top: 10px; } @@ -1196,14 +957,17 @@ dialog :link { .grab-to-pan-grab { cursor: grab !important; } + .grab-to-pan-grab *:not(input):not(textarea):not(button):not(select):not(:link) { cursor: inherit !important; } + .grab-to-pan-grab:active, .grab-to-pan-grabbing { cursor: grabbing !important; } + .grab-to-pan-grabbing { position: fixed; background: rgb(0 0 0 / 0); @@ -1213,76 +977,16 @@ dialog :link { z-index: 50000; /* should be higher than anything else in PDF.js! */ } -.toolbarButton { - &.labeled { - border-radius: 0; - display: inline-block; - height: auto; - margin: 0; - padding: 0 0 1px; - padding-inline-start: 36px; - position: relative; - min-height: 26px; - min-width: 100%; - text-align: start; - white-space: normal; - width: auto; - - &:is(a) { - padding-top: 5px; - text-decoration: none; - - &[href="#"] { - opacity: 0.5; - pointer-events: none; - } - } - - &::before { - inset-inline-start: 12px; - opacity: var(--doorhanger-icon-opacity); - top: 5px; - } - - &:not(.toggled):is(:hover, :focus-visible) { - background-color: var(--doorhanger-hover-bg-color); - color: var(--doorhanger-hover-color); - } - - > span { - display: unset; - padding-inline-end: 4px; - } - } -} - #secondaryToolbar { - background-color: var(--doorhanger-bg-color); - cursor: default; - font: message-box; - font-size: 12px; height: auto; - inset-inline-end: 4px; - line-height: 14px; - margin: 4px 2px; - padding: 6px 0 10px; + width: 220px; position: absolute; - text-align: left; - top: var(--toolbar-height); z-index: 30000; - - :is(button, a) { - font: message-box; - outline: none; - } + cursor: default; + min-height: 26px; + max-height: calc(var(--viewer-container-height) - 40px); #secondaryToolbarButtonContainer { - margin-bottom: -4px; - max-height: calc(var(--viewer-container-height) - 40px); - max-width: 220px; - min-height: 26px; - overflow-y: auto; - /*#if GENERIC*/ #secondaryOpenFile::before { mask-image: var(--toolbarButton-openFile-icon); @@ -1367,201 +1071,628 @@ dialog :link { } } -#findbar { - background-color: var(--toolbar-bg-color); - cursor: default; - font: message-box; +@page { + margin: 0; +} + +#printContainer { + display: none; +} + +@media print { + body { + background: rgb(0 0 0 / 0) none; + } + + body[data-pdfjsprinting] #outerContainer { + display: none; + } + + body[data-pdfjsprinting] #printContainer { + display: block; + } + + #printContainer { + height: 100%; + } + + /* wrapper around (scaled) print canvas elements */ + #printContainer > .printedPage { + page-break-after: always; + page-break-inside: avoid; + + /* The wrapper always cover the whole page. */ + height: 100%; + width: 100%; + + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + } + + #printContainer > .xfaPrintedPage .xfaPage { + position: absolute; + } + + #printContainer > .xfaPrintedPage { + page-break-after: always; + page-break-inside: avoid; + width: 100%; + height: 100%; + position: relative; + } + + #printContainer > .printedPage :is(canvas, img) { + /* The intrinsic canvas / image size will make sure that we fit the page. */ + max-width: 100%; + max-height: 100%; + + direction: ltr; + display: block; + } +} + +.visibleMediumView { + display: none !important; +} + +.toolbarLabel { + min-width: 16px; + height: 100%; + padding-inline: 4px; + margin: 2px; + border-radius: 2px; + color: var(--main-color); font-size: 12px; - height: auto; - inset-inline-start: 64px; line-height: 14px; - margin: 4px 2px; - min-width: 300px; - padding: 0 4px; - position: absolute; text-align: left; - top: var(--toolbar-height); - z-index: 30000; + user-select: none; + cursor: default; + box-sizing: border-box; - * { - float: var(--inline-start); - position: relative; + display: inline flex; + flex-direction: column; + align-items: center; + justify-content: center; + + > label { + width: 100%; } +} - > div { - height: var(--toolbar-height); +a.toolbarButton { + text-decoration: none; + + &[href="#"] { + opacity: 0.5; + pointer-events: none; } +} - :is(button, input) { - font: message-box; - outline: none; +.toolbarButton { + height: 100%; + aspect-ratio: 1; + display: flex; + align-items: center; + justify-content: center; + background: none; + border: none; + color: var(--main-color); + outline: none; + border-radius: 2px; + box-sizing: border-box; + font: message-box; + flex: none; + position: relative; + + > span { + display: inline-block; + width: 0; + height: 0; + overflow: hidden; } - input { - &[type="checkbox"] { - pointer-events: none; + &::before { + opacity: var(--toolbar-icon-opacity); + display: inline-block; + width: var(--icon-size); + height: var(--icon-size); + content: ""; + background-color: var(--toolbar-icon-bg-color); + mask-size: cover; + mask-position: center; + } + + &.toggled { + background-color: var(--toggled-btn-bg-color); + color: var(--toggled-btn-color); - &:checked + .toolbarLabel { - background-color: var(--toggled-btn-bg-color) !important; - color: var(--toggled-btn-color); + &::before { + background-color: var(--toggled-btn-color); + } + + &:hover { + outline: var(--toggled-hover-btn-outline) !important; + + &:active { + background-color: var(--toggled-hover-active-btn-color); } } } - label { - user-select: none; + &:is(:hover, :focus-visible) { + background-color: var(--button-hover-color); + + &::before { + background-color: var(--toolbar-icon-hover-bg-color); + } } - :is(label:hover, input:focus-visible + label) { - background-color: var(--button-hover-color); - color: var(--toggled-btn-color); + &:is([disabled="disabled"], [disabled]) { + opacity: 0.5; + pointer-events: none; + } + + &.labeled { + width: 100%; + height: var(--menuitem-height); + justify-content: flex-start; + gap: 8px; + padding-inline-start: 12px; + aspect-ratio: unset; + + :is(:hover, :focus-visible) { + background-color: transparent; + color: var(--doorhanger-hover-color); + } + + > span { + display: inline-block; + width: max-content; + height: auto; + } + } +} + +.toolbarButtonWithContainer { + height: 100%; + aspect-ratio: 1; + display: inline-block; + position: relative; + flex: none; + + > .toolbarButton { + width: 100%; + height: 100%; + } + + .menuContainer { + width: 100%; + height: auto; + max-height: calc( + var(--viewer-container-height) - var(--toolbar-height) - + var(--doorhanger-height) + ); + display: flex; + flex-direction: column; + box-sizing: border-box; + padding-block: 5px; + overflow-y: auto; + } + + .editorParamsToolbar { + height: auto; + width: 220px; + position: absolute; + z-index: 30000; + cursor: default; + + #editorStampAddImage::before { + mask-image: var(--editorParams-stampAddImage-icon); + } + + .editorParamsLabel { + flex: none; + font: menu; + font-size: 13px; + font-style: normal; + font-weight: 400; + line-height: 150%; + color: var(--main-color); + width: fit-content; + inset-inline-start: 0; + } + + .editorParamsToolbarContainer { + width: 100%; + height: auto; + display: flex; + flex-direction: column; + box-sizing: border-box; + padding-inline: 10px; + padding-block: 10px; + + > .editorParamsSetter { + min-height: 26px; + display: flex; + align-items: center; + justify-content: space-between; + } + + .editorParamsColor { + width: 32px; + height: 32px; + flex: none; + padding: 0; + } + + .editorParamsSlider { + background-color: transparent; + width: 90px; + flex: 0 1 0; + font: message-box; + + &::-moz-range-progress { + background-color: black; + } + + /*#if !MOZCENTRAL*/ + &::-webkit-slider-runnable-track, + /*#endif*/ + &::-moz-range-track { + background-color: black; + } + + /*#if !MOZCENTRAL*/ + &::-webkit-slider-thumb, + /*#endif*/ + &::-moz-range-thumb { + background-color: white; + } + } + } + } +} + +#secondaryToolbar { + height: auto; + width: 220px; + position: absolute; + z-index: 30000; + cursor: default; + min-height: 26px; + max-height: calc(var(--viewer-container-height) - 40px); +} + +.toolbarHorizontalGroup { + height: 100%; + display: inline flex; + flex-direction: row; + align-items: center; + justify-content: space-between; + gap: 1px; + box-sizing: border-box; +} + +#findbar { + --input-horizontal-padding: 4px; + + width: max-content; + max-width: 80vw; + min-height: var(--toolbar-height); + height: auto; + position: absolute; + z-index: 30000; + cursor: default; + padding: 0; + min-width: 300px; + background-color: var(--toolbar-bg-color); + box-sizing: border-box; + flex-wrap: wrap; + justify-content: flex-start; + + > * { + height: var(--toolbar-height); + padding: 2px; + } + + #findPreviousButton::before { + mask-image: var(--findbarButton-previous-icon); } - #findbarInputContainer { - margin-inline-end: 4px; + #findNextButton::before { + mask-image: var(--findbarButton-next-icon); + } + + #findInputContainer { + margin-inline-start: 2px; #findInput { width: 200px; + padding: 5px var(--input-horizontal-padding); /*#if !MOZCENTRAL*/ &::-webkit-input-placeholder { color: rgb(191 191 191); } - /*#endif*/ + /*#endif*/ &::placeholder { font-style: normal; } .loadingInput:has(> &[data-status="pending"])::after { - display: block; + display: inline; visibility: visible; + inset-inline-end: calc(var(--input-horizontal-padding) + 1px); } &[data-status="notFound"] { background-color: rgb(255 102 102); } } - - #findPreviousButton::before { - mask-image: var(--findbarButton-previous-icon); - } - - #findNextButton::before { - mask-image: var(--findbarButton-next-icon); - } } #findbarMessageContainer { + display: none; + gap: 4px; + #findResultsCount { background-color: rgb(217 217 217); color: rgb(82 82 82); - margin: 5px; - padding: 4px 5px; - text-align: center; + padding-block: 4px; + + &:empty { + display: none; + } + } + + &:has(> :is(#findResultsCount, #findMsg):not(:empty)) { + display: inline-flex; } #findMsg { &[data-status="notFound"] { font-weight: bold; } + + &:empty { + display: none; + } + } + } +} + +.dropdownToolbarButton { + display: inline flex; + flex-direction: row; + align-items: center; + justify-content: center; + position: relative; + + width: fit-content; + min-width: 140px; + padding: 0; + background-color: var(--dropdown-btn-bg-color); + border: var(--dropdown-btn-border); + border-radius: 2px; + color: var(--main-color); + font-size: 12px; + line-height: 14px; + user-select: none; + cursor: default; + box-sizing: border-box; + outline: none; + + &:hover { + background-color: var(--button-hover-color); + } + + > select { + appearance: none; + width: inherit; + min-width: inherit; + height: 28px; + font: message-box; + font-size: 12px; + color: var(--main-color); + margin: 0; + padding-block: 1px 2px; + padding-inline: 6px 38px; + border: none; + outline: none; + background-color: var(--dropdown-btn-bg-color); + + > option { + background: var(--doorhanger-bg-color); + color: var(--main-color); } - *:empty { - display: none; + &:is(:hover, :focus-visible) { + background-color: var(--button-hover-color); + color: var(--toggled-btn-color); } } - &.wrapContainers { - > div { - clear: both; + &::after { + /* All matching images have a size of 16x16 + * All relevant containers have a size of 28x28 */ + position: absolute; + display: inline; + width: var(--icon-size); + height: var(--icon-size); + + content: ""; + background-color: var(--toolbar-icon-bg-color); + mask-size: cover; + + inset-inline-end: 4px; + pointer-events: none; + mask-image: var(--toolbarButton-menuArrow-icon); + } + + &:is(:hover, :focus-visible, :active)::after { + background-color: var(--toolbar-icon-hover-bg-color); + } +} + +#toolbarContainer { + --menuitem-height: calc(var(--toolbar-height) - 6px); + + height: var(--toolbar-height); + padding: var(--toolbar-vertical-padding) var(--toolbar-horizontal-padding); + position: relative; + box-sizing: border-box; + font: message-box; + background-color: var(--toolbar-bg-color); + box-shadow: var(--toolbar-box-shadow); + border-bottom: var(--toolbar-border-bottom); + + #toolbarViewer { + width: 100%; + height: 100%; + justify-content: space-between; + + > * { + flex: none; } - > #findbarMessageContainer { - height: auto; + input { + font: message-box; + } - > * { - clear: both; - } + .toolbarButtonSpacer { + width: 30px; + display: block; + height: 1px; + } + + #toolbarViewerLeft #numPages.toolbarLabel { + padding-inline-start: 3px; + flex: none; } } - @media all and (max-width: 690px) { - & { - inset-inline-start: 34px; + #loadingBar { + /* Define these variables here, and not in :root, to avoid reflowing the + entire viewer when updating progress (see issue 15958). */ + --progressBar-percent: 0%; + --progressBar-end-offset: 0; + + position: absolute; + inset-inline: 0 var(--progressBar-end-offset); + height: 4px; + background-color: var(--progressBar-bg-color); + border-bottom: 1px solid var(--toolbar-border-color); + transition-property: inset-inline-start; + transition-duration: var(--sidebar-transition-duration); + transition-timing-function: var(--sidebar-transition-timing-function); + + .progress { + position: absolute; + top: 0; + inset-inline-start: 0; + width: 100%; + transform: scaleX(var(--progressBar-percent)); + transform-origin: calc(50% - 50% * var(--dir-factor)) 0; + height: 100%; + background-color: var(--progressBar-color); + overflow: hidden; + transition: transform 200ms; + } + + &.indeterminate .progress { + transform: none; + background-color: var(--progressBar-blend-color); + transition: none; + + .glimmer { + @keyframes progressIndeterminate { + 0% { + transform: translateX(calc(-142px * var(--dir-factor))); + } + + 100% { + transform: translateX(0); + } + } + + position: absolute; + top: 0; + inset-inline-start: 0; + height: 100%; + width: calc(100% + 150px); + background: repeating-linear-gradient( + 135deg, + var(--progressBar-blend-color) 0, + var(--progressBar-bg-color) 5px, + var(--progressBar-bg-color) 45px, + var(--progressBar-color) 55px, + var(--progressBar-color) 95px, + var(--progressBar-blend-color) 100px + ); + animation: progressIndeterminate 1s linear infinite; + } } } } -@page { - margin: 0; -} +#secondaryToolbar { + #firstPage::before { + mask-image: var(--secondaryToolbarButton-firstPage-icon); + } -#printContainer { - display: none; -} + #lastPage::before { + mask-image: var(--secondaryToolbarButton-lastPage-icon); + } -@media print { - body { - background: rgb(0 0 0 / 0) none; + #pageRotateCcw::before { + mask-image: var(--secondaryToolbarButton-rotateCcw-icon); } - body[data-pdfjsprinting] #outerContainer { - display: none; + + #pageRotateCw::before { + mask-image: var(--secondaryToolbarButton-rotateCw-icon); } - body[data-pdfjsprinting] #printContainer { - display: block; + + #cursorSelectTool::before { + mask-image: var(--secondaryToolbarButton-selectTool-icon); } - #printContainer { - height: 100%; + + #cursorHandTool::before { + mask-image: var(--secondaryToolbarButton-handTool-icon); } - /* wrapper around (scaled) print canvas elements */ - #printContainer > .printedPage { - page-break-after: always; - page-break-inside: avoid; - /* The wrapper always cover the whole page. */ - height: 100%; - width: 100%; + #scrollPage::before { + mask-image: var(--secondaryToolbarButton-scrollPage-icon); + } - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; + #scrollVertical::before { + mask-image: var(--secondaryToolbarButton-scrollVertical-icon); } - #printContainer > .xfaPrintedPage .xfaPage { - position: absolute; + #scrollHorizontal::before { + mask-image: var(--secondaryToolbarButton-scrollHorizontal-icon); } - #printContainer > .xfaPrintedPage { - page-break-after: always; - page-break-inside: avoid; - width: 100%; - height: 100%; - position: relative; + #scrollWrapped::before { + mask-image: var(--secondaryToolbarButton-scrollWrapped-icon); } - #printContainer > .printedPage :is(canvas, img) { - /* The intrinsic canvas / image size will make sure that we fit the page. */ - max-width: 100%; - max-height: 100%; + #spreadNone::before { + mask-image: var(--secondaryToolbarButton-spreadNone-icon); + } - direction: ltr; - display: block; + #spreadOdd::before { + mask-image: var(--secondaryToolbarButton-spreadOdd-icon); } -} -.visibleMediumView { - display: none !important; -} + #spreadEven::before { + mask-image: var(--secondaryToolbarButton-spreadEven-icon); + } -@media all and (max-width: 900px) { - #toolbarViewerMiddle { - display: table; - margin: auto; - left: auto; - position: inherit; - transform: none; + #documentProperties::before { + mask-image: var(--secondaryToolbarButton-documentProperties-icon); } } @@ -1569,6 +1700,7 @@ dialog :link { #sidebarContainer { background-color: var(--sidebar-narrow-bg-color); } + #outerContainer.sidebarOpen #viewerContainer { inset-inline-start: 0 !important; } @@ -1578,11 +1710,12 @@ dialog :link { :root { --editor-toolbar-base-offset: 40px; } + #outerContainer .hiddenMediumView { display: none !important; } #outerContainer .visibleMediumView:not(.hidden, [hidden]) { - display: inherit !important; + display: inline-block !important; } } @@ -1591,7 +1724,8 @@ dialog :link { .hiddenSmallView * { display: none !important; } - .toolbarButtonSpacer { + + #toolbarContainer #toolbarViewer .toolbarButtonSpacer { width: 0; } } diff --git a/web/viewer.html b/web/viewer.html index 33004b7a2b787..73ebe8da72dcf 100644 --- a/web/viewer.html +++ b/web/viewer.html @@ -93,23 +93,23 @@ - +
-
+
-
- - - -
@@ -119,7 +119,7 @@
-
@@ -139,272 +139,89 @@
- - - - - - - - - - - -
-
-
-
- -
- + +
+
+
-
- - - - -
-
-
- - - - +
+ + + +
- -
- - - - - -
- -
-
-
-
- +
- @@ -421,6 +238,211 @@
+
+
+
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ +
+ +
+ + + +
+ +
+ +
+ + +
+
@@ -644,7 +666,7 @@
- +