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