Skip to content

Commit 0698249

Browse files
fix(ui): make readme markdown copy more reliable with prefetch and loading state
1 parent b08e2f0 commit 0698249

File tree

1 file changed

+57
-16
lines changed

1 file changed

+57
-16
lines changed

app/pages/package/[[org]]/[name].vue

Lines changed: 57 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -95,29 +95,70 @@ const {
9595
},
9696
)
9797
98+
function maybePrefetchReadmeMarkdown() {
99+
if (import.meta.server) return
100+
if (!readmeData.value.mdExists) return
101+
if (readmeMarkdownStatus.value !== 'idle') return
102+
void fetchReadmeMarkdown()
103+
}
104+
105+
watch([() => readmeData.value.mdExists, readmeMarkdownStatus], () => {
106+
maybePrefetchReadmeMarkdown()
107+
}, { immediate: true })
108+
98109
//copy README file as Markdown
99110
const { copied: copiedReadme, copy: copyReadme } = useClipboard({
100111
source: () => '',
101112
copiedDuring: 2000,
102113
legacy: true,
103114
})
115+
const isCopyingReadme = shallowRef(false)
116+
117+
const readmeCopyTooltip = computed(() =>
118+
isCopyingReadme.value ? $t('common.loading') : $t('package.readme.copy_as_markdown'),
119+
)
120+
121+
const readmeCopyAriaLabel = computed(() => {
122+
if (isCopyingReadme.value) return $t('common.loading')
123+
if (copiedReadme.value) return $t('common.copied')
124+
return $t('package.readme.copy_as_markdown')
125+
})
126+
127+
const readmeCopyIcon = computed(() => {
128+
if (isCopyingReadme.value) return 'i-svg-spinners:ring-resize'
129+
if (copiedReadme.value) return 'i-lucide:check'
130+
return 'i-simple-icons:markdown'
131+
})
132+
133+
const readmeCopyText = computed(() => {
134+
if (isCopyingReadme.value) return $t('common.loading')
135+
if (copiedReadme.value) return $t('common.copied')
136+
return $t('common.copy')
137+
})
104138
105139
function prefetchReadmeMarkdown() {
106-
if (readmeMarkdownStatus.value === 'idle') {
107-
fetchReadmeMarkdown()
108-
}
140+
maybePrefetchReadmeMarkdown()
109141
}
110142
111143
async function copyReadmeHandler() {
112-
let markdown = readmeMarkdownData.value?.markdown
113-
if (!markdown) {
114-
await fetchReadmeMarkdown()
115-
markdown = readmeMarkdownData.value?.markdown
116-
}
144+
if (isCopyingReadme.value) return
117145
118-
if (!markdown) return
146+
isCopyingReadme.value = true
147+
148+
try {
149+
let markdown = readmeMarkdownData.value?.markdown
150+
if (!markdown) {
151+
await fetchReadmeMarkdown()
152+
markdown = readmeMarkdownData.value?.markdown
153+
}
119154
120-
await copyReadme(markdown)
155+
if (!markdown) return
156+
157+
await copyReadme(markdown)
158+
}
159+
finally {
160+
isCopyingReadme.value = false
161+
}
121162
}
122163
123164
// Track active TOC item based on scroll position
@@ -988,20 +1029,20 @@ const showSkeleton = shallowRef(false)
9881029
<!-- Copy readme as Markdown button -->
9891030
<TooltipApp
9901031
v-if="readmeData?.mdExists"
991-
:text="$t('package.readme.copy_as_markdown')"
1032+
:text="readmeCopyTooltip"
9921033
position="bottom"
9931034
>
9941035
<ButtonBase
9951036
@mouseenter="prefetchReadmeMarkdown"
9961037
@focus="prefetchReadmeMarkdown"
9971038
@click="copyReadmeHandler()"
1039+
:disabled="isCopyingReadme"
1040+
:aria-busy="isCopyingReadme ? 'true' : 'false'"
9981041
:aria-pressed="copiedReadme"
999-
:aria-label="
1000-
copiedReadme ? $t('common.copied') : $t('package.readme.copy_as_markdown')
1001-
"
1002-
:classicon="copiedReadme ? 'i-lucide:check' : 'i-simple-icons:markdown'"
1042+
:aria-label="readmeCopyAriaLabel"
1043+
:classicon="readmeCopyIcon"
10031044
>
1004-
{{ copiedReadme ? $t('common.copied') : $t('common.copy') }}
1045+
{{ readmeCopyText }}
10051046
</ButtonBase>
10061047
</TooltipApp>
10071048
<ReadmeTocDropdown

0 commit comments

Comments
 (0)