Files
freno-dev/src/components/ui/PasswordInput.tsx
2026-01-06 10:40:15 -05:00

64 lines
1.9 KiB
TypeScript

import { JSX, splitProps, createSignal, Show } from "solid-js";
import Input, { InputProps } from "./Input";
import Eye from "~/components/icons/Eye";
import EyeSlash from "~/components/icons/EyeSlash";
import PasswordStrengthMeter from "~/components/PasswordStrengthMeter";
export interface PasswordInputProps extends Omit<InputProps, "type"> {
showStrength?: boolean;
defaultVisible?: boolean;
passwordValue?: string;
}
export default function PasswordInput(props: PasswordInputProps) {
const [local, inputProps] = splitProps(props, [
"showStrength",
"defaultVisible",
"passwordValue",
"class",
"containerClass"
]);
const [showPassword, setShowPassword] = createSignal(
local.defaultVisible || false
);
return (
<div class="flex flex-col items-center gap-2">
<div class={local.containerClass || "input-group relative mx-4 mb-2"}>
<Input
{...inputProps}
type={showPassword() ? "text" : "password"}
class={`w-full pr-10 ${local.class || ""}`}
containerClass=""
/>
<button
type="button"
onClick={() => setShowPassword(!showPassword())}
class="text-subtext0 absolute right-0 bottom-2 transition-all hover:brightness-125"
aria-label={showPassword() ? "Hide password" : "Show password"}
>
<Show
when={showPassword()}
fallback={
<EyeSlash
height={24}
width={24}
strokeWidth={1}
class="stroke-text"
/>
}
>
<Eye height={24} width={24} strokeWidth={1} class="stroke-text" />
</Show>
</button>
</div>
{local.showStrength && local.passwordValue !== undefined && (
<PasswordStrengthMeter password={local.passwordValue} />
)}
</div>
);
}