Skip to content

Commit 1f37840

Browse files
committed
feat: 🎸 add loading to component-doc
1 parent 26f3bda commit 1f37840

File tree

2 files changed

+103
-61
lines changed

2 files changed

+103
-61
lines changed

.vitepress/theme/components/ComponentDoc.vue

+70-61
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
<script setup lang="ts">
22
import { ref, onMounted } from 'vue'
33
import { tr } from '../../i18n'
4+
import Loading from './Loading.vue'
45
56
const props = defineProps({
67
path: {
@@ -15,6 +16,7 @@ const props = defineProps({
1516
})
1617
1718
const meta = ref<any>(null)
19+
const loading = ref(false)
1820
1921
const t = (key :string) => {
2022
return tr(props.locale, `api.${key}`)
@@ -23,93 +25,100 @@ const t = (key :string) => {
2325
onMounted(async () => {
2426
const componentDocRoot = props.locale === 'en'
2527
? `/data/api`
26-
: `/data/api/${props.locale}`;
28+
: `/data/api/${props.locale}`
2729
try {
2830
const jsonPath = `${componentDocRoot}/${props.path}.json?raw`
31+
32+
loading.value = true;
2933
const response = await fetch(jsonPath)
3034
if (!response.ok) {
3135
throw new Error(`HTTP error! Status: ${response.status}`)
3236
}
3337
meta.value = await response.json()
38+
loading.value = false
3439
} catch (err) {
40+
loading.value = false
3541
console.error('Failed to load API data:', err)
3642
}
3743
})
3844
</script>
3945

4046
<template>
4147
<section class="component-doc">
42-
<div class="name">
43-
{{ meta?.description }}
44-
</div>
45-
<PluginTabs>
46-
<PluginTabsTab :label="t('props')" v-if="meta?.props">
47-
<div v-for="(prop, index) in meta.props" :key="index" class="item">
48-
<div class="item-main">
49-
<div>
50-
<code>{{ prop.name }}</code>:
51-
<span class="text-tips">{{ prop.type?.name || '—' }}</span>
48+
<loading v-if="loading" />
49+
<template v-else>
50+
<div class="name">
51+
{{ meta?.description }}
52+
</div>
53+
<PluginTabs>
54+
<PluginTabsTab :label="t('props')" v-if="meta?.props">
55+
<div v-for="(prop, index) in meta.props" :key="index" class="item">
56+
<div class="item-main">
57+
<div>
58+
<code>{{ prop.name }}</code>:
59+
<span class="text-tips">{{ prop.type?.name || '—' }}</span>
60+
</div>
61+
<div class="default-value">
62+
<code>{{ prop.defaultValue?.value || '—' }}</code>
63+
</div>
5264
</div>
53-
<div class="default-value">
54-
<code>{{ prop.defaultValue?.value || '—' }}</code>
65+
<div class="description text-tips" v-if="prop.description">
66+
<div class="text-tip">{{ t('description') }}</div>
67+
<div class="text-info">{{ prop.description }}</div>
5568
</div>
5669
</div>
57-
<div class="description text-tips" v-if="prop.description">
58-
<div class="text-tip">{{ t('description') }}</div>
59-
<div class="text-info">{{ prop.description }}</div>
60-
</div>
61-
</div>
62-
</PluginTabsTab>
63-
<PluginTabsTab :label="t('events')" v-if="meta?.events">
64-
<div v-for="(item, index) in meta.events" :key="index" class="item">
65-
<div class="item-main">
66-
<div>
67-
<code>{{ item.name }}</code>:
68-
<span class="text-tips">({{ item.type?.names.join(',') || '—' }}) => void</span>
70+
</PluginTabsTab>
71+
<PluginTabsTab :label="t('events')" v-if="meta?.events">
72+
<div v-for="(item, index) in meta.events" :key="index" class="item">
73+
<div class="item-main">
74+
<div>
75+
<code>{{ item.name }}</code>:
76+
<span class="text-tips">({{ item.type?.names.join(',') || '—' }}) => void</span>
77+
</div>
6978
</div>
70-
</div>
71-
<div class="description text-tips" v-if="item.description">
72-
<div class="text-tip">{{ t('description') }}</div>
73-
<div class="text-info">{{ item.description }}</div>
74-
</div>
75-
</div>
76-
</PluginTabsTab>
77-
<PluginTabsTab :label="t('slots')" v-if="meta?.slots">
78-
<div v-for="(item, index) in meta.slots" :key="index" class="item">
79-
<div class="item-main">
80-
<div>
81-
<code>{{ item.name }}</code>
79+
<div class="description text-tips" v-if="item.description">
80+
<div class="text-tip">{{ t('description') }}</div>
81+
<div class="text-info">{{ item.description }}</div>
8282
</div>
8383
</div>
84-
<div class="description text-tips" v-if="item.description">
85-
<div class="text-tip">{{ t('description') }}</div>
86-
<div class="text-info">{{ item.description }}</div>
84+
</PluginTabsTab>
85+
<PluginTabsTab :label="t('slots')" v-if="meta?.slots">
86+
<div v-for="(item, index) in meta.slots" :key="index" class="item">
87+
<div class="item-main">
88+
<div>
89+
<code>{{ item.name }}</code>
90+
</div>
91+
</div>
92+
<div class="description text-tips" v-if="item.description">
93+
<div class="text-tip">{{ t('description') }}</div>
94+
<div class="text-info">{{ item.description }}</div>
95+
</div>
8796
</div>
88-
</div>
89-
</PluginTabsTab>
90-
<PluginTabsTab :label="t('expose')" v-if="meta?.expose">
91-
<div v-for="(item, index) in meta.expose" :key="index" class="item">
92-
<div class="item-main">
93-
<div>
94-
<code>{{ item.name }}</code>
95-
<template v-if="item.tags?.length">
96-
:
97-
<span class="text-tips">
97+
</PluginTabsTab>
98+
<PluginTabsTab :label="t('expose')" v-if="meta?.expose">
99+
<div v-for="(item, index) in meta.expose" :key="index" class="item">
100+
<div class="item-main">
101+
<div>
102+
<code>{{ item.name }}</code>
103+
<template v-if="item.tags?.length">
104+
:
105+
<span class="text-tips">
98106
({{ item.tags.map((e: any) => e.name).join(',') || '—' }}) => void
99107
</span>
100-
</template>
108+
</template>
109+
</div>
110+
</div>
111+
<div class="description text-tips" v-if="item.description">
112+
<div class="text-tip">{{ t('description') }}</div>
113+
<div class="text-info" v-html="item.description" />
101114
</div>
102115
</div>
103-
<div class="description text-tips" v-if="item.description">
104-
<div class="text-tip">{{ t('description') }}</div>
105-
<div class="text-info" v-html="item.description" />
106-
</div>
107-
</div>
108-
</PluginTabsTab>
109-
</PluginTabs>
110-
<div class="name">
111-
<a :href="meta?.sourceFiles[0]" target="_blank">{{ t('viewSource') }}</a>
112-
</div>
116+
</PluginTabsTab>
117+
</PluginTabs>
118+
<div class="name">
119+
<a :href="meta?.sourceFiles[0]" target="_blank">{{ t('viewSource') }}</a>
120+
</div>
121+
</template>
113122
</section>
114123
</template>
115124

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<template>
2+
<div class="spinner"></div>
3+
</template>
4+
5+
<script setup lang="ts">
6+
7+
</script>
8+
9+
<style scoped>
10+
.loading {
11+
position: fixed;
12+
top: 0;
13+
left: 0;
14+
width: 100%;
15+
height: 100%;
16+
display: flex;
17+
justify-content: center;
18+
align-items: center;
19+
background: rgba(255, 255, 255, 0.8);
20+
}
21+
.spinner {
22+
width: 30px;
23+
height: 30px;
24+
border: 3px solid var(--vp-c-divider);
25+
border-top-color: var(--vp-c-brand-1);
26+
border-radius: 50%;
27+
animation: spin 1s linear infinite;
28+
}
29+
@keyframes spin {
30+
0% { transform: rotate(0deg); }
31+
100% { transform: rotate(360deg); }
32+
}
33+
</style>

0 commit comments

Comments
 (0)