feat: integration screen

This commit is contained in:
fsylvain committed 2026-09-27 18:04:43 +02:00
1 parent a9a208b80a
commit ad55137883
13 files changed
+786 -6

No files matched your search

+62
View File
@@ -0,0 +1,62 @@
<script setup lang="ts">
import { computed, ref, watchEffect } from 'vue'
import { useCopyToClipboard } from '@/composables/useCopyToClipboard'
import { highlightToHtml, useShikiHighlighter } from '@/composables/useShikiHighlighter'
const props = defineProps<{
code: string
lang: string
label?: string
}>()
const { copied, copy } = useCopyToClipboard()
const buttonLabel = computed(() => (copied.value ? 'Copied' : 'Copy'))
const buttonIcon = computed(() => (copied.value ? 'i-lucide-check' : 'i-lucide-copy'))
const highlightedHtml = ref<string | null>(null)
watchEffect(async () => {
const highlighter = await useShikiHighlighter()
highlightedHtml.value = highlightToHtml(highlighter, props.code, props.lang)
})
function onCopy() {
copy(props.code)
}
</script>
<template>
<div class="bg-elevated">
<div class="flex h-8 items-center justify-between border-b border-default pr-2 pl-4">
<span class="font-mono text-xs leading-tight font-medium text-muted">{{
label ?? lang
}}</span>
<UButton
:icon="buttonIcon"
color="neutral"
variant="ghost"
size="xs"
:aria-label="`Copy ${label ?? lang} example`"
aria-live="polite"
class="gap-1.5 px-1.5 font-medium text-toned"
:ui="{ leadingIcon: 'size-3.5' }"
@click="onCopy"
>
{{ buttonLabel }}
</UButton>
</div>
<div
v-if="highlightedHtml"
tabindex="0"
class="shiki-block overflow-x-auto px-4 py-3.5 font-mono text-code whitespace-pre"
v-html="highlightedHtml"
/>
<pre
v-else
tabindex="0"
class="overflow-x-auto px-4 py-3.5 font-mono text-code whitespace-pre text-default"
>{{ code }}</pre
>
</div>
</template>
+73
View File
@@ -0,0 +1,73 @@
<script setup lang="ts">
import { ref } from 'vue'
import CodeBlock from '@/components/CodeBlock.vue'
defineProps<{
method: 'GET'
path: string
description: string
examples: { fetch: string; curl: string; response: string }
}>()
const activeTab = ref('fetch')
const tabItems = [
{ label: 'fetch', value: 'fetch' },
{ label: 'curl', value: 'curl' },
{ label: 'Response', value: 'response' },
]
</script>
<template>
<UCard
:ui="{
root: 'border border-default ring-0 divide-default',
header: 'p-4 sm:p-4',
body: 'p-0 sm:p-0',
}"
>
<template #header>
<div class="flex flex-col gap-2">
<div class="flex flex-wrap items-center gap-2.5">
<UBadge :label="method" color="neutral" variant="solid" class="font-mono" />
<span class="font-mono text-base font-medium text-highlighted">{{ path }}</span>
</div>
<span class="text-toned">{{ description }}</span>
</div>
</template>
<UTabs
v-model="activeTab"
:items="tabItems"
variant="link"
color="primary"
:ui="{
root: 'gap-0',
list: 'gap-5 border-b border-default px-4 py-0 before:hidden',
trigger: 'h-9 grow-0 px-0 text-sm font-normal data-[state=active]:font-medium',
content: 'mt-0',
}"
>
<template #content="{ item }">
<CodeBlock
v-if="item.value === 'fetch'"
label="JavaScript"
lang="javascript"
:code="examples.fetch"
/>
<pre
v-else-if="item.value === 'curl'"
tabindex="0"
class="overflow-x-auto bg-elevated px-4 py-3.5 font-mono text-code whitespace-pre text-default"
>{{ examples.curl }}</pre
>
<pre
v-else
tabindex="0"
class="overflow-x-auto bg-elevated px-4 py-3.5 font-mono text-code whitespace-pre text-default"
>{{ examples.response }}</pre
>
</template>
</UTabs>
</UCard>
</template>