Form Examples
Real-world examples of using Vue Custom Tooltip with forms, including input helpers, validation feedback, and form-related patterns.
Input Helpers
Basic Input Tooltips
Show code
vue
<template>
<form class="space-y-4 max-w-md">
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
Username
</label>
<Tooltip content="Username must be 3-20 characters" trigger="focus">
<input
type="text"
placeholder="Enter username"
class="w-full border border-gray-300 dark:border-gray-600 rounded px-3 py-2 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
>
</Tooltip>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
Email
</label>
<Tooltip content="We'll never share your email" trigger="focus">
<input
type="email"
placeholder="your@email.com"
class="w-full border border-gray-300 dark:border-gray-600 rounded px-3 py-2 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
>
</Tooltip>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
Password
</label>
<Tooltip content="Must be at least 8 characters with uppercase, lowercase, and numbers" trigger="focus">
<input
type="password"
placeholder="Enter password"
class="w-full border border-gray-300 dark:border-gray-600 rounded px-3 py-2 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
>
</Tooltip>
</div>
</form>
</template>vue
<template>
<form class="space-y-4 max-w-md">
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
Username
</label>
<input
v-tooltip.focus="'Username must be 3-20 characters'"
type="text"
placeholder="Enter username"
class="w-full border border-gray-300 dark:border-gray-600 rounded px-3 py-2 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
Email
</label>
<input
v-tooltip.focus="'We will never share your email'"
type="email"
placeholder="your@email.com"
class="w-full border border-gray-300 dark:border-gray-600 rounded px-3 py-2 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
Password
</label>
<input
v-tooltip.focus.top="'Must be at least 8 characters with uppercase, lowercase, and numbers'"
type="password"
placeholder="Enter password"
class="w-full border border-gray-300 dark:border-gray-600 rounded px-3 py-2 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
>
</div>
</form>
</template>Form Validation
Dynamic Validation Feedback
Show code
vue
<script setup>
import { computed, ref } from 'vue'
const email = ref('')
const password = ref('')
const confirmPassword = ref('')
const emailValid = computed(() => {
if (!email.value) return null
const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
return regex.test(email.value)
})
const passwordStrength = computed(() => {
if (!password.value) return 'empty'
const hasUpper = /[A-Z]/.test(password.value)
const hasLower = /[a-z]/.test(password.value)
const hasNumber = /[0-9]/.test(password.value)
const length = password.value.length >= 8
if (hasUpper && hasLower && hasNumber && length) return 'strong'
if ((hasUpper || hasLower) && hasNumber && length) return 'medium'
return 'weak'
})
const passwordsMatch = computed(() => {
if (!password.value || !confirmPassword.value) return null
return password.value === confirmPassword.value
})
const getEmailTooltip = computed(() => {
if (!email.value) return 'Enter a valid email'
return emailValid.value ? '✓ Email valid!' : '✗ Invalid email format'
})
const getPasswordTooltip = computed(() => {
if (!password.value) return 'Must be at least 8 characters'
const strength = { weak: '✗ Weak', medium: '◐ Medium', strong: '✓ Strong' }
return strength[passwordStrength.value]
})
const getConfirmTooltip = computed(() => {
if (!confirmPassword.value) return 'Confirm your password'
return passwordsMatch.value ? '✓ Passwords match!' : '✗ Passwords do not match'
})
const emailClass = computed(() => {
if (emailValid.value === null) return ''
return emailValid.value ? 'border-green-500' : 'border-red-500'
})
const passwordClass = computed(() => {
if (passwordStrength.value === 'empty') return ''
const classes = {
weak: 'border-red-500',
medium: 'border-yellow-500',
strong: 'border-green-500'
}
return classes[passwordStrength.value]
})
const confirmClass = computed(() => {
if (passwordsMatch.value === null) return ''
return passwordsMatch.value ? 'border-green-500' : 'border-red-500'
})
</script>
<template>
<form class="space-y-4 max-w-md">
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
Email
</label>
<Tooltip
:content="getEmailTooltip"
:tooltip-class="emailValid ? 'tooltip-success' : 'tooltip-error'"
position="right"
>
<input
v-model="email"
type="email"
placeholder="your@email.com"
:class="['w-full border-2 rounded px-3 py-2 bg-white dark:bg-gray-700 text-gray-900 dark:text-white', emailClass]"
>
</Tooltip>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
Password
</label>
<Tooltip
:content="getPasswordTooltip"
:tooltip-class="passwordStrength === 'strong' ? 'tooltip-success' : 'tooltip-warning'"
position="right"
>
<input
v-model="password"
type="password"
placeholder="Enter password"
:class="['w-full border-2 rounded px-3 py-2 bg-white dark:bg-gray-700 text-gray-900 dark:text-white', passwordClass]"
>
</Tooltip>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
Confirm Password
</label>
<Tooltip
:content="getConfirmTooltip"
:tooltip-class="passwordsMatch ? 'tooltip-success' : 'tooltip-error'"
position="right"
>
<input
v-model="confirmPassword"
type="password"
placeholder="Confirm password"
:class="['w-full border-2 rounded px-3 py-2 bg-white dark:bg-gray-700 text-gray-900 dark:text-white', confirmClass]"
>
</Tooltip>
</div>
</form>
</template>
<style scoped>
.tooltip-success .tooltip-content {
background: #10b981 !important;
color: white !important;
}
.tooltip-success .tooltip-arrow {
background: #10b981 !important;
border-color: #10b981 !important;
}
.tooltip-error .tooltip-content {
background: #ef4444 !important;
color: white !important;
}
.tooltip-error .tooltip-arrow {
background: #ef4444 !important;
border-color: #ef4444 !important;
}
.tooltip-warning .tooltip-content {
background: #f59e0b !important;
color: white !important;
}
.tooltip-warning .tooltip-arrow {
background: #f59e0b !important;
border-color: #f59e0b !important;
}
</style>Checkbox and Radio Groups
Labeled Options with Help
Show code
vue
<template>
<div class="space-y-4 max-w-md">
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-3">
Notification Preferences
</label>
<div class="space-y-2">
<label class="flex items-center gap-2 cursor-pointer">
<input type="checkbox" class="rounded" />
<span class="text-sm">Email notifications</span>
<Tooltip content="Get notified about important updates via email" position="right">
<span class="w-4 h-4 bg-blue-500 text-white rounded-full flex items-center justify-center text-xs cursor-help">
?
</span>
</Tooltip>
</label>
<label class="flex items-center gap-2 cursor-pointer">
<input type="checkbox" class="rounded" />
<span class="text-sm">SMS alerts</span>
<Tooltip content="Receive critical alerts via text message" position="right">
<span class="w-4 h-4 bg-blue-500 text-white rounded-full flex items-center justify-center text-xs cursor-help">
?
</span>
</Tooltip>
</label>
<label class="flex items-center gap-2 cursor-pointer">
<input type="checkbox" class="rounded" />
<span class="text-sm">Push notifications</span>
<Tooltip content="Receive notifications in your browser" position="right">
<span class="w-4 h-4 bg-blue-500 text-white rounded-full flex items-center justify-center text-xs cursor-help">
?
</span>
</Tooltip>
</label>
</div>
</div>
</div>
</template>vue
<template>
<div class="space-y-4 max-w-md">
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-3">
Notification Preferences
</label>
<div class="space-y-2">
<label class="flex items-center gap-2 cursor-pointer">
<input type="checkbox" class="rounded" />
<span class="text-sm">Email notifications</span>
<span
v-tooltip.right="'Get notified about important updates via email'"
class="w-4 h-4 bg-blue-500 text-white rounded-full flex items-center justify-center text-xs cursor-help"
>
?
</span>
</label>
<label class="flex items-center gap-2 cursor-pointer">
<input type="checkbox" class="rounded" />
<span class="text-sm">SMS alerts</span>
<span
v-tooltip.right="'Receive critical alerts via text message'"
class="w-4 h-4 bg-blue-500 text-white rounded-full flex items-center justify-center text-xs cursor-help"
>
?
</span>
</label>
<label class="flex items-center gap-2 cursor-pointer">
<input type="checkbox" class="rounded" />
<span class="text-sm">Push notifications</span>
<span
v-tooltip.right="'Receive notifications in your browser'"
class="w-4 h-4 bg-blue-500 text-white rounded-full flex items-center justify-center text-xs cursor-help"
>
?
</span>
</label>
</div>
</div>
</div>
</template>Select Dropdowns
Select with Helper
Show code
vue
<template>
<form class="space-y-4 max-w-md">
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
Subscription Plan
</label>
<Tooltip
content="Choose a plan based on your needs. You can upgrade or downgrade anytime."
trigger="focus"
position="top"
>
<select
class="w-full border border-gray-300 dark:border-gray-600 rounded px-3 py-2 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
>
<option>Select a plan</option>
<option>Basic ($9/month)</option>
<option>Pro ($29/month)</option>
<option>Enterprise (Custom)</option>
</select>
</Tooltip>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
Country
</label>
<Tooltip
content="This is required for accurate pricing and compliance"
trigger="focus"
>
<select
class="w-full border border-gray-300 dark:border-gray-600 rounded px-3 py-2 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
>
<option>Select country</option>
<option>United States</option>
<option>United Kingdom</option>
<option>Canada</option>
<option>Other</option>
</select>
</Tooltip>
</div>
</form>
</template>Required Fields Indicator
Visual Indicators with Tooltips
Show code
vue
<template>
<form class="space-y-4 max-w-md">
<div class="flex items-center gap-2 mb-4">
<Tooltip content="Fields marked with this symbol are required">
<span class="text-red-500 text-lg cursor-help">*</span>
</Tooltip>
<span class="text-sm text-gray-600 dark:text-gray-400">
= Required field
</span>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
<span class="text-red-500">*</span> Full Name
</label>
<input
type="text"
placeholder="John Doe"
class="w-full border border-gray-300 dark:border-gray-600 rounded px-3 py-2 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
<span class="text-red-500">*</span> Email Address
</label>
<input
type="email"
placeholder="john@example.com"
class="w-full border border-gray-300 dark:border-gray-600 rounded px-3 py-2 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
Company (Optional)
</label>
<input
type="text"
placeholder="Your Company"
class="w-full border border-gray-300 dark:border-gray-600 rounded px-3 py-2 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
>
</div>
</form>
</template>vue
<template>
<form class="space-y-4 max-w-md">
<div class="flex items-center gap-2 mb-4">
<span v-tooltip="'Fields marked with this symbol are required'" class="text-red-500 text-lg cursor-help">
*
</span>
<span class="text-sm text-gray-600 dark:text-gray-400">
= Required field
</span>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
<span class="text-red-500">*</span> Full Name
</label>
<input
type="text"
placeholder="John Doe"
class="w-full border border-gray-300 dark:border-gray-600 rounded px-3 py-2 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
<span class="text-red-500">*</span> Email Address
</label>
<input
type="email"
placeholder="john@example.com"
class="w-full border border-gray-300 dark:border-gray-600 rounded px-3 py-2 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
>
</div>
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
Company (Optional)
</label>
<input
type="text"
placeholder="Your Company"
class="w-full border border-gray-300 dark:border-gray-600 rounded px-3 py-2 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
>
</div>
</form>
</template>Submit Button Tooltips
Contextual Button Helpers
Show code
vue
<script setup>
import { computed, ref } from 'vue'
const formValid = ref(false)
const isSubmitting = ref(false)
const submitTooltip = computed(() => {
if (isSubmitting.value) return 'Submitting...'
if (!formValid.value) return 'Please fill in all required fields'
return 'Click to submit the form'
})
</script>
<template>
<form class="space-y-4 max-w-md">
<div>
<label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">
Email
</label>
<input
type="email"
placeholder="your@email.com"
@change="formValid = $event.target.value.length > 0"
class="w-full border border-gray-300 dark:border-gray-600 rounded px-3 py-2 bg-white dark:bg-gray-700 text-gray-900 dark:text-white"
>
</div>
<div>
<Tooltip :content="submitTooltip" position="top">
<Button
label="Submit"
:disabled="!formValid || isSubmitting"
class="w-full"
/>
</Tooltip>
</div>
</form>
</template>