@qnx/vuetify

An extendable library of Vuetify form components & more.
2,252 5
Install
npm install @qnx/vuetify
Latest Version:0.8.5
Vue:1 · 2 · 3
License:MIT
Last Updated:Jun 17, 2026
Links: GitHub  ·  npm
Maintainer: yatendra121kushwaha

@qnx/vuetify

Declarative Vuetify form, table, and list components that talk to your API for you.

npm version npm downloads license Vue 3 Vuetify 4

📖 Documentation · 🤖 MCP Server: npx @qnx/vuetify-mcp


🚀 Overview

@qnx/vuetify is a Vue 3 component library built on top of Vuetify that removes the repetitive plumbing behind data-driven UIs. Forms, server-side tables, and infinite lists handle their own validation, HTTP requests, error display, pagination, and request cancellation — so your templates stay declarative.

Built for Vue 3 teams using Vuetify who are tired of rewriting the same axios + loading-state + error-mapping boilerplate on every page.

Use it for:

  • 📝 Forms with schema validation and automatic server-error mapping
  • 📊 Server-side data tables with paging, sorting, and filtering
  • 📜 Infinite-scroll lists wired to a paginated endpoint
  • 🔗 Filter forms linked to a table or list by a shared id

✨ Features

  • Zero fetch boilerplate — set an action, the request lifecycle is managed for you
  • Automatic error mapping — server validation errors map straight to form fields
  • Race-condition safe — in-flight requests are cancelled on change and unmount
  • Server-side tables & lists — paging, sorting, and filtering built in
  • TypeScript-first — generics flow your item types into slots
  • Localizable — override every built-in UI string with one call
  • Tree-shakeable — sideEffects: false, import only what you use

🧱 Tech Stack

Layer Technology
Framework Vue 3
UI Vuetify 4
Validation vee-validate 4 + Yup (optional)
State Pinia 3
HTTP axios via @qnx/composables
Language TypeScript
Rich text (opt) TinyMCE

⚡ Quick Start

Get a validated, API-connected form on screen in under 5 minutes.

Prerequisites

Requirement Version
Node.js ^18.13 · ^20.11 · >=22
Vue ^3.5
Vuetify ^4.1

1. Install

# npm
npm install @qnx/vuetify

# pnpm
pnpm add @qnx/vuetify

# yarn / bun
yarn add @qnx/vuetify
bun add @qnx/vuetify

Install the peer dependencies:

npm install vuetify@^4.1.0 pinia vee-validate axios @qnx/composables

2. Register

// main.ts
import { createApp } from 'vue'
import { createVuetify } from 'vuetify'
import { createPinia } from 'pinia'
import VqVuetify from '@qnx/vuetify'
import App from './App.vue'

createApp(App)
  .use(createVuetify())
  .use(createPinia())
  .use(VqVuetify)        // globally registers all Vq* components
  .mount('#app')

Prefer explicit imports? Skip .use(VqVuetify) and import components directly: import { VqForm, VqTextField } from '@qnx/vuetify'.

3. Use

<script setup>
import { object, string } from 'yup'

const schema = object({
  email: string().required().email(),
  password: string().required()
})
</script>

<template>
  <VqForm id="login" action="auth/login" :validation-schema="schema">
    <VqTextField name="email" label="Email" />
    <VqTextField name="password" label="Password" type="password" />
    <VqSubmitBtn />
  </VqForm>
</template>

That's it — validation, submission, loading state, and server-error display are handled. Next, point requests at your API in Configuration.

📂 Project Structure

src/
├─ components/
│  ├─ Vuetify/      # VqForm, VqDataTable, VqList, field inputs…
│  ├─ Basic/        # VqSubmitBtn, snackbar message queue
│  └─ Tinymce/      # VqTextEditor (optional integration)
├─ composables/     # useVqForm, useVqDataTable, useVqList
├─ config/          # locale / i18n strings
├─ store/           # Pinia stores (form state, messages)
├─ types/           # shared TypeScript types
├─ integrations.ts  # opt-in entry for optional components
└─ index.ts         # public entry + Vue plugin

🔧 Configuration

Point requests at your API

Components send requests through the shared axios instance from @qnx/composables. Configure its base URL once at startup:

import axios from 'axios'
import { setAxiosInstance } from '@qnx/composables/axios'

setAxiosInstance(
  axios.create({
    baseURL: import.meta.env.VITE_API_URL, // e.g. https://api.example.com
    headers: { Accept: 'application/json' }
  })
)

Now a component action="users" resolves to GET {baseURL}/users.

Required plugins

@qnx/vuetify relies on Vuetify and Pinia being installed on the app (see Quick Start). Pinia backs internal form and message state.

Rich text editor (optional)

VqTextEditor ships from the optional /integrations entry and requires @tinymce/tinymce-vue. Set the asset base URL once:

import { setConfig } from '@qnx/vuetify/integrations'
import { VqTextEditor } from '@qnx/vuetify/integrations'

setConfig({ baseUrl: '/tinymce' })

📸 Demo

Resource Link
📖 Documentation https://qnx-vuetify-docs.vercel.app/
🎮 Live Examples https://qnx-vuetify-sample.vercel.app/ (soon)

🧪 Usage Examples

Form with validation

<script setup>
import { object, string } from 'yup'

const schema = object({
  name: string().required(),
  email: string().required().email()
})
const onSuccess = (res) => console.log(res)
</script>

<template>
  <VqForm
    id="create-user"
    action="user/create"
    method="POST"
    :validation-schema="schema"
    @submited-success="onSuccess"
  >
    <VqTextField name="name" label="Name" />
    <VqTextField name="email" label="Email" />
    <VqSubmitBtn />
  </VqForm>
</template>

Server-side data table

Pagination, sorting, debounced filtering, request cancellation, and loading state — all internal:

<script setup lang="ts">
import { useVqDataTable, collectVqHeaders } from '@qnx/vuetify'

interface User { id: number; name: string; email: string }

const UsersTable = useVqDataTable<User>()
const headers = collectVqHeaders([
  { title: 'Name', key: 'name' },
  { title: 'Email', key: 'email' }
])
</script>

<template>
  <UsersTable id="users" action="users" :headers="headers">
    <template #item="{ item, index }">
      <tr>
        <VqSerialNo :index="index + 1" />
        <td>{{ item.name }}</td>
        <td>{{ item.email }}</td>
      </tr>
    </template>
  </UsersTable>
</template>

Infinite-scroll list

<template>
  <VqList id="posts" action="posts" :page-size="10">
    <template #default="{ items }">
      <div v-for="post in items" :key="post.id">{{ post.title }}</div>
    </template>
    <template #load-more>
      <VqListLoadMoreBtn />
    </template>
  </VqList>
</template>

Filter + table pattern

A VqTableFilter and VqDataTable (or VqList) share an id; changing a filter reloads the data automatically:

<template>
  <VqTableFilter id="users">
    <VqTextField name="search" label="Search" />
  </VqTableFilter>

  <VqDataTable id="users" action="users" :headers="headers" />
</template>

📘 API Reference

Form Components

Use inside a VqForm / useVqForm wrapper — they bind to form state and display validation automatically.

Component Description
VqForm Form wrapper — submission, validation, server calls
VqTextField Text input bound to form state
VqTextarea Textarea bound to form state
VqAutocomplete Autocomplete/select, supports remote items
VqCheckbox Checkbox bound to form state
VqDatePicker Date picker bound to form state
VqTimePicker Time picker bound to form state
VqColorPicker Color picker bound to form state
VqOtpInput OTP input bound to form state
VqFileInput File input bound to form state
VqFileUpload File upload with upload handling
VqSubmitBtn Submit button reflecting form busy state
VqForm props & events

Props

Prop Type Default Description
id string — Unique form identifier (required)
action string — API endpoint for submission (required)
method string "POST" HTTP method
initialValues object undefined Initial values — form resets when this changes
validationSchema object undefined Yup validation schema
valuesSchema object undefined Maps nested response fields to flat form fields
formData boolean false Submit as multipart/form-data
successResponseHandler function — Custom success handler
errorResponseHandler function — Custom error handler

Events

Event Payload Emitted when
submited-success ApiResponse Server responds successfully
submited-error ApiResponse Server returns a validation error
submited-client-error — Client-side validation fails

Data Table Components

Component Description
VqDataTable Server-side table on Vuetify's VDataTableServer
VqSerialNo <td> with the row's serial number
VqDatatableItemAction Row action button with a confirmation dialog
VqDataTable & VqDatatableItemAction props

VqDataTable

Prop Type Default Description
id string — Identifier (required)
action string — Fetch endpoint (required)
method string "GET" HTTP method
page number 1 Initial page
itemsPerPage number 10 Rows per page
sortBy SortByValue[] [{ key: "name", order: "asc" }] Default sort

VqDatatableItemAction

Prop Type Default Description
id string — Table ID — reloads after action (req.)
itemId string "0" Row ID, appended to action as a path
action string "user/change-status" API endpoint
method string "PUT" HTTP method
title string locale.confirmTitle Dialog title
description string locale.confirmDeleteDescription Dialog message
icon string mdiDelete MDI icon path

List Components

Component Description
VqList Infinite-scroll list integrating with VqTableFilter
VqListLoadMoreBtn Loads the next page — used inside VqList
VqTableFilter Filter form linked to a table/list by id
VqList & VqTableFilter props

VqList

Prop Type Default Description
id string — Identifier (required)
action string — Fetch endpoint (required)
pageSize number 10 Items per page

VqTableFilter

Prop Type Default Description
id string — Must match the paired table/list (required)

Composables

Composable Returns
useVqForm(options) A form wrapper plus state helpers (resetForm, errors, values)
useVqDataTable<T>() A typed VqDataTable with inference for item slots
useVqList<T>() A typed VqList with inference for the default slot's items
collectVqHeaders(h) Prepends a # serial-number column to a headers array
import { useVqForm } from '@qnx/vuetify'
import { object, string } from 'yup'

const { wrapper: EditUser, resetForm } = useVqForm({
  formId: 'edit-user',
  validationSchema: object({ name: string().required() }),
  initialValues: { name: '' }
})

Localization

Override any built-in string ("Submit", "Load More", dialog labels…) with setVqLocale. It accepts a partial — omitted keys keep the English default. resetVqLocale() restores defaults.

import { setVqLocale } from '@qnx/vuetify'

setVqLocale({
  submit: 'Enviar',
  loadMore: 'Cargar más',
  confirmTitle: 'Confirmación',
  confirmDeleteDescription: '¿Eliminar este registro?',
  confirm: 'Confirmar',
  cancel: 'Cancelar'
})

🤖 MCP Server

AI assistants can query this library's docs through the @qnx/vuetify-mcp server.

Tool Description
get_component_list List all components grouped by category
get_component_docs Full docs for a component: props, events, examples
get_composable_list List all composables with descriptions
get_composable_docs Full docs for a composable
get_installation_guide Installation steps and peer dependencies
get_usage_guide Practical usage examples

Supported clients: Claude Desktop · Claude Code · Cursor · Windsurf · Cline · Continue.dev · Codex CLI · ChatGPT Desktop

{
  "mcpServers": {
    "qnx-vuetify": {
      "command": "npx",
      "args": ["-y", "@qnx/vuetify-mcp"]
    }
  }
}

🤝 Contributing

Contributions are welcome! For major changes, open an issue first to discuss the direction.

git clone https://github.com/yatendra121/vq-vuetify.git
cd vq-vuetify
pnpm install
pnpm test:unit     # run the test suite
pnpm lint          # lint & autofix
pnpm build         # build the library

Please keep changes focused and update tests as appropriate.

📄 License

MIT © 2023–PRESENT Yatendra Kushwaha

Related Packages

@rc-component/async-validator

Validate form asynchronous

99,929,287 16
@molgenis/molgenis-ui-form

Library for generating HTML web forms

6,017 0
@qtxr/vue-form

Powerful Vue forms based on @qtxr/form

3,348
@agtm/nuxt-form

Gerador de Formulário para o nuxt framework

2,560 1
vue-master-form

vue fast create form

1,660

Version History

Version Released Vue License
0.8.5 * MIT
0.8.1 * MIT
0.8.0 * MIT
0.7.20 * MIT
0.7.12 * MIT