Files
estel_docs/app/components/content/ProseH3.vue

91 lines
2.7 KiB
Vue
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<template>
<h3
:id
:class="['scroll-m-20 font-semibold tracking-tight [&:not(:first-child)]:mt-8 mb-3 flex items-center gap-2', themeSizeClass, themeDecorClass]"
:style="h3Style"
>
<span
v-if="showLeadingLine"
aria-hidden="true"
class="inline-block"
:class="themeLineClass"
:style="lineStyle"
/>
<NuxtLink
v-if="id && generate"
:to="`#${id}`"
>
<slot />
</NuxtLink>
<slot v-else />
</h3>
</template>
<script setup lang="ts">
const { id } = defineProps<{ id?: string }>()
const { headings } = useRuntimeConfig().public.mdc
const generate = computed(() => id && ((typeof headings?.anchorLinks === 'boolean' && headings?.anchorLinks === true) || (typeof headings?.anchorLinks === 'object' && headings?.anchorLinks?.h3)))
// 主题风格:
// - classic左侧竖线主色无额外背景
// - elegant底部虚线
// - minimal卡片式浅色主色背景 + 左侧竖线
const { selectedTheme, selectedThemeColor, customColor, themeColors } = useTheme()
const themeSizeClass = computed(() => {
return selectedTheme.value === 'classic'
? 'text-xl lg:text-1xl'
: 'text-1xl lg:text-2xl'
})
const isClassic = computed(() => selectedTheme.value === 'classic')
const isElegant = computed(() => selectedTheme.value === 'elegant')
const isMinimal = computed(() => selectedTheme.value === 'minimal')
const showLeadingLine = computed(() => isClassic.value || isMinimal.value || isElegant.value)
const primaryHex = computed(() => {
if (selectedThemeColor.value === 'custom') return customColor.value
const found = themeColors.find(c => c.value === selectedThemeColor.value)
return found?.color || '#3B82F6'
})
const themeDecorClass = computed(() => {
if (isElegant.value) return 'border-b border-dashed pb-1 border-primary dark:border-primary'
if (isMinimal.value) return 'px-3 py-2'
return ''
})
const themeLineClass = computed(() => {
return isClassic.value ? 'w-1 h-[0.9em]' : 'w-1 h-[1em]'
})
const lineStyle = computed(() => ({
backgroundColor: primaryHex.value,
borderRadius: '4px'
}))
function hexToRgba(hex: string, alpha: number): string {
const normalized = String(hex).replace('#', '')
const bigint = parseInt(normalized.length === 3
? normalized.split('').map(ch => ch + ch).join('')
: normalized, 16)
const r = (bigint >> 16) & 255
const g = (bigint >> 8) & 255
const b = bigint & 255
return `rgba(${r}, ${g}, ${b}, ${Math.min(Math.max(alpha, 0), 1)})`
}
const h3Style = computed(() => {
if (isMinimal.value) {
return {
backgroundColor: hexToRgba(primaryHex.value, 0.08),
border: `1px solid ${hexToRgba(primaryHex.value, 0.2)}`,
borderRadius: 'var(--ui-card-radius)'
}
}
return {}
})
</script>