feat(integration): add image variants section and standardize code snippets
This commit is contained in:
1 parent
6f9ae6207a
commit
e6746f2be7
28 files changed
+2256
-422
No files matched your search
@@ -0,0 +1,120 @@
|
||||
<script setup lang="ts">
|
||||
import { t } from '@/i18n'
|
||||
|
||||
import { computed, ref } from 'vue'
|
||||
import { useCopyToClipboard } from '@/composables/useCopyToClipboard'
|
||||
import type { CodeSnippetTab } from '@/lib/codeSnippet'
|
||||
|
||||
const props = defineProps<{
|
||||
tabs: CodeSnippetTab[]
|
||||
}>()
|
||||
|
||||
const active = defineModel<string>('active')
|
||||
|
||||
const { copied, copy } = useCopyToClipboard()
|
||||
|
||||
const tabList = ref<HTMLElement | null>(null)
|
||||
const copyButton = ref<{ $el: HTMLElement } | null>(null)
|
||||
|
||||
const current = computed(() => props.tabs.find((tab) => tab.k === active.value) ?? props.tabs[0])
|
||||
const single = computed(() => props.tabs.length === 1)
|
||||
const copyLabel = computed(() => (copied.value ? t('Copied') : t('Copy')))
|
||||
const copyIcon = computed(() => (copied.value ? 'i-lucide-check' : 'i-lucide-copy'))
|
||||
|
||||
const TAB_BASE =
|
||||
'flex h-8 cursor-pointer items-center px-2.5 text-sm whitespace-nowrap focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-primary'
|
||||
const TAB_SELECTED = 'font-medium text-highlighted shadow-[inset_0_-2px_0_var(--ui-primary)]'
|
||||
const TAB_IDLE = 'font-normal text-toned'
|
||||
|
||||
function isSelected(tab: CodeSnippetTab) {
|
||||
return tab.k === current.value?.k
|
||||
}
|
||||
|
||||
function select(tab: CodeSnippetTab) {
|
||||
active.value = tab.k
|
||||
}
|
||||
|
||||
function targetIndex(key: string, from: number) {
|
||||
const last = props.tabs.length - 1
|
||||
const targets: Record<string, number> = {
|
||||
ArrowRight: from === last ? 0 : from + 1,
|
||||
ArrowLeft: from === 0 ? last : from - 1,
|
||||
Home: 0,
|
||||
End: last,
|
||||
}
|
||||
return targets[key]
|
||||
}
|
||||
|
||||
function onTabKeydown(event: KeyboardEvent, index: number) {
|
||||
const target = targetIndex(event.key, index)
|
||||
if (target === undefined) {
|
||||
return
|
||||
}
|
||||
event.preventDefault()
|
||||
select(props.tabs[target]!)
|
||||
const buttons = tabList.value?.querySelectorAll<HTMLElement>('[role="tab"]')
|
||||
buttons?.[target]?.focus()
|
||||
}
|
||||
|
||||
function onCopy() {
|
||||
copy(current.value?.code ?? '')
|
||||
}
|
||||
|
||||
function focusCopy() {
|
||||
copyButton.value?.$el?.focus()
|
||||
}
|
||||
|
||||
defineExpose({ focusCopy })
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div class="flex min-w-0 flex-col border border-default bg-elevated text-default">
|
||||
<div class="flex min-h-11 items-center gap-2 border-b border-default pr-1 pl-2">
|
||||
<div
|
||||
ref="tabList"
|
||||
role="tablist"
|
||||
:aria-label="t('Language')"
|
||||
class="flex min-w-0 flex-1 gap-0.5 overflow-x-auto"
|
||||
>
|
||||
<template v-if="single">
|
||||
<span class="flex h-8 items-center px-2.5 text-sm font-normal text-muted">{{
|
||||
current?.label
|
||||
}}</span>
|
||||
</template>
|
||||
<template v-else>
|
||||
<button
|
||||
v-for="(tab, index) in tabs"
|
||||
:key="tab.k"
|
||||
type="button"
|
||||
role="tab"
|
||||
:aria-selected="isSelected(tab)"
|
||||
:tabindex="isSelected(tab) ? 0 : -1"
|
||||
:class="[TAB_BASE, isSelected(tab) ? TAB_SELECTED : TAB_IDLE]"
|
||||
@click="select(tab)"
|
||||
@keydown="onTabKeydown($event, index)"
|
||||
>
|
||||
{{ tab.label }}
|
||||
</button>
|
||||
</template>
|
||||
</div>
|
||||
<UButton
|
||||
ref="copyButton"
|
||||
:icon="copyIcon"
|
||||
color="neutral"
|
||||
variant="ghost"
|
||||
:aria-label="t('Copy code')"
|
||||
class="h-8 min-w-11 justify-center gap-1.5 rounded-none px-2.5 text-sm font-medium focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-primary"
|
||||
:class="copied ? 'text-success' : 'text-highlighted'"
|
||||
:ui="{ leadingIcon: 'size-3.5' }"
|
||||
@click="onCopy"
|
||||
>
|
||||
<span aria-live="polite">{{ copyLabel }}</span>
|
||||
</UButton>
|
||||
</div>
|
||||
<pre
|
||||
tabindex="0"
|
||||
class="m-0 overflow-x-auto px-4 py-3 font-mono text-code whitespace-pre text-highlighted"
|
||||
>{{ current?.code }}</pre
|
||||
>
|
||||
</div>
|
||||
</template>
|
||||
Reference in new issue
Block a user