Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 5b14fa3

Browse filesBrowse files
committed
Add code block and code group components
1 parent b5f906a commit 5b14fa3
Copy full SHA for 5b14fa3

File tree

Expand file treeCollapse file tree

4 files changed

+142
-1
lines changed
Filter options
Expand file treeCollapse file tree

4 files changed

+142
-1
lines changed

‎src/.vitepress/theme/CodeBlock.vue

Copy file name to clipboard
+22Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
<template>
2+
<div class="code-block" :class="[active && 'active']">
3+
<slot />
4+
</div>
5+
</template>
6+
7+
<script setup>
8+
defineProps({
9+
title: { type: String, required: true },
10+
active: { type: Boolean, default: false }
11+
})
12+
</script>
13+
14+
<style scoped>
15+
.code-block {
16+
display: none;
17+
}
18+
19+
.code-block.active {
20+
display: block;
21+
}
22+
</style>

‎src/.vitepress/theme/CodeGroup.vue

Copy file name to clipboard
+109Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
<script setup>
2+
import { onMounted, computed, ref, useSlots, watch } from 'vue'
3+
4+
const slots = useSlots()
5+
const tabLabels = computed(() => slots.default().map(key => key.props.title))
6+
7+
const activeTabIndex = ref(0)
8+
const tabs = ref([])
9+
10+
const underline = ref(null)
11+
12+
const updateHighlighteUnderlinePosition = () => {
13+
const activeTab = tabs.value[activeTabIndex.value]
14+
if (!activeTab) {
15+
return
16+
}
17+
18+
underline.value.style.left = `${activeTab.offsetLeft}px`
19+
underline.value.style.width = `${activeTab.clientWidth}px`
20+
}
21+
22+
onMounted(() => {
23+
updateHighlighteUnderlinePosition()
24+
})
25+
26+
const slot = ref(null)
27+
28+
const switchTab = (i) => {
29+
const tabs = slot.value.children
30+
31+
for (const tab of tabs) {
32+
tab.classList.remove('active')
33+
}
34+
35+
tabs[i].classList.add('active')
36+
}
37+
38+
watch(activeTabIndex, (value) => {
39+
switchTab(value)
40+
})
41+
42+
const updateTabs = i => {
43+
activeTabIndex.value = i
44+
updateHighlighteUnderlinePosition()
45+
}
46+
</script>
47+
48+
<template>
49+
<div class="code-group">
50+
<div class="buttons">
51+
<button
52+
v-for="(label, i) in tabLabels"
53+
ref="tabs"
54+
:key="label"
55+
class="button mono"
56+
:class="[activeTabIndex === i && 'active']"
57+
@click="updateTabs(i)"
58+
>{{ label }}</button>
59+
<span ref="underline" class="highlight-underline" />
60+
</div>
61+
<div ref="slot">
62+
<slot ref="inner" />
63+
</div>
64+
</div>
65+
</template>
66+
67+
<style scoped>
68+
.buttons {
69+
border: 0 solid #e2e8f0;
70+
border-top-left-radius: .375rem;
71+
border-top-right-radius: .375rem;
72+
border-bottom-width: 2px;
73+
border-color: #4a5568;
74+
padding-left: .5rem;
75+
padding-right: .5rem;
76+
background-color: #2d3748;
77+
font-size: .875rem;
78+
line-height: 1.25rem;
79+
color: #fff;
80+
position: relative;
81+
}
82+
83+
button {
84+
outline: none;
85+
padding-left: 1rem;
86+
padding-right: 1rem;
87+
padding-top: .75rem;
88+
padding-bottom: .75rem;
89+
color: #cbd5e0;
90+
font-weight: 700;
91+
}
92+
93+
.highlight-underline {
94+
background-color: #00cd81;
95+
position: absolute;
96+
bottom: -2px;
97+
height: 2px;
98+
transition: left .15s,width .15s;
99+
bottom: -2px;
100+
height: 2px;
101+
transition: left 150ms, width 150ms;
102+
}
103+
104+
.code-group :deep([class*="language-"]){
105+
border-top-left-radius: 0;
106+
border-top-right-radius: 0;
107+
margin-top: 0;
108+
}
109+
</style>

‎src/.vitepress/theme/index.ts

Copy file name to clipboardExpand all lines: src/.vitepress/theme/index.ts
+6Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ import { createFluentVue } from 'fluent-vue'
55

66
import { format } from 'date-fns'
77

8+
import CodeGroup from './CodeGroup.vue'
9+
import CodeBlock from './CodeBlock.vue'
10+
811
import './theme.css'
912

1013
const bundle = new FluentBundle('en', {
@@ -24,5 +27,8 @@ export default {
2427
...DefaultTheme,
2528
enhanceApp({ app, router, siteData }) {
2629
app.use(fluent)
30+
31+
app.component('code-group', CodeGroup)
32+
app.component('code-block', CodeBlock)
2733
}
2834
}

‎src/.vitepress/theme/theme.css

Copy file name to clipboardExpand all lines: src/.vitepress/theme/theme.css
+5-1Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,5 +16,9 @@ code {
1616
}
1717

1818
pre {
19-
font-family: "JetBrains Mono", "Consolas", "Monaco", "Andale Mono", "Ubuntu Mono", monospace;
19+
font-family: var(--font-family-code);
20+
}
21+
22+
.mono {
23+
font-family: var(--font-family-code)
2024
}

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.