src/skills/web-ui-vuetify/SKILL.md
Material Design component library for Vue 3
npx skillsauth add agents-inc/skills web-ui-vuetifyInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Quick Guide: Vuetify provides 80+ pre-styled Vue 3 components implementing Material Design. Configure with
createVuetify()-- setthemefor colors,defaultsfor global component props, andblueprint: md3for MD3 compliance. Usev-defaults-providerfor scoped prop overrides. Customize at the SASS level with@use 'vuetify/settings'for compile-time changes. Current: v3.8.x --useRulescomposable for form validation, date picker improvements, performance optimizations. Vuetify is template-driven -- prefer declarative props/slots over imperative JS.
<critical_requirements>
All code must follow project conventions in CLAUDE.md (kebab-case, named exports, import ordering,
import type, named constants)
(You MUST install and register Vuetify as a Vue plugin via app.use(vuetify) -- components will not render without the plugin)
(You MUST use the defaults system in createVuetify() or v-defaults-provider for consistent component props -- never repeat the same prop on every instance)
(You MUST use named slots (v-slot:item.<key>, v-slot:prepend) for component customization -- not wrapper divs with manual styling)
(You MUST define v-data-table headers and column arrays outside the component -- inline arrays cause re-renders on every parent update)
</critical_requirements>
Auto-detection: Vuetify, vuetify, createVuetify, v-btn, v-card, v-data-table, v-text-field, v-select, v-autocomplete, v-dialog, v-navigation-drawer, v-app-bar, v-toolbar, v-chip, v-snackbar, v-form, v-defaults-provider, v-theme-provider, useTheme, useDisplay, useDate, useRules, mdi, @mdi/font, vuetify/blueprints, vuetify/settings, vuetify/styles
When to use:
When NOT to use:
Key patterns covered:
createVuetify(), themes, and blueprintsv-defaults-provideruseRules composableuseTheme / useDisplay composablesDetailed Resources:
Vuetify is an opinionated, batteries-included component library. Unlike headless libraries, Vuetify ships styled components with a complete design system. Its power comes from three layers of customization:
createVuetify({ theme }). All components inherit automatically.defaults config or v-defaults-provider. Change every v-btn to variant="outlined" in one line.@use 'vuetify/settings'. Changes border-radius, heights, font families at the CSS level.Vuetify 3.x key features:
vuetify-loader / vite-plugin-vuetifymd3) for MD3 complianceuseTheme, useDisplay, useDate, useRulesv-defaults-provider for scoped prop cascading (unique to Vuetify)Every Vuetify app requires createVuetify() and app.use(). The plugin provides the theme, defaults, icons, and locale to all components.
import { createApp } from "vue";
import { createVuetify } from "vuetify";
const vuetify = createVuetify({
theme: {
defaultTheme: "light",
themes: {
light: {
colors: {
primary: "#1867C0",
secondary: "#5CBBF6",
},
},
},
},
defaults: {
VBtn: { variant: "flat", rounded: "lg" },
VTextField: { variant: "outlined", density: "comfortable" },
VCard: { elevation: 2, rounded: "lg" },
},
});
const app = createApp(App);
app.use(vuetify);
app.mount("#app");
Why good: single configuration point, all components inherit theme and default props, tree-shakeable
For blueprints, SASS variables, TypeScript augmentation, and SSR setup, see examples/core.md.
Define multiple themes in createVuetify and toggle with useTheme. Vuetify generates CSS variables for each theme.
<script setup>
import { useTheme } from "vuetify";
const theme = useTheme();
function toggleTheme() {
theme.global.name.value = theme.global.current.value.dark ? "light" : "dark";
}
</script>
<template>
<v-btn @click="toggleTheme" icon="mdi-brightness-6" />
</template>
Why good: reactive theme switching, CSS variables prevent flash of wrong theme, custom themes can extend built-in ones
For custom theme creation and color variations, see examples/core.md.
The defaults system is Vuetify's most powerful consistency tool. Set props globally in createVuetify() or scope them with v-defaults-provider.
<template>
<!-- All buttons inside this provider get these defaults -->
<v-defaults-provider
:defaults="{
VBtn: { color: 'secondary', variant: 'tonal' },
VCard: { elevation: 0, border: true },
}"
>
<v-card>
<v-card-text>
<!-- This button is tonal + secondary without explicit props -->
<v-btn>Scoped Default</v-btn>
</v-card-text>
</v-card>
</v-defaults-provider>
</template>
Why good: eliminates prop repetition, section-specific styling without CSS, nests and cascades like CSS scoping
Vuetify components expose named slots for every internal element. Use v-slot to replace or augment internal rendering.
<template>
<v-text-field label="Amount" type="number">
<template v-slot:prepend-inner>
<v-icon>mdi-currency-usd</v-icon>
</template>
<template v-slot:append-inner>
<v-chip size="x-small" color="success">.00</v-chip>
</template>
</v-text-field>
</template>
Why good: customizes internal elements without CSS overrides, type-safe slot props, preserves component behavior
For data table column slots, see examples/data-tables.md.
v-data-table handles sorting, pagination, filtering, and selection. Define headers outside the template, use v-slot:item.<key> for custom column rendering.
<script setup>
const headers = [
{ title: "Name", key: "name" },
{ title: "Status", key: "status" },
{ title: "Actions", key: "actions", sortable: false },
];
</script>
<template>
<v-data-table :items="items" :headers="headers">
<template v-slot:item.status="{ item }">
<v-chip
:color="item.status === 'active' ? 'success' : 'error'"
size="small"
>
{{ item.status }}
</v-chip>
</template>
<template v-slot:item.actions="{ item }">
<v-icon size="small" @click="edit(item)">mdi-pencil</v-icon>
</template>
</v-data-table>
</template>
Why good: headers array is stable (no re-render), slot customization per column, built-in sort/filter/paginate
For server-side data tables, expandable rows, and search, see examples/data-tables.md.
Vuetify forms use :rules arrays on inputs. Each rule is a function returning true or an error string. The useRules composable (v3.8+) provides common validators.
<script setup>
import { ref } from "vue";
import { useRules } from "vuetify/labs/rules";
const form = ref(null);
const email = ref("");
const rules = useRules();
async function submit(event: SubmitEvent) {
const { valid } = await form.value.validate();
if (!valid) return;
// proceed with submission
}
</script>
<template>
<v-form ref="form" validate-on="submit" @submit.prevent="submit">
<v-text-field
v-model="email"
label="Email"
:rules="[rules.required(), rules.email()]"
/>
<v-btn type="submit" color="primary">Submit</v-btn>
</v-form>
</template>
Why good: declarative validation, useRules eliminates boilerplate rule functions, validate-on controls timing
For custom rules, multi-field validation, and input types, see examples/forms.md.
The useDisplay composable provides reactive breakpoint state. Use it for logic-driven responsive behavior (template responsiveness uses Vuetify's grid props).
<script setup>
import { useDisplay } from "vuetify";
const { mobile, mdAndUp, name } = useDisplay();
</script>
<template>
<v-navigation-drawer v-if="mdAndUp" permanent />
<v-navigation-drawer v-else v-model="drawer" temporary />
<v-app-bar :density="mobile ? 'compact' : 'default'" />
</template>
Why good: reactive breakpoint booleans, avoids CSS media query duplication in script, matches Vuetify's breakpoint system
</patterns>Use vite-plugin-vuetify (Vite) or webpack-plugin-vuetify (Webpack) for automatic tree-shaking. Only imported components are bundled.
// vite.config.ts
import vuetify from "vite-plugin-vuetify";
export default {
plugins: [vuetify({ autoImport: true })],
};
Without the plugin, import vuetify/components and vuetify/directives to include everything (larger bundle).
// GOOD: headers defined outside component
const headers: DataTableHeader[] = [{ title: "Name", key: "name" }];
// BAD: inline array recreated every render
// <v-data-table :headers="[{ title: 'Name', key: 'name' }]" />
Need to change at runtime? --> Use theme colors in createVuetify()
Need compile-time CSS changes? --> Use SASS variables (@use 'vuetify/settings')
Need per-section prop defaults? --> Use v-defaults-provider (zero CSS cost)
</performance>
<red_flags>
High Priority Issues:
app.use(vuetify) -- components render as empty custom elements without the pluginv-data-table -- causes full table re-render on every parent updatethis.$vuetify in Composition API -- use useTheme(), useDisplay(), useDate() composables insteadvuetify/components and vuetify/directives when vite-plugin-vuetify is available -- negates tree-shakingMedium Priority Issues:
variant, density, rounded on every component instance -- use defaults in createVuetify() instead#1867C0) in templates instead of using theme colors (color="primary")v-if to toggle dialogs/drawers instead of v-model -- loses transition animations and internal stateCommon Mistakes:
import 'vuetify/styles' when not using the build plugin -- no styles load at all!important to override Vuetify styles -- use SASS variables or class prop with higher specificityvalidate-on on v-form -- defaults to input which validates on every keystroke (use "submit" or "blur lazy" for better UX)v-col without a parent v-row inside v-container -- grid system requires the full nestingGotchas & Edge Cases:
density accepts "default", "comfortable", "compact" -- it is NOT a numeric valuev-data-table-server is a separate component for server-side pagination -- do not use v-data-table with manual paginationv-defaults-provider cascades -- nested providers merge with parent, later values winuseDisplay breakpoints differ from CSS breakpoints in default config (xs: 0, sm: 600, md: 960, lg: 1280, xl: 1920, xxl: 2560)variations generate -lighten-N and -darken-N color variants automatically -- do not manually define themv-model on v-dialog controls visibility -- do not use value prop (Vue 3 v-model replaces .sync)styles.configFile pointing to your settings file</red_flags>
<critical_reminders>
All code must follow project conventions in CLAUDE.md (kebab-case, named exports, import ordering,
import type, named constants)
(You MUST install and register Vuetify as a Vue plugin via app.use(vuetify) -- components will not render without the plugin)
(You MUST use the defaults system in createVuetify() or v-defaults-provider for consistent component props -- never repeat the same prop on every instance)
(You MUST use named slots (v-slot:item.<key>, v-slot:prepend) for component customization -- not wrapper divs with manual styling)
(You MUST define v-data-table headers and column arrays outside the component -- inline arrays cause re-renders on every parent update)
Failure to follow these rules will produce unstyled components, unnecessary re-renders, and inconsistent UI.
</critical_reminders>
development
VitePress 1.x — Vue-powered static site generator for documentation sites, built on Vite
tools
Docusaurus 3.x documentation framework — site configuration, docs/blog plugins, sidebars, versioning, MDX, swizzling, and deployment
development
TanStack Form patterns - useForm, form.Field, validators, arrays, linked fields, createFormHook, type safety
tools
Tauri 2.x commands, IPC bridge, permission system, plugins, window management, system tray, packaging