diff --git a/l10n/en-US/viewer.ftl b/l10n/en-US/viewer.ftl index a7fdf58ceab7b..b3aed968c52a4 100644 --- a/l10n/en-US/viewer.ftl +++ b/l10n/en-US/viewer.ftl @@ -323,8 +323,17 @@ pdfjs-editor-ink-button-label = Draw pdfjs-editor-stamp-button = .title = Add or edit images pdfjs-editor-stamp-button-label = Add or edit images -pdfjs-editor-remove-button = - .title = Remove + +## Remove button for the various kind of editor. + +pdfjs-editor-remove-ink-button = + .title = Remove drawing +pdfjs-editor-remove-freetext-button = + .title = Remove text +pdfjs-editor-remove-stamp-button = + .title = Remove image + +## # Editor Parameters pdfjs-editor-free-text-color-input = Color diff --git a/src/display/editor/alt_text.js b/src/display/editor/alt_text.js new file mode 100644 index 0000000000000..8981235c557e2 --- /dev/null +++ b/src/display/editor/alt_text.js @@ -0,0 +1,180 @@ +/* Copyright 2023 Mozilla Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { noContextMenu } from "../display_utils.js"; + +class AltText { + #altText = ""; + + #altTextDecorative = false; + + #altTextButton = null; + + #altTextTooltip = null; + + #altTextTooltipTimeout = null; + + #altTextWasFromKeyBoard = false; + + #editor = null; + + static _l10nPromise = null; + + constructor(editor) { + this.#editor = editor; + } + + static initialize(l10nPromise) { + AltText._l10nPromise ||= l10nPromise; + } + + async render() { + const altText = (this.#altTextButton = document.createElement("button")); + altText.className = "altText"; + const msg = await AltText._l10nPromise.get( + "pdfjs-editor-alt-text-button-label" + ); + altText.textContent = msg; + altText.setAttribute("aria-label", msg); + altText.tabIndex = "0"; + altText.addEventListener("contextmenu", noContextMenu); + altText.addEventListener("pointerdown", event => event.stopPropagation()); + + const onClick = event => { + event.preventDefault(); + this.#editor._uiManager.editAltText(this.#editor); + }; + altText.addEventListener("click", onClick, { capture: true }); + altText.addEventListener("keydown", event => { + if (event.target === altText && event.key === "Enter") { + this.#altTextWasFromKeyBoard = true; + onClick(event); + } + }); + await this.#setState(); + + return altText; + } + + finish() { + if (!this.#altTextButton) { + return; + } + this.#altTextButton.focus({ focusVisible: this.#altTextWasFromKeyBoard }); + this.#altTextWasFromKeyBoard = false; + } + + get data() { + return { + altText: this.#altText, + decorative: this.#altTextDecorative, + }; + } + + /** + * Set the alt text data. + */ + set data({ altText, decorative }) { + if (this.#altText === altText && this.#altTextDecorative === decorative) { + return; + } + this.#altText = altText; + this.#altTextDecorative = decorative; + this.#setState(); + } + + toggle(enabled = false) { + if (!this.#altTextButton) { + return; + } + if (!enabled && this.#altTextTooltipTimeout) { + clearTimeout(this.#altTextTooltipTimeout); + this.#altTextTooltipTimeout = null; + } + this.#altTextButton.disabled = !enabled; + } + + destroy() { + this.#altTextButton?.remove(); + this.#altTextButton = null; + this.#altTextTooltip = null; + } + + async #setState() { + const button = this.#altTextButton; + if (!button) { + return; + } + if (!this.#altText && !this.#altTextDecorative) { + button.classList.remove("done"); + this.#altTextTooltip?.remove(); + return; + } + button.classList.add("done"); + + AltText._l10nPromise + .get("pdfjs-editor-alt-text-edit-button-label") + .then(msg => { + button.setAttribute("aria-label", msg); + }); + let tooltip = this.#altTextTooltip; + if (!tooltip) { + this.#altTextTooltip = tooltip = document.createElement("span"); + tooltip.className = "tooltip"; + tooltip.setAttribute("role", "tooltip"); + const id = (tooltip.id = `alt-text-tooltip-${this.#editor.id}`); + button.setAttribute("aria-describedby", id); + + const DELAY_TO_SHOW_TOOLTIP = 100; + button.addEventListener("mouseenter", () => { + this.#altTextTooltipTimeout = setTimeout(() => { + this.#altTextTooltipTimeout = null; + this.#altTextTooltip.classList.add("show"); + this.#editor._uiManager._eventBus.dispatch("reporttelemetry", { + source: this, + details: { + type: "editing", + subtype: this.editorType, + data: { + action: "alt_text_tooltip", + }, + }, + }); + }, DELAY_TO_SHOW_TOOLTIP); + }); + button.addEventListener("mouseleave", () => { + if (this.#altTextTooltipTimeout) { + clearTimeout(this.#altTextTooltipTimeout); + this.#altTextTooltipTimeout = null; + } + this.#altTextTooltip?.classList.remove("show"); + }); + } + tooltip.innerText = this.#altTextDecorative + ? await AltText._l10nPromise.get( + "pdfjs-editor-alt-text-decorative-tooltip" + ) + : this.#altText; + + if (!tooltip.parentNode) { + button.append(tooltip); + } + + const element = this.#editor.getImageForAltText(); + element?.setAttribute("aria-describedby", tooltip.id); + } +} + +export { AltText }; diff --git a/src/display/editor/editor.js b/src/display/editor/editor.js index 5808ee8114d49..a9b6ac4cd7e05 100644 --- a/src/display/editor/editor.js +++ b/src/display/editor/editor.js @@ -23,6 +23,7 @@ import { KeyboardManager, } from "./tools.js"; import { FeatureTest, shadow, unreachable } from "../../shared/util.js"; +import { AltText } from "./alt_text.js"; import { EditorToolbar } from "./toolbar.js"; import { noContextMenu } from "../display_utils.js"; @@ -41,17 +42,7 @@ import { noContextMenu } from "../display_utils.js"; class AnnotationEditor { #allResizerDivs = null; - #altText = ""; - - #altTextDecorative = false; - - #altTextButton = null; - - #altTextTooltip = null; - - #altTextTooltipTimeout = null; - - #altTextWasFromKeyBoard = false; + #altText = null; #keepAspectRatio = false; @@ -95,10 +86,6 @@ class AnnotationEditor { static _zIndex = 1; - // When one of the dimensions of an editor is smaller than this value, the - // button to edit the alt text is visually moved outside of the editor. - static SMALL_EDITOR_SIZE = 0; - static get _resizerKeyboardManager() { const resize = AnnotationEditor.prototype._resizeWithKeyboard; const small = AnnotationEditorUIManager.TRANSLATE_SMALL; @@ -631,11 +618,6 @@ class AnnotationEditor { if (!this.#keepAspectRatio) { this.div.style.height = `${((100 * height) / parentHeight).toFixed(2)}%`; } - this.#altTextButton?.classList.toggle( - "small", - width < AnnotationEditor.SMALL_EDITOR_SIZE || - height < AnnotationEditor.SMALL_EDITOR_SIZE - ); } fixDims() { @@ -709,7 +691,7 @@ class AnnotationEditor { return; } - this.#toggleAltTextButton(false); + this.#altText?.toggle(false); const boundResizerPointermove = this.#resizerPointermove.bind(this, name); const savedDraggable = this._isDraggable; @@ -732,7 +714,7 @@ class AnnotationEditor { const pointerUpCallback = () => { this.parent.togglePointerEvents(true); - this.#toggleAltTextButton(true); + this.#altText?.toggle(true); this._isDraggable = savedDraggable; window.removeEventListener("pointerup", pointerUpCallback); window.removeEventListener("blur", pointerUpCallback); @@ -917,136 +899,19 @@ class AnnotationEditor { this.fixAndSetPosition(); } - async addAltTextButton() { - if (this.#altTextButton) { - return; - } - const altText = (this.#altTextButton = document.createElement("button")); - altText.className = "altText"; - const msg = await AnnotationEditor._l10nPromise.get( - "pdfjs-editor-alt-text-button-label" - ); - altText.textContent = msg; - altText.setAttribute("aria-label", msg); - altText.tabIndex = "0"; - altText.addEventListener("contextmenu", noContextMenu); - altText.addEventListener("pointerdown", event => event.stopPropagation()); - - const onClick = event => { - this.#altTextButton.hidden = true; - event.preventDefault(); - this._uiManager.editAltText(this); - }; - altText.addEventListener("click", onClick, { capture: true }); - altText.addEventListener("keydown", event => { - if (event.target === altText && event.key === "Enter") { - this.#altTextWasFromKeyBoard = true; - onClick(event); - } - }); - this.#setAltTextButtonState(); - this.div.append(altText); - if (!AnnotationEditor.SMALL_EDITOR_SIZE) { - // We take the width of the alt text button and we add 40% to it to be - // sure to have enough space for it. - const PERCENT = 40; - AnnotationEditor.SMALL_EDITOR_SIZE = Math.min( - 128, - Math.round(altText.getBoundingClientRect().width * (1 + PERCENT / 100)) - ); - } - } - - async #setAltTextButtonState() { - const button = this.#altTextButton; - if (!button) { - return; - } - if (!this.#altText && !this.#altTextDecorative) { - button.classList.remove("done"); - this.#altTextTooltip?.remove(); - return; - } - button.classList.add("done"); - - AnnotationEditor._l10nPromise - .get("pdfjs-editor-alt-text-edit-button-label") - .then(msg => { - button.setAttribute("aria-label", msg); - }); - let tooltip = this.#altTextTooltip; - if (!tooltip) { - this.#altTextTooltip = tooltip = document.createElement("span"); - tooltip.className = "tooltip"; - tooltip.setAttribute("role", "tooltip"); - const id = (tooltip.id = `alt-text-tooltip-${this.id}`); - button.setAttribute("aria-describedby", id); - - const DELAY_TO_SHOW_TOOLTIP = 100; - button.addEventListener("mouseenter", () => { - this.#altTextTooltipTimeout = setTimeout(() => { - this.#altTextTooltipTimeout = null; - this.#altTextTooltip.classList.add("show"); - this._uiManager._eventBus.dispatch("reporttelemetry", { - source: this, - details: { - type: "editing", - subtype: this.editorType, - data: { - action: "alt_text_tooltip", - }, - }, - }); - }, DELAY_TO_SHOW_TOOLTIP); - }); - button.addEventListener("mouseleave", () => { - if (this.#altTextTooltipTimeout) { - clearTimeout(this.#altTextTooltipTimeout); - this.#altTextTooltipTimeout = null; - } - this.#altTextTooltip?.classList.remove("show"); - }); - } - tooltip.innerText = this.#altTextDecorative - ? await AnnotationEditor._l10nPromise.get( - "pdfjs-editor-alt-text-decorative-tooltip" - ) - : this.#altText; - - if (!tooltip.parentNode) { - button.append(tooltip); - } - - const element = this.getImageForAltText(); - element?.setAttribute("aria-describedby", tooltip.id); - } - - #toggleAltTextButton(enabled = false) { - if (!this.#altTextButton) { - return; - } - if (!enabled && this.#altTextTooltipTimeout) { - clearTimeout(this.#altTextTooltipTimeout); - this.#altTextTooltipTimeout = null; - } - this.#altTextButton.disabled = !enabled; - } - altTextFinish() { - if (!this.#altTextButton) { - return; - } - this.#altTextButton.hidden = false; - this.#altTextButton.focus({ focusVisible: this.#altTextWasFromKeyBoard }); - this.#altTextWasFromKeyBoard = false; + this.#altText?.finish(); } - addEditToolbar() { + async addEditToolbar() { if (this.#editToolbar || this.#isInEditMode) { return; } this.#editToolbar = new EditorToolbar(this); this.div.append(this.#editToolbar.render()); + if (this.#altText) { + this.#editToolbar.addAltTextButton(await this.#altText.render()); + } } removeEditToolbar() { @@ -1055,29 +920,37 @@ class AnnotationEditor { } this.#editToolbar.remove(); this.#editToolbar = null; + + // We destroy the alt text but we don't null it because we want to be able + // to restore it in case the user undoes the deletion. + this.#altText?.destroy(); } getClientDimensions() { return this.div.getBoundingClientRect(); } + async addAltTextButton() { + if (this.#altText) { + return; + } + AltText.initialize(AnnotationEditor._l10nPromise); + this.#altText = new AltText(this); + await this.addEditToolbar(); + } + get altTextData() { - return { - altText: this.#altText, - decorative: this.#altTextDecorative, - }; + return this.#altText?.data; } /** * Set the alt text data. */ - set altTextData({ altText, decorative }) { - if (this.#altText === altText && this.#altTextDecorative === decorative) { + set altTextData(data) { + if (!this.#altText) { return; } - this.#altText = altText; - this.#altTextDecorative = decorative; - this.#setAltTextButtonState(); + this.#altText.data = data; } /** @@ -1413,11 +1286,6 @@ class AnnotationEditor { this._uiManager.removeEditor(this); } - // The editor is removed so we can remove the alt text button and if it's - // restored then it's up to the subclass to add it back. - this.#altTextButton?.remove(); - this.#altTextButton = null; - this.#altTextTooltip = null; if (this.#moveInDOMTimeout) { clearTimeout(this.#moveInDOMTimeout); this.#moveInDOMTimeout = null; @@ -1585,7 +1453,17 @@ class AnnotationEditor { select() { this.makeResizable(); this.div?.classList.add("selectedEditor"); - this.addEditToolbar(); + if (!this.#editToolbar) { + this.addEditToolbar().then(() => { + if (this.div?.classList.contains("selectedEditor")) { + // The editor can have been unselected while we were waiting for the + // edit toolbar to be created, hence we want to be sure that this + // editor is still selected. + this.#editToolbar?.show(); + } + }); + return; + } this.#editToolbar?.show(); } @@ -1614,21 +1492,13 @@ class AnnotationEditor { * When the user disables the editing mode some editors can change some of * their properties. */ - disableEditing() { - if (this.#altTextButton) { - this.#altTextButton.hidden = true; - } - } + disableEditing() {} /** * When the user enables the editing mode some editors can change some of * their properties. */ - enableEditing() { - if (this.#altTextButton) { - this.#altTextButton.hidden = false; - } - } + enableEditing() {} /** * The editor is about to be edited. diff --git a/src/display/editor/toolbar.js b/src/display/editor/toolbar.js index d78cf70837638..5bb65d44a98fb 100644 --- a/src/display/editor/toolbar.js +++ b/src/display/editor/toolbar.js @@ -95,7 +95,10 @@ class EditorToolbar { const button = document.createElement("button"); button.className = "delete"; button.tabIndex = 0; - button.setAttribute("data-l10n-id", "pdfjs-editor-remove-button"); + button.setAttribute( + "data-l10n-id", + `pdfjs-editor-remove-${this.#editor.editorType}-button` + ); this.#addListenersToElement(button); button.addEventListener("click", e => { this.#editor._uiManager.delete(); @@ -103,6 +106,17 @@ class EditorToolbar { this.#buttons.append(button); } + addAltTextButton(button) { + this.#addListenersToElement(button); + this.#buttons.prepend(button, this.#divider); + } + + get #divider() { + const divider = document.createElement("div"); + divider.className = "divider"; + return divider; + } + remove() { this.#toolbar.remove(); } diff --git a/test/integration/stamp_editor_spec.mjs b/test/integration/stamp_editor_spec.mjs index c98242aa61f10..67fed531458b7 100644 --- a/test/integration/stamp_editor_spec.mjs +++ b/test/integration/stamp_editor_spec.mjs @@ -293,9 +293,6 @@ describe("Stamp Editor", () => { // Click on the alt-text button. await page.click(buttonSelector); - // Check that the alt-text button has been hidden. - await page.waitForSelector(`${buttonSelector}[hidden]`); - // Wait for the alt-text dialog to be visible. await page.waitForSelector("#altTextDialog", { visible: true }); @@ -314,7 +311,7 @@ describe("Stamp Editor", () => { ); // Wait for the alt-text button to have the correct icon. - await page.waitForSelector(`${buttonSelector}:not([hidden]).done`); + await page.waitForSelector(`${buttonSelector}.done`); // Hover the button. await page.hover(buttonSelector); @@ -427,10 +424,8 @@ describe("Stamp Editor", () => { ? page.waitForSelector(`${buttonSelector}:focus`) : page.waitForSelector(`${buttonSelector}:focus-visible`)); await page.keyboard.press("Enter"); - await page.waitForSelector(`${buttonSelector}[hidden]`); await page.waitForSelector("#altTextDialog", { visible: true }); await page.keyboard.press("Escape"); - await page.waitForSelector(`${buttonSelector}:not([hidden])`); await (browserName === "chrome" ? page.waitForSelector(`${buttonSelector}:focus`) : page.waitForSelector(`${buttonSelector}:focus-visible`)); diff --git a/web/annotation_editor_layer_builder.css b/web/annotation_editor_layer_builder.css index 4d39dfe4f7b49..d7554fc14611a 100644 --- a/web/annotation_editor_layer_builder.css +++ b/web/annotation_editor_layer_builder.css @@ -43,22 +43,6 @@ /*#else*/ --editorInk-editing-cursor: url(images/cursor-editorInk.svg) 0 16, pointer; /*#endif*/ - - --alt-text-opacity: 0.8; - --alt-text-add-image: url(images/altText_add.svg); - --alt-text-done-image: url(images/altText_done.svg); - --alt-text-bg-color: rgb(43 42 51 / var(--alt-text-opacity)); - --alt-text-fg-color: #fbfbfe; - --alt-text-border-color: var(--alt-text-bg-color); - --alt-text-hover-bg-color: rgb(82 82 94 / var(--alt-text-opacity)); - --alt-text-hover-fg-color: var(--alt-text-fg-color); - --alt-text-hover-border-color: var(--alt-text-hover-bg-color); - --alt-text-active-bg-color: rgb(91 91 102 / var(--alt-text-opacity)); - --alt-text-active-fg-color: var(--alt-text-fg-color); - --alt-text-active-border-color: var(--alt-text-hover-bg-color); - --alt-text-focus-outline-color: #0060df; - --alt-text-focus-border-color: #f0f0f4; - --alt-text-shadow: 0 2px 6px 0 rgb(28 27 34 / 0.5); } @media (min-resolution: 1.1dppx) { @@ -77,29 +61,17 @@ --resizer-bg-color: ButtonText; --hover-outline-color: Highlight; --hover-outline-around-color: SelectedItemText; - - --alt-text-bg-color: Canvas; - --alt-text-fg-color: ButtonText; - --alt-text-border-color: ButtonText; - --alt-text-hover-bg-color: Canvas; - --alt-text-hover-fg-color: SelectedItem; - --alt-text-hover-border-color: SelectedItem; - --alt-text-active-bg-color: ButtonFace; - --alt-text-active-fg-color: SelectedItem; - --alt-text-active-border-color: ButtonText; - --alt-text-focus-outline-color: CanvasText; - --alt-text-focus-border-color: ButtonText; - --alt-text-shadow: none; - --alt-text-opacity: 1; } } [data-editor-rotation="90"] { transform: rotate(90deg); } + [data-editor-rotation="180"] { transform: rotate(180deg); } + [data-editor-rotation="270"] { transform: rotate(270deg); } @@ -204,11 +176,12 @@ --editor-toolbar-focus-outline-color: #0060df; --editor-toolbar-shadow: 0 2px 6px 0 rgb(58 57 68 / 0.2); --editor-toolbar-vert-offset: 6px; + --editor-toolbar-height: 28px; + --editor-toolbar-padding: 2px; @media (prefers-color-scheme: dark) { --editor-toolbar-bg-color: #2b2a33; --editor-toolbar-fg-color: #fbfbfe; - --editor-toolbar-border-color: #2b2a33; --editor-toolbar-hover-bg-color: #52525e; --editor-toolbar-active-bg-color: #5b5b66; --editor-toolbar-focus-outline-color: #0df; @@ -226,18 +199,20 @@ display: flex; width: fit-content; - height: 28px; + height: var(--editor-toolbar-height); flex-direction: column; justify-content: center; align-items: center; cursor: default; pointer-events: auto; + box-sizing: content-box; + padding: var(--editor-toolbar-padding); position: absolute; inset-inline-end: 0; inset-block-start: calc(100% + var(--editor-toolbar-vert-offset)); - border-radius: 4px; + border-radius: 6px; background-color: var(--editor-toolbar-bg-color); border: 1px solid var(--editor-toolbar-border-color); box-shadow: var(--editor-toolbar-shadow); @@ -250,19 +225,33 @@ border-color: transparent; } + &:dir(ltr) { + transform-origin: 100% 0; + } + + &:dir(rtl) { + transform-origin: 0 0; + } + .buttons { display: flex; - padding: 0 2px; justify-content: center; align-items: center; - gap: 4px; + gap: 0; + height: 100%; + + .divider { + width: 1px; + height: calc( + 2 * var(--editor-toolbar-padding) + var(--editor-toolbar-height) + ); + background-color: var(--editor-toolbar-border-color); + display: inline-block; + margin-inline: 2px; + } .delete { - width: 24px; - height: 24px; - cursor: pointer; - border: none; - background-color: transparent; + width: var(--editor-toolbar-height); &::before { content: ""; @@ -277,6 +266,14 @@ } > * { + height: var(--editor-toolbar-height); + } + + > :not(.divider) { + border: none; + background-color: transparent; + cursor: pointer; + &:hover { border-radius: 2px; background-color: var(--editor-toolbar-hover-bg-color); @@ -288,10 +285,91 @@ } &:focus-visible { - border-radius: 3px; + border-radius: 2px; outline: 2px solid var(--editor-toolbar-focus-outline-color); } } + + .altText { + --alt-text-add-image: url(images/altText_add.svg); + --alt-text-done-image: url(images/altText_done.svg); + + display: flex; + align-items: center; + justify-content: center; + width: max-content; + padding-inline: 8px; + pointer-events: all; + font: menu; + font-weight: 590; + font-size: 12px; + color: var(--editor-toolbar-fg-color); + + &:disabled { + pointer-events: none; + } + + &::before { + content: ""; + mask-image: var(--alt-text-add-image); + mask-repeat: no-repeat; + mask-position: center; + display: inline-block; + width: 12px; + height: 13px; + background-color: var(--editor-toolbar-fg-color); + margin-inline-end: 4px; + } + + &.done::before { + mask-image: var(--alt-text-done-image); + } + + .tooltip { + display: none; + + &.show { + --alt-text-tooltip-bg: #f0f0f4; + --alt-text-tooltip-fg: #15141a; + --alt-text-tooltip-border: #8f8f9d; + --alt-text-tooltip-shadow: 0px 2px 6px 0px rgb(58 57 68 / 0.2); + + @media (prefers-color-scheme: dark) { + --alt-text-tooltip-bg: #1c1b22; + --alt-text-tooltip-fg: #fbfbfe; + --alt-text-tooltip-shadow: 0px 2px 6px 0px #15141a; + } + + @media screen and (forced-colors: active) { + --alt-text-tooltip-bg: Canvas; + --alt-text-tooltip-fg: CanvasText; + --alt-text-tooltip-border: CanvasText; + --alt-text-tooltip-shadow: none; + } + + display: inline-flex; + flex-direction: column; + align-items: center; + justify-content: center; + position: absolute; + top: calc(100% + 2px); + inset-inline-start: 0; + padding-block: 2px 3px; + padding-inline: 3px; + max-width: 300px; + width: max-content; + height: auto; + font-size: 12px; + + border: 0.5px solid var(--alt-text-tooltip-border); + background: var(--alt-text-tooltip-bg); + box-shadow: var(--alt-text-tooltip-shadow); + color: var(--alt-text-tooltip-fg); + + pointer-events: none; + } + } + } } } } @@ -494,40 +572,17 @@ [data-main-rotation="180"] [data-editor-rotation="270"], [data-main-rotation="270"] [data-editor-rotation="180"] ) { - & .altText { - rotate: 270deg; - - &:dir(ltr) { - inset-inline-start: calc(100% - 8px); - - &.small { - inset-inline-start: calc(100% + 8px); - inset-block-start: 100%; - } - } - - &:dir(rtl) { - inset-block-end: calc(100% - 8px); - - &.small { - inset-inline-start: -8px; - inset-block-start: 0; - } - } - } - .editToolbar { rotate: 270deg; &:dir(ltr) { - inset-inline-start: calc(100% + var(--editor-toolbar-vert-offset)); + inset-inline-end: calc(0px - var(--editor-toolbar-vert-offset)); inset-block-start: 0; } &:dir(rtl) { inset-inline-end: calc(100% + var(--editor-toolbar-vert-offset)); - inset-block-end: 0; - inset-block-start: unset; + inset-block-start: 0; } } } @@ -539,23 +594,10 @@ [data-main-rotation="180"] [data-editor-rotation="0"], [data-main-rotation="270"] [data-editor-rotation="270"] ) { - & .altText { - rotate: 180deg; - - inset-block-end: calc(100% - 8px); - inset-inline-start: calc(100% - 8px); - - &.small { - inset-inline-start: 100%; - inset-block-start: -8px; - } - } - .editToolbar { rotate: 180deg; - inset-inline-start: 0; - inset-block-end: calc(100% + var(--editor-toolbar-vert-offset)); - inset-block-start: unset; + inset-inline-end: 100%; + inset-block-start: calc(0pc - var(--editor-toolbar-vert-offset)); } } @@ -566,182 +608,22 @@ [data-main-rotation="180"] [data-editor-rotation="90"], [data-main-rotation="270"] [data-editor-rotation="0"] ) { - & .altText { - rotate: 90deg; - - &:dir(ltr) { - inset-block-end: calc(100% - 8px); - - &.small { - inset-inline-start: -8px; - inset-block-start: 0; - } - } - - &:dir(rtl) { - inset-inline-start: calc(100% - 8px); - - &.small { - inset-inline-start: calc(100% + 8px); - inset-block-start: 100%; - } - } - } - .editToolbar { rotate: 90deg; &:dir(ltr) { inset-inline-end: calc(100% + var(--editor-toolbar-vert-offset)); - inset-block-end: 0; - inset-block-start: unset; + inset-block-start: 100%; } &:dir(rtl) { - inset-inline-start: calc(100% + var(--editor-toolbar-vert-offset)); + inset-inline-start: calc(0px - var(--editor-toolbar-vert-offset)); inset-block-start: 0; } } } } -.altText { - display: flex; - align-items: center; - justify-content: center; - padding-inline: 4px; - width: max-content; - height: 24px; - min-width: 88px; - z-index: 1; - pointer-events: all; - - color: var(--alt-text-fg-color); - font: menu; - font-size: 12px; - border-radius: 4px; - border: 1px solid var(--alt-text-border-color); - background-color: var(--alt-text-bg-color); - box-shadow: var(--alt-text-shadow); - - position: absolute; - inset-block-end: 8px; - inset-inline-start: 8px; - - &:disabled { - pointer-events: none; - } - - &:dir(ltr) { - transform-origin: 0 100%; - } - - &:dir(rtl) { - transform-origin: 100% 100%; - } - - &.small { - &:dir(ltr) { - transform-origin: 0 0; - } - - &:dir(rtl) { - transform-origin: 100% 0; - } - - inset-block-end: unset; - inset-inline-start: 0; - inset-block-start: calc(100% + 8px); - } - - &:hover { - background-color: var(--alt-text-hover-bg-color); - border-color: var(--alt-text-hover-border-color); - color: var(--alt-text-hover-fg-color); - cursor: pointer; - - &::before { - background-color: var(--alt-text-hover-fg-color); - } - } - - &:active { - background-color: var(--alt-text-active-bg-color); - border-color: var(--alt-text-active-border-color); - color: var(--alt-text-active-fg-color); - - &::before { - background-color: var(--alt-text-active-fg-color); - } - } - - &:focus-visible { - outline: 2px solid var(--alt-text-focus-outline-color); - border-color: var(--alt-text-focus-border-color); - } - - &::before { - content: ""; - mask-image: var(--alt-text-add-image); - mask-repeat: no-repeat; - mask-position: center; - display: inline-block; - width: 12px; - height: 13px; - background-color: var(--alt-text-fg-color); - margin-inline-end: 4px; - } - - &.done::before { - mask-image: var(--alt-text-done-image); - } - - & .tooltip { - display: none; - - &.show { - --alt-text-tooltip-bg: #f0f0f4; - --alt-text-tooltip-fg: #15141a; - --alt-text-tooltip-border: #8f8f9d; - --alt-text-tooltip-shadow: 0px 2px 6px 0px rgb(58 57 68 / 0.2); - - @media (prefers-color-scheme: dark) { - --alt-text-tooltip-bg: #1c1b22; - --alt-text-tooltip-fg: #fbfbfe; - --alt-text-tooltip-shadow: 0px 2px 6px 0px #15141a; - } - - @media screen and (forced-colors: active) { - --alt-text-tooltip-bg: Canvas; - --alt-text-tooltip-fg: CanvasText; - --alt-text-tooltip-border: CanvasText; - --alt-text-tooltip-shadow: none; - } - - display: inline-flex; - flex-direction: column; - align-items: center; - justify-content: center; - position: absolute; - top: calc(100% + 2px); - inset-inline-start: 0; - padding-block: 2px 3px; - padding-inline: 3px; - max-width: 300px; - width: max-content; - height: auto; - font-size: 12px; - - border: 0.5px solid var(--alt-text-tooltip-border); - background: var(--alt-text-tooltip-bg); - box-shadow: var(--alt-text-tooltip-shadow); - color: var(--alt-text-tooltip-fg); - - pointer-events: none; - } - } -} - #altTextDialog { --dialog-bg-color: white; --dialog-border-color: white; @@ -1062,7 +944,7 @@ } .editToolbar { - transform-origin: center; + transform-origin: center !important; } } }