Skip to content

@qnx/vuetifyVue 3 Components for Vuetify 4

Drop-in form inputs, server-driven tables, infinite-scroll lists, and toast notifications — with built-in validation, API integration, and zero boilerplate.

What is @qnx/vuetify? ​

@qnx/vuetify is a Vue 3 component library built on top of Vuetify 4. It provides ready-to-use components that eliminate the repetitive work of building forms, data tables, and lists in Vuetify apps:

  • Form inputs that bind to vee-validate automatically — no v-model, no useField in your component
  • VqForm that submits to your API via axios, shows loading state, and maps server errors to fields
  • VqDataTable that handles server-side pagination, sorting, and re-fetches on filter change
  • VqList with infinite scroll and filter integration
  • Toast notifications via a simple useMessageInstance() composable

Installation ​

bash
npm install @qnx/vuetify

Install peer dependencies:

bash
npm install vuetify@latest @qnx/composables vee-validate yup axios

Quick Example ​

Form with Validation ​

vue
<script setup>
import { VqForm, VqTextField, VqAutocomplete, VqSubmitBtn } from "@qnx/vuetify";
import { object, string } from "yup";

const schema = object({
  name: string().required("Name is required"),
  email: string().required().email("Invalid email"),
  role: string().required("Please select a role"),
});
</script>

<template>
  <VqForm
    id="create-user"
    action="users/create"
    method="POST"
    :validation-schema="schema"
    @submited-success="(res) => console.log('Done:', res)"
  >
    <VqTextField name="name" label="Full Name" />
    <VqTextField name="email" label="Email" type="email" />
    <VqAutocomplete name="role" label="Role" :items="['Admin', 'Editor', 'Viewer']" />
    <VqSubmitBtn>Create User</VqSubmitBtn>
  </VqForm>
</template>

Data Table with Filters ​

vue
<script setup>
import {
  VqDataTable, VqTableFilter, VqTextField,
  VqSerialNo, VqDatatableItemAction, collectVqHeaders
} from "@qnx/vuetify";

const headers = collectVqHeaders([
  { title: "Name", key: "name" },
  { title: "Email", key: "email" },
  { title: "Actions", key: "actions", sortable: false },
]);
</script>

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

  <VqDataTable id="users" action="users/list" :headers="headers">
    <template #item="{ item, index }">
      <tr>
        <VqSerialNo :index="index" />
        <td>{{ item.name }}</td>
        <td>{{ item.email }}</td>
        <td>
          <VqDatatableItemAction
            id="users"
            :item-id="String(item.id)"
            action="users/delete"
            method="DELETE"
          />
        </td>
      </tr>
    </template>
  </VqDataTable>
</template>

Infinite Scroll List ​

vue
<template>
  <VqList id="posts" action="posts/list" :page-size="15" v-slot="{ items, loading }">
    <v-list>
      <v-list-item
        v-for="post in items"
        :key="post.id"
        :title="post.title"
        :subtitle="post.author"
      />
    </v-list>
    <v-skeleton-loader v-if="loading" type="list-item@3" />
    <VqListLoadMoreBtn />
  </VqList>
</template>

Component Overview ​

CategoryComponents
Form InputsVqTextField, VqTextarea, VqCheckbox, VqAutocomplete, VqDatePicker, VqTimePicker, VqColorPicker, VqOtpInput, VqFileInput, VqFileUpload
Form WrappersVqForm, useVqForm, VqSubmitBtn
Data TableVqDataTable, useVqDataTable, VqSerialNo, collectVqHeaders, VqDatatableItemAction
ListVqList, useVqList, VqTableFilter, VqListLoadMoreBtn
NotificationsMessageQueue, useMessageInstance
Rich TextVqTextEditor (via /integrations)