shadcn.io is not affiliated with official shadcn/ui
Password Generator Dialog Block for Vue
A sign-up page with a dialog shown open that suggests a password: a mono output with Copy and a new one, Random or Passphrase, a length slider, four character switches and a strength worked out in bits.
Installation
Overview
Let people choose a strong password without inventing one, with this generator dialog for Vue with Ark UI. It opens from the sign-up page of Vaultmoth, a team password manager: the form is drawn under a soft scrim inside a hairline frame with a plus mark on each corner, and its header holds an outline Suggest a password Button. The dialog shows the password in a mono row with a Copy Button and a button for a new one, a Segment Group for Random or Passphrase, a Slider for the length (8 to 40 characters) or the number of words (4 to 12), four Switches for lowercase, uppercase, numbers and symbols, and a Progress bar with the strength in words. The strength is worked out, not guessed: bits are the length times log2 of the pool, under 50 weak, under 80 fair, then strong. Use this password, the only Shine Button, fills the drawn form's password field. For preview the dialog is drawn open in place when the page loads; the Suggest a password button opens the real Dialog. For sign-up, password changes and any form that asks for a new secret.
FAQ
Why is the dialog already open, and what do I keep?
So you can see it without a click. On load the dialog is a copy drawn in place over the page: a native dialog element that isn't modal, so nothing is trapped, hidden or focused. The Suggest a password button opens the real Dialog, modal, with its focus trap, Escape and focus return, and the copy stays closed until a reload. Both show the same GeneratorFields component and share the block's state. In your app keep the Dialog and drop the copy: the "in-place" state, the scrim and the dialog element inside the frame.
How is the strength worked out?
From how the password was made, which is what entropy measures. A random password is its length times log2 of the number of characters it may use (85 characters for all four kinds is a little over 6.4 bits each); a passphrase is its words times 7 bits, because the word list holds 128. Under 50 bits reads Weak, under 80 Fair, then Strong, and the numbers sit in FAIR_AT and STRONG_AT. It says nothing about a password a person typed: judging those is a different problem.
Where does the randomness come from?
From the browser's crypto.getRandomValues, with rejection sampling so no character is likelier than another, and only when you press something: a new password is drawn in a handler, never while rendering, so the first paint is the same everywhere. The password shown on load is typed in the file. A random password always holds at least one character of each kind that is switched on.
Why can't I turn the last switch off?
A password has to be made of something. The last kind that is on stays on, a note beside the strength says so ("Keep at least one kind on") and the status message repeats it. In Passphrase mode the switches are disabled because they don't apply; the slider counts words instead.
What stays local, and how do I wire it for real?
Copy is the real clipboard (it needs a secure page, and says so when the browser refuses). Nothing is stored or sent: Use this password only fills the drawn form's password field with dots and says where they came from. In your app pass the password to your form's field in use, let the browser's password manager offer to save it, and never log it.
Is it accessible from the keyboard?
Yes. The real dialog is named by its title and described by its sentence, focus starts on the Copy button and stays inside until it closes, and Escape, Cancel and the close button return focus to the header's button. The kind of password is a group of two with arrow keys, the slider takes the arrow keys, and each switch is a labelled control. The trigger is the Suggest a password button wrapped in DialogTrigger with asChild, and the dialog is controlled with open and onOpenChange. The password is never read out by the status message, only its length and strength.