Skip to content

LxInputPassword

Visão geral

O componente LxInputPassword é utilizado para exibir um campo de entrada de senha com funcionalidade de toggle para visualização. Ele é baseado no componente LxInputText e inclui um botão "olho" embutido que permite ao usuário alternar entre visualizar e ocultar a senha digitada. O componente suporta diversas opções de personalização, incluindo rótulo, mensagens de erro, texto de ajuda e validações.

Clique para visualizar o código
vue
<script setup>
import { ref } from 'vue';
import { LxInputPassword } from '@lde/lxcomponents';

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

<template>
	<LxInputPassword 
		id="input-password-example" 
		v-model="password" 
		label="Senha"
		placeholder="Digite sua senha"
	/>
</template>

Formato do v-model

⚠️ O v-model é obrigatório (required: true). Recebe e emite String | null.

Inicialização: ref('') — sempre string vazia, nunca null.

Saída (modelValue após digitação):

"minha-senha123"   // a string digitada pelo usuário

Propriedades

NomeDescriçãoTipoPadrão
idIdentificador único do campo de entrada.StringRequired
modelValueValor do campo de entrada (senha).
Nota: Utilizar a implementação padrão com o v-model.
StringRequired
labelRótulo do campo de entrada.String''
errorTextTexto de erro exibido quando o campo é inválido.String''
isInvalidIndica se o campo está em estado inválido.Booleanfalse
helpTextTexto de ajuda exibido abaixo do campo de entrada.String''
requiredIndica se o campo é obrigatório.Booleanfalse
sizeTamanho do campo de entrada ('sm', 'md', 'lg').String'md'
iconClasse do ícone a ser exibido no lado esquerdo do campo (ex: 'fas fa-lock').String''
showToggleDefine se o botão de toggle de visualização da senha deve ser exibido.Booleantrue

Eventos

NomeDescrição
update:modelValueEmitido quando o valor do campo de entrada é atualizado.
Nota: Utilizar a implementação padrão com o v-model.

Slots

NomeDescrição
label-contentConteúdo personalizado para o rótulo do campo de entrada.
error-contentConteúdo personalizado para a mensagem de erro.
help-contentConteúdo personalizado para o texto de ajuda.

Atributos

O componente LxInputPassword permite que você passe atributos personalizados para o campo de entrada utilizando fallthrough attributes do Vue. Isso é feito através do uso de useAttrs para herdar atributos não reconhecidos e aplicá-los ao elemento de entrada. Esses atributos serão passados diretamente para o input.

Exemplo de Uso

Veja um exemplo de como passar um placeholder e autocomplete personalizado para o campo de entrada:

Clique para visualizar o código
vue
<template>
  <LxInputPassword
    id="login-password"
    v-model="password"
    label="Senha"
    placeholder="Digite sua senha secreta"
    autocomplete="new-password"
  />
</template>

Classes Padrão

O componente LxInputPassword utiliza uma série de classes CSS padrão que podem ser personalizadas. Essas classes permitem que você estilize qualquer parte do campo de entrada usando :deep com a classe desejada.

NomeDescrição
lx-input-password-wrapperConteúdo personalizado para o container.
lx-input-passwordConteúdo personalizado para o input.
lx-input-password-labelConteúdo personalizado para o rótulo do campo de entrada.
lx-input-password-containerConteúdo personalizado para o container do input e botões.
lx-input-password-iconConteúdo personalizado para o ícone do campo de entrada.
lx-input-password-toggle-btnConteúdo personalizado para o botão de toggle de visualização.
lx-input-password-invalid-messageConteúdo personalizado para o texto de erro.
lx-input-password-help-messageConteúdo personalizado para o texto de ajuda.

Exemplo de Personalização

Você pode personalizar o estilo do campo de entrada utilizando as classes padrão com o seletor :deep. Veja um exemplo de como alterar o estilo do botão de toggle:

Clique para visualizar o código
vue
<style scoped>
:deep(.lx-input-password-toggle-btn) {
  color: #007bff;
}

:deep(.lx-input-password-toggle-btn:hover) {
  color: #0056b3;
}
</style>

Exemplos de Uso

Veja diferentes casos de uso do componente LxInputPassword:

Senha Básica
Com Validação
Use uma senha forte
Com Ícone
Senha de 8-20 caracteres
Confirmar Senha
Tamanho Pequeno
Tamanho Grande
Sem Toggle
Desabilitado
Clique para visualizar o código
vue
<script setup>
import { ref } from 'vue';
import { LxInputPassword } from '@lde/lxcomponents';

// Exemplo 1: Senha básica
const password1 = ref('');

// Exemplo 2: Com validação
const password2 = ref('');
const isInvalid = ref(false);

const validatePassword = () => {
	isInvalid.value = password2.value.length > 0 && password2.value.length < 8;
};

// Exemplo 3: Com ícone
const password3 = ref('');

// Exemplo 4: Confirmar senha
const password4 = ref('');
const confirmPassword = ref('');
const passwordsMatch = ref(true);

const checkPasswordMatch = () => {
	passwordsMatch.value = password4.value === confirmPassword.value;
};
</script>

<template>
	<div class="examples-container">
		<div class="row g-4">
			<!-- Exemplo 1 -->
			<div class="col-md-6">
				<h5>Senha Básica</h5>
				<LxInputPassword
					id="password-basic"
					v-model="password1"
					label="Senha"
					:required="true"
				/>
			</div>

			<!-- Exemplo 2 -->
			<div class="col-md-6">
				<h5>Com Validação</h5>
				<LxInputPassword
					id="password-validation"
					v-model="password2"
					label="Senha"
					:is-invalid="isInvalid"
					error-text="A senha deve ter no mínimo 8 caracteres"
					help-text="Use uma senha forte"
					:required="true"
					@input="validatePassword"
				/>
			</div>

			<!-- Exemplo 3 -->
			<div class="col-md-6">
				<h5>Com Ícone</h5>
				<LxInputPassword
					id="password-icon"
					v-model="password3"
					label="Senha de Acesso"
					icon="fas fa-lock"
					help-text="Senha de 8-20 caracteres"
				/>
			</div>

			<!-- Exemplo 4 -->
			<div class="col-md-6">
				<h5>Confirmar Senha</h5>
				<LxInputPassword
					id="password-new"
					v-model="password4"
					label="Nova Senha"
					class="mb-3"
					@input="checkPasswordMatch"
				/>
				<LxInputPassword
					id="password-confirm"
					v-model="confirmPassword"
					label="Confirmar Senha"
					:is-invalid="!passwordsMatch && confirmPassword.length > 0"
					error-text="As senhas não coincidem"
					@input="checkPasswordMatch"
				/>
			</div>

			<!-- Exemplo 5 -->
			<div class="col-md-6">
				<h5>Tamanho Pequeno</h5>
				<LxInputPassword
					id="password-small"
					v-model="password1"
					label="Senha"
					size="sm"
				/>
			</div>

			<!-- Exemplo 6 -->
			<div class="col-md-6">
				<h5>Tamanho Grande</h5>
				<LxInputPassword
					id="password-large"
					v-model="password1"
					label="Senha"
					size="lg"
				/>
			</div>

			<!-- Exemplo 7 -->
			<div class="col-md-6">
				<h5>Sem Toggle</h5>
				<LxInputPassword
					id="password-no-toggle"
					v-model="password1"
					label="Senha"
					:show-toggle="false"
					icon="fas fa-shield-alt"
				/>
			</div>

			<!-- Exemplo 8 -->
			<div class="col-md-6">
				<h5>Desabilitado</h5>
				<LxInputPassword
					id="password-disabled"
					v-model="password1"
					label="Senha"
					disabled
				/>
			</div>
		</div>
	</div>
</template>

<style scoped>
.examples-container {
	padding: 1.5rem;
	background-color: var(--vp-c-bg-soft);
	border-radius: 8px;
}

h5 {
	margin-bottom: 1rem;
	color: var(--vp-c-text-1);
	font-weight: 600;
}
</style>

Playground

Explore as diferentes configurações do componente LxInputPassword:

Configurações

Resultado

Digite uma senha forte
Valor atual: senha123
Clique para visualizar o código
vue
<script setup>
import { ref } from 'vue';
import { LxInputPassword } from '@lde/lxcomponents';

const password = ref('senha123');
const label = ref('Senha');
const helpText = ref('Digite uma senha forte');
const errorText = ref('');
const isInvalid = ref(false);
const required = ref(true);
const disabled = ref(false);
const readonly = ref(false);
const size = ref('md');
const icon = ref('');
const showToggle = ref(true);

const sizes = ['sm', 'md', 'lg'];
const icons = ['', 'fas fa-lock', 'fas fa-key', 'fas fa-shield-alt'];
</script>

<template>
	<div class="playground-container">
		<div class="row">
			<div class="col-md-6">
				<h4>Configurações</h4>
				<div class="mb-3">
					<label class="form-label">Label</label>
					<input v-model="label" type="text" class="form-control" />
				</div>
				<div class="mb-3">
					<label class="form-label">Help Text</label>
					<input v-model="helpText" type="text" class="form-control" />
				</div>
				<div class="mb-3">
					<label class="form-label">Error Text</label>
					<input v-model="errorText" type="text" class="form-control" />
				</div>
				<div class="mb-3">
					<label class="form-label">Tamanho</label>
					<select v-model="size" class="form-select">
						<option v-for="s in sizes" :key="s" :value="s">{{ s }}</option>
					</select>
				</div>
				<div class="mb-3">
					<label class="form-label">Ícone</label>
					<select v-model="icon" class="form-select">
						<option value="">Nenhum</option>
						<option v-for="i in icons.slice(1)" :key="i" :value="i">{{ i }}</option>
					</select>
				</div>
				<div class="mb-3 form-check">
					<input v-model="isInvalid" type="checkbox" class="form-check-input" id="invalid-check" />
					<label class="form-check-label" for="invalid-check">Is Invalid</label>
				</div>
				<div class="mb-3 form-check">
					<input v-model="required" type="checkbox" class="form-check-input" id="required-check" />
					<label class="form-check-label" for="required-check">Required</label>
				</div>
				<div class="mb-3 form-check">
					<input v-model="disabled" type="checkbox" class="form-check-input" id="disabled-check" />
					<label class="form-check-label" for="disabled-check">Disabled</label>
				</div>
				<div class="mb-3 form-check">
					<input v-model="readonly" type="checkbox" class="form-check-input" id="readonly-check" />
					<label class="form-check-label" for="readonly-check">Readonly</label>
				</div>
				<div class="mb-3 form-check">
					<input v-model="showToggle" type="checkbox" class="form-check-input" id="toggle-check" />
					<label class="form-check-label" for="toggle-check">Show Toggle</label>
				</div>
			</div>
			<div class="col-md-6">
				<h4>Resultado</h4>
				<LxInputPassword
					id="input-password-playground"
					v-model="password"
					:label="label"
					:help-text="helpText"
					:error-text="errorText"
					:is-invalid="isInvalid"
					:required="required"
					:disabled="disabled"
					:readonly="readonly"
					:size="size"
					:icon="icon"
					:show-toggle="showToggle"
				/>
				<div class="mt-3">
					<strong>Valor atual:</strong> {{ password || '(vazio)' }}
				</div>
			</div>
		</div>
	</div>
</template>

<style scoped>
.playground-container {
	padding: 1rem;
	background-color: var(--vp-c-bg-soft);
	border-radius: 8px;
}
</style>

Exemplo Prático: Formulário de Login

Veja um exemplo completo de formulário de login utilizando o componente LxInputPassword:

Clique para visualizar o código
vue
<script setup>
import { ref } from 'vue';
import { LxInputText, LxInputPassword, LxButton } from '@lde/lxcomponents';

const email = ref('');
const password = ref('');
const emailError = ref('');
const passwordError = ref('');
const isSubmitting = ref(false);

const validateEmail = () => {
	if (!email.value) {
		emailError.value = 'E-mail é obrigatório';
		return false;
	}
	const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
	if (!emailRegex.test(email.value)) {
		emailError.value = 'E-mail inválido';
		return false;
	}
	emailError.value = '';
	return true;
};

const validatePassword = () => {
	if (!password.value) {
		passwordError.value = 'Senha é obrigatória';
		return false;
	}
	if (password.value.length < 6) {
		passwordError.value = 'Senha deve ter no mínimo 6 caracteres';
		return false;
	}
	passwordError.value = '';
	return true;
};

const handleSubmit = async () => {
	const isEmailValid = validateEmail();
	const isPasswordValid = validatePassword();

	if (isEmailValid && isPasswordValid) {
		isSubmitting.value = true;
		// Simula chamada de API
		await new Promise(resolve => setTimeout(resolve, 1500));
		alert('Login realizado com sucesso!');
		isSubmitting.value = false;
	}
};
</script>

<template>
	<div class="login-form-container">
		<div class="card shadow-sm">
			<div class="card-body p-4">
				<h3 class="text-center mb-4">Login</h3>
				
				<form @submit.prevent="handleSubmit">
					<div class="mb-3">
						<LxInputText
							id="login-email"
							v-model="email"
							label="E-mail"
							type="email"
							placeholder="seuemail@exemplo.com"
							:is-invalid="!!emailError"
							:error-text="emailError"
							:required="true"
							icon="fas fa-envelope"
							@blur="validateEmail"
						/>
					</div>

					<div class="mb-4">
						<LxInputPassword
							id="login-password"
							v-model="password"
							label="Senha"
							placeholder="Digite sua senha"
							:is-invalid="!!passwordError"
							:error-text="passwordError"
							:required="true"
							icon="fas fa-lock"
							autocomplete="current-password"
							@blur="validatePassword"
						/>
					</div>

					<div class="d-flex justify-content-between align-items-center mb-3">
						<div class="form-check">
							<input class="form-check-input" type="checkbox" id="remember-me">
							<label class="form-check-label" for="remember-me">
								Lembrar-me
							</label>
						</div>
						<a href="#" class="text-decoration-none">Esqueceu a senha?</a>
					</div>

					<LxButton
						type="submit"
						class="w-100"
						:disabled="isSubmitting"
					>
						{{ isSubmitting ? 'Entrando...' : 'Entrar' }}
					</LxButton>
				</form>

				<hr class="my-4">

				<p class="text-center mb-0">
					Não tem uma conta? <a href="#" class="text-decoration-none">Cadastre-se</a>
				</p>
			</div>
		</div>
	</div>
</template>

<style scoped>
.login-form-container {
	max-width: 400px;
	margin: 2rem auto;
	padding: 1rem;
}

.card {
	border: none;
	border-radius: 12px;
}

h3 {
	color: var(--vp-c-text-1);
	font-weight: 600;
}

a {
	color: var(--lx-primary, #007bff);
	font-size: 0.9rem;
}

a:hover {
	text-decoration: underline !important;
}

.form-check-label {
	font-size: 0.9rem;
	color: var(--vp-c-text-2);
}
</style>

Boas Práticas

Segurança

  • Use autocomplete="current-password" para logins existentes
  • Use autocomplete="new-password" para criação de novas senhas
  • Sempre valide senhas no backend
  • Implemente políticas de senha forte

Acessibilidade

  • Sempre forneça um label descritivo
  • Use helpText para orientar os usuários sobre requisitos de senha
  • Use errorText para mensagens claras de validação
  • O botão de toggle possui labels adequados para leitores de tela

UX

  • Exiba requisitos de senha antes do usuário digitar
  • Valide em tempo real quando apropriado
  • Use confirmação de senha para cadastros e alterações
  • Considere usar indicadores de força de senha

Desenvolvido pelo time Linx Microvix