Enforces style and architectural standards for Vuetify 4, including buttons, dialogs, and form validation.

Install

mkdir -p .claude/skills/vuetify && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/18118" && unzip -o skill.zip -d .claude/skills/vuetify && rm skill.zip

Installs to .claude/skills/vuetify

Activation

This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.

Esposter Vuetify 4 conventions — StyledButton for primary actions, @click navigateTo navigation (Vuetify :to lint-banned), v-prefixed auto-imported composables (useVDisplay/useVTheme), global defaults never repeated, v-btn tooltips, mergeProps for nested activators, typed SelectItemCategoryDefinition for selects/lists/menus (clearable banned), enum-value-as-display-title, dialog form validity (StyledFormDialog vs StyledEditFormDialog), StyledList, useVRules form validation, StyledAvatar, CSS custom properties over SASS variables, and scrollspy sub-nav. Apply when writing or reviewing Vuetify components, dialogs, selects, forms, or lists.
645 chars✓ has a “when” triggerlonger than Claude Code's old 250-char listing cap (fine on current versions)
Intermediate

Key capabilities

  • Apply StyledButton for primary actions
  • Implement navigation via navigateTo
  • Use v-prefixed auto-imported composables
  • Manage nested activators with mergeProps
  • Standardize dialog form validity

How it works

The skill enforces architectural patterns and naming conventions for Vuetify 4 components, including specific button styling and navigation handling.

Inputs & outputs

You give it
Vuetify component or dialog implementation
You get back
Standardized, lint-compliant component code

When to use vuetify

  • Reviewing Vuetify component implementation
  • Standardizing dialog forms and list layouts
  • Implementing consistent button styling and navigation

About this skill

Vuetify Conventions

Primary Buttons

Use StyledButton for every confirm / complete / primary call-to-action button (create, save, accept, publish, request, start). Never use a raw color="primary" v-btn — the global VBtn default has a transparent background, so a primary-coloured button reads badly on the app's transparent / v-main base; StyledButton renders the midnight-bloom gradient + white text instead.

  • Pass Vuetify props through :button-props="{ ... }" (camelCase — e.g. { prependIcon: 'mdi-plus', disabled: !isValid, loading: isSubmitting }). For navigation put :to="RoutePath.X" on the <StyledButton> (it falls through to the root v-btn) — never a to inside buttonProps.
  • type is a native attribute, not a typed VBtn prop — put type="submit" directly on <StyledButton> (it falls through to the root v-btn), never inside buttonProps (which fails typecheck).
  • @click and other native listeners also fall through to the root v-btn.
  • Destructive confirms stay a color="error" v-btn (error red is visible on the transparent base) — StyledButton is for positive/primary actions only.

StyledTooltipIconButton shape — isIconButton

Vuetify's icon prop on v-btn doesn't just place an icon — it switches the button to the icon-button variant: circular, equal width/height, no min-width. StyledTooltipIconButton passes :icon by default, so converting a regular <v-tooltip> + <v-btn> (icon as a <v-icon> child, rectangular shape) to it silently turns the button into a circle. When the rectangular default-button shape is intended, pass :is-icon-button="false" — the component then renders a regular v-btn with the icon as a child. rounded/tile in buttonProps cannot restore the rectangle (they only change corners, not the forced square dimensions).

Navigation — :to for Plain Links, @click="navigateTo(...)" for Logic-Then-Navigate

Vuetify components (v-btn, v-card, v-list-item, v-tab, v-chip, StyledButton, …) with a plain destination take :to directly — it renders a real anchor, so cmd/ctrl/middle-click open-in-new-tab works. Use an @click="navigateTo(...)" handler only when the action runs logic before navigating or computes the target at click time:

  • For wrapper components put :to/@click directly on the wrapper — StyledButton / StyledTooltipIconButton fall them through to the root v-btn. Never pass to inside :button-props.
  • Route targets always come from RoutePath (@esposter/shared), never string-built.

See the routing skill, which owns link choice, the raw-<a> ban, and imperative navigation.

Auto-Imported Composables — v Prefix

Vuetify composables are auto-imported with a v prefix. Never import from "vuetify" directly — they are globally available:

// auto-imported with v prefix — never import { useDisplay } from "vuetify"
const { smAndDown } = useVDisplay();

Common: useVDisplay(), useVTheme(), useVLocale(), useVDate().

Global Defaults (vuetify.config.ts)

These variants are set globally and must never be repeated on individual components:

ComponentDefault
VAutocompletevariant="outlined"
VColorInputvariant="outlined"
VComboboxvariant="outlined"
VFileInputvariant="outlined"
VSelectvariant="outlined"
VTextareavariant="outlined"
VTextFieldvariant="outlined"
VBtnflat, transparent background
VDialogmaxWidth="100%", width=500
VTooltiplocation="top"

Button Conventions

  • Every icon-only v-btn must have a v-tooltip — wrap with v-tooltip + descriptive text so the action is discoverable. A button with visible label text (text="Remove" or default-slot text) is self-describing and does not need a tooltip.
  • #activator slot always first in v-tooltip (and v-menu).
  • Icon choice for create actions — use the semantically specific MDI icon when available: mdi-table-row-plus-after (add rows), mdi-table-column-plus-after (add columns). Fall back to mdi-plus for generic create.
<v-tooltip text="Descriptive action">
  <template #activator="{ props: tooltipProps }">
    <v-btn icon="mdi-some-icon" size="small" tile :="tooltipProps" @click="doSomething()" />
  </template>
</v-tooltip>

Nested Activators — mergeProps, Never Stacked v-bind

When one button is the activator for multiple overlays (a v-menu/v-dialog/v-hover and a v-tooltip), each overlay's #activator slot hands you its own props object. Combine them with mergeProps(...) from vue on a single :=never stack two := binds (:="menuProps" :="tooltipProps"). A second v-bind of the same key silently overrides the first, so the loser's onClick / onMouseenter / class is dropped; mergeProps chains event handlers and concatenates class/style instead.

Order: structural/outer activator(s) first, tooltip last — e.g. mergeProps(menuProps, tooltipProps), mergeProps(dialogProps, tooltipProps), mergeProps(hoverProps, tooltipProps), or three-way mergeProps(tooltipActivatorProps, hoverProps, buttonProps).

<v-menu>
  <template #activator="{ props: menuProps }">
    <v-tooltip text="Options">
      <template #activator="{ props: tooltipProps }">
        <v-btn icon="mdi-dots-vertical" :="mergeProps(menuProps, tooltipProps)" />
      </template>
    </v-tooltip>
  </template>
</v-menu>

A custom dialog/menu button that exposes an #activator slot should merge its own tooltip into the slot props so consumers don't have to:

<v-dialog>
  <template #activator="{ props: dialogProps }">
    <v-tooltip text="Settings">
      <template #activator="{ props: tooltipProps }">
        <slot name="activator" :="mergeProps(dialogProps, tooltipProps)" />
      </template>
    </v-tooltip>
  </template>
</v-dialog>

Consumers then bind the slot scope directly (:="activatorProps") — do not wrap such an activator in a second v-tooltip; it already has one.

Icon Buttons Inside Input Slots

When placing a v-btn inside a v-text-field slot (e.g. #append-inner), use variant="plain" and omit color. The global VBtn default sets style: { backgroundColor: "transparent" } inline, which variant="flat" + color="primary" cannot override. variant="plain" works with the transparent default and lets the icon inherit the surrounding text color.

<!-- CORRECT — plain variant works with the transparent default -->
<v-tooltip text="Add item">
  <template #activator="{ props: tooltipProps }">
    <v-btn icon="mdi-plus" variant="plain" :="tooltipProps" @click="submit()" />
  </template>
</v-tooltip>

Vuetify Selects and List Items

  • v-list-item icon placementprepend-icon for decorative/category icons (before the title); append-icon for action/severity icons (after, e.g. moderation actions). Action icon color/value come from the relevant AdminAction*Map constants — never hardcode inline.

  • Type items as SelectItemCategoryDefinition<T>[] ({ title: string, value: T }) from @/models/vuetify/SelectItemCategoryDefinition for v-autocomplete/v-select/v-list-item. Never inline untyped { title, value } arrays — extract to a typed constant.

  • Never specify item-title/item-value — Vuetify defaults ("title", "value") match SelectItemCategoryDefinition. If source data has different field names, map it to { title, value } at the call site — never pass the raw shape and compensate with item-title/item-value.

    // CORRECT — map to SelectItemCategoryDefinition<T> so no extra props needed
    const categoryItems = computed<SelectItemCategoryDefinition<string>[]>(() => [
      { title: "None", value: "" },
      ...categories.value.map(({ id, name }) => ({ title: name, value: id })),
    ]);
    // <v-select :items="categoryItems" />
    
  • clearable is BANNED on selects — clearing emits null, which violates the no-null convention and fails non-nullable API inputs. Model "no selection / all" as an explicit first item carrying the empty sentinel ({ title: "All members", value: "" }, { title: "No limit", value: 0 }) so the ref stays a plain inferred ref("")/ref(0) and the sentinel propagates end-to-end (see the typescript skill's sentinel section).

  • Name the items constant to reflect what the value represents — e.g. columnIds for SelectItemCategoryDefinition<string>[] where each value is a column ID.

  • Prefer enum values as display titles — set title to the enum member itself (title: SomeEnum.Foo) so key and value stay the same string. Update enum string values to match the intended label when reasonable, rather than inventing a separate title.

    Pick the construction by what each item carries:

    ShapeConstructionCanonical example
    Enum value as title + extra fields (icon)as const satisfies Record<Enum, …> map + parseDictionaryToArray(Map, "value")DataSourceTypeItemCategoryDefinitions
    Custom titles / an empty-sentinel itemplain SelectItemCategoryDefinition<T>[] array literalBooleanFilterValueItemCategoryDefinitions
    Enum value needing display formattingObject.values(Enum).map(...) through prettify()`StringTransformationItemCategoryDefin

Content truncated.

When not to use it

  • Never use raw color='primary' v-btn
  • Never use :to for router navigation
  • Never stack multiple v-binds for activators

Prerequisites

Vuetify 4Nuxt

Limitations

  • Bans :to for router navigation
  • Requires specific activator slot ordering
  • Requires StyledButton for primary actions

How it compares

This approach mandates global defaults and specific composable usage to prevent inconsistent component behavior across the application.

Compared to similar skills

vuetify side by side with the closest alternatives in the catalog.

SkillInstallsUpdatedSafetyDifficulty
vuetify (this skill)010dNo flagsIntermediate
scroll-experience1016moNo flagsIntermediate
anthropic-frontend-design126moNo flagsIntermediate
infographic-structure-creator15moNo flagsIntermediate

Try saying

Example prompts that trigger this skill in your AI assistant.

You might also like

scroll-experience

davila7

Expert in building immersive scroll-driven experiences - parallax storytelling, scroll animations, interactive narratives, and cinematic web experiences. Like NY Times interactives, Apple product pages, and award-winning web experiences. Makes websites feel like experiences, not just pages. Use when: scroll animation, parallax, scroll storytelling, interactive story, cinematic website.

101142

anthropic-frontend-design

chaibuilder

Create distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, artifacts, posters, or applications (examples include websites, landing pages, dashboards, React components, HTML/CSS layouts, or when styling/beautifying any web UI). Generates creative, polished code and UI design that avoids generic AI aesthetics.

1237

infographic-structure-creator

antvis

Generate or update infographic Structure components for this repo (TypeScript/TSX in src/designs/structures). Use when asked to design, implement, or modify structure layouts (list/compare/sequence/hierarchy/relation/geo/chart), including layout logic, component composition, and registration.

110

logo-with-variants

crafter-station

Create logo components with multiple variants (icon, wordmark, logo) and light/dark modes. Use when the user provides logo SVG files and wants to create a variant-based logo component following the Clerk pattern in the Elements project.

47

design-context

WellApp-ai

Refresh UI/UX context from design system, Storybook, and codebase

17

threejs-postprocessing

CloudAI-X

Three.js post-processing - EffectComposer, bloom, DOF, screen effects. Use when adding visual effects, color grading, blur, glow, or creating custom screen-space shaders.

17

Search skills

Search the agent skills registry