Custom Component
VuePress pages are Vue applications under the hood, so Vue components can be used directly in Markdown. This article shows how to create, register and use a custom component with the plume theme — the colored cards on this page are the final result.
1. Create the component
Create DemoCard.vue under docs/.vuepress/theme/components/:
<script setup>
defineProps({
title: { type: String, default: '' },
color: { type: String, default: '#2a9dff' },
})
</script>
<template>
<div class="demo-card" :style="{ '--demo-card-color': color }">
<p v-if="title" class="demo-card-title">{{ title }}</p>
<div class="demo-card-body">
<slot />
</div>
</div>
</template>
<style scoped>
.demo-card {
margin: 16px 0;
padding: 14px 18px;
border: 1px solid var(--demo-card-color);
border-left-width: 4px;
border-radius: 8px;
}
</style>The component accepts title and color props, and receives nested content written in Markdown through <slot />.
2. Register the component
Register it globally in docs/.vuepress/client.ts:
import { defineClientConfig } from 'vuepress/client'
import DemoCard from './theme/components/DemoCard.vue'
export default defineClientConfig({
enhance({ app }) {
app.component('DemoCard', DemoCard)
},
})3. Use it in Markdown
Once registered, the component tag can be used directly in any Markdown file:
<DemoCard title="This is a custom component" color="#8b5cf6">
It works right inside Markdown, with `props` and slots.
</DemoCard>Actual rendered result:
This is a custom component
It works right inside Markdown, with `props` and slots.
Try another color
The `color` prop changes the accent color of the card.
Notes
- Prefer PascalCase component names (e.g.
DemoCard) to avoid conflicts with native HTML tags - Styles declared with
scopedstay inside the component and won't leak into the page - To use global state (such as route info) inside the component, install plugins in the
enhancehook or import the composables provided byvuepress/client
Copyright
Copyright Ownership:fantasy
License under:Attribution 4.0 International (CC-BY-4.0)