Bug 1911121 - Create a LoginForm Component for Contextual Password Manager. r=fluent-reviewers,desktop-theme-reviewers,bolsson,hjones,issammani,ayeddi,dao,accessibility-frontend-reviewers

Differential Revision: https://phabricator.services.mozilla.com/D218341
This commit is contained in:
Sidharth Sachdev 2024-09-14 15:27:32 +00:00
Родитель f8904f7f9b
Коммит 0815749aa8
14 изменённых файлов: 168 добавлений и 42 удалений

Просмотреть файл

@ -85,6 +85,9 @@ var gExceptionPaths = [
// Strip on Share parameter lists
"chrome://global/content/antitracking/",
// CSS file is referenced inside JS in login-form.mjs
"chrome://global/content/megalist/LoginFormComponent/",
];
// These are not part of the omni.ja file, so we find them only when running

Просмотреть файл

@ -4,8 +4,9 @@
:host {
display: grid;
grid-template-areas: "label label" "input actions";
grid-template-areas: "label" "input" "explainer";
grid-template-columns: minmax(0, auto) min-content;
grid-gap: var(--space-small);
align-items: center;
}
@ -29,38 +30,23 @@ input.input-field {
text-overflow: ellipsis;
overflow: hidden;
appearance: textfield;
grid-area: input;
& + .explainer {
display: none;
}
}
.reveal-password-button {
grid-area: actions;
width: 32px;
height: 32px;
min-width: 0;
background: url("chrome://browser/content/aboutlogins/icons/password.svg") center no-repeat;
grid-area: input;
justify-self: end;
cursor: pointer;
-moz-context-properties: fill;
fill: currentColor;
color: inherit;
opacity: 0.8;
}
.reveal-password-button.revealed {
background-image: url("chrome://browser/content/aboutlogins/icons/password-hide.svg");
.origin-input {
grid-area: input;
}
/** button.reveal-password-button needed to override --in-content-button-background-hover in common-shared.css **/
button.reveal-password-button:hover {
opacity: 0.6;
background-color: transparent;
}
/** button.reveal-password-button needed to override --in-content-button-background-active in common-shared.css **/
button.reveal-password-button:hover:active {
opacity: 1;
background-color: transparent;
}
.actions {
display: flex;
justify-content: end;
.explainer {
grid-area: explainer;
}

Просмотреть файл

@ -16,22 +16,28 @@ export const stylesTemplate = () =>
export const editableFieldTemplate = ({
type,
value,
inputId,
disabled,
onFocus,
onBlur,
labelL10nId,
noteL10nId,
}) =>
html`
<label for="input" class="field-label" data-l10n-id=${labelL10nId}> </label>
<input
id="input"
class="input-field"
data-l10n-id=${ifDefined(inputId)}
type=${type}
value=${value}
aria-describedby="explainer"
?disabled=${disabled}
@focus=${onFocus}
@blur=${onBlur}
/>
<div class="actions">
<slot name="actions"></slot>
</div>
<span
id="explainer"
role="note"
class="explainer text-deemphasized"
data-l10n-id=${ifDefined(noteL10nId)}
></span>
`;

Просмотреть файл

@ -13,7 +13,14 @@ class LoginOriginField extends MozLitElement {
get readonlyTemplate() {
return html`
<label
for="origin"
class="field-label"
data-l10n-id="login-item-origin-label"
>
</label>
<a
id="origin"
class="origin-input"
dir="auto"
target="_blank"
@ -29,12 +36,13 @@ class LoginOriginField extends MozLitElement {
render() {
return html`
${stylesTemplate()}
<label class="field-label" data-l10n-id="login-item-origin-label"></label>
${this.readonly
? this.readonlyTemplate
: editableFieldTemplate({
type: "url",
value: this.value,
labelL10nId: "login-item-origin-label",
noteL10nId: "passwords-origin-tooltip",
})}
`;
}

Просмотреть файл

@ -34,13 +34,15 @@ class LoginPasswordField extends MozLitElement {
: this._value;
}
#revealIconSrc(concealed) {
return concealed
? "chrome://browser/content/aboutlogins/icons/password-hide.svg"
: "chrome://browser/content/aboutlogins/icons/password.svg";
}
render() {
return html`
${stylesTemplate()}
<label
class="field-label"
data-l10n-id="login-item-password-label"
></label>
${editableFieldTemplate({
type: this.#type,
value: this.#password,
@ -48,7 +50,18 @@ class LoginPasswordField extends MozLitElement {
disabled: this.readonly,
onFocus: this.handleFocus,
onBlur: this.handleBlur,
labelL10nId: "login-item-password-label",
noteL10nId: "passwords-password-tooltip",
})}
<moz-button
data-l10n-id=${this.visible
? "login-item-password-conceal-checkbox"
: "login-item-password-reveal-checkbox"}
class="reveal-password-button"
type="icon ghost"
iconSrc=${this.#revealIconSrc(this.visible)}
@click=${this.toggleVisibility}
></moz-button>
`;
}
@ -69,7 +82,6 @@ class LoginPasswordField extends MozLitElement {
if (this.visible) {
this.onPasswordVisible?.();
}
this.input.focus();
}
}

Просмотреть файл

@ -14,14 +14,12 @@ class LoginUsernameField extends MozLitElement {
render() {
return html`
${stylesTemplate()}
<label
class="field-label"
data-l10n-id="login-item-username-label"
></label>
${editableFieldTemplate({
type: "text",
value: this.value,
disabled: this.readonly,
labelL10nId: "login-item-username-label",
noteL10nId: "passwords-username-tooltip",
})}
`;
}

Просмотреть файл

@ -100,6 +100,13 @@ export async function insertFTLIfNeeded(fileName) {
`browser/branding/nightly/locales/en-US/${rest}`
);
ftlContents = imported.default;
} else if (root == "preview") {
// eslint-disable-next-line no-unsanitized/method
let imported = await import(
/* webpackInclude: /\.ftl$/ */
`toolkit/components/satchel/megalist/content/${rest}`
);
ftlContents = imported.default;
}
if (loadedResources.has(fileName)) {

Просмотреть файл

@ -27,6 +27,8 @@ module.exports = {
`${projectRoot}/browser/components/backup/content/**/*.stories.mjs`,
// Reader View components stories
`${projectRoot}/toolkit/components/reader/**/*.stories.mjs`,
// megalist components stories
`${projectRoot}/toolkit/components/satchel/megalist/content/**/*.stories.mjs`,
// Everything else
"../stories/**/*.stories.@(js|jsx|mjs|ts|tsx|md)",
// Design system files

Просмотреть файл

@ -115,6 +115,8 @@ login-item-copied-username-button-text = Copied!
login-item-password-label = Password
login-item-password-reveal-checkbox =
.aria-label = Show password
login-item-password-conceal-checkbox =
.aria-label = Hide password
login-item-copy-password-button-text = Copy
login-item-copied-password-button-text = Copied!
about-logins-login-item-save-changes-button = Save

Просмотреть файл

@ -8,3 +8,4 @@ toolkit.jar:
content/global/megalist/MegalistAlpha.mjs (megalist/content/MegalistAlpha.mjs)
content/global/megalist/PasswordCard.mjs (megalist/content/PasswordCard.mjs)
content/global/megalist/Dialog.mjs (megalist/content/Dialog.mjs)
content/global/megalist/LoginFormComponent/login-form.css (megalist/content/LoginFormComponent/login-form.css)

Просмотреть файл

@ -0,0 +1,14 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
.delete-login-button-container {
display: flex;
justify-content: end;
height: 0;
}
/* Add spacing between fieldset legend text and fields */
login-origin-field {
margin-block-start: var(--space-medium);
}

Просмотреть файл

@ -0,0 +1,60 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
import { html, when } from "chrome://global/content/vendor/lit.all.mjs";
import { MozLitElement } from "chrome://global/content/lit-utils.mjs";
/* eslint-disable-next-line import/no-unassigned-import, mozilla/no-browser-refs-in-toolkit */
import "chrome://browser/content/aboutlogins/components/input-field/login-origin-field.mjs";
/* eslint-disable-next-line import/no-unassigned-import, mozilla/no-browser-refs-in-toolkit */
import "chrome://browser/content/aboutlogins/components/input-field/login-username-field.mjs";
/* eslint-disable-next-line import/no-unassigned-import, mozilla/no-browser-refs-in-toolkit */
import "chrome://browser/content/aboutlogins/components/input-field/login-password-field.mjs";
export class LoginForm extends MozLitElement {
static properties = {
type: { type: String, reflect: true },
};
render() {
const heading =
this.type !== "edit" ? "passwords-create-label" : "passwords-edit-label";
return html`<link
rel="stylesheet"
href="chrome://global/content/megalist/LoginFormComponent/login-form.css"
/>
<moz-card>
${when(
this.type === "edit",
() => html`
<div class="delete-login-button-container">
<moz-button
class="delete-login-button"
type="icon"
iconSrc="chrome://global/skin/icons/delete.svg"
></moz-button>
</div>
`
)}
<form>
<moz-fieldset data-l10n-id=${heading}>
<login-origin-field></login-origin-field>
<login-username-field></login-username-field>
<login-password-field></login-password-field>
<moz-button-group>
<moz-button data-l10n-id="login-item-cancel-button"></moz-button>
<moz-button
data-l10n-id="login-item-save-new-button"
type="primary"
>
</moz-button>
</moz-button-group>
</moz-fieldset>
</form>
</moz-card>`;
}
}
customElements.define("login-form", LoginForm);

Просмотреть файл

@ -0,0 +1,17 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
// eslint-disable-next-line import/no-unresolved
import { html } from "lit.all.mjs";
import "./login-form.mjs";
export default {
title: "Domain-specific UI Widgets/Credential Management/Login Form",
component: "login-form",
};
window.MozXULElement.insertFTLIfNeeded("preview/megalist.ftl");
export const AddLoginForm = () => html`<login-form type="add"></login-form>`;
export const EditLoginForm = () => html`<login-form type="edit"></login-form>`;

Просмотреть файл

@ -146,6 +146,16 @@ passwords-radiobutton-all = All ({ $total })
# $total (number) - Total number of alerts
passwords-radiobutton-alerts = Alerts ({ $total })
## Login Form
passwords-create-label =
.label = Add password
passwords-edit-label =
.label = Edit password
passwords-origin-tooltip = Enter the exact address where youll sign in to this site.
passwords-username-tooltip = Enter the username, email address, or account number you use to sign in.
passwords-password-tooltip = Enter the password used to sign in to this account.
## Payments
payments-command-create = Add Payment Method