Forms
Vanduo ships framework-wide defaults for native form controls. Use the documented
.vd-* form classes for stable component markup, and load app-specific overrides after Vanduo when embedding into an existing design system. In Vue 3, the <VdInput> component (below) wraps this markup with label / hint / error / prefix / suffix props. VdInput — label / hint / error / prefix / suffix
The Vue 3 <VdInput> bundles the common field anatomy — label, helper text, validation message and affixes — into one component on the unified status-variant palette. type="number" binds a real number.
As it appears on your card.
Enter a valid email address.
$USD
Bound value: 42 (number)
@
That username is available.Usage
<script setup lang="ts">
import { VdInput } from "@vanduo-oss/vd3";
const email = ref("");
const amount = ref(0);
</script>
<template>
<!-- Label + helper text -->
<VdInput v-model="email" type="email" label="Email"
hint="We'll never share it." />
<!-- Error message also styles the field as danger -->
<VdInput v-model="email" type="email" label="Email"
error="Enter a valid email address." />
<!-- Prefix / suffix + number model (emits a number) -->
<VdInput v-model="amount" type="number" label="Amount"
prefix="$" suffix="USD" />
</template>Component API
| Prop / event | Description |
|---|---|
v-model (modelValue) | Two-way value. Emits a number when type="number", otherwise a string. |
:label | Field label rendered above the input. |
:hint | Helper text below the input (hidden when error is set). |
:error | Error message; its presence also styles the input as danger. |
:prefix / :suffix | Static text/symbol before / after the input. |
:variant | 'success' | 'danger' validation state (error implies danger). |
:size | 'sm' | 'md' | 'lg' input height (default 'md'). |
native attrs | type, placeholder, disabled, readonly, required, min/max/step, pattern, autocomplete… |
@blur / @focus | Forwarded focus events. |
Grouped inputs — VdCheckboxGroup / VdRadioGroup / VdSelect
Three Vue 3 wrappers build a full option group from a :options array and a v-model — a multi-select checkbox set, a single-choice radio set, and a themed native <select>.
Selected: a11y
Plan: pro
Framework: —
Usage
<script setup lang="ts">
import { ref } from "vue";
import { VdCheckboxGroup, VdRadioGroup, VdSelect } from "@vanduo-oss/vd3";
const checks = ref<string[]>(["a11y"]);
const plan = ref("pro");
const framework = ref("");
</script>
<template>
<VdCheckboxGroup
v-model="checks"
name="features"
:options="[
{ value: 'a11y', label: 'Accessibility' },
{ value: 'ssr', label: 'SSR-safe' },
]"
/>
<VdRadioGroup
v-model="plan"
name="plan"
:options="[
{ value: 'free', label: 'Free' },
{ value: 'pro', label: 'Pro' },
]"
/>
<VdSelect
v-model="framework"
name="framework"
placeholder="Choose a framework"
:options="[
{ value: 'vue', label: 'Vue 3' },
{ value: 'nuxt', label: 'Nuxt' },
]"
/>
</template>Component API (Vue 3)
| Component | Props (v-model + options) |
|---|---|
VdCheckboxGroup | v-model (string[]) · :options ({ value, label, disabled? }) · :name · :inline · :size · :disabled |
VdRadioGroup | v-model (string) · :options ({ value, label, disabled?, icon? }) · :name · :inline · :size · :disabled |
VdSelect | v-model (string) · :options ({ value, label, disabled? }) · :name · :id · :placeholder · :disabled · :required |
Input Fields
Choose an option
Option 1
Option 2
Option 3
Custom-select wiring (other inputs are pure CSS):
<script setup lang="ts">
import { VdCustomSelect } from "@vanduo-oss/vd3";
const value = ref('');
const options = [{ value: '1', label: 'Option 1' }];
</script>
<template>
<VdCustomSelect v-model="value" :options="options" />
</template><!-- Text Input -->
<div class="vd-form-group">
<label for="text-input">Text Input</label>
<input type="text" id="text-input" class="vd-input"
placeholder="Enter text">
</div>
<!-- Select -->
<div class="vd-form-group">
<label for="select-input">Select</label>
<select id="select-input" class="vd-input">
<option>Option 1</option>
</select>
</div>
<!-- Custom Select -->
<div class="vd-form-group">
<label for="custom-select-input">Custom Select</label>
<select id="custom-select-input" class="vd-input vd-custom-select-input"
data-custom-select>
<option>Choose an option</option>
<option>Option 1</option>
</select>
</div>Form Controls
<!-- Checkbox -->
<div class="vd-form-group">
<label class="checkbox">
<input type="checkbox" checked>
<span>Checked checkbox</span>
</label>
</div>
<!-- Radio -->
<div class="vd-form-group">
<label class="radio">
<input type="radio" name="radio-demo" checked>
<span>Radio option 1</span>
</label>
</div>
<!-- Switch -->
<div class="vd-form-group">
<label class="switch">
<input type="checkbox" checked>
<span class="switch-slider"></span>
<span>Toggle switch</span>
</label>
</div>
<!-- Range -->
<div class="vd-form-group">
<label for="range-input">Range: <span id="range-value">50</span></label>
<input type="range" id="range-input" class="range" min="0" max="100"
value="50">
</div>Form Validation States
Looks good!
Please provide a valid value.
<!-- Valid state -->
<div class="vd-form-group">
<label for="valid-input">Valid Input</label>
<input type="text" id="valid-input" class="vd-input vd-input-valid"
value="Valid value">
<div class="vd-form-feedback vd-form-feedback-valid">Looks good!</div>
</div>
<!-- Invalid state -->
<div class="vd-form-group">
<label for="invalid-input">Invalid Input</label>
<input type="text" id="invalid-input" class="vd-input vd-input-invalid"
value="Invalid value">
<div class="vd-form-feedback vd-form-feedback-invalid">Please provide a
valid value.</div>
</div>Input Groups
USD
https:///api
<div class="vd-form-group">
<label for="input-prefix">With prefix</label>
<div class="vd-input-group">
<span class="vd-input-group-prefix"><i class="ph ph-at"></i></span>
<input type="text" id="input-prefix" class="vd-input" placeholder="username">
</div>
</div>
<div class="vd-form-group">
<label for="input-suffix">With suffix</label>
<div class="vd-input-group">
<input type="text" id="input-suffix" class="vd-input" placeholder="0.00">
<span class="vd-input-group-suffix">USD</span>
</div>
</div>
<div class="vd-form-group vd-mb-0">
<label for="input-both">Prefix + suffix</label>
<div class="vd-input-group">
<span class="vd-input-group-prefix">https://</span>
<input type="text" id="input-both" class="vd-input" placeholder="example.com">
<span class="vd-input-group-suffix">/api</span>
</div>
</div>Input Sizes
<div class="vd-form-group">
<label for="input-sm">Small</label>
<input type="text" id="input-sm" class="vd-input vd-input-sm" placeholder="Small input">
</div>
<div class="vd-form-group">
<label for="input-default">Default</label>
<input type="text" id="input-default" class="vd-input" placeholder="Default input">
</div>
<div class="vd-form-group vd-mb-0">
<label for="input-lg">Large</label>
<input type="text" id="input-lg" class="vd-input vd-input-lg" placeholder="Large input">
</div>Password Toggle
<div class="vd-form-group vd-mb-0">
<label for="password-toggle">Password</label>
<div class="vd-input-group">
<input type="password" id="password-toggle" class="vd-input" placeholder="Enter password">
<button type="button" class="vd-btn vd-btn-outline vd-input-group-suffix"
data-toggle="password" aria-label="Toggle password visibility">
<i class="ph ph-eye"></i>
</button>
</div>
</div>Class Reference
| Class | Description | Type |
|---|---|---|
.vd-form-group | Wrapper for form controls (adds margin, stacking) | Structure |
.vd-input | Base styling for text, email, password, select | Base |
.vd-input-sm | Compact input height and font size | Size |
.vd-input-lg | Taller input height and larger font size | Size |
.vd-input-group | Wrapper for input + prefix/suffix buttons or text | Structure |
.vd-input-group-prefix | Text or icon before the input inside a group | Structure |
.vd-input-group-suffix | Text or icon after the input inside a group | Structure |
.textarea | Base styling for multiline text inputs | Base |
.checkbox | Wrapper for custom checkbox controls | Structure |
.radio | Wrapper for custom radio button controls | Structure |
.switch | Wrapper for toggle switch controls | Structure |
.range | Custom styling for range/slider inputs | Base |
.vd-input-valid | Applies success indicator and green border | State |
.vd-input-invalid | Applies error indicator and red border | State |
.vd-form-feedback | Base class for validation message text | Structure |
.vd-form-feedback-valid | Success validation message (green) | State |
.vd-form-feedback-invalid | Error validation message (red) | State |
disabled | Native attribute to disable any form control | State (attr) |