@qnx/vuetify

June 17, 2026 · View on GitHub

@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-shakeablesideEffects: false, import only what you use

🧱 Tech Stack

LayerTechnology
FrameworkVue 3
UIVuetify 4
Validationvee-validate 4 + Yup (optional)
StatePinia 3
HTTPaxios via @qnx/composables
LanguageTypeScript
Rich text (opt)TinyMCE

⚡ Quick Start

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

Prerequisites

RequirementVersion
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

ResourceLink
📖 Documentationhttps://qnx-vuetify-docs.vercel.app/
🎮 Live Exampleshttps://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.

ComponentDescription
VqFormForm wrapper — submission, validation, server calls
VqTextFieldText input bound to form state
VqTextareaTextarea bound to form state
VqAutocompleteAutocomplete/select, supports remote items
VqCheckboxCheckbox bound to form state
VqDatePickerDate picker bound to form state
VqTimePickerTime picker bound to form state
VqColorPickerColor picker bound to form state
VqOtpInputOTP input bound to form state
VqFileInputFile input bound to form state
VqFileUploadFile upload with upload handling
VqSubmitBtnSubmit button reflecting form busy state
VqForm props & events

Props

PropTypeDefaultDescription
idstringUnique form identifier (required)
actionstringAPI endpoint for submission (required)
methodstring"POST"HTTP method
initialValuesobjectundefinedInitial values — form resets when this changes
validationSchemaobjectundefinedYup validation schema
valuesSchemaobjectundefinedMaps nested response fields to flat form fields
formDatabooleanfalseSubmit as multipart/form-data
successResponseHandlerfunctionCustom success handler
errorResponseHandlerfunctionCustom error handler

Events

EventPayloadEmitted when
submited-successApiResponseServer responds successfully
submited-errorApiResponseServer returns a validation error
submited-client-errorClient-side validation fails

Data Table Components

ComponentDescription
VqDataTableServer-side table on Vuetify's VDataTableServer
VqSerialNo<td> with the row's serial number
VqDatatableItemActionRow action button with a confirmation dialog
VqDataTable & VqDatatableItemAction props

VqDataTable

PropTypeDefaultDescription
idstringIdentifier (required)
actionstringFetch endpoint (required)
methodstring"GET"HTTP method
pagenumber1Initial page
itemsPerPagenumber10Rows per page
sortBySortByValue[][{ key: "name", order: "asc" }]Default sort

VqDatatableItemAction

PropTypeDefaultDescription
idstringTable ID — reloads after action (req.)
itemIdstring"0"Row ID, appended to action as a path
actionstring"user/change-status"API endpoint
methodstring"PUT"HTTP method
titlestringlocale.confirmTitleDialog title
descriptionstringlocale.confirmDeleteDescriptionDialog message
iconstringmdiDeleteMDI icon path

List Components

ComponentDescription
VqListInfinite-scroll list integrating with VqTableFilter
VqListLoadMoreBtnLoads the next page — used inside VqList
VqTableFilterFilter form linked to a table/list by id
VqList & VqTableFilter props

VqList

PropTypeDefaultDescription
idstringIdentifier (required)
actionstringFetch endpoint (required)
pageSizenumber10Items per page

VqTableFilter

PropTypeDefaultDescription
idstringMust match the paired table/list (required)

Composables

ComposableReturns
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.

ToolDescription
get_component_listList all components grouped by category
get_component_docsFull docs for a component: props, events, examples
get_composable_listList all composables with descriptions
get_composable_docsFull docs for a composable
get_installation_guideInstallation steps and peer dependencies
get_usage_guidePractical 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