From 256b38b29be45a1f08736c1422630ec41721390c Mon Sep 17 00:00:00 2001 From: David Roper Date: Fri, 14 Aug 2026 15:18:15 -0400 Subject: [PATCH 1/7] feat: add generate password method to password string field --- .../Form/StringField/StringFieldPassword.tsx | 42 +++++++++++++++++-- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/src/components/Form/StringField/StringFieldPassword.tsx b/src/components/Form/StringField/StringFieldPassword.tsx index b393692..bb1a327 100644 --- a/src/components/Form/StringField/StringFieldPassword.tsx +++ b/src/components/Form/StringField/StringFieldPassword.tsx @@ -1,10 +1,11 @@ import { useEffect, useState } from 'react'; import type { StringFormField } from '@douglasneuroinformatics/libui-form-types'; -import { EyeIcon, EyeOffIcon } from 'lucide-react'; +import { EyeIcon, EyeOffIcon, SparklesIcon } from 'lucide-react'; import { motion } from 'motion/react'; -import { Input, Label } from '#components'; +import { Input, Label, Tooltip } from '#components'; +import { useTranslation } from '#hooks'; import { cn } from '#utils'; import { FieldGroup } from '../FieldGroup/FieldGroup.tsx'; @@ -14,13 +15,23 @@ import type { BaseFieldComponentProps } from '../types.ts'; export type PasswordStrengthValue = 0 | 1 | 2 | 3 | 4; export type StringFieldPasswordProps = BaseFieldComponentProps & - Extract; + Extract & { + /** + * A function used to generate a password for this field. When provided, a button is rendered in + * the input that fills the field with the returned value and reveals it. + * + * Declared here rather than coming from `StringFormField`, and should be removed once the + * form types package publishes it on the password variant. + */ + generatePassword?: (this: void) => string; + }; export const StringFieldPassword = ({ calculateStrength, description, disabled, error, + generatePassword, label, name, readOnly, @@ -29,6 +40,7 @@ export const StringFieldPassword = ({ }: StringFieldPasswordProps) => { const [strength, setStrength] = useState(calculateStrength ? 0 : null); const [show, setShow] = useState(false); + const { t } = useTranslation(); useEffect(() => { if (calculateStrength) { setStrength(value ? calculateStrength(value) : 0); @@ -43,6 +55,7 @@ export const StringFieldPassword = ({ setValue(event.target.value)} /> + {generatePassword && ( + + { + setValue(generatePassword()); + // A generated password the user cannot read is of little use, so reveal it. + setShow(true); + }} + > + + + +

{t({ en: 'Generate a password', fr: 'Générer un mot de passe' })}

+
+
+ )}