# Temporary Solution for Reveal Password Feature \[Visible Eye\]

**URL:** <https://community.hivepress.io/t/temporary-solution-for-reveal-password-feature-visible-eye/17082>\
**Category:** HivePress\
**Tags:** code\
**Created:** [November 15, 2025, 3:48pm UTC](https://community.hivepress.io/t/temporary-solution-for-reveal-password-feature-visible-eye/17082 "2025-11-15T15:48:49Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![Marcel1987](https://community.hivepress.io/letter_avatar_proxy/v4/letter/m/ecd19e/32.png) [@Marcel1987](https://community.hivepress.io/u/Marcel1987)\
**Post date:** [November 15, 2025, 3:48pm UTC](https://community.hivepress.io/t/temporary-solution-for-reveal-password-feature-visible-eye/17082/1 "2025-11-15T15:48:49Z")

</div>

Hello Community,

I’ve written a code snippet that allows you to add an eye icon to the password field of the HivePress login. This lets you see your password and vice versa.

I implemented it using “Code Snippets”.

- Create a new snippet

- Give it a name

- Display in all areas

- PHP

- 

```php
add_action('wp_footer', function () {

    // Nur auf Seiten mit dem HivePress Login-Formular
    if (!apply_filters('hivepress_is_login_page', is_page())) {
        return;
    }
    ?>

    <style>
    /* Input-Wrap korrekt positionieren */
    .hp-password-wrapper {
        position: relative;
    }

    .hp-password-toggle {
        position: absolute;
        right: 12px;
        top: 50%;
        transform: translateY(-50%);
        background: none;
        border: none;
        padding: 0;
        cursor: pointer;
        opacity: 0.7;
        width: 24px;
        height: 24px;
    }

    .hp-password-toggle:hover {
        opacity: 1;
    }

    .hp-password-toggle svg {
        width: 22px;
        height: 22px;
        pointer-events: none;
    }
    </style>

    <script>
    document.addEventListener("DOMContentLoaded", function () {

        function initPasswordToggle() {
            // Passwortfeld sicher abfragen (HivePress-Login)
            const pwField = document.querySelector('form input[type="password"][name="password"]');
            if (!pwField) return;

            // Wrapper nur erstellen, wenn nicht vorhanden
            if (!pwField.parentElement.classList.contains("hp-password-wrapper")) {
                const wrapper = document.createElement("div");
                wrapper.classList.add("hp-password-wrapper");

                // Input in Wrapper einbetten
                pwField.parentNode.insertBefore(wrapper, pwField);
                wrapper.appendChild(pwField);
            }

            const wrapper = pwField.parentElement;

            // Button nur einmal einfügen
            if (wrapper.querySelector(".hp-password-toggle")) return;

            const btn = document.createElement("button");
            btn.type = "button";
            btn.className = "hp-password-toggle";

            btn.innerHTML = `
            <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
                <path d="M1 12s4-7 11-7 11 7 11 7-4 7-11 7-11-7-11-7z"></path>
                <circle cx="12" cy="12" r="3"></circle>
            </svg>
            `;

            wrapper.appendChild(btn);

            let visible = false;

            btn.addEventListener("click", function () {
                visible = !visible;
                pwField.type = visible ? "text" : "password";

                btn.innerHTML = visible
                    ? `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
                        <path d="M17.94 17.94A10.94 10.94 0 0 1 12 19c-7 0-11-7-11-7a21.77 21.77 0 0 1 5.06-5.94"/>
                        <path d="M1 1l22 22"/>
                        <path d="M14.12 14.12A3 3 0 0 1 9.88 9.88"/>
                    </svg>`
                    : `<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
                        <path d="M1 12s4-7 11-7 11 7 11 7-4 7-11 7-11-7-11-7z"></path>
                        <circle cx="12" cy="12" r="3"></circle>
                    </svg>`;
            });
        }

        // 1. sofort versuchen
        initPasswordToggle();

        // 2. wiederholen, falls HivePress dynamisch nachlädt
        setTimeout(initPasswordToggle, 300);
        setTimeout(initPasswordToggle, 800);
    });
    </script>

    <?php
});

```

- Save and activate

I hope everyone who’s been looking for this solution enjoys it.

Best regards, Marcel

---

<div class="post-metadata">

**Author:** ![ChrisB](https://community.hivepress.io/user_avatar/community.hivepress.io/chrisb/32/14185_2.png) [@ChrisB](https://community.hivepress.io/u/ChrisB)\
**Post date:** [November 15, 2025, 4:03pm UTC](https://community.hivepress.io/t/temporary-solution-for-reveal-password-feature-visible-eye/17082/2 "2025-11-15T16:03:30Z")

</div>

Thanks for sharing this, @Marcel1987! 🙌

---

<div class="post-metadata">

**Author:** ![Marcel1987](https://community.hivepress.io/letter_avatar_proxy/v4/letter/m/ecd19e/32.png) [@Marcel1987](https://community.hivepress.io/u/Marcel1987)\
**Post date:** [November 15, 2025, 4:21pm UTC](https://community.hivepress.io/t/temporary-solution-for-reveal-password-feature-visible-eye/17082/3 "2025-11-15T16:21:30Z")

</div>

Thank you. @ChrisB

I’m also currently working on code that requires a double password entry for registration, and that allows users to view the password.

Most importantly, registration shouldn’t be possible unless the password is entered twice.

---

<div class="post-metadata">

**Author:** ![Marcel1987](https://community.hivepress.io/letter_avatar_proxy/v4/letter/m/ecd19e/32.png) [@Marcel1987](https://community.hivepress.io/u/Marcel1987)\
**Post date:** [November 15, 2025, 4:57pm UTC](https://community.hivepress.io/t/temporary-solution-for-reveal-password-feature-visible-eye/17082/4 "2025-11-15T16:57:53Z")

</div>

I’ve now added a second field to the registration process. This makes the code visible, and registration is blocked if the password is different twice. Additionally, a score of at least 8 characters (Easy, Medium, Strong) is displayed. Since I’m a German user, you only need to adjust the code sections to your language.

The same procedure applies when going to the “Code Snippet” section.

-Create a new snippet  
-Give it a name  
-PHP  
-Show on all pages

```php
<?php
/**
 * 1) PHP: Registrierungsformular-Feld 'password_confirm' hinzufügen
 * Sowie: Ein Hook nach dem 'password'-Feld, um den Score-Container einzufügen.
 */
add_filter('hivepress/v1/forms/user_register', function ($form) {

    if (isset($form['fields']['password'])) {

        $new_fields = [];

        foreach ($form['fields'] as $key => $field) {
            $new_fields[$key] = $field;

            if ($key === 'password') {
                // Fügen Sie nach dem 'password'-Feld einen unsichtbaren Platzhalter ein,
                // in den wir den Score-Container über JS/HTML einfügen können,
                // oder wir nutzen wp_footer, um es zu platzieren (was wir in 3 machen).

                // password_confirm direkt nach password
                $new_fields['password_confirm'] = [
                    'type' => 'password',
                    'label' => __('Passwort bestätigen', 'hivepress'),
                    'required' => true,
                    // Wenn du das Placeholder wieder entfernen möchtest, lass es weg:
                    // 'placeholder' => __('Passwort wiederholen', 'hivepress'),
                    'display_type'=> 'password',
                ];
            }
        }

        $form['fields'] = $new_fields;
    }

    return $form;
});

/**
 * 2) Server-seitige Validierung: Passwörter gleich? (Unverändert)
 */
add_filter('hivepress/v1/models/user/validate', function ($errors, $model) {

    $request = hivepress()->request;

    if (!$request) return $errors;

    $password = $request->get_param('password');
    $confirm = $request->get_param('password_confirm');

    if (empty($password) && empty($confirm)) {
        return $errors;
    } elseif ($password !== $confirm) {
        $errors['password_confirm'] = __('Die beiden Passwörter stimmen nicht überein.', 'hivepress');
    }

    // Optional: Server-seitige Mindestlängenprüfung (zusätzlich zu HivePress' required)
    if (!empty($password) && strlen($password) < 8) {
        $errors['password'] = __('Das Passwort muss mindestens 8 Zeichen lang sein.', 'hivepress');
    }

    return $errors;
}, 10, 2);

/**
 * 3) JS + CSS: Positionierung, Icons, Live-Check UND PASSWORD STRENGTH
 */
add_action('wp_footer', function () {

    // nur auf HivePress-Registrierungsseite
    if (!apply_filters('hivepress_is_register_page', is_page())) {
        return;
    }
    ?>

    <style>
    .hp-form __field--password_confirm .hp-form__ field__label {
        display: block !important;
        visibility: visible !important;
        position: static !important;
        height: auto !important;
        width: auto !important;
        margin-bottom: 5px !important;
    }
    label[for="password_confirm"] {
        display: block !important;
        visibility: visible !important;
        position: static !important;
        height: auto !important;
        width: auto !important;
        z-index: 10 !important; 
        margin-bottom: 5px !important;
        color: #333333 !important;
        font-weight: bold !important;
    }

    /* ----------------------------------------------------------------
    * NEUES CSS FÜR DEN PASSWORD-SCORE
    * ---------------------------------------------------------------- */
    #password-strength {
        margin-top: 6px;
        font-size: 13px;
        line-height: 1.4;
        min-height: 20px; /* Hält den Platz, damit das Layout nicht springt */
    }

    /* Style für die verschiedenen Stärken */
    .strength-indicator {
        display: inline-block;
        font-weight: bold;
        padding: 2px 6px;
        border-radius: 4px;
        color: #ffffff; /* Weißer Text auf farbigem Hintergrund */
        margin-left: 5px;
    }

    /* Farben für die Stärken */
    .strength-weak {
        background-color: #ff4136; /* Rot */
    }
    .strength-medium {
        background-color: #ff851b; /* Orange */
    }
    .strength-strong {
        background-color: #2ecc40; /* Grün */
    }

    /* Wrapper für Input, damit das Icon absolut positioniert werden kann */
    .hp-password-wrapper {
        position: relative;
        display: block;
        width: 100%;
    }
    /* Input bleibt 100% Breite */
    .hp-password-wrapper input {
        width: 100%;
        box-sizing: border-box;
        padding-right: 44px; /* Platz für das Icon */
    }
    .hp-password-toggle {
        position: absolute;
        right: 12px;
        top: 50%;
        transform: translateY(-50%);
        background: none;
        border: none;
        cursor: pointer;
        width: 32px;
        height: 32px;
        display: flex;
        align-items: center;
        justify-content: center;
        padding: 0;
        opacity: .8;
    }
    .hp-password-toggle:hover { opacity: 1; }
    /* Schönes, dünnes SVG wie im Beispiel zuvor */
    .hp-password-toggle svg {
        width: 20px;
        height: 20px;
        stroke: currentColor;
        fill: none;
        stroke-width: 1.6;
        pointer-events: none;
    }
    /* Fehlertext unter dem Feld */
    .hp-password-error {
        color: #d63638;
        font-size: 13px;
        margin-top: 6px;
    }
    /* Optional: roter Rahmen, wenn ungültig */
    .hp-password-mismatch input {
        border-color: #d63638 !important;
        box-shadow: 0 0 0 1px rgba(214,54,56,0.08);
    }
    </style>

    <script>
    (function () {
        // Utility: SVG Icons (hidden / visible)
        const SVG_EYE = `<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
            <path d="M1 12s4-7 11-7 11 7 11 7-4 7-11 7-11-7-11-7z" />
            <circle cx="12" cy="12" r="3" />
        </svg>`;

        const SVG_EYE_OFF = `<svg viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" aria-hidden="true">
            <path d="M17.94 17.94A10.94 10.94 0 0 1 12 19c-7 0-11-7-11-7a21.77 21.77 0 0 1 5.06-5.94"/>
            <path d="M1 1l22 22"/>
            <path d="M14.12 14.12A3 3 0 0 1 9.88 9.88"/>
        </svg>`;

        
        /**
         * NEUE FUNKTION: Passwortstärke prüfen
         * Prüft Länge (8 Zeichen) und Komplexität (leicht/mittel/stark).
         */
        function checkPasswordStrength(password) {
            let score = 0;
            const lengthOk = password.length >= 8;

            if (password.length > 0) {
                // Kriterium 1: Länge
                if (password.length >= 8) {
                    score += 1;
                }

                // Kriterium 2: Klein- oder Großbuchstaben
                if (password.match(/[a-z]/) || password.match(/[A-Z]/)) {
                    score += 1;
                }

                // Kriterium 3: Zahlen
                if (password.match(/\d/)) {
                    score += 1;
                }

                // Kriterium 4: Sonderzeichen
                if (password.match(/[^a-zA-Z\d\s]/)) {
                    score += 1;
                }
            }

            // Definiere die Stufen (Score 0-4)
            let strengthText = '';
            let strengthClass = '';

            if (password.length === 0) {
                strengthText = '';
                strengthClass = '';
            } else if (score < 2) {
                strengthText = 'Schwach';
                strengthClass = 'strength-weak';
            } else if (score <= 3) {
                strengthText = 'Mittel';
                strengthClass = 'strength-medium';
            } else {
                strengthText = 'Stark';
                strengthClass = 'strength-strong';
            }

            return { score, strengthText, strengthClass, lengthOk };
        }

        // Hilfsfunktionen (Unverändert)
        function addWrapperIfMissing(input) {
            if (!input) return null;
            if (input.parentElement && input.parentElement.classList.contains('hp-password-wrapper')) {
                return input.parentElement;
            }
            const wrapper = document.createElement('div');
            wrapper.className = 'hp-password-wrapper';
            input.parentNode.insertBefore(wrapper, input);
            wrapper.appendChild(input);
            return wrapper;
        }

        function addToggle(input) {
            if (!input) return;
            const wrapper = addWrapperIfMissing(input);
            if (!wrapper) return;
            if (wrapper.querySelector('.hp-password-toggle')) return;
            const btn = document.createElement('button');
            btn.type = 'button';
            btn.className = 'hp-password-toggle';
            btn.setAttribute('aria-label', 'Passwort anzeigen');
            btn.innerHTML = SVG_EYE;
            let visible = false;
            btn.addEventListener('click', function (e) {
                e.preventDefault();
                visible = !visible;
                input.type = visible ? 'text' : 'password';
                btn.setAttribute('aria-label', visible ? 'Passwort verbergen' : 'Passwort anzeigen');
                btn.innerHTML = visible ? SVG_EYE_OFF : SVG_EYE;
            });
            btn.addEventListener('keydown', function (e) {
                if (e.key === ' ' || e.key === 'Enter') {
                    e.preventDefault();
                    btn.click();
                }
            });
            wrapper.appendChild(btn);
        }

        function ensureConfirmPosition(passwordInput, confirmInput) {
            if (!passwordInput || !confirmInput) return;
            const findFieldWrapper = (input) => {
                let current = input.parentNode;
                while (current && current.tagName !== 'FORM' && current.tagName !== 'BODY') {
                    if (current.classList.contains('hp-form__field')) { 
                        return current;
                    }
                    current = current.parentNode;
                }
                return null;
            };

            const pwdFieldWrap = findFieldWrapper(passwordInput);
            const confFieldWrap = findFieldWrapper(confirmInput);

            if (!pwdFieldWrap || !confFieldWrap) return;
            if (pwdFieldWrap.nextSibling === confFieldWrap) return;

            if (pwdFieldWrap.parentNode) {
                pwdFieldWrap.parentNode.insertBefore(confFieldWrap, pwdFieldWrap.nextSibling);
            }
        }
        

        function addClientValidation(form, pwInput, confirmInput) {
            if (!form || !pwInput || !confirmInput) return;

            // Fehler-Element (Passwort-Mismatch)
            let err = form.querySelector('.hp-password-error');
            if (!err) {
                err = document.createElement('div');
                err.className = 'hp-password-error';
                const confWrap = confirmInput.parentElement;
                const fieldWrapper = confWrap.closest('.hp-form__field') || confWrap.parentNode;
                if(fieldWrapper) {
                     fieldWrapper.parentNode.insertBefore(err, fieldWrapper.nextSibling);
                } else {
                     confWrap.parentNode.insertBefore(err, confWrap.nextSibling);
                }
            }
            
            // NEUES Element: Passwortstärke-Anzeige
            let strengthDiv = form.querySelector('#password-strength');
            if (!strengthDiv) {
                strengthDiv = document.createElement('div');
                strengthDiv.id = 'password-strength';
                
                // Wir finden den Wrapper des Haupt-Passwortfeldes
                const pwWrap = pwInput.parentElement;
                const pwFieldWrapper = pwWrap.closest('.hp-form__field') || pwWrap.parentNode;

                // Position: direkt nach dem Haupt-Passwortfeld-Wrapper
                if(pwFieldWrapper) {
                     pwFieldWrapper.parentNode.insertBefore(strengthDiv, pwFieldWrapper.nextSibling);
                } else {
                     pwWrap.parentNode.insertBefore(strengthDiv, pwWrap.nextSibling);
                }
            }

            function updateVisualState() {
                const pw = pwInput.value || '';
                const cf = confirmInput.value || '';
                
                // 1. Passwort-Stärke prüfen und anzeigen
                const strength = checkPasswordStrength(pw);
                
                // Anzeige der 8-Zeichen-Prüfung + Stärke
                let strengthHtml = '';
                if (pw.length > 0) {
                    const lengthStatus = strength.lengthOk 
                        ? '✅ Mindestens 8 Zeichen' 
                        : '❌ Mindestens 8 Zeichen';
                    
                    strengthHtml = `${lengthStatus} 
                                    <span class="strength-indicator ${strength.strengthClass}">
                                        ${strength.strengthText}
                                    </span>`;
                }
                strengthDiv.innerHTML = strengthHtml;
                

                // 2. Passwort-Mismatch-Prüfung
                const fieldWrapper = confirmInput.closest('.hp-form__field') || confirmInput.parentElement;

                if (pw === '' && cf === '') {
                    confirmInput.setCustomValidity('');
                    err.textContent = '';
                    fieldWrapper.classList.remove('hp-password-mismatch');
                    return;
                }

                if (pw === cf) {
                    confirmInput.setCustomValidity('');
                    err.textContent = '';
                    fieldWrapper.classList.remove('hp-password-mismatch');
                } else {
                    confirmInput.setCustomValidity('Die Passwörter stimmen nicht überein.');
                    err.textContent = 'Die Passwörter stimmen nicht überein.';
                    fieldWrapper.classList.add('hp-password-mismatch');
                }
            }

            // Live-Feedback
            pwInput.addEventListener('input', updateVisualState);
            confirmInput.addEventListener('input', updateVisualState);

            // Beim Submit: blockieren, wenn unterschiedlich oder zu kurz
            form.addEventListener('submit', function (e) {
                const pw = pwInput.value || '';
                const cf = confirmInput.value || '';
                const strength = checkPasswordStrength(pw);

                let shouldPrevent = false;

                if (pw !== cf) {
                    shouldPrevent = true;
                }
                
                // Client-seitige Prüfung der Mindestlänge (muss mit Server-seitig übereinstimmen)
                if (!strength.lengthOk && pw.length > 0) {
                    shouldPrevent = true;
                    // Fügt visuelle Hinweise für die Länge hinzu, falls nicht vorhanden
                    if (!strengthDiv.textContent.includes('Mindestens 8 Zeichen')) {
                         updateVisualState();
                    }
                }
                
                if (shouldPrevent) {
                    e.preventDefault();
                    e.stopPropagation();
                    updateVisualState();

                    // Fokus auf das Feld, das den Fehler verursacht
                    if (pw !== cf) {
                        confirmInput.focus();
                    } else if (!strength.lengthOk) {
                        pwInput.focus();
                    }
                }
            });
            // Initialer Check, falls der Browser Passwörter vorausfüllt
            updateVisualState();
        }

        // Haupt-Init (Unverändert)
        function initRegistrationPasswordFeatures() {
            const forms = Array.from(document.querySelectorAll('form'));

            let registerForm = null;
            for (let f of forms) {
                if (f.querySelector('input[name="password"]') && (f.querySelector('input[name="email"]') || f.querySelector('input[name="username"]'))) {
                    registerForm = f;
                    break;
                }
            }

            if (!registerForm) {
                registerForm = forms.find(f => f.querySelector('input[name="password_confirm"]')) || document.querySelector('form');
                if (!registerForm) return;
            }

            const pwInput = registerForm.querySelector('input[name="password"]');
            const confirmInput = registerForm.querySelector('input[name="password_confirm"]');

            if (!pwInput || !confirmInput) return;

            ensureConfirmPosition(pwInput, confirmInput);
            addToggle(pwInput);
            addToggle(confirmInput);
            addClientValidation(registerForm, pwInput, confirmInput);
        }

        initRegistrationPasswordFeatures();
        setTimeout(initRegistrationPasswordFeatures, 250);
        setTimeout(initRegistrationPasswordFeatures, 700);
        setTimeout(initRegistrationPasswordFeatures, 1500);
    })();
    </script>

    <?php
});

```

Save

I hope this helps some users!

---

<div class="post-metadata">

**Author:** ![ChrisB](https://community.hivepress.io/user_avatar/community.hivepress.io/chrisb/32/14185_2.png) [@ChrisB](https://community.hivepress.io/u/ChrisB)\
**Post date:** [November 15, 2025, 5:02pm UTC](https://community.hivepress.io/t/temporary-solution-for-reveal-password-feature-visible-eye/17082/5 "2025-11-15T17:02:06Z")

</div>

I love when people like yourself join the community!

Thank you for sharing this snippet, as well, @Marcel1987.

---

<div class="post-metadata">

**Author:** ![kseniia](https://community.hivepress.io/user_avatar/community.hivepress.io/kseniia/32/13513_2.png) [@kseniia](https://community.hivepress.io/u/kseniia)\
**Post date:** [November 17, 2025, 2:07pm UTC](https://community.hivepress.io/t/temporary-solution-for-reveal-password-feature-visible-eye/17082/6 "2025-11-17T14:07:40Z")

</div>

Hi,

Thank you for sharing your solutions and contributing to the community! This can be very helpful for others.

---

<div class="post-metadata">

**Author:** ![Marcel1987](https://community.hivepress.io/letter_avatar_proxy/v4/letter/m/ecd19e/32.png) [@Marcel1987](https://community.hivepress.io/u/Marcel1987)\
**Post date:** [December 1, 2025, 5:02am UTC](https://community.hivepress.io/t/temporary-solution-for-reveal-password-feature-visible-eye/17082/7 "2025-12-01T05:02:16Z")

</div>

Hello community,

I’ve revised my code again today, as it only worked with the pop-up.

Now it also works with the regular login field and registration.

Insert the code as before in the plugin or in the functions.php file.

Code Login:

```php
add_action('wp_footer', function () {

    // Nur dort aktivieren, wo ein HivePress Login-Feld existiert
    if ( !apply_filters('hivepress_is_login_page', is_page()) ) {
        // Trotzdem nicht abbrechen – auch Popups müssen funktionieren!
        // => wir prüfen im Script selbst die Felder
    }
    ?>

    <style>
    .hp-password-wrapper {
        position: relative;
        width: 100%;
    }
    .hp-password-wrapper input[type="password"] {
        width: 100%;
        padding-right: 44px;
    }
    .hp-password-toggle {
        position: absolute;
        right: 12px;
        top: 50%;
        transform: translateY(-50%);
        background: none;
        border: none;
        cursor: pointer;
        width: 28px;
        height: 28px;
        padding: 0;
        opacity: .75;
    }
    .hp-password-toggle:hover {
        opacity: 1;
    }
    .hp-password-toggle svg {
        width: 22px;
        height: 22px;
        stroke: currentColor;
        fill: none;
        stroke-width: 2;
        pointer-events: none;
    }
    </style>

    <script>
    document.addEventListener("DOMContentLoaded", function () {

        const EYE = `
            <svg viewBox="0 0 24 24">
                <path d="M1 12s4-7 11-7 11 7 11 7-4 7-11 7-11-7-11-7z"></path>
                <circle cx="12" cy="12" r="3"></circle>
            </svg>
        `;

        const EYE_OFF = `
            <svg viewBox="0 0 24 24">
                <path d="M17.94 17.94A10.94 10.94 0 0 1 12 19c-7 0-11-7-11-7a21.77 21.77 0 0 1 5.06-5.94"/>
                <path d="M1 1l22 22"/>
                <path d="M14.12 14.12A3 3 0 0 1 9.88 9.88"/>
            </svg>
        `;

        function enhancePasswordFields() {

            // Suche ALLE Passwortfelder – sowohl Popup, als auch normales Formular
            const pwFields = document.querySelectorAll('input[type="password"][name="password"]');

            if (!pwFields.length) return;

            pwFields.forEach(function (pw) {

                // Bereits erweitert?
                if (pw.parentElement.classList.contains("hp-password-wrapper")) return;

                // Wrapper erzeugen
                const wrapper = document.createElement("div");
                wrapper.classList.add("hp-password-wrapper");

                pw.parentNode.insertBefore(wrapper, pw);
                wrapper.appendChild(pw);

                // Button erstellen
                const btn = document.createElement("button");
                btn.type = "button";
                btn.className = "hp-password-toggle";
                btn.innerHTML = EYE;

                wrapper.appendChild(btn);

                // Toggle-Logik
                let visible = false;
                btn.addEventListener("click", function () {
                    visible = !visible;
                    pw.type = visible ? "text" : "password";
                    btn.innerHTML = visible ? EYE_OFF : EYE;
                });

            });
        }

        // Sofort ausführen
        enhancePasswordFields();

        // Wiederholen, da HivePress Popups dynamisch geladen werden
        setTimeout(enhancePasswordFields, 250);
        setTimeout(enhancePasswordFields, 700);
        setTimeout(enhancePasswordFields, 1500);
        setInterval(enhancePasswordFields, 2000); // Sicherheit für spätes Rendering

    });
    </script>

    <?php
});

```

Code registration:

```php
<?php
/**
 * Final: Universaler HivePress Registration Enhancer (Verbessert)
 * - Vermeidet doppelte Elemente / mehrfaches Initialisieren
 * - Sorgt für korrekte Reihenfolge und nur eine Fehlermeldung / Score-Anzeige
 * - Fügt password_confirm (server-side) hinzu, validiert server- & client-side
 */

/**
 * 1) Server-seitig: password_confirm direkt nach password einfügen (wenn noch nicht vorhanden)
 */
add_filter('hivepress/v1/forms/user_register', function ($form) {

    if (!isset($form['fields']) || !is_array($form['fields'])) {
        return $form;
    }

    if (isset($form['fields']['password']) && !isset($form['fields']['password_confirm'])) {
        $new_fields = [];
        foreach ($form['fields'] as $key => $field) {
            $new_fields[$key] = $field;
            if ($key === 'password') {
                $new_fields['password_confirm'] = [
                    'type' => 'password',
                    'label' => __('Passwort bestätigen', 'hivepress'),
                    'required' => true,
                    'display_type' => 'password',
                ];
            }
        }
        $form['fields'] = $new_fields;
    }

    return $form;
});

/**
 * 2) Server-seitige Validierung (sichert Registrierung zuverlässig ab)
 */
$validate_callback = function ($errors, $model) {
    $request = hivepress()->request ?? null;
    if (!$request) return $errors;

    $pw = $request->get_param('password');
    $pw2 = $request->get_param('password_confirm');

    if (($pw !== null || $pw2 !== null) && $pw !== $pw2) {
        $errors['password_confirm'] = __('Die eingegebenen Passwörter stimmen nicht überein.', 'hivepress');
    }

    if (!empty($pw) && is_string($pw) && strlen($pw) < 8) {
        $errors['password'] = __('Das Passwort muss mindestens 8 Zeichen lang sein.', 'hivepress');
    }

    return $errors;
};

add_filter('hivepress/v1/models/user_register/validate', $validate_callback, 10, 2);
add_filter('hivepress/v1/models/user/validate', $validate_callback, 10, 2);

/**
 * 3) Frontend: JS + CSS (Icons, Position, Strength, Live-Validation)
 * Verbesserungen: idempotent, keine Duplikate, korrekte Reihenfolge
 */
add_action('wp_footer', function () {
    ?>
    <style>
    .hp-password-wrapper { position: relative; width:100%; }
    .hp-password-wrapper input[type="password"], .hp-password-wrapper input[type="text"] { padding-right:46px; box-sizing:border-box; width:100%; }
    .hp-password-toggle { position:absolute; right:10px; top:50%; transform:translateY(-50%); background:none; border:none; width:36px; height:36px; display:flex; align-items:center; justify-content:center; cursor:pointer; opacity:.85; }
    .hp-password-toggle svg { width:20px; height:20px; stroke:currentColor; fill:none; stroke-width:1.6; pointer-events:none; }
    .hp-password-error { color:#d63638; font-size:13px; margin-top:6px; }
    .hp-password-mismatch input { border-color:#d63638 !important; }
    #hp-password-strength { margin-top:6px; font-size:13px; min-height:20px; }
    .hp-strength-indicator { font-weight:700; padding:2px 6px; border-radius:4px; color:#fff; margin-left:8px; }
    .hp-strength-weak{ background:#ff4136; } .hp-strength-medium{ background:#ff851b; } .hp-strength-strong{ background:#2ecc40; }
    </style>

    <script>
    (function () {

        const SVG_EYE = '<svg viewBox="0 0 24 24"><path d="M1 12s4-7 11-7 11 7 11 7-4 7-11 7-11-7-11-7z"/><circle cx="12" cy="12" r="3"/></svg>';
        const SVG_EYE_OFF = '<svg viewBox="0 0 24 24"><path d="M17.94 17.94A10.94 10.94 0 0 1 12 19c-7 0-11-7-11-7a21.77 21.77 0 0 1 5.06-5.94"/><path d="M1 1l22 22"/><path d="M14.12 14.12A3 3 0 0 1 9.88 9.88"/></svg>';

        /** Erkennung: ist Formular eine Registrierung? (Login explizit ausschließen) */
        function isLikelyRegisterForm(form) {
            if (!form || form.nodeName !== 'FORM') return false;
            const action = (form.getAttribute('action') || form.getAttribute('data-action') || '').toLowerCase();
            const classes = (form.className || '').toLowerCase();

            // Eindeutige Kennzeichen für Login -> ausschließen
            if ( action.includes('/login') ||
                 classes.includes('login') ||
                 classes.includes('hp-form--login') ||
                 form.querySelector('input[name="rememberme"]') ||
                 form.querySelector('input[name="log"]') ) {
                return false;
            }

            // Kennzeichen für Registrierung
            if ( action.includes('/register') ||
                 classes.includes('register') ||
                 classes.includes('hp-form--register') ||
                 (form.querySelector('input[name="email"]') && form.querySelector('input[name="password"]')) ) {
                return true;
            }

            return false;
        }

        /** Einmalige Kennzeichnung einer Form, damit sie nicht mehrfach bearbeitet wird */
        function markFormEnhanced(form) {
            form.classList.add('hp-password-enhanced');
        }
        function isFormEnhanced(form) {
            return form.classList && form.classList.contains('hp-password-enhanced');
        }

        /** Passwortstärke (einfach) */
        function checkPasswordStrength(pw) {
            let score = 0;
            if (!pw || pw.length === 0) return {score:0, text:'', cls:'', lengthOk:false};
            if (pw.length >= 8) score++;
            if (/[a-z]/.test(pw) && /[A-Z]/.test(pw)) score++;
            if (/\d/.test(pw)) score++;
            if (/[^a-zA-Z0-9]/.test(pw)) score++;
            if (score < 2) return {score, text:'Schwach', cls:'hp-strength-weak', lengthOk: pw.length >= 8};
            if (score <= 3) return {score, text:'Mittel', cls:'hp-strength-medium', lengthOk: pw.length >= 8};
            return {score, text:'Stark', cls:'hp-strength-strong', lengthOk: pw.length >= 8};
        }

        /** Wrapper erzeugen oder bestehenden wiederverwenden */
        function addWrapperIfMissing(input) {
            if (!input) return null;
            // Wenn bereits in hp-password-wrapper
            if (input.parentElement && input.parentElement.classList.contains('hp-password-wrapper')) {
                return input.parentElement;
            }

            // Falls .hp-form__field vorhanden, nutzen wir den als Referenz und packen Input hinein
            const fieldWrap = input.closest('.hp-form__field');
            if (fieldWrap) {
                // Wenn fieldWrap bereits einen hp-password-wrapper enthält, nutzen wir diesen
                const existingWrapper = fieldWrap.querySelector('.hp-password-wrapper');
                if (existingWrapper) {
                    // move input inside existingWrapper if not already inside
                    if (input.parentElement !== existingWrapper) {
                        existingWrapper.appendChild(input);
                    }
                    return existingWrapper;
                }
                // Erzeuge inneren wrapper
                const wrapper = document.createElement('div');
                wrapper.className = 'hp-password-wrapper';
                // Füge wrapper an die Stelle des inputs und verschiebe input rein
                input.parentNode.insertBefore(wrapper, input);
                wrapper.appendChild(input);
                return wrapper;
            }

            // Default-Fall: neuen wrapper direkt um das Input legen
            const wrapper = document.createElement('div');
            wrapper.className = 'hp-password-wrapper';
            input.parentNode.insertBefore(wrapper, input);
            wrapper.appendChild(input);
            return wrapper;
        }

        /** Toggle-Button hinzufügen (idempotent) */
        function addToggleToInput(input) {
            if (!input) return;
            const wrapper = addWrapperIfMissing(input);
            if (!wrapper) return;
            if (wrapper.querySelector('.hp-password-toggle')) return; // bereits vorhanden

            const btn = document.createElement('button');
            btn.type = 'button';
            btn.className = 'hp-password-toggle';
            btn.setAttribute('aria-label', 'Passwort anzeigen');
            btn.innerHTML = SVG_EYE;

            let visible = false;
            btn.addEventListener('click', function (e) {
                e.preventDefault();
                visible = !visible;
                try { input.type = visible ? 'text' : 'password'; } catch (err) {}
                btn.setAttribute('aria-label', visible ? 'Passwort verbergen' : 'Passwort anzeigen');
                btn.innerHTML = visible ? SVG_EYE_OFF : SVG_EYE;
            });

            btn.addEventListener('keydown', function (e) {
                if (e.key === ' ' || e.key === 'Enter') {
                    e.preventDefault();
                    btn.click();
                }
            });

            wrapper.appendChild(btn);
        }

        /** Sicherstellen, dass confirm direkt nach password steht (DOM-Reordering) */
        function ensureConfirmAfterPassword(form, pwInput, confirmInput) {
            if (!pwInput || !confirmInput) return;

            const pwFieldWrap = pwInput.closest('.hp-form__field') || pwInput.parentElement;
            const confFieldWrap = confirmInput.closest('.hp-form__field') || confirmInput.parentElement;
            if (!pwFieldWrap || !confFieldWrap) return;

            // Wenn confirm bereits direkt danach steht: fertig
            if (pwFieldWrap.nextSibling === confFieldWrap) return;

            // Verschiebe confirm direkt nach pw
            if (pwFieldWrap.parentNode) {
                pwFieldWrap.parentNode.insertBefore(confFieldWrap, pwFieldWrap.nextSibling);
            }
        }

        /** Falls serverseitig kein confirm vorhanden: clientseitig erzeugen (idempotent) */
        function ensureConfirmField(form, pwInput) {
            if (!form || !pwInput) return null;
            let confirmInput = form.querySelector('input[name="password_confirm"]');
            if (confirmInput) return confirmInput;

            // Erzeuge nur, wenn noch nicht vorhanden
            // prepare markup similar to HivePress
            const fieldWrap = document.createElement('div');
            fieldWrap.className = 'hp-form __field hp-form__ field--password hp-form__field--password_confirm';

            const label = document.createElement('label');
            label.className = 'hp-field __label hp-form__ label';
            label.innerHTML = '<span>Passwort bestätigen</span>';
            fieldWrap.appendChild(label);

            confirmInput = document.createElement('input');
            confirmInput.type = 'password';
            confirmInput.name = 'password_confirm';
            confirmInput.required = true;
            confirmInput.maxLength = 64;
            confirmInput.className = 'hp-field hp-field--password';
            fieldWrap.appendChild(confirmInput);

            // Platziere direkt nach pw field wrapper wenn möglich
            const pwFieldWrap = pwInput.closest('.hp-form__field') || pwInput.parentElement;
            if (pwFieldWrap && pwFieldWrap.parentNode) {
                pwFieldWrap.parentNode.insertBefore(fieldWrap, pwFieldWrap.nextSibling);
            } else {
                // Fallback: in die .hp-form__fields oder ans Ende des Formulars
                const container = form.querySelector('.hp-form__fields') || form;
                container.appendChild(fieldWrap);
            }

            return confirmInput;
        }

        /** Clientseitige Validation: nur ein Fehler-Element & nur eine Strength-Anzeige erzeugen */
        function attachClientValidation(form, pwInput, confirmInput) {
            if (!form || !pwInput || !confirmInput) return;

            // Kennzeichnung, damit wir nicht mehrere Validation-Attachments durchführen
            if (form.dataset.hpValidationAttached === '1') return;
            form.dataset.hpValidationAttached = '1';

            // Error-Element: falls nicht vorhanden erzeugen
            let err = form.querySelector('.hp-password-error');
            if (!err) {
                err = document.createElement('div');
                err.className = 'hp-password-error';
                // Position: nach confirm field wrapper (wenn vorhanden)
                const confWrap = confirmInput.closest('.hp-form__field') || confirmInput.parentElement;
                if (confWrap && confWrap.parentNode) {
                    confWrap.parentNode.insertBefore(err, confWrap.nextSibling);
                } else {
                    confirmInput.parentNode.insertBefore(err, confirmInput.nextSibling);
                }
            }

            // Strength-Element: falls nicht vorhanden erzeugen (ID pro form vermeiden Duplikate)
            let strengthDiv = form.querySelector('.hp-password-strength');
            if (!strengthDiv) {
                strengthDiv = document.createElement('div');
                strengthDiv.className = 'hp-password-strength';
                // Position: nach password field wrapper
                const pwWrap = pwInput.closest('.hp-form__field') || pwInput.parentElement;
                if (pwWrap && pwWrap.parentNode) {
                    pwWrap.parentNode.insertBefore(strengthDiv, pwWrap.nextSibling);
                } else {
                    pwInput.parentNode.insertBefore(strengthDiv, pwInput.nextSibling);
                }
            }

            function updateVisuals() {
                const p = pwInput.value || '';
                const c = confirmInput.value || '';

                // Strength
                const s = checkPasswordStrength(p);
                if (s.text) {
                    strengthDiv.innerHTML = (p.length >= 8 ? '✅ Mindestens 8 Zeichen' : '❌ Mindestens 8 Zeichen')
                        + ' <span class="hp-strength-indicator ' + s.cls + '">' + s.text + '</span>';
                } else {
                    strengthDiv.innerHTML = '';
                }

                // Match
                const confWrap = confirmInput.closest('.hp-form__field') || confirmInput.parentElement;
                if (p === '' && c === '') {
                    err.textContent = '';
                    confirmInput.setCustomValidity('');
                    confWrap.classList.remove('hp-password-mismatch');
                    return true;
                }

                if (p === c) {
                    err.textContent = '';
                    confirmInput.setCustomValidity('');
                    confWrap.classList.remove('hp-password-mismatch');
                    return s.lengthOk;
                } else {
                    err.textContent = 'Die Passwörter stimmen nicht überein.';
                    confirmInput.setCustomValidity('Die Passwörter stimmen nicht überein.');
                    confWrap.classList.add('hp-password-mismatch');
                    return false;
                }
            }

            // Live events (idempotent)
            pwInput.removeEventListener && pwInput.removeEventListener('input', updateVisuals);
            confirmInput.removeEventListener && confirmInput.removeEventListener('input', updateVisuals);
            pwInput.addEventListener('input', updateVisuals);
            confirmInput.addEventListener('input', updateVisuals);

            // Submit interception: capture + mousedown + click on submit buttons
            function preventIfInvalid(e) {
                const ok = updateVisuals();
                const p = pwInput.value || '';
                const s = checkPasswordStrength(p);

                if (!ok || !s.lengthOk) {
                    if (e && e.preventDefault) e.preventDefault();
                    if (e && e.stopImmediatePropagation) e.stopImmediatePropagation();
                    if (e && e.stopPropagation) e.stopPropagation();
                    // Fokus aufs fehlerhafte Feld
                    if (!ok) confirmInput.focus(); else pwInput.focus();
                    return false;
                }
                return true;
            }

            // Capture submit early
            form.addEventListener('submit', function (e) { preventIfInvalid(e); }, true);

            // Buttons
            const submits = Array.from(form.querySelectorAll('button[type="submit"], input[type="submit"]'));
            submits.forEach(btn => {
                // avoid duplicate attachments
                if (btn.dataset.hpSubmitHook === '1') return;
                btn.dataset.hpSubmitHook = '1';
                btn.addEventListener('click', function (e) { preventIfInvalid(e); }, true);
                btn.addEventListener('mousedown', function (e) { preventIfInvalid(e); }, true);
            });

            // Initial run for autofill
            setTimeout(updateVisuals, 120);
        }

        /** Enhance a single form once */
        function enhanceRegisterForm(form) {
            if (!isLikelyRegisterForm(form)) return;
            if (isFormEnhanced(form)) return; // schon bearbeitet

            // Markieren (vermeidet Double-Processing)
            markFormEnhanced(form);

            // Finde password (Hauptfeld)
            const pwInput = form.querySelector('input[name="password"]') || form.querySelector('input[type="password"]');
            if (!pwInput) return;

            // Confirm (falls nicht vorhanden clientseitig erzeugen)
            const confirmInput = ensureConfirmField(form, pwInput);
            if (!confirmInput) return;

            // Stelle Reihenfolge sicher
            ensureConfirmAfterPassword(form, pwInput, confirmInput);

            // Icons setzen
            addToggleToInput(pwInput);
            addToggleToInput(confirmInput);

            // Validation & Strength (einmalig)
            attachClientValidation(form, pwInput, confirmInput);
        }

        /** Initial scan + MutationObserver zum Erfassen dynamischer Inserts */
        function initEnhancer() {
            // einmaliger Scan
            Array.from(document.querySelectorAll('form')).forEach(form => enhanceRegisterForm(form));

            // observer für später geladene forms/popups
            const observer = new MutationObserver(function (mutations) {
                mutations.forEach(m => {
                    if (!m.addedNodes) return;
                    m.addedNodes.forEach(node => {
                        if (!(node instanceof HTMLElement)) return;
                        // Falls direkt ein form eingefügt wurde
                        if (node.tagName === 'FORM') {
                            enhanceRegisterForm(node);
                        } else {
                            // Suche forms im subtree
                            const childForms = node.querySelectorAll ? node.querySelectorAll('form') : [];
                            Array.from(childForms).forEach(f => enhanceRegisterForm(f));
                        }
                    });
                });
            });

            observer.observe(document.body, { childList: true, subtree: true });

            // zusätzliche Zeit-Fallbacks (für langsame Builder)
            setTimeout(() => Array.from(document.querySelectorAll('form')).forEach(f => enhanceRegisterForm(f)), 300);
            setTimeout(() => Array.from(document.querySelectorAll('form')).forEach(f => enhanceRegisterForm(f)), 900);
            setTimeout(() => Array.from(document.querySelectorAll('form')).forEach(f => enhanceRegisterForm(f)), 2500);
        }

        if (document.readyState === 'loading') {
            document.addEventListener('DOMContentLoaded', initEnhancer);
        } else {
            initEnhancer();
        }

    })();
    </script>
    <?php
});

```

Best regards, Marcel

---

<div class="post-metadata">

**Author:** ![kseniia](https://community.hivepress.io/user_avatar/community.hivepress.io/kseniia/32/13513_2.png) [@kseniia](https://community.hivepress.io/u/kseniia)\
**Post date:** [December 1, 2025, 7:32pm UTC](https://community.hivepress.io/t/temporary-solution-for-reveal-password-feature-visible-eye/17082/8 "2025-12-01T19:32:20Z")

</div>

Hi,

Thanks so much for sharing! It’s great to see our users contributing to the community like this. This will definitely be helpful to others with similar requests.

---

<div class="post-metadata">

**Author:** ![kseniia](https://community.hivepress.io/user_avatar/community.hivepress.io/kseniia/32/13513_2.png) [@kseniia](https://community.hivepress.io/u/kseniia)\
**Post date:** [December 15, 2025, 10:33pm UTC](https://community.hivepress.io/t/temporary-solution-for-reveal-password-feature-visible-eye/17082/9 "2025-12-15T22:33:05Z")

</div>

Hi,

We’ve released this feature, and it’s now available in the official version.

---

<div class="post-metadata">

**Author:** ![Marcel1987](https://community.hivepress.io/letter_avatar_proxy/v4/letter/m/ecd19e/32.png) [@Marcel1987](https://community.hivepress.io/u/Marcel1987)\
**Post date:** [December 19, 2025, 12:52pm UTC](https://community.hivepress.io/t/temporary-solution-for-reveal-password-feature-visible-eye/17082/10 "2025-12-19T12:52:34Z")

</div>

I’m glad to read that, and I hope I’ve been able to help some of you.

Thank you for contributing to the improvement.

---

<div class="post-metadata">

**Author:** ![system](https://community.hivepress.io/user_avatar/community.hivepress.io/system/32/13990_2.png) [@system](https://community.hivepress.io/u/system)\
**Post date:** [January 18, 2026, 12:53pm UTC](https://community.hivepress.io/t/temporary-solution-for-reveal-password-feature-visible-eye/17082/11 "2026-01-18T12:53:23Z")

</div>

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.
