commit 75259352201f05beaca3f1d8dc56c0b582d60a21
parent 57d3feae5d6f71d9b7aa0e05b9f2e516ce662d2c
Author: Erik Nordin <enordin@mozilla.com>
Date: Tue, 23 Dec 2025 16:05:28 +0000
Bug 1992233 - Part 1/3: Add Source Section Clear Button r=translations-reviewers,fluent-reviewers,bolsson,gregtatum
This commit adds the actions column and clear button to the source section
of the about:translations page. This introduces the new UI element sonly,
ensuring that the pre-existing lofic is consistent, especially resizing.
At this point, the button is always shown and has no functionality.
Subsequent commits will add the show/hide/click logic as well as tests.
Differential Revision: https://phabricator.services.mozilla.com/D277055
Diffstat:
4 files changed, 112 insertions(+), 7 deletions(-)
diff --git a/toolkit/components/translations/content/about-translations.css b/toolkit/components/translations/content/about-translations.css
@@ -27,6 +27,9 @@
--AT-content-width: calc(var(--AT-section-height) * 4.5);
--AT-content-max: calc(100vw - var(--AT-viewport-padding) * 2);
+
+ --AT-square-button-large: calc(var(--size-item-large) + var(--space-small));
+ --AT-square-button-small: var(--size-item-large);
}
body {
@@ -36,7 +39,7 @@ body {
align-items: flex-start;
visibility: hidden;
margin: 0;
- row-gap: var(--space-xlarge);
+ row-gap: var(--space-xxlarge);
padding: var(--AT-page-padding-block-start) var(--AT-viewport-padding) var(--AT-page-padding-block-end);
}
@@ -84,12 +87,23 @@ body {
margin: 0;
}
-#about-translations-swap-languages-button[type~="icon"]::part(button) {
- width: var(--size-item-xlarge);
- height: var(--size-item-xlarge);
- transform: rotate(90deg) scaleX(-1);
- background-image: url("chrome://global/skin/icons/arrows-updown.svg");
- background-size: var(--size-item-medium);
+#about-translations-swap-languages-button {
+ align-self: center;
+
+ &[type~="icon"]::part(button) {
+ width: var(--AT-square-button-large);
+ height: var(--AT-square-button-large);
+ transform: rotate(90deg) scaleX(-1);
+ background-image: url("chrome://global/skin/icons/arrows-updown.svg");
+ background-size: var(--size-item-medium);
+ }
+}
+
+#about-translations-clear-button[type~="icon"]::part(button) {
+ width: var(--AT-square-button-small);
+ height: var(--AT-square-button-small);
+ background-image: url("chrome://global/skin/icons/close.svg");
+ background-size: var(--size-item-small);
}
#about-translations-source-section,
@@ -98,6 +112,20 @@ body {
min-height: var(--AT-section-height);
}
+#about-translations-source-section {
+ display: grid;
+ grid-template-columns: 1fr auto;
+ background-color: var(--background-color-box);
+ border: 1px solid var(--border-color);
+ border-radius: var(--border-radius-medium);
+ overflow: hidden;
+
+ &.focus-section {
+ outline: var(--focus-outline);
+ outline-offset: -1px;
+ }
+}
+
#about-translations-target-section {
background-color: var(--background-color-box);
border: 1px solid var(--border-color);
@@ -118,6 +146,23 @@ body {
resize: none;
}
+#about-translations-source-textarea {
+ border: none;
+ border-radius: 0;
+ background-color: transparent;
+ padding-inline-end: var(--space-xsmall);
+
+ &:focus-visible {
+ outline: none;
+ }
+}
+
+#about-translations-source-actions {
+ padding: var(--space-xsmall);
+ min-width: var(--AT-square-button-small);
+ background-color: transparent;
+}
+
#about-translations-target-textarea {
border: none;
border-radius: 0;
diff --git a/toolkit/components/translations/content/about-translations.html b/toolkit/components/translations/content/about-translations.html
@@ -120,6 +120,14 @@
data-l10n-id="about-translations-input-placeholder"
spellcheck="false"
></textarea>
+ <div id="about-translations-source-actions">
+ <moz-button
+ id="about-translations-clear-button"
+ type="ghost icon"
+ data-l10n-id="about-translations-clear-button"
+ tabindex="-1"
+ ></moz-button>
+ </div>
</div>
<div id="about-translations-empty-section"></div>
<div id="about-translations-target-section">
diff --git a/toolkit/components/translations/content/about-translations.mjs b/toolkit/components/translations/content/about-translations.mjs
@@ -196,6 +196,8 @@ class AboutTranslations {
* mainUserInterface: HTMLElement,
* sourceLanguageSelector: HTMLSelectElement,
* sourceSection: HTMLElement,
+ * sourceSectionActionsColumn: HTMLElement,
+ * sourceSectionClearButton: HTMLElement,
* sourceSectionTextArea: HTMLTextAreaElement,
* swapLanguagesButton: HTMLElement,
* targetLanguageSelector: HTMLSelectElement,
@@ -234,6 +236,12 @@ class AboutTranslations {
sourceSection: /** @type {HTMLElement} */ (
document.getElementById("about-translations-source-section")
),
+ sourceSectionActionsColumn: /** @type {HTMLElement} */ (
+ document.getElementById("about-translations-source-actions")
+ ),
+ sourceSectionClearButton: /** @type {HTMLElement} */ (
+ document.getElementById("about-translations-clear-button")
+ ),
sourceSectionTextArea: /** @type {HTMLTextAreaElement} */ (
document.getElementById("about-translations-source-textarea")
),
@@ -362,6 +370,7 @@ class AboutTranslations {
copyButton,
learnMoreLink,
sourceLanguageSelector,
+ sourceSectionActionsColumn,
sourceSectionTextArea,
swapLanguagesButton,
targetLanguageSelector,
@@ -375,7 +384,16 @@ class AboutTranslations {
"input",
this.#onSourceLanguageInput
);
+ sourceSectionActionsColumn.addEventListener(
+ "pointerdown",
+ this.#onSourceSectionActionsPointerDown
+ );
sourceSectionTextArea.addEventListener("input", this.#onSourceTextInput);
+ sourceSectionTextArea.addEventListener(
+ "focus",
+ this.#onSourceTextAreaFocus
+ );
+ sourceSectionTextArea.addEventListener("blur", this.#onSourceTextAreaBlur);
swapLanguagesButton.addEventListener("click", this.#onSwapLanguagesButton);
targetLanguageSelector.addEventListener(
"input",
@@ -443,6 +461,36 @@ class AboutTranslations {
};
/**
+ * Handles pointerdown events within the source section's actions column.
+ *
+ * Clicking empty space within the column should behave as though the
+ * textarea was clicked, but clicking the clear button should preserve
+ * the default behavior.
+ */
+ #onSourceSectionActionsPointerDown = event => {
+ if (event.target?.closest?.("#about-translations-clear-button")) {
+ return;
+ }
+
+ event.preventDefault();
+ this.elements.sourceSectionTextArea.focus();
+ };
+
+ /**
+ * Handles focusing the source section by outlining the entire section.
+ */
+ #onSourceTextAreaFocus = () => {
+ this.elements.sourceSection.classList.add("focus-section");
+ };
+
+ /**
+ * Handles blur events on the source section's text area.
+ */
+ #onSourceTextAreaBlur = () => {
+ this.elements.sourceSection.classList.remove("focus-section");
+ };
+
+ /**
* Handles pointerdown events within the target section's actions row.
*
* Clicking empty space within the actions row should behave as though
diff --git a/toolkit/locales/en-US/toolkit/about/aboutTranslations.ftl b/toolkit/locales/en-US/toolkit/about/aboutTranslations.ftl
@@ -59,3 +59,7 @@ about-translations-translating-message = Translating…
# source and target languages, reversing the direction of translation.
about-translations-swap-languages =
.title = Swap languages
+
+# The title attribute for the button that clears the source text area.
+about-translations-clear-button =
+ .title = Clear source text