66 lines
2.5 KiB
Vue
66 lines
2.5 KiB
Vue
<script setup>
|
|
/**
|
|
* RqInput.vue — Champ de saisie RecruitQuizz
|
|
*
|
|
* @prop modelValue String (v-model)
|
|
* @prop placeholder String
|
|
* @prop type String (text, email, password, search…)
|
|
* @prop icon 'search' | 'mail' | 'lock' — icône préfixe
|
|
* @prop error String — message d'erreur
|
|
* @prop label String — label au-dessus du champ
|
|
*/
|
|
import { computed } from 'vue';
|
|
|
|
const props = defineProps({
|
|
modelValue: { type: String, default: '' },
|
|
placeholder: { type: String, default: '' },
|
|
type: { type: String, default: 'text' },
|
|
icon: { type: String, default: null },
|
|
error: { type: String, default: null },
|
|
label: { type: String, default: null },
|
|
});
|
|
|
|
const emit = defineEmits(['update:modelValue']);
|
|
|
|
const iconPaths = {
|
|
search: 'M11 17.25a6.25 6.25 0 110-12.5 6.25 6.25 0 010 12.5zM16 16l4.5 4.5',
|
|
mail: 'M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2zM22 6l-10 7L2 6',
|
|
lock: 'M19 11H5a2 2 0 00-2 2v7a2 2 0 002 2h14a2 2 0 002-2v-7a2 2 0 00-2-2zM7 11V7a5 5 0 0110 0v4',
|
|
};
|
|
</script>
|
|
|
|
<template>
|
|
<div class="flex flex-col gap-1.5 w-full">
|
|
<!-- Label -->
|
|
<label v-if="label" class="text-2xs font-black uppercase tracking-[0.14em] text-ink/50">
|
|
{{ label }}
|
|
</label>
|
|
|
|
<!-- Input wrapper -->
|
|
<div class="relative">
|
|
<!-- Icon -->
|
|
<span v-if="icon" class="absolute left-3 top-1/2 -translate-y-1/2 text-ink/30 pointer-events-none">
|
|
<svg width="15" height="15" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round">
|
|
<path :d="iconPaths[icon]" />
|
|
</svg>
|
|
</span>
|
|
|
|
<input
|
|
:type="type"
|
|
:value="modelValue"
|
|
:placeholder="placeholder"
|
|
@input="emit('update:modelValue', $event.target.value)"
|
|
:class="[
|
|
'w-full rounded-[10px] border bg-surface font-sans text-sm font-semibold text-ink placeholder:text-ink/30 outline-none transition-all duration-150',
|
|
'focus:border-primary focus:ring-2 focus:ring-primary/15',
|
|
icon ? 'pl-9 pr-4 py-2.5' : 'px-4 py-2.5',
|
|
error ? 'border-accent focus:border-accent focus:ring-accent/15' : 'border-ink/10',
|
|
]"
|
|
/>
|
|
</div>
|
|
|
|
<!-- Error -->
|
|
<p v-if="error" class="text-2xs font-bold text-accent">{{ error }}</p>
|
|
</div>
|
|
</template>
|