Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Preview Password Type Bundle Laravel Package

codeplace-io/preview-password-type-bundle

Symfony bundle providing a PreviewPasswordType form field that adds a show/hide toggle to password inputs, letting users preview what they type. Easy to install, configure, and drop into existing Symfony forms for improved usability and fewer typos. Includes a configurable toggle and works with stan...

View on GitHub
Deep Wiki
Context7

Getting Started

This is a Symfony bundle, not a Laravel package. There is no service provider, no config file Laravel would auto-discover, and nothing that will render in Blade out of the box. Treat it as a reference implementation for a show/hide password field and port the pieces you need.

Read the repository in this order before writing any code:

  1. src/Form/Type/PreviewPasswordType.php — the actual form type. Note which options it adds (show_label, hide_label, toggle, etc.) and whether it extends PasswordType or TextType.
  2. Resources/views/ — the Twig template. This is the markup you will translate to Blade; it tells you the wrapper structure and class names.
  3. Resources/public/js/ (or an inline <script> in the template) — the toggle logic. Check whether it binds on DOMContentLoaded, by class, or by data-* attribute.
  4. DependencyInjection/ and Resources/config/services.yaml — usually trivial for a bundle this size, but confirms there is no hidden behavior.
  5. composer.json — required Symfony Form/Twig versions. If those are old, expect the Twig syntax to need small adjustments when porting.

First use case: the "eye" toggle on a login form or a change-password form.

Minimal Laravel path:

{{-- resources/views/components/password-input.blade.php --}}
@props(['name' => 'password', 'id' => null, 'autocomplete' => 'current-password'])
@php $id = $id ?? $name; @endphp

<div class="relative" x-data="{ show: false }">
    <input
        :type="show ? 'text' : 'password'"
        type="password"
        id="{{ $id }}"
        name="{{ $name }}"
        autocomplete="{{ $autocomplete }}"
        {{ $attributes->merge(['class' => 'form-input pr-10']) }}
    >
    <button type="button" @click="show = !show"
            :aria-pressed="show"
            aria-label="Show password"
            class="absolute inset-y-0 right-0 px-3">
        <span x-text="show ? 'Hide' : 'Show'"></span>
    </button>
</div>

That gives you 90% of what the bundle does, with zero Symfony dependencies.

Implementation Patterns

Single component, many forms. Use the same <x-password-input> in login, register, password reset, and password change. Pass autocomplete="current-password" for login/change and autocomplete="new-password" for register/reset. Keeping one component avoids the drift you get when each form rolls its own toggle.

Progressive enhancement. Render type="password" server-side and let JS flip it. If JS fails, the field still works. Never render type="text" by default.

Alpine is the path of least resistance in Laravel (Breeze, Jetstream, Filament all ship it). Vanilla equivalent if you are not using Alpine:

document.addEventListener('click', (e) => {
  const btn = e.target.closest('[data-toggle-password]');
  if (!btn) return;
  const input = document.getElementById(btn.dataset.togglePassword);
  const showing = input.type === 'text';
  input.type = showing ? 'password' : 'text';
  btn.setAttribute('aria-pressed', String(!showing));
});

Delegation matters here — see the gotchas.

Livewire. Put the toggle state in Alpine (x-data), not a Livewire property, so re-renders don't reset it. Bind the input with wire:model as usual; the type attribute is a DOM concern and does not need to round-trip.

Symfony context. If you actually are in a Symfony app, register the bundle in config/bundles.php and use PreviewPasswordType directly in your form builder. Override the form theme block if you need custom markup.

Asset registration. If you port any JS from the bundle, add it as a Vite entry (resources/js/password-toggle.js) and import it in app.js. Do not inline it in the Blade component if you have a CSP.

Gotchas and Tips

Framework mismatch is the big one. composer require codeplace-io/preview-password-type-bundle into a Laravel app will pull in Symfony Form and Twig as transitive dependencies and do nothing useful. The bundle is small enough that copying two files is cleaner and avoids a dependency graph you'll regret at upgrade time.

Password managers. Flipping type between password and text can cause 1Password, Bitwarden, and Chrome's built-in manager to re-prompt or stop offering autofill. Keep autocomplete correct and test against the managers your users actually have. Avoid toggling on page load.

Never repopulate the password value. Laravel's old('password') will happily echo a submitted password back into the HTML. Always render value="" on password inputs, including the toggle component, and never add old() to it.

Cursor and selection jump. Changing input.type resets the caret to the end. If the user is mid-edit with the value shown, save selectionStart/selectionEnd before the toggle and restore after. Small detail, noticeable in long passwords.

Accessibility. Use a real <button type="button"> with aria-pressed and an aria-label. A bare <i class="fa-eye"> with a click handler is not focusable and not announced. type="button" is mandatory — a default submit button will submit the form when clicked.

Rebinding after DOM swaps. If the toggle stops working after a Livewire update, an HTMX swap, or a modal open, the bundle's script is almost certainly bound on DOMContentLoaded. Rewrite it as delegated on document (as above) rather than debugging the timing.

Naming collisions in hybrid setups. If you keep both a Symfony and a Laravel codebase, don't call your Blade component preview-password and your form type PreviewPasswordType in ways that get confused during copy-paste. Namespace the Blade component (x-forms.password) and its props explicitly.

Debugging checklist for a dead toggle:

  • Inspect the rendered input — is type="password" still there?
  • Does the button have type="button"?
  • Is Alpine/your entry actually loaded on this page (check Network tab, not just vite.config.js)?
  • Was the bundle's JS inline in the Twig template and did you forget to copy it?

Extension points. In Symfony, override the form theme block. In Laravel, expose the icon as a <x-slot:icon> so consumers can swap an SVG for a font icon without editing the component. Keep the labels (show_label / hide_label equivalents) as props so they can be translated with __().

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
gmostafa/php-graphql-client
xeviant/paystack
snowsoft/faker
meditationsteps/blogetc
animalyoung/laravel-influxdb
onix-solutions/sms-telera
lonely-lights/prosetta
oxygen/data
oxygen/core
jengo/base
xiloryx/log-collector
a21ns1g4ts/filament-stripe
la-php/laravel-admin
artisan-build/community-prompts
vleroy/smart
ayles-software/laravel-australian-public-holidays
cboxdk/laravel-id-spatie
cboxdk/laravel-id-billing
cboxdk/laravel-id-billing-bridge
simple-as-fuck/php-performance-log