CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-vuetify

Vue Material Component Framework implementing Google's Material Design specification with comprehensive UI components, theming system, and accessibility features.

Pending
Overview
Eval results
Files

forms.mddocs/

Forms

Form components and validation utilities for user input collection and data entry.

Capabilities

VForm

Form wrapper component with validation, submission handling, and state management.

/**
 * Form wrapper with validation and submission handling
 */
const VForm: Component;

interface FormProps {
  /** Form model value for validation state */
  modelValue?: boolean;
  /** Fast fail validation mode */
  fastFail?: boolean;
  /** Read-only form state */
  readonly?: boolean;
  /** Disabled form state */
  disabled?: boolean;
  /** Validate on blur */
  validateOn?: 'blur' | 'input' | 'submit' | 'blur lazy' | 'input lazy' | 'submit lazy';
}

interface FormExposed {
  /** Validate all form fields */
  validate(): Promise<{ valid: boolean; errors: ValidationError[] }>;
  /** Reset all form fields */
  reset(): void;
  /** Reset validation state */
  resetValidation(): void;
  /** Check if form is valid */
  isValid: Ref<boolean>;
  /** Form validation errors */
  errors: Ref<ValidationError[]>;
}

// Events
interface FormEvents {
  'update:modelValue': (valid: boolean) => void;
  'submit': (event: SubmitEventPromise) => void;
}

interface SubmitEventPromise extends Event {
  /** Promise that resolves when validation completes */
  readonly valid: Promise<{ valid: boolean; errors: ValidationError[] }>;
}

interface ValidationError {
  /** Field identifier */
  id: string | number;
  /** Error message */
  errorMessages: string[];
}

Usage Examples:

<template>
  <v-form
    ref="form"
    v-model="valid"
    @submit.prevent="handleSubmit"
  >
    <v-text-field
      v-model="name"
      :rules="nameRules"
      label="Name"
      required
    />
    
    <v-text-field
      v-model="email"
      :rules="emailRules"
      label="Email"
      type="email"
      required
    />
    
    <v-btn
      type="submit"
      :disabled="!valid"
      color="primary"
    >
      Submit
    </v-btn>
  </v-form>
</template>

<script setup>
const form = ref();
const valid = ref(false);
const name = ref('');
const email = ref('');

const nameRules = [
  v => !!v || 'Name is required',
  v => v.length >= 2 || 'Name must be at least 2 characters',
];

const emailRules = [
  v => !!v || 'Email is required',
  v => /.+@.+\..+/.test(v) || 'Email must be valid',
];

const handleSubmit = async () => {
  const { valid } = await form.value.validate();
  if (valid) {
    // Submit form data
    console.log('Form is valid, submitting...');
  }
};
</script>

VTextField

Single-line text input field with validation and formatting capabilities.

/**
 * Single-line text input component
 */
const VTextField: Component;

interface TextFieldProps {
  /** Input value */
  modelValue?: string | number;
  /** Input type */
  type?: 'text' | 'password' | 'email' | 'url' | 'tel' | 'number';
  /** Field label */
  label?: string;
  /** Placeholder text */
  placeholder?: string;
  /** Hint text */
  hint?: string;
  /** Persistent hint */
  persistentHint?: boolean;
  /** Validation rules */
  rules?: ValidationRule[];
  /** Error messages */
  errorMessages?: string | string[];
  /** Error state */
  error?: boolean;
  /** Success state */
  success?: boolean;
  /** Disabled state */
  disabled?: boolean;
  /** Readonly state */
  readonly?: boolean;
  /** Required field indicator */
  required?: boolean;
  /** Field density */
  density?: 'default' | 'comfortable' | 'compact';
  /** Field variant */
  variant?: 'filled' | 'outlined' | 'underlined' | 'plain' | 'solo' | 'solo-inverted' | 'solo-filled';
  /** Hide details */
  hideDetails?: boolean | 'auto';
  /** Prepend icon */
  prependIcon?: string;
  /** Append icon */
  appendIcon?: string;
  /** Prepend inner icon */
  prependInnerIcon?: string;
  /** Append inner icon */
  appendInnerIcon?: string;
  /** Clear icon */
  clearIcon?: string;
  /** Clearable input */
  clearable?: boolean;
  /** Counter for character count */
  counter?: boolean | number | string;
  /** Maximum length */
  maxlength?: number | string;
  /** Prefix text */
  prefix?: string;
  /** Suffix text */
  suffix?: string;
  /** Loading state */
  loading?: boolean;
  /** Autofocus */
  autofocus?: boolean;
}

// Events
interface TextFieldEvents {
  'update:modelValue': (value: string | number) => void;
  'click:prepend': (event: MouseEvent) => void;
  'click:append': (event: MouseEvent) => void;
  'click:prependInner': (event: MouseEvent) => void;
  'click:appendInner': (event: MouseEvent) => void;
  'click:clear': (event: MouseEvent) => void;
  'focus': (event: FocusEvent) => void;
  'blur': (event: FocusEvent) => void;
  'keydown': (event: KeyboardEvent) => void;
}

Usage Examples:

<template>
  <!-- Basic text field -->
  <v-text-field
    v-model="username"
    label="Username"
    prepend-inner-icon="mdi-account"
  />

  <!-- Password field -->
  <v-text-field
    v-model="password"
    :type="showPassword ? 'text' : 'password'"
    label="Password"
    :append-inner-icon="showPassword ? 'mdi-eye' : 'mdi-eye-off'"
    @click:append-inner="showPassword = !showPassword"
  />

  <!-- Validated field -->
  <v-text-field
    v-model="email"
    :rules="emailRules"
    label="Email"
    type="email"
    hint="Enter a valid email address"
    persistent-hint
  />

  <!-- With counter -->
  <v-text-field
    v-model="description"
    label="Description"
    counter="200"
    maxlength="200"
  />
</template>

VTextarea

Multi-line text input area for longer text content.

/**
 * Multi-line text input component
 */
const VTextarea: Component;

interface TextareaProps extends Omit<TextFieldProps, 'type' | 'prependInnerIcon' | 'appendInnerIcon'> {
  /** Number of rows */
  rows?: number | string;
  /** Maximum number of rows */
  maxRows?: number | string;
  /** Auto-grow height */
  autoGrow?: boolean;
  /** No resize handle */
  noResize?: boolean;
}

Usage Examples:

<template>
  <!-- Basic textarea -->
  <v-textarea
    v-model="message"
    label="Message"
    rows="3"
  />

  <!-- Auto-growing textarea -->
  <v-textarea
    v-model="content"
    label="Content"
    auto-grow
    max-rows="10"
  />

  <!-- With validation -->
  <v-textarea
    v-model="feedback"
    :rules="[v => v.length >= 10 || 'Minimum 10 characters required']"
    label="Feedback"
    counter="500"
    maxlength="500"
  />
</template>

VSelect

Dropdown selection component with single or multiple selection modes.

/**
 * Dropdown selection component
 */
const VSelect: Component;

interface SelectProps {
  /** Selected value(s) */
  modelValue?: any;
  /** Selection items */
  items?: any[];
  /** Item title key */
  itemTitle?: string | ((item: any) => string);
  /** Item value key */
  itemValue?: string | ((item: any) => any);
  /** Item props key */
  itemProps?: string | ((item: any) => Record<string, any>);
  /** Return object instead of value */
  returnObject?: boolean;
  /** Multiple selection */
  multiple?: boolean;
  /** Chips display for multiple */
  chips?: boolean;
  /** Closable chips */
  closableChips?: boolean;
  /** Field label */
  label?: string;
  /** Placeholder text */
  placeholder?: string;
  /** Validation rules */
  rules?: ValidationRule[];
  /** Menu props */
  menuProps?: Record<string, any>;
  /** Clearable selection */
  clearable?: boolean;
  /** Loading state */
  loading?: boolean;
  /** Hide selected items from list */
  hideSelected?: boolean;
  /** Menu open state */
  menu?: boolean;
}

// Events
interface SelectEvents {
  'update:modelValue': (value: any) => void;
  'update:menu': (open: boolean) => void;
}

Usage Examples:

<template>
  <!-- Basic select -->
  <v-select
    v-model="selectedItem"
    :items="items"
    label="Choose an option"
    item-title="text"
    item-value="value"
  />

  <!-- Multiple select with chips -->
  <v-select
    v-model="selectedItems"
    :items="items"
    label="Multiple selection"
    multiple
    chips
    closable-chips
    item-title="text"
    item-value="value"
  />

  <!-- Object return format -->
  <v-select
    v-model="selectedObject"
    :items="complexItems"
    label="Select user"
    item-title="name"
    item-value="id"
    return-object
  />
</template>

<script setup>
const items = [
  { text: 'Option 1', value: 1 },
  { text: 'Option 2', value: 2 },
  { text: 'Option 3', value: 3 },
];

const complexItems = [
  { id: 1, name: 'John Doe', email: 'john@example.com' },
  { id: 2, name: 'Jane Smith', email: 'jane@example.com' },
];
</script>

VCombobox

Combobox component allowing both selection from list and free text input.

/**
 * Combobox with selection and text input capabilities
 */
const VCombobox: Component;

interface ComboboxProps extends SelectProps {
  /** Allow custom values */
  customValue?: boolean;
  /** Delimiter for multiple values */
  delimiters?: string[];
  /** Filter function */
  customFilter?: FilterFunction;
}

Usage Examples:

<template>
  <!-- Basic combobox -->
  <v-combobox
    v-model="selectedTags"
    :items="availableTags"
    label="Tags"
    multiple
    chips
    delimiters=" ,"
  />

  <!-- Custom value combobox -->
  <v-combobox
    v-model="customSelection"
    :items="predefinedOptions"
    label="Select or enter custom"
    custom-value
  />
</template>

VAutocomplete

Autocomplete component with filtering and async data loading capabilities.

/**
 * Autocomplete input with filtering
 */
const VAutocomplete: Component;

interface AutocompleteProps extends SelectProps {
  /** Search input value */
  search?: string;
  /** Custom filter function */
  customFilter?: FilterFunction;
  /** Filter function keys */
  customKeyFilter?: Record<string, FilterFunction>;
  /** No filter mode for server-side filtering */
  noFilter?: boolean;
  /** Auto-select first item */
  autoSelectFirst?: boolean;
}

// Events
interface AutocompleteEvents extends SelectEvents {
  'update:search': (search: string) => void;
}

Usage Examples:

<template>
  <!-- Basic autocomplete -->
  <v-autocomplete
    v-model="selectedUser"
    :items="users"
    label="Search users"
    item-title="name"
    item-value="id"
  />

  <!-- Server-side filtering -->
  <v-autocomplete
    v-model="selectedItem"
    v-model:search="searchQuery"
    :items="searchResults"
    :loading="searching"
    label="Search items"
    no-filter
    @update:search="performSearch"
  />
</template>

<script setup>
const searchQuery = ref('');
const searchResults = ref([]);
const searching = ref(false);

const performSearch = async (query) => {
  if (!query) {
    searchResults.value = [];
    return;
  }
  
  searching.value = true;
  try {
    const results = await api.search(query);
    searchResults.value = results;
  } finally {
    searching.value = false;
  }
};
</script>

VCheckbox

Checkbox input component for boolean selections.

/**
 * Checkbox input component
 */
const VCheckbox: Component;

interface CheckboxProps {
  /** Checkbox value */
  modelValue?: any;
  /** True value when checked */
  trueValue?: any;
  /** False value when unchecked */
  falseValue?: any;
  /** Indeterminate state */
  indeterminate?: boolean;
  /** Checkbox label */
  label?: string;
  /** Validation rules */
  rules?: ValidationRule[];
  /** Disabled state */
  disabled?: boolean;
  /** Readonly state */
  readonly?: boolean;
  /** Error state */
  error?: boolean;
  /** Checkbox color */
  color?: string;
  /** Hide details */
  hideDetails?: boolean | 'auto';
  /** Field density */
  density?: 'default' | 'comfortable' | 'compact';
}

// Events
interface CheckboxEvents {
  'update:modelValue': (value: any) => void;
  'update:indeterminate': (indeterminate: boolean) => void;
}

Usage Examples:

<template>
  <!-- Basic checkbox -->
  <v-checkbox
    v-model="agreed"
    label="I agree to the terms"
  />

  <!-- Custom values -->
  <v-checkbox
    v-model="status"
    true-value="active"
    false-value="inactive"
    label="Active status"
  />

  <!-- Indeterminate checkbox -->
  <v-checkbox
    v-model="selectAll"
    :indeterminate="someSelected"
    @click="toggleAll"
    label="Select all"
  />
</template>

VRadio & VRadioGroup

Radio button components for single selection from multiple options.

/**
 * Radio button component
 */
const VRadio: Component;

interface RadioProps {
  /** Radio value */
  value?: any;
  /** Radio label */
  label?: string;
  /** Disabled state */
  disabled?: boolean;
  /** Readonly state */
  readonly?: boolean;
  /** Radio color */
  color?: string;
  /** Field density */
  density?: 'default' | 'comfortable' | 'compact';
}

/**
 * Radio group container
 */
const VRadioGroup: Component;

interface RadioGroupProps {
  /** Selected value */
  modelValue?: any;
  /** Group label */
  label?: string;
  /** Validation rules */
  rules?: ValidationRule[];
  /** Error state */
  error?: boolean;
  /** Error messages */
  errorMessages?: string | string[];
  /** Disabled state */
  disabled?: boolean;
  /** Readonly state */
  readonly?: boolean;
  /** Inline layout */
  inline?: boolean;
  /** Hide details */
  hideDetails?: boolean | 'auto';
  /** Field density */
  density?: 'default' | 'comfortable' | 'compact';
}

// Events
interface RadioGroupEvents {
  'update:modelValue': (value: any) => void;
}

Usage Examples:

<template>
  <v-radio-group v-model="selectedOption" label="Choose an option">
    <v-radio
      v-for="option in options"
      :key="option.value"
      :value="option.value"
      :label="option.text"
    />
  </v-radio-group>

  <!-- Inline radio group -->
  <v-radio-group
    v-model="size"
    label="Size"
    inline
  >
    <v-radio value="small" label="Small" />
    <v-radio value="medium" label="Medium" />
    <v-radio value="large" label="Large" />
  </v-radio-group>
</template>

VSwitch

Toggle switch component for boolean state control.

/**
 * Toggle switch component
 */
const VSwitch: Component;

interface SwitchProps {
  /** Switch value */
  modelValue?: any;
  /** True value when on */
  trueValue?: any;
  /** False value when off */
  falseValue?: any;
  /** Switch label */
  label?: string;
  /** Validation rules */
  rules?: ValidationRule[];
  /** Disabled state */
  disabled?: boolean;
  /** Readonly state */
  readonly?: boolean;
  /** Loading state */
  loading?: boolean;
  /** Error state */
  error?: boolean;
  /** Switch color */
  color?: string;
  /** Inset style */
  inset?: boolean;
  /** Flat style (no elevation) */
  flat?: boolean;
  /** Hide details */
  hideDetails?: boolean | 'auto';
  /** Field density */
  density?: 'default' | 'comfortable' | 'compact';
}

// Events
interface SwitchEvents {
  'update:modelValue': (value: any) => void;
}

Usage Examples:

<template>
  <!-- Basic switch -->
  <v-switch
    v-model="enabled"
    label="Enable notifications"
  />

  <!-- Custom values -->
  <v-switch
    v-model="mode"
    true-value="dark"
    false-value="light"
    label="Dark mode"
  />

  <!-- Loading switch -->
  <v-switch
    v-model="autoSave"
    :loading="saving"
    label="Auto-save"
  />
</template>

VSlider & VRangeSlider

Slider components for numeric value selection.

/**
 * Single value slider component
 */
const VSlider: Component;

interface SliderProps {
  /** Slider value */
  modelValue?: number | string;
  /** Minimum value */
  min?: number | string;
  /** Maximum value */
  max?: number | string;
  /** Step increment */
  step?: number | string;
  /** Slider label */
  label?: string;
  /** Validation rules */
  rules?: ValidationRule[];
  /** Disabled state */
  disabled?: boolean;
  /** Readonly state */
  readonly?: boolean;
  /** Show thumb label */
  thumbLabel?: boolean | 'always';
  /** Thumb size */
  thumbSize?: number | string;
  /** Show ticks */
  showTicks?: boolean | 'always';
  /** Tick labels */
  tickLabels?: string[];
  /** Tick size */
  tickSize?: number | string;
  /** Vertical orientation */
  vertical?: boolean;
  /** Slider color */
  color?: string;
  /** Track color */
  trackColor?: string;
  /** Track fill color */
  trackFillColor?: string;
  /** Track size */
  trackSize?: number | string;
  /** Thumb color */
  thumbColor?: string;
  /** Hide details */
  hideDetails?: boolean | 'auto';
  /** Field density */
  density?: 'default' | 'comfortable' | 'compact';
}

/**
 * Range slider with dual handles
 */
const VRangeSlider: Component;

interface RangeSliderProps extends Omit<SliderProps, 'modelValue'> {
  /** Range values [min, max] */
  modelValue?: number[];
}

// Events
interface SliderEvents {
  'update:modelValue': (value: number | number[]) => void;
  'start': (value: number | number[]) => void;
  'end': (value: number | number[]) => void;
}

Usage Examples:

<template>
  <!-- Basic slider -->
  <v-slider
    v-model="volume"
    :min="0"
    :max="100"
    label="Volume"
    thumb-label
  />

  <!-- Range slider -->
  <v-range-slider
    v-model="priceRange"
    :min="0"
    :max="1000"
    :step="10"
    label="Price Range"
    thumb-label="always"
  />

  <!-- Slider with ticks -->
  <v-slider
    v-model="rating"
    :min="1"
    :max="5"
    :step="1"
    label="Rating"
    show-ticks="always"
    :tick-labels="['Poor', 'Fair', 'Good', 'Very Good', 'Excellent']"
  />
</template>

VFileInput

File upload input component with drag-and-drop support.

/**
 * File input component
 */
const VFileInput: Component;

interface FileInputProps {
  /** Selected files */
  modelValue?: File | File[];
  /** Accept file types */
  accept?: string;
  /** Multiple file selection */
  multiple?: boolean;
  /** Field label */
  label?: string;
  /** Placeholder text */
  placeholder?: string;
  /** Validation rules */
  rules?: ValidationRule[];
  /** Disabled state */
  disabled?: boolean;
  /** Readonly state */
  readonly?: boolean;
  /** Show file size */
  showSize?: boolean | ((file: File) => string);
  /** Clearable selection */
  clearable?: boolean;
  /** Chips display for multiple files */
  chips?: boolean;
  /** Counter for file count */
  counter?: boolean;
  /** Prepend icon */
  prependIcon?: string;
  /** Append icon */
  appendIcon?: string;
  /** Hide details */
  hideDetails?: boolean | 'auto';
}

// Events
interface FileInputEvents {
  'update:modelValue': (files: File | File[]) => void;
  'click:prepend': (event: MouseEvent) => void;
  'click:append': (event: MouseEvent) => void;
  'click:clear': (event: MouseEvent) => void;
}

Usage Examples:

<template>
  <!-- Basic file input -->
  <v-file-input
    v-model="selectedFile"
    label="Choose file"
    accept="image/*"
  />

  <!-- Multiple files with chips -->
  <v-file-input
    v-model="selectedFiles"
    label="Choose files"
    multiple
    chips
    show-size
    counter
  />

  <!-- With validation -->
  <v-file-input
    v-model="document"
    :rules="fileRules"
    label="Upload document"
    accept=".pdf,.doc,.docx"
  />
</template>

<script setup>
const fileRules = [
  v => !!v || 'File is required',
  v => !v || v.size <= 5 * 1024 * 1024 || 'File must be less than 5MB',
];
</script>

VNumberInput

Numeric input component with increment/decrement controls.

/**
 * Number input with controls
 */
const VNumberInput: Component;

interface NumberInputProps {
  /** Number value */
  modelValue?: number;
  /** Minimum value */
  min?: number;
  /** Maximum value */
  max?: number;
  /** Step increment */
  step?: number;
  /** Field label */
  label?: string;
  /** Validation rules */
  rules?: ValidationRule[];
  /** Disabled state */
  disabled?: boolean;
  /** Readonly state */
  readonly?: boolean;
  /** Hide control buttons */
  hideControls?: boolean;
  /** Control variant */
  controlVariant?: 'default' | 'stacked' | 'split';
  /** Reverse controls */
  reverse?: boolean;
  /** Hide details */
  hideDetails?: boolean | 'auto';
}

// Events
interface NumberInputEvents {
  'update:modelValue': (value: number) => void;
}

Usage Examples:

<template>
  <!-- Basic number input -->
  <v-number-input
    v-model="quantity"
    :min="1"
    :max="100"
    label="Quantity"
  />

  <!-- Stacked controls -->
  <v-number-input
    v-model="price"
    :step="0.01"
    :min="0"
    label="Price"
    control-variant="stacked"
  />
</template>

VOtpInput

One-time password (OTP) input component for verification codes.

/**
 * OTP/PIN input component
 */
const VOtpInput: Component;

interface OtpInputProps {
  /** OTP value */
  modelValue?: string;
  /** Number of input fields */
  length?: number;
  /** Input type */
  type?: 'text' | 'number' | 'password';
  /** Field variant */
  variant?: 'filled' | 'outlined' | 'underlined' | 'plain';
  /** Validation rules */
  rules?: ValidationRule[];
  /** Disabled state */
  disabled?: boolean;
  /** Readonly state */
  readonly?: boolean;
  /** Field density */
  density?: 'default' | 'comfortable' | 'compact';
  /** Hide details */
  hideDetails?: boolean | 'auto';
  /** Placeholder character */
  placeholder?: string;
  /** Autofocus */
  autofocus?: boolean;
}

// Events
interface OtpInputEvents {
  'update:modelValue': (value: string) => void;
  'finish': (value: string) => void;
}

Usage Examples:

<template>
  <!-- Basic OTP input -->
  <v-otp-input
    v-model="otpCode"
    :length="6"
    type="number"
    @finish="handleOtpComplete"
  />

  <!-- Password OTP -->
  <v-otp-input
    v-model="pinCode"
    :length="4"
    type="password"
    variant="outlined"
  />
</template>

Types

// Validation types
type ValidationRule<T = any> = 
  | true 
  | string 
  | ((value: T) => true | string);

// Form submission event
interface SubmitEventPromise extends Event {
  readonly valid: Promise<{ valid: boolean; errors: ValidationError[] }>;
}

// Validation error structure
interface ValidationError {
  id: string | number;
  errorMessages: string[];
}

// Field variants
type FieldVariant = 'filled' | 'outlined' | 'underlined' | 'plain' | 'solo' | 'solo-inverted' | 'solo-filled';

// Input types
type InputType = 'text' | 'password' | 'email' | 'url' | 'tel' | 'number';

// Density options
type Density = 'default' | 'comfortable' | 'compact';

// Filter function for autocomplete/combobox
type FilterFunction = (item: any, queryText: string, itemText: string) => boolean;

Install with Tessl CLI

npx tessl i tessl/npm-vuetify

docs

components.md

composables.md

data-display.md

directives.md

feedback.md

forms.md

framework-core.md

icons.md

index.md

internationalization.md

lab-components.md

navigation.md

theming.md

transitions.md

utilities.md

tile.json