Skip to content

Components

Overview

VitePress allows you to use Vue components directly in your Markdown files, creating interactive and dynamic documentation. This guide covers how to use components in VitePress, from basic usage to advanced techniques.

Using Components in Markdown

Basic Usage

You can use Vue components directly in your Markdown files:

md
# My Page

This is a regular paragraph.

<MyComponent />

More Markdown content...

Passing Props

Pass props to components just like in Vue templates:

md
<MyComponent 
  title="Hello World" 
  :count="5" 
  @click="handleClick" 
/>

Using Slots

Components can receive content through slots:

md
<CustomContainer>
  This content will be passed as the default slot.
  
  - You can use **Markdown** inside slots
  - Lists work too
</CustomContainer>

Named slots are also supported:

md
<CustomLayout>
  <template #header>
    # This is the header
  </template>
  
  Main content goes here.
  
  <template #footer>
    *Footer content with Markdown*
  </template>
</CustomLayout>

Creating Components

Local Components

Create components in your VitePress theme directory:

.vitepress/
  theme/
    components/
      MyComponent.vue
vue
<!-- .vitepress/theme/components/MyComponent.vue -->
<script setup>
import { ref } from 'vue'

const count = ref(0)
</script>

<template>
  <div class="my-component">
    <p>Current count: {{ count }}</p>
    <button @click="count++">Increment</button>
  </div>
</template>

<style scoped>
.my-component {
  padding: 1rem;
  border: 1px solid #ddd;
  border-radius: 4px;
}
</style>

Registering Components

Register your components in the theme's index.js file:

js
// .vitepress/theme/index.js
import DefaultTheme from 'vitepress/theme'
import MyComponent from './components/MyComponent.vue'

export default {
  ...DefaultTheme,
  enhanceApp({ app }) {
    app.component('MyComponent', MyComponent)
  }
}

Using Script Setup in Markdown

You can use <script setup> directly in Markdown files:

md
<script setup>
import { ref } from 'vue'

const count = ref(0)
const increment = () => count.value++
</script>

# Interactive Component

Current count: {{ count }}

<button @click="increment">Increment</button>

Built-in Components

VitePress provides several built-in components:

Badge

Add status badges to your text:

md
<Badge type="info" text="default" />
<Badge type="tip" text="recommended" />
<Badge type="warning" text="caution" />
<Badge type="danger" text="deprecated" />

Code

Enhanced code blocks with titles and highlighting:

md
<Code lang="js" title="example.js">
export function hello() {
  console.log('Hello World')
}
</Code>

Custom Containers

Create styled content containers:

md
::: info
This is an info box.
:::

::: tip
This is a tip.
:::

::: warning
This is a warning.
:::

::: danger
This is a dangerous warning.
:::

::: details
This is a details block.
:::

Advanced Component Techniques

Client-Only Components

Some components should only run on the client side:

vue
<!-- .vitepress/theme/components/ClientOnly.vue -->
<script>
export default {
  data: () => ({ mounted: false }),
  mounted() {
    this.mounted = true
  },
  render() {
    return this.mounted ? this.$slots.default() : null
  }
}
</script>

Use it to wrap components that require browser APIs:

md
<ClientOnly>
  <MapComponent />
</ClientOnly>

Async Components

Load components asynchronously for better performance:

js
// .vitepress/theme/index.js
import DefaultTheme from 'vitepress/theme'
import { defineAsyncComponent } from 'vue'

const HeavyComponent = defineAsyncComponent(() => 
  import('./components/HeavyComponent.vue')
)

export default {
  ...DefaultTheme,
  enhanceApp({ app }) {
    app.component('HeavyComponent', HeavyComponent)
  }
}

Interactive Demos

Create interactive code demos:

vue
<!-- .vitepress/theme/components/Demo.vue -->
<script setup>
import { ref, computed } from 'vue'

const props = defineProps({
  code: String
})

const showCode = ref(false)
const toggleCode = () => {
  showCode.value = !showCode.value
}
</script>

<template>
  <div class="demo">
    <div class="demo-preview">
      <slot></slot>
    </div>
    <div class="demo-actions">
      <button @click="toggleCode">{{ showCode ? 'Hide Code' : 'Show Code' }}</button>
    </div>
    <div v-if="showCode" class="demo-code">
      <pre><code>{{ code }}</code></pre>
    </div>
  </div>
</template>

<style scoped>
.demo {
  border: 1px solid #ddd;
  border-radius: 4px;
  margin: 1rem 0;
}
.demo-preview {
  padding: 1.5rem;
}
.demo-actions {
  padding: 0.5rem 1rem;
  border-top: 1px solid #ddd;
}
.demo-code {
  border-top: 1px solid #ddd;
  padding: 1rem;
  background-color: #f8f8f8;
}
</style>

Use it in your Markdown:

md
<Demo code="<button>Click Me</button>">
  <button>Click Me</button>
</Demo>

Component Libraries

Using External Component Libraries

Install and use external Vue component libraries:

bash
npm install element-plus

Register in your theme:

js
// .vitepress/theme/index.js
import DefaultTheme from 'vitepress/theme'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'

export default {
  ...DefaultTheme,
  enhanceApp({ app }) {
    app.use(ElementPlus)
  }
}

Use in your Markdown:

md
# Using Element Plus

<el-button type="primary">Primary Button</el-button>
<el-date-picker v-model="date" type="date" placeholder="Pick a date" />

<script setup>
import { ref } from 'vue'
const date = ref(new Date())
</script>

Creating a Component Library

Document your own component library with VitePress:

  1. Create a demo component:
vue
<!-- .vitepress/theme/components/ComponentDemo.vue -->
<script setup>
import { defineProps } from 'vue'

const props = defineProps({
  component: Object,
  description: String
})
</script>

<template>
  <div class="component-demo">
    <div class="component-demo-example">
      <component :is="component" />
    </div>
    <div class="component-demo-description">
      <p>{{ description }}</p>
    </div>
  </div>
</template>
  1. Use it to showcase components:
md
<script setup>
import { Button } from 'my-component-library'
import ComponentDemo from '../.vitepress/theme/components/ComponentDemo.vue'
</script>

# Button Component

<ComponentDemo 
  :component="Button" 
  description="A customizable button component with various styles." 
/>

## Props

| Name | Type | Default | Description |
| ---- | ---- | ------- | ----------- |
| type | String | 'default' | Button type |
| size | String | 'medium' | Button size |

Best Practices

  1. Keep Components Simple: Focus on a single responsibility per component.

  2. Optimize for SSR: Ensure components work with server-side rendering.

  3. Use Client-Only When Needed: Wrap browser-only code in client-only components.

  4. Provide Fallbacks: Include fallback content for components that might fail.

  5. Document Props: Clearly document component props and events.

  6. Style Isolation: Use scoped styles or CSS modules to prevent style leakage.

  7. Accessibility: Ensure components are accessible with proper ARIA attributes.

Frequently Asked Questions

How do I use components only on specific pages?

Use dynamic imports in your page's <script setup> section:

md
<script setup>
import { defineAsyncComponent } from 'vue'
const PageSpecificComponent = defineAsyncComponent(() => 
  import('../components/PageSpecificComponent.vue')
)
</script>

# Page with Specific Component

<PageSpecificComponent />

Can I use components from npm packages?

Yes, install the package and register its components in your theme's index.js:

js
// .vitepress/theme/index.js
import DefaultTheme from 'vitepress/theme'
import { ComponentFromPackage } from 'some-package'

export default {
  ...DefaultTheme,
  enhanceApp({ app }) {
    app.component('ComponentFromPackage', ComponentFromPackage)
  }
}

How do I handle component errors?

Use Vue's error handling with errorCaptured or a global error handler:

js
// .vitepress/theme/index.js
export default {
  ...DefaultTheme,
  enhanceApp({ app }) {
    app.config.errorHandler = (err) => {
      console.error('Global error:', err)
    }
  }
}

This document will be continuously updated. If you have any questions, please provide feedback through GitHub Issues.

VitePress Development Guide