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)