
Vue Jsx Best Practices
Write or migrate Vue 3 JSX/TSX render functions using HTML attribute names so TypeScript and templates stay consistent and React habits do not slip in.
Overview
Vue JSX Best Practices is an agent skill for the Build phase that teaches Vue 3 JSX to use HTML attributes (`class`, `for`) instead of React conventions (`className`, `htmlFor`).
Install
npx skills add https://github.com/hyf0/vue-skills --skill vue-jsx-best-practicesWhat is this skill?
- Documents MEDIUM-impact gotcha: Vue JSX uses HTML attributes, not React `className` / `htmlFor`
- 5-item task checklist covering class, for, events, React migrations, and TS config
- Explains TypeScript errors on React conventions versus lenient runtime conversion
- Covers standard `on` prefixed event names (onClick, onInput) in Vue JSX
- Includes incorrect vs recommended patterns for migrating React components to Vue
- 5-item task checklist in the skill body
- Impact rating: MEDIUM for React-style attribute misuse
Adoption & trust: 1.7k installs on skills.sh; 2.5k GitHub stars; 3/3 security scanners passed (skills.sh audits).
What problem does it solve?
Your agent or team keeps writing React-style attributes in Vue JSX, triggering TypeScript errors and inconsistent UI code.
Who is it for?
Indie devs adding JSX render functions, porting React snippets into Vue 3, or linting agent output in a Vue + TypeScript repo.
Skip if: Projects using only Vue SFC templates with no JSX, or React-only codebases where Vue JSX rules do not apply.
When should I use this skill?
Writing or reviewing Vue 3 JSX/TSX where React attribute conventions (`className`, `htmlFor`) may appear.
What do I get? / Deliverables
Vue JSX and TSX follow HTML-aligned attribute and event conventions so migrated components type-check and match Vue template style.
- Convention-aligned Vue JSX/TSX attribute and event usage
- Checklist-complete component migrations from React-style JSX
Recommended Skills
Journey fit
How it compares
Use as a Vue-specific JSX convention sheet, not a general React-to-Vue migration framework.
Common Questions / FAQ
Who is vue-jsx-best-practices for?
Solo builders and small teams using Vue 3 with JSX/TSX who want agents to emit HTML-style attributes consistent with Vue templates.
When should I use vue-jsx-best-practices?
During Build frontend work whenever you author render functions, migrate React components, or fix TS errors on `className`/`htmlFor` in Vue JSX.
Is vue-jsx-best-practices safe to install?
It is documentation-only guidance with no shell or network requirements; still review the Security Audits panel on this Prism page before adding any skill pack.
SKILL.md
READMESKILL.md - Vue Jsx Best Practices
# Vue JSX Uses HTML Attributes Not React Conventions **Impact: MEDIUM** - Vue's JSX transform uses standard HTML attribute names (`class`, `for`) instead of React's JavaScript-friendly names (`className`, `htmlFor`). With proper TypeScript configuration, using React conventions like `className` or `htmlFor` will produce TypeScript errors, which is good for catching these inconsistencies early. Note that Vue's runtime is lenient and will actually convert these attributes correctly, but using HTML attributes is the recommended practice for consistency with Vue templates and proper type safety. When writing JSX in Vue, use the same attribute names you would use in regular HTML templates. This is a fundamental difference from React's JSX where `class` and `for` are reserved JavaScript keywords. ## Task Checklist - [ ] Use `class` instead of `className` in Vue JSX - [ ] Use `for` instead of `htmlFor` in Vue JSX - [ ] Use standard HTML event names with `on` prefix (onClick, onInput) - [ ] When migrating React components to Vue, update all attribute names - [ ] Configure TypeScript properly for Vue JSX type inference **Incorrect (React-style):** ```jsx // AVOID: React conventions cause TypeScript errors in Vue JSX // (Vue runtime is lenient and converts these, but types don't allow them) export default { setup() { return () => ( <div className="container"> <label htmlFor="email">Email:</label> <input id="email" className="input-field" /> </div> ) } } ``` ```tsx // AVOID: TypeScript will reject className/htmlFor with Vue's JSX types const Button = () => ( <button className="btn btn-primary" // TS error: Property 'className' does not exist htmlFor="form" // TS error: Property 'htmlFor' does not exist > Submit </button> ) ``` **Correct (Vue-style):** ```jsx // CORRECT: Use standard HTML attributes export default { setup() { return () => ( <div class="container"> <label for="email">Email:</label> <input id="email" class="input-field" /> </div> ) } } ``` ```tsx // CORRECT: Vue TSX with HTML attributes const Button = () => ( <button class="btn btn-primary" > Submit </button> ) ``` ## TypeScript Configuration for Vue JSX To enable proper type inference and IntelliSense for Vue JSX/TSX, configure your `tsconfig.json`: ```json { "compilerOptions": { "jsx": "preserve", "jsxImportSource": "vue" } } ``` Starting from Vue 3.4, Vue no longer implicitly registers the global JSX namespace, so `jsxImportSource` is required for TypeScript to use Vue's JSX type definitions. ## Vite Configuration For Vite projects, ensure you have the JSX plugin configured in `vite.config.ts`: ```typescript import { defineConfig } from 'vite' import vue from '@vitejs/plugin-vue' import vueJsx from '@vitejs/plugin-vue-jsx' export default defineConfig({ plugins: [vue(), vueJsx()] }) ``` ## Other Attribute Differences | React JSX | Vue JSX | HTML | |-----------|---------|------| | className | class | class | | htmlFor | for | for | | onChange | onInput (for live updates) | oninput | | tabIndex | tabindex | tabindex | | readOnly | readonly | readonly | ## Event Handling in Vue JSX ```jsx // Vue JSX event handling export default { setup() { const handleClick = () => console.log('clicked') const handleInput = (e) => console.log(e.target.value) return () => ( <div> <button onClick={handleClick}>Click</button> <input onInput={handleInput} /> {/* Event modifiers via helper */} <div onClick={withModifiers(handleClick, ['self'])}> Only triggers on self </div> </div> ) } } ``` ## Reference - [Vue.js