PascalCase for Component Naming

May 28, 20266 min read

Why PascalCase for Components

Vue and React both mandate PascalCase for component names. This isn't arbitrary — it solves a real ambiguity problem. In HTML, lowercase tags are reserved for native elements (<div>, <span>, <button>). PascalCase names (<UserProfile>, <SearchBar>) immediately distinguish custom components from native elements.

Without this convention, <userprofile> could be a custom component or an unknown HTML element. The browser treats unknown lowercase tags as inline elements, which leads to subtle rendering bugs. PascalCase eliminates the ambiguity entirely.

Framework Rules

Vue

Vue's style guide lists PascalCase component names as essential (the strongest category). The rules:

  • Component files: UserProfile.vue, SearchBar.vue
  • In templates: <UserProfile /> or <user-profile /> (both work, but PascalCase is preferred)
  • In components registration: UserProfile
// Component registration
import UserProfile from './UserProfile.vue'

export default {
  components: {
    UserProfile  // PascalCase key
  }
}

Vue auto-imports in Nuxt follow the same rule: components/UserProfile.vue becomes <UserProfile>.

React

React requires PascalCase more strictly — lowercase component names render as native HTML elements:

// This renders a <userprofile> HTML element — NOT your component
function userprofile() { return <div>Hello</div> }
<userprofile />  // BUG: renders unknown HTML element

// This renders your React component correctly
function UserProfile() { return <div>Hello</div> }
<UserProfile />  // Correct

This distinction is enforced at the JSX level. React's JSX transform treats lowercase tags as strings (native elements) and PascalCase tags as component references.

Naming Patterns by Component Type

Component TypePascalCase ExampleFile Name
Page sectionHeroSectionHeroSection.vue
UI primitiveBaseButtonBaseButton.vue
LayoutAppHeaderAppHeader.vue
FormLoginFormLoginForm.vue
List itemProductCardProductCard.vue
Modal/dialogConfirmDialogConfirmDialog.vue
UtilityAnimatedCounterAnimatedCounter.vue

Prefix Conventions

Many teams add prefixes to signal component categories:

  • Base: BaseButton, BaseInput — reusable primitives
  • App: AppHeader, AppSidebar — application layout components
  • The: TheNavigation, TheFooter — singleton components (one per page)

These prefixes are optional but help organize large component libraries.

Enforcing PascalCase

ESLint for Vue

// eslint.config.js
import vuePlugin from 'eslint-plugin-vue'

export default [
  ...vuePlugin.configs['flat/recommended'],
  {
    rules: {
      'vue/component-definition-name-casing': ['error', 'PascalCase'],
      'vue/component-name-in-template-casing': ['error', 'PascalCase'],
    }
  }
]

ESLint for React

// eslint.config.js
import reactPlugin from 'eslint-plugin-react'

export default [
  {
    rules: {
      'react/jsx-pascal-case': ['error', {
        allowAllCaps: false,
        ignore: [],
      }]
    }
  }
]

Nuxt Auto-Import Naming

Nuxt generates component names from file paths. components/tools/JsonFormatter.vue becomes ToolsJsonFormatter. To keep names clean:

  • Use flat directories for frequent components: components/SearchBar.vue<SearchBar>
  • Use nested directories for grouping: components/admin/UserTable.vue<AdminUserTable>
  • Configure path prefixes in nuxt.config.ts if needed
// nuxt.config.ts
export default defineNuxtConfig({
  components: [
    { path: '~/components', pathPrefix: false },  // Flat naming regardless of directory
  ]
})

Common Mistakes

1. Abbreviated Names

Avoid UsrPrfl or BtnGrp. Component names should be descriptive. The extra characters cost nothing in terms of performance, but cryptic names cost a lot in readability.

2. Single-Word Names

Button.vue, Form.vue, Table.vue — these collide with native HTML elements and third-party libraries. Prefix them: BaseButton, ContactForm, DataTable.

3. Inconsistent Casing in Templates

Mixing <UserProfile> and <user-profile> in the same project confuses readers. Pick one and enforce it with ESLint.

4. Prop Names in PascalCase

Props should use camelCase in JavaScript and kebab-case in templates — never PascalCase:

<!-- Bad -->
<UserProfile UserName="john" />

<!-- Good -->
<UserProfile userName="john" />
<!-- or in templates: -->
<UserProfile user-name="john" />

Try It Yourself

Need to convert component names between casings? Transform user-profile to UserProfile, snake_case to PascalCase, and more with our free tool.

👉 Free Case Converter