npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@bootcn-vue/field-password

v0.2.2

Published

Password field component with show/hide toggle

Readme

@bootcn-vue/field-password

Complete password field component with show/hide toggle functionality for Vue 3.

npm version License: MIT

📚 Documentation

View Components & Examples - Interactive Storybook

Overview

A complete, production-ready password field component with toggle visibility, label, help text, error messages, and an optional helper slot. Perfect for login forms, registration, and password change interfaces.

Installation

Using CLI (Recommended)

# Initialize bootcn-vue (if not already done)
npx @bootcn-vue/cli@latest init

# Add field-password component (when available)
npx @bootcn-vue/cli@latest add field-password

Direct Installation

npm install @bootcn-vue/field-password @bootcn-vue/forms @bootcn-vue/core bootstrap

Features

  • Show/Hide Toggle - Eye icon button to toggle password visibility
  • Cursor Position Preservation - Maintains cursor position when toggling
  • Complete Field - Label, input, help text, and error messages included
  • Helper Slot - Flexible slot for requirements, strength indicators, or "Forgot password?" links
  • Accessible - Full ARIA support and keyboard navigation
  • Validation - Built-in error message display
  • Tooltips - Optional info tooltips next to labels
  • TypeScript - Full type safety
  • Bootstrap Styled - Consistent with Bootstrap 5 forms
  • RDS Spacing - Uses RDS spacing system

Usage

Basic Example

<script setup lang="ts">
import { FieldPassword } from "@bootcn-vue/field-password";
import { ref } from "vue";

const password = ref("");
</script>

<template>
  <FieldPassword
    id="password"
    label="Password"
    v-model="password"
    placeholder="Enter your password"
    required
  />
</template>

Login Form

<script setup lang="ts">
import { FieldPassword } from "@bootcn-vue/field-password";
import { ref } from "vue";

const password = ref("");
</script>

<template>
  <form @submit.prevent="handleLogin">
    <FieldPassword
      id="password"
      label="Password"
      v-model="password"
      placeholder="Enter your password"
      autocomplete="current-password"
      required
    >
      <template #helper>
        <a href="/forgot-password" class="small text-muted">
          Forgot password?
        </a>
      </template>
    </FieldPassword>

    <button type="submit" class="btn btn-primary mt-space-sm">Sign In</button>
  </form>
</template>

Registration with Password Requirements

<script setup lang="ts">
import { FieldPassword } from "@bootcn-vue/field-password";
import { ref, computed } from "vue";

const password = ref("");

const requirements = computed(() => ({
  length: password.value.length >= 8,
  uppercase: /[A-Z]/.test(password.value),
  lowercase: /[a-z]/.test(password.value),
  number: /[0-9]/.test(password.value),
  special: /[!@#$%^&*]/.test(password.value),
}));

const allMet = computed(() => Object.values(requirements.value).every(Boolean));
</script>

<template>
  <FieldPassword
    id="password"
    label="Create Password"
    v-model="password"
    placeholder="Choose a strong password"
    autocomplete="new-password"
    required
  >
    <template #helper>
      <div class="small mt-space-xxs">
        <p class="mb-1 fw-semibold">Password must contain:</p>
        <ul class="list-unstyled mb-0">
          <li :class="requirements.length ? 'text-success' : 'text-muted'">
            <i
              :class="
                requirements.length
                  ? 'fa-solid fa-check'
                  : 'fa-regular fa-circle'
              "
            />
            At least 8 characters
          </li>
          <li :class="requirements.uppercase ? 'text-success' : 'text-muted'">
            <i
              :class="
                requirements.uppercase
                  ? 'fa-solid fa-check'
                  : 'fa-regular fa-circle'
              "
            />
            One uppercase letter
          </li>
          <li :class="requirements.lowercase ? 'text-success' : 'text-muted'">
            <i
              :class="
                requirements.lowercase
                  ? 'fa-solid fa-check'
                  : 'fa-regular fa-circle'
              "
            />
            One lowercase letter
          </li>
          <li :class="requirements.number ? 'text-success' : 'text-muted'">
            <i
              :class="
                requirements.number
                  ? 'fa-solid fa-check'
                  : 'fa-regular fa-circle'
              "
            />
            One number
          </li>
          <li :class="requirements.special ? 'text-success' : 'text-muted'">
            <i
              :class="
                requirements.special
                  ? 'fa-solid fa-check'
                  : 'fa-regular fa-circle'
              "
            />
            One special character (!@#$%^&*)
          </li>
        </ul>
      </div>
    </template>
  </FieldPassword>
</template>

With Validation

<script setup lang="ts">
import { FieldPassword } from "@bootcn-vue/field-password";
import { ref, computed } from "vue";

const password = ref("");
const error = computed(() => {
  if (!password.value) return "Password is required";
  if (password.value.length < 8)
    return "Password must be at least 8 characters";
  if (!/[A-Z]/.test(password.value))
    return "Password must contain an uppercase letter";
  if (!/[0-9]/.test(password.value)) return "Password must contain a number";
  return "";
});
</script>

<template>
  <FieldPassword
    id="password"
    label="Password"
    v-model="password"
    :error="error"
    help-text="Choose a strong password"
    required
  />
</template>

Password Confirmation

<script setup lang="ts">
import { FieldPassword } from "@bootcn-vue/field-password";
import { ref, computed } from "vue";

const password = ref("");
const confirmPassword = ref("");

const confirmError = computed(() => {
  if (!confirmPassword.value) return "Please confirm your password";
  if (confirmPassword.value !== password.value) return "Passwords do not match";
  return "";
});
</script>

<template>
  <div>
    <FieldPassword
      id="password"
      label="New Password"
      v-model="password"
      placeholder="Enter password"
      autocomplete="new-password"
      required
    />

    <FieldPassword
      id="confirm-password"
      label="Confirm Password"
      v-model="confirmPassword"
      placeholder="Re-enter password"
      autocomplete="new-password"
      :error="confirmError"
      required
      class="mt-space-sm"
    />
  </div>
</template>

With Tooltip

<script setup lang="ts">
import { FieldPassword } from "@bootcn-vue/field-password";
import { ref } from "vue";

const password = ref("");
</script>

<template>
  <FieldPassword
    id="password"
    label="Password"
    v-model="password"
    tooltip-message="Your password should be at least 8 characters and include uppercase, lowercase, and numbers"
    required
  />
</template>

Optional Field

<script setup lang="ts">
import { FieldPassword } from "@bootcn-vue/field-password";
import { ref } from "vue";

const optionalPassword = ref("");
</script>

<template>
  <FieldPassword
    id="optional-password"
    label="Additional Password"
    v-model="optionalPassword"
    :is-optional="true"
    optional-text="Optional"
    help-text="Only required for advanced features"
  />
</template>

Props

| Prop | Type | Default | Description | | ---------------- | ------------------------------------ | -------------------- | -------------------------------------- | | id | string | required | Unique ID for the input element | | label | string | required | Label text for the field | | modelValue | string | '' | v-model binding for the password value | | placeholder | string | undefined | Placeholder text | | required | boolean | false | Mark field as required | | disabled | boolean | false | Disable the input | | readonly | boolean | false | Make input readonly | | error | string | undefined | Error message to display | | helpText | string | undefined | Help text below input | | tooltipMessage | string | undefined | Tooltip next to label | | isOptional | boolean | false | Show optional badge | | optionalText | string | 'Optional' | Custom optional badge text | | labelLevel | 'h1'\|'h2'\|'h3'\|'h4'\|'h5'\|'h6' | 'h3' | Heading level for label | | labelSize | 'small'\|'medium'\|'large' | 'small' | Label font size | | labelVisible | boolean | true | Show/hide label visually | | autocomplete | string | 'current-password' | Autocomplete attribute | | class | string | undefined | Additional CSS classes |

Autocomplete values:

  • current-password - For login forms (default)
  • new-password - For registration and password change forms

Slots

helper

Custom content area below the input field, perfect for:

  • Password requirements checklist
  • Password strength indicator
  • "Forgot password?" link
  • Additional help text or actions
<template>
  <FieldPassword id="pwd" label="Password">
    <template #helper>
      <!-- Your custom content here -->
    </template>
  </FieldPassword>
</template>

Note: The helper slot replaces helpText prop if both are provided.

Events

| Event | Payload | Description | | ------------------- | -------- | -------------------------------- | | update:modelValue | string | Emitted when input value changes |

Toggle Button Behavior

The show/hide toggle button:

  • Shows an eye icon (👁️) when password is hidden
  • Shows an eye-slash icon (👁️‍🗨️) when password is visible
  • Has proper aria-label for screen readers
  • Preserves cursor position when toggling
  • Uses type="button" to prevent form submission
  • Is keyboard accessible (Tab to focus, Enter/Space to toggle)

Accessibility

The component follows WCAG 2.1 guidelines:

  • Proper Labels - Label associated with input via for/id
  • Toggle Button - Accessible with aria-label and screen reader text
  • Required Fields - aria-required attribute
  • Error States - aria-invalid and aria-describedby for errors
  • Help Text - Associated via aria-describedby
  • Keyboard Navigation - Full keyboard support
  • Focus Management - Proper focus indicators
  • Screen Readers - All content announced properly

Styling

The component uses Bootstrap 5 classes and RDS spacing:

<template>
  <FieldPassword
    id="password"
    label="Password"
    v-model="password"
    class="mb-space-md"
  />
</template>

Form Integration

Works seamlessly with form libraries:

With VeeValidate

<script setup lang="ts">
import { FieldPassword } from "@bootcn-vue/field-password";
import { useField } from "vee-validate";

const { value, errorMessage } = useField("password", "required|min:8");
</script>

<template>
  <FieldPassword
    id="password"
    label="Password"
    v-model="value"
    :error="errorMessage"
    required
  />
</template>

With Zod

<script setup lang="ts">
import { FieldPassword } from "@bootcn-vue/field-password";
import { ref, computed } from "vue";
import { z } from "zod";

const passwordSchema = z
  .string()
  .min(8, "Password must be at least 8 characters")
  .regex(/[A-Z]/, "Must contain uppercase letter")
  .regex(/[0-9]/, "Must contain number");

const password = ref("");

const error = computed(() => {
  const result = passwordSchema.safeParse(password.value);
  return result.success ? "" : result.error.issues[0].message;
});
</script>

<template>
  <FieldPassword
    id="password"
    label="Password"
    v-model="password"
    :error="error"
  />
</template>

Security Considerations

  • Password is masked by default (type="password")
  • Toggle button allows users to verify input
  • Cursor position is preserved to avoid user confusion
  • No password value is exposed in DOM attributes
  • Works with browser password managers
  • Supports autocomplete for better UX

Dependencies

  • @bootcn-vue/forms - Form primitives (includes InputPassword)
  • @bootcn-vue/core - Core utilities
  • @fortawesome/vue-fontawesome - Icons for toggle button

Peer Dependencies

  • vue ^3.5.0
  • bootstrap ^5.3.0

Links

Related Packages

License

MIT © Shashank Shandilya