feat(web): Added password field visibility toggle (#7368)

* Added password field visibility toggle

* improvements to password input field

* fix e2e and change tabindex

* add missing name=password

* remove unnecessary type prop

---------

Co-authored-by: Jan108 <dasJan108@gmail.com>
Co-authored-by: Michel Heusschen <59014050+michelheusschen@users.noreply.github.com>
This commit is contained in:
Jan108 2024-02-24 21:28:56 +01:00 committed by GitHub
parent 9d3ed719e0
commit 038e69fd02
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 101 additions and 74 deletions

View file

@ -0,0 +1,50 @@
<script lang="ts">
import { mdiEyeOffOutline, mdiEyeOutline } from '@mdi/js';
import type { HTMLInputAttributes } from 'svelte/elements';
import Icon from '../elements/icon.svelte';
interface $$Props extends HTMLInputAttributes {
password: string;
autocomplete: string;
required?: boolean;
onInput?: (value: string) => void;
}
export let password: $$Props['password'];
export let required = true;
export let onInput: $$Props['onInput'] = undefined;
let showPassword = false;
</script>
<div class="relative w-full">
<input
{...$$restProps}
class="immich-form-input w-full !pr-12"
type={showPassword ? 'text' : 'password'}
{required}
value={password}
on:input={(e) => {
password = e.currentTarget.value;
onInput?.(password);
}}
/>
{#if password.length > 0}
<button
type="button"
tabindex="-1"
class="absolute inset-y-0 end-0 px-4 text-gray-700 dark:text-gray-200"
on:click={() => (showPassword = !showPassword)}
title={showPassword ? 'Hide password' : 'Show password'}
>
<Icon path={showPassword ? mdiEyeOffOutline : mdiEyeOutline} size="1.25em" />
</button>
{/if}
</div>
<style>
input::-ms-reveal {
display: none;
}
</style>

View file

@ -10,6 +10,7 @@
<script lang="ts">
import { quintOut } from 'svelte/easing';
import { fly } from 'svelte/transition';
import PasswordField from '../password-field.svelte';
export let inputType: SettingInputFieldType;
export let value: string | number;
@ -22,6 +23,7 @@
export let required = false;
export let disabled = false;
export let isEdited = false;
export let passwordAutocomplete: string = 'current-password';
const handleInput = (e: Event) => {
value = (e.target as HTMLInputElement).value;
@ -64,20 +66,35 @@
<slot name="desc" />
{/if}
<input
class="immich-form-input w-full pb-2"
aria-describedby={desc ? `${label}-desc` : undefined}
aria-labelledby="{label}-label"
id={label}
name={label}
type={inputType}
min={min.toString()}
max={max.toString()}
{step}
{required}
{value}
on:input={handleInput}
{disabled}
{title}
/>
{#if inputType !== SettingInputFieldType.PASSWORD}
<input
class="immich-form-input w-full pb-2"
aria-describedby={desc ? `${label}-desc` : undefined}
aria-labelledby="{label}-label"
id={label}
name={label}
type={inputType}
min={min.toString()}
max={max.toString()}
{step}
{required}
{value}
on:input={handleInput}
{disabled}
{title}
/>
{:else}
<PasswordField
aria-describedby={desc ? `${label}-desc` : undefined}
aria-labelledby="{label}-label"
id={label}
name={label}
autocomplete={passwordAutocomplete}
{required}
password={value.toString()}
onInput={(passwordValue) => (value = passwordValue)}
{disabled}
{title}
/>
{/if}
</div>