130 lines
3.1 KiB
Vue
130 lines
3.1 KiB
Vue
<script setup lang="ts">
|
|
import VPLink from 'vitepress/dist/client/theme-default/components/VPLink.vue'
|
|
import { computed, useCssModule } from 'vue';
|
|
import { NAVBAR_HEIGHT } from '../constants'
|
|
import { Icons } from '@beeline/design-tokens/js/iconfont/icons'
|
|
import CustomAvatar from './CustomAvatar.vue';
|
|
|
|
const { disabled, scrollTo, link, items } = defineProps<{
|
|
icon: string
|
|
title: string
|
|
link?: string
|
|
scrollTo?: string
|
|
disabled?: boolean
|
|
items?: ItemFeature[]
|
|
}>()
|
|
|
|
type ItemFeature = {
|
|
title: string
|
|
link?: string
|
|
}
|
|
|
|
const style = useCssModule()
|
|
const classes = computed(() => ({
|
|
[style.CustomFeature]: true,
|
|
[style.CustomFeatureDisabled]: disabled || !link && !scrollTo,
|
|
}))
|
|
|
|
const handleClick = (event: Event) => {
|
|
if (scrollTo) {
|
|
const targetElTop = document.querySelector(scrollTo)?.getBoundingClientRect().top
|
|
|
|
if (targetElTop) {
|
|
event.stopPropagation()
|
|
window.scrollTo({ behavior: 'smooth', top: targetElTop + window.scrollY - NAVBAR_HEIGHT - 32 })
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<template>
|
|
<Component :is="!disabled && link ? VPLink : 'article'"
|
|
:class="classes" @click="handleClick">
|
|
<CustomAvatar :class="$style.CustomFeatureIcon" :icon="icon as Icons" />
|
|
|
|
<div :class="$style.CustomFeatureContent">
|
|
<Component :is="!disabled && link ? VPLink : 'article'" v-bind="{ ...(!disabled && link && { href: link }) }">
|
|
<p :class="$style.CustomFeatureTitle" :href="`/docs${link}`">
|
|
{{ title }}
|
|
</p>
|
|
</Component>
|
|
<div :class="$style.CustomFeatureContainer">
|
|
<div v-for="(item, i) in items" :key="i">
|
|
<Component
|
|
:is="!disabled && item.link ? VPLink : 'article'"
|
|
v-bind="{ ...(!disabled && item.link && { href: item.link }) }"
|
|
:class="{ [style.CustomFeatureDisabled]: disabled || !item.link }"
|
|
>
|
|
<p :class="$style.CustomFeatureSubtitle">{{ item.title }}</p>
|
|
</Component>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</Component>
|
|
</template>
|
|
|
|
<style lang="scss" module>
|
|
@use "@beeline/design-tokens/scss/tokens/globals/sizes";
|
|
@use "@beeline/design-tokens/scss/tokens/themes";
|
|
@use "@beeline/design-tokens/scss/mixin";
|
|
|
|
.CustomFeature {
|
|
$el: &;
|
|
border-radius: sizes.$size-border-radius-x6;
|
|
border: 1px solid themes.$color-border;
|
|
max-width: 344px;
|
|
padding: sizes.$size-spacing-x8 sizes.$size-spacing-x6;
|
|
|
|
&WithScroll {
|
|
cursor: pointer;
|
|
}
|
|
|
|
&Icon {
|
|
#{$el}Disabled & {
|
|
color: themes.$color-text-disabled;
|
|
}
|
|
}
|
|
|
|
&Content {
|
|
display: flex;
|
|
flex-direction: column;
|
|
padding-top: sizes.$size-spacing-x4;
|
|
gap: sizes.$size-spacing-x6;
|
|
}
|
|
|
|
&Title {
|
|
@include mixin.h4;
|
|
color: themes.$color-text-active;
|
|
|
|
&:hover {
|
|
color: themes.$color-text-link;
|
|
}
|
|
|
|
#{$el}Disabled & {
|
|
color: themes.$color-text-disabled;
|
|
}
|
|
}
|
|
|
|
&Subtitle {
|
|
@include mixin.caption;
|
|
|
|
&:hover {
|
|
color: themes.$color-text-link;
|
|
}
|
|
|
|
#{$el}Disabled & {
|
|
color: themes.$color-text-disabled;
|
|
}
|
|
|
|
#{$el}WithScroll & {
|
|
color: themes.$color-text-active;
|
|
}
|
|
}
|
|
|
|
&Container {
|
|
display: flex;
|
|
gap: sizes.$size-spacing-x4;
|
|
}
|
|
}
|
|
</style>
|