commit 1707ffd5f777b28c4b52dcbabb2b1cfdfc79bb1f
parent 759b941d2431c23ca53792c8af791fe0b0717141
Author: Sebastian <sebasjm@taler-systems.com>
Date: Fri, 27 Feb 2026 11:37:53 -0300
fix #11159
Diffstat:
11 files changed, 104 insertions(+), 49 deletions(-)
diff --git a/packages/merchant-backoffice-ui/src/components/form/Input.tsx b/packages/merchant-backoffice-ui/src/components/form/Input.tsx
@@ -22,16 +22,33 @@ import { ComponentChildren, h, VNode } from "preact";
import { InputProps, useField } from "./useField.js";
import { Tooltip } from "../Tooltip.js";
-export type SupportedTextInputType =
- | "text"
- | "numeric"
- | "decimal"
- | "tel"
- | "email"
- | "url"
- | "search"
- | "multiline"
- | "password";
+export type SupportedTextInputType =
+ | "text"
+ | "numeric"
+ | "decimal"
+ | "tel"
+ | "email"
+ | "url"
+ | "search"
+ | "multiline"
+ | "password";
+
+// https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Attributes/autocomplete
+export type SupportedAutocomplete =
+ | "username"
+ | "current-password"
+ | "new-password"
+ | "one-time-code"
+ | "organization"
+ | "street-address"
+ | "country"
+ | "postal-code"
+ | "language"
+ | "url"
+ | "photo"
+ | "email"
+ | "tel";
+
interface Props<T> extends InputProps<T> {
inputType?: SupportedTextInputType;
expand?: boolean;
@@ -42,6 +59,7 @@ interface Props<T> extends InputProps<T> {
children?: ComponentChildren;
focus?: boolean;
dontRemember?: boolean;
+ autoComplete?: SupportedAutocomplete;
}
export function doAutoFocus<T extends HTMLElement>(
@@ -103,7 +121,7 @@ export function InternalTextInputSwitch({
{...(rest as any)}
ref={focus ? doAutoFocus : undefined}
class={hasError ? "input is-danger" : "input"}
- type={inputType}
+ type={inputType ?? "text"}
/>
);
}
@@ -121,6 +139,7 @@ export function Input<T>({
dontRemember,
inputType,
inputExtra,
+ autoComplete,
side,
fromStr = defaultFromString,
toStr = defaultToString,
@@ -152,21 +171,24 @@ export function Input<T>({
: "control has-icons-right"
}
>
- <InternalTextInputSwitch
- hasError={error}
- {...inputExtra}
- inputType={inputType}
- placeholder={placeholder}
- autocomplete={dontRemember ? "off" : undefined}
- readonly={readonly}
- disabled={readonly}
- name={String(name)}
- focus={focus}
- value={toStr(value)}
- onChange={(e: h.JSX.TargetedEvent<HTMLInputElement>): void =>
- onChange(fromStr(e.currentTarget.value))
- }
- />
+ <fieldset>
+ <InternalTextInputSwitch
+ hasError={error}
+ {...inputExtra}
+ inputType={inputType}
+ placeholder={placeholder}
+ autocomplete={dontRemember ? "off" : undefined}
+ readonly={readonly}
+ disabled={readonly}
+ autoComplete={autoComplete}
+ name={String(name)}
+ focus={focus}
+ value={toStr(value)}
+ onChange={(e: h.JSX.TargetedEvent<HTMLInputElement>): void =>
+ onChange(fromStr(e.currentTarget.value))
+ }
+ />
+ </fieldset>
{help}
{children}
</p>
diff --git a/packages/merchant-backoffice-ui/src/components/form/InputPassword.tsx b/packages/merchant-backoffice-ui/src/components/form/InputPassword.tsx
@@ -28,6 +28,7 @@ export interface Props<T> extends InputProps<T> {
addonAfter?: ComponentChildren;
children?: ComponentChildren;
side?: ComponentChildren;
+ autoComplete?: "current-password" | "new-password";
}
export function InputPassword<T>({
@@ -38,7 +39,7 @@ export function InputPassword<T>({
help,
tooltip,
expand,
- addonAfter,
+ autoComplete,
children,
side,
}: Props<keyof T>): VNode {
@@ -50,6 +51,7 @@ export function InputPassword<T>({
side={side}
label={label}
placeholder={placeholder}
+ autoComplete={autoComplete}
help={help}
tooltip={tooltip}
addonAfterAction={() => {
diff --git a/packages/merchant-backoffice-ui/src/components/form/InputWithAddon.tsx b/packages/merchant-backoffice-ui/src/components/form/InputWithAddon.tsx
@@ -21,7 +21,11 @@
import { ComponentChildren, h, VNode } from "preact";
import { InputProps, useField } from "./useField.js";
import { Tooltip } from "../Tooltip.js";
-import { InternalTextInputSwitch, SupportedTextInputType } from "./Input.js";
+import {
+ InternalTextInputSwitch,
+ SupportedAutocomplete,
+ SupportedTextInputType,
+} from "./Input.js";
export interface Props<T> extends InputProps<T> {
expand?: boolean;
@@ -35,6 +39,7 @@ export interface Props<T> extends InputProps<T> {
inputExtra?: any;
children?: ComponentChildren;
side?: ComponentChildren;
+ autoComplete?: SupportedAutocomplete;
}
const defaultToString = (f?: any): string => f || "";
@@ -48,6 +53,7 @@ export function InputWithAddon<T>({
expand,
label,
addonBeforeLarge,
+ autoComplete,
placeholder,
help,
tooltip,
@@ -97,19 +103,22 @@ export function InputWithAddon<T>({
required ? " has-icons-right" : ""
}`}
>
- <InternalTextInputSwitch
- {...(inputExtra || {})}
- class={error ? "input is-danger" : "input"}
- inputType={inputType}
- placeholder={placeholder}
- readonly={readonly}
- disabled={readonly}
- name={String(name)}
- value={toStr(value)}
- onChange={(e: h.JSX.TargetedEvent<HTMLInputElement>): void =>
- onChange(fromStr(e.currentTarget.value))
- }
- />
+ <fieldset>
+ <InternalTextInputSwitch
+ {...(inputExtra || {})}
+ class={error ? "input is-danger" : "input"}
+ inputType={inputType}
+ placeholder={placeholder}
+ readonly={readonly}
+ autoComplete={autoComplete}
+ disabled={readonly}
+ name={String(name)}
+ value={toStr(value)}
+ onChange={(e: h.JSX.TargetedEvent<HTMLInputElement>): void =>
+ onChange(fromStr(e.currentTarget.value))
+ }
+ />
+ </fieldset>
{children}
</p>
{addonAfter && (
diff --git a/packages/merchant-backoffice-ui/src/components/instance/DefaultInstanceFormFields.tsx b/packages/merchant-backoffice-ui/src/components/instance/DefaultInstanceFormFields.tsx
@@ -62,6 +62,7 @@ export function DefaultInstanceFormFields({
readonly={readonlyId}
label={i18n.str`Username`}
tooltip={i18n.str`Name of the instance in URLs. The 'admin' instance is special in that it is used to administer other instances.`}
+ autoComplete="username"
/>
)}
@@ -69,24 +70,28 @@ export function DefaultInstanceFormFields({
name="name"
label={i18n.str`Business name`}
tooltip={i18n.str`Legal name of the business represented by this instance.`}
+ autoComplete="organization"
/>
<Input<Entity>
name="email"
label={i18n.str`Email`}
tooltip={i18n.str`Contact email`}
+ autoComplete="email"
/>
<Input<Entity>
name="phone_number"
label={i18n.str`Phone number`}
tooltip={i18n.str`Contact phone`}
+ autoComplete="tel"
/>
<FragmentPersonaFlag point={UIElement.option_advanceInstanceSettings}>
<Input<Entity>
name="website"
label={i18n.str`Website URL`}
tooltip={i18n.str`URL.`}
+ autoComplete="url"
/>
<InputImage<Entity>
diff --git a/packages/merchant-backoffice-ui/src/paths/admin/create/CreatePage.tsx b/packages/merchant-backoffice-ui/src/paths/admin/create/CreatePage.tsx
@@ -270,12 +270,13 @@ export function CreatePage({ onConfirm, onBack, forceId }: Props): VNode {
name="password"
label={i18n.str`New password`}
tooltip={i18n.str`Next password to be used`}
+ autoComplete="new-password"
/>
- <Input<Entity>
+ <InputPassword<Entity>
name="repeat"
label={i18n.str`Repeat password`}
tooltip={i18n.str`Confirm the same password`}
- inputType="password"
+ autoComplete="new-password"
/>
<div class="buttons is-right mt-5">
{onBack && (
diff --git a/packages/merchant-backoffice-ui/src/paths/instance/accounts/create/CreatePage.tsx b/packages/merchant-backoffice-ui/src/paths/instance/accounts/create/CreatePage.tsx
@@ -281,6 +281,7 @@ export function CreatePage({ onCreated, onBack }: Props): VNode {
help="https://bank.demo.taler.net/accounts/${USERNAME}/taler-revenue/"
expand
tooltip={i18n.str`From where the merchant can download information about incoming wire transfers to this account`}
+ inputType="url"
/>
<InputSelector
name="credit_facade_credentials.type"
@@ -299,12 +300,14 @@ export function CreatePage({ onCreated, onBack }: Props): VNode {
name="credit_facade_credentials.username"
label={i18n.str`Username`}
tooltip={i18n.str`Username to access the account information.`}
+ autoComplete="username"
/>
<InputPassword
name="credit_facade_credentials.password"
expand
label={i18n.str`Password`}
tooltip={i18n.str`Password to access the account information.`}
+ autoComplete="current-password"
/>
</Fragment>
) : undefined}
diff --git a/packages/merchant-backoffice-ui/src/paths/instance/accounts/update/UpdatePage.tsx b/packages/merchant-backoffice-ui/src/paths/instance/accounts/update/UpdatePage.tsx
@@ -387,12 +387,14 @@ export function UpdatePage({ account, onUpdated, onBack }: Props): VNode {
name="credit_facade_credentials.username"
label={i18n.str`Username`}
tooltip={i18n.str`Username to access the account information.`}
+ autoComplete="username"
/>
<InputPassword
name="credit_facade_credentials.password"
expand
label={i18n.str`Password`}
tooltip={i18n.str`Password to access the account information.`}
+ autoComplete="current-password"
/>
</Fragment>
) : undefined}
diff --git a/packages/merchant-backoffice-ui/src/paths/instance/password/DetailPage.tsx b/packages/merchant-backoffice-ui/src/paths/instance/password/DetailPage.tsx
@@ -108,6 +108,7 @@ export function DetailPage({
label={i18n.str`Current password`}
tooltip={i18n.str`In order to verify that you have access.`}
expand
+ autoComplete="current-password"
/>
)}
<InputPassword<State>
@@ -115,12 +116,13 @@ export function DetailPage({
expand
label={i18n.str`New password`}
tooltip={i18n.str`Next password to be used`}
+ autoComplete="new-password"
/>
- <Input<State>
+ <InputPassword<State>
name="repeat"
label={i18n.str`Repeat password`}
tooltip={i18n.str`Confirm the same password`}
- inputType="password"
+ autoComplete="new-password"
/>
</Fragment>
<div class="buttons is-right mt-5">
diff --git a/packages/merchant-backoffice-ui/src/paths/login/index.tsx b/packages/merchant-backoffice-ui/src/paths/login/index.tsx
@@ -160,6 +160,7 @@ export function LoginPage({ showCreateAccount, focus }: Props): VNode {
ref={focus ? doAutoFocus : undefined}
// placeholder={i18n.str`instance name`}
name="username"
+ autoComplete="username"
value={username}
onInput={(e): void =>
setUsername(e?.currentTarget.value)
@@ -186,6 +187,7 @@ export function LoginPage({ showCreateAccount, focus }: Props): VNode {
type={hidePassword ? "password" : "text"}
// placeholder={i18n.str`current password`}
name="token"
+ autoComplete="current-password"
value={password}
onInput={(e): void =>
setPassword(e?.currentTarget.value)
diff --git a/packages/merchant-backoffice-ui/src/paths/newAccount/index.tsx b/packages/merchant-backoffice-ui/src/paths/newAccount/index.tsx
@@ -267,30 +267,35 @@ export function NewAccount({ onCancel, onCreated }: Props): VNode {
name="id"
label={i18n.str`Username`}
tooltip={i18n.str`Name of the instance in URLs. The 'admin' instance is special in that it is used to administer other instances.`}
+ autoComplete="username"
/>
<Input<Account>
name="name"
label={i18n.str`Business name`}
tooltip={i18n.str`Legal name of the business represented by this instance.`}
+ autoComplete="organization"
/>
<InputPassword<Account>
expand
label={i18n.str`New password`}
tooltip={i18n.str`Next password to be used`}
name="password"
+ autoComplete="new-password"
/>
- <Input<Account>
+ <InputPassword<Account>
label={i18n.str`Repeat password`}
tooltip={i18n.str`Confirm the same password`}
- inputType="password"
name="repeat"
+ expand
+ autoComplete="new-password"
/>
{serverRequiresEmail ? (
<Input<Account>
label={i18n.str`Email`}
tooltip={i18n.str`Contact email`}
name="email"
+ autoComplete="email"
/>
) : undefined}
{serverRequiresSms ? (
@@ -298,6 +303,7 @@ export function NewAccount({ onCancel, onCreated }: Props): VNode {
label={i18n.str`Phone`}
tooltip={i18n.str`Contact phone number`}
name="phone"
+ autoComplete="tel"
/>
) : undefined}
<InputToggle
diff --git a/packages/merchant-backoffice-ui/src/paths/resetAccount/index.tsx b/packages/merchant-backoffice-ui/src/paths/resetAccount/index.tsx
@@ -165,11 +165,12 @@ export function ResetAccount({
label={i18n.str`New password`}
name="password"
expand
+ autoComplete="new-password"
/>
- <Input<Form>
+ <InputPassword<Form>
label={i18n.str`Repeat password`}
- inputType="password"
name="repeat"
+ autoComplete="new-password"
/>
</section>
<footer