feat: Add support for feature spotlight components (#11012)

This commit is contained in:
Sivin Varghese
2025-03-19 01:47:42 +05:30
committed by GitHub
parent 8291c84cc3
commit 9d49b69f2e
27 changed files with 4296 additions and 8 deletions

View File

@@ -0,0 +1,38 @@
<script setup>
import FeatureSpotlight from './FeatureSpotlight.vue';
</script>
<template>
<Story
title="Components/FeatureSpotlight/Default"
:layout="{ type: 'grid', width: '1000px' }"
>
<Variant title="Default with learn more URL">
<div class="p-6 bg-n-background">
<FeatureSpotlight
title="Captain Assistant"
note="Captain Assistant engages directly with customers, learns from your help docs and past conversations, and delivers instant, accurate responses. It handles the initial queries, providing quick resolutions before transferring to an agent when needed."
video-url=""
thumbnail=""
fallback-thumbnail="/assets/images/dashboard/captain/assistant-light.svg"
fallback-thumbnail-dark="/assets/images/dashboard/captain/assistant-dark.svg"
learn-more-url="https://www.chatwoot.com/hc/user-guide/articles/1738101547-creating-an-assistant-with-captain"
/>
</div>
</Variant>
<Variant title="With Video URL and Thumbnail">
<div class="p-6 bg-n-background">
<FeatureSpotlight
title="Captain Assistant"
note="Captain Assistant engages directly with customers, learns from your help docs and past conversations, and delivers instant, accurate responses. It handles the initial queries, providing quick resolutions before transferring to an agent when needed."
video-url="https://www.youtube.com/watch?v=E4xUHyAAktY"
thumbnail="https://i.ytimg.com/an_webp/E4xUHyAAktY/mqdefault_6s.webp?du=3000&sqp=CJaKmL4G&rs=AOn4CLCmfy1TMOcW4UsjQTgyKRp4TSGZgg"
fallback-thumbnail="/assets/images/dashboard/captain/assistant-light.svg"
fallback-thumbnail-dark="/assets/images/dashboard/captain/assistant-dark.svg"
learn-more-url="https://www.chatwoot.com/hc/user-guide/articles/1738101547-creating-an-assistant-with-captain"
/>
</div>
</Variant>
</Story>
</template>

View File

@@ -0,0 +1,95 @@
<script setup>
import { ref } from 'vue';
import Button from 'dashboard/components-next/button/Button.vue';
defineProps({
title: { type: String, default: '' },
note: { type: String, default: '' },
videoUrl: { type: String, default: '' },
thumbnail: { type: String, default: '' },
fallbackThumbnail: { type: String, default: '' },
fallbackThumbnailDark: { type: String, default: '' },
learnMoreUrl: { type: String, default: '' },
});
const imageError = ref(false);
const handleImageError = () => {
imageError.value = true;
};
const openLink = link => {
if (link) {
window.open(link, '_blank');
}
};
</script>
<template>
<section class="custom-dashed-border rounded-2xl py-5 px-6">
<div class="flex flex-col md:flex-row items-start md:items-center gap-6">
<div
class="flex-shrink-0 bg-gray-800 w-[7.5rem] h-[6.5rem] rounded-lg flex items-center justify-center overflow-hidden"
>
<img
v-if="!imageError && thumbnail"
:src="thumbnail"
:alt="title"
draggable="false"
class="w-full h-full object-cover rounded-lg"
loading="lazy"
@error="handleImageError"
/>
<template v-else>
<img
v-if="fallbackThumbnailDark"
:src="fallbackThumbnailDark"
:alt="title"
draggable="false"
class="w-full h-full object-cover hidden dark:block rounded-lg"
loading="lazy"
/>
<img
v-if="fallbackThumbnail"
:src="fallbackThumbnail"
:alt="title"
draggable="false"
class="w-full h-full object-cover block dark:hidden rounded-lg"
loading="lazy"
/>
</template>
</div>
<div class="flex flex-col flex-1 gap-3 ltr:pr-8 rtl:pl-8">
<p v-if="note" class="text-n-slate-12 text-sm mb-0">{{ note }}</p>
<div class="flex gap-3">
<slot name="actions">
<Button
v-if="videoUrl"
:label="$t('FEATURE_SPOTLIGHT.WATCH_VIDEO')"
sm
faded
slate
icon="i-lucide-circle-play"
@click="openLink(videoUrl)"
/>
<Button
v-if="learnMoreUrl"
:label="$t('FEATURE_SPOTLIGHT.LEARN_MORE')"
sm
faded
slate
trailing-icon
icon="i-lucide-arrow-up-right"
@click="openLink(learnMoreUrl)"
/>
</slot>
</div>
</div>
</div>
</section>
</template>

View File

@@ -0,0 +1,44 @@
<script setup>
import FeatureSpotlightPopover from './FeatureSpotlightPopover.vue';
</script>
<template>
<Story
title="Components/FeatureSpotlight/Popup"
:layout="{ type: 'grid', width: '800px' }"
>
<Variant title="Default with learn more URL">
<div class="p-6 h-[450px] bg-n-background">
<div class="flex gap-8">
<FeatureSpotlightPopover
button-label="Learn about Assistant"
title="Captain Assistant"
note="Captain Assistant engages directly with customers, learns from your help docs and past conversations, and delivers instant, accurate responses. It handles the initial queries, providing quick resolutions before transferring to an agent when needed."
video-url=""
thumbnail=""
fallback-thumbnail="/assets/images/dashboard/captain/assistant-popover-light.svg"
fallback-thumbnail-dark="/assets/images/dashboard/captain/assistant-popover-dark.svg"
learn-more-url="https://www.chatwoot.com/hc/user-guide/articles/1738101547-creating-an-assistant-with-captain"
/>
</div>
</div>
</Variant>
<Variant title="With Video Thumbnail and URL">
<div class="p-6 h-[450px] bg-n-background">
<div class="flex gap-8">
<FeatureSpotlightPopover
button-label="Learn about Assistant"
title="Captain Assistant"
note="Captain Assistant engages directly with customers, learns from your help docs and past conversations, and delivers instant, accurate responses. It handles the initial queries, providing quick resolutions before transferring to an agent when needed."
video-url="https://www.youtube.com/watch?v=E4xUHyAAktY"
thumbnail="https://i.ytimg.com/an_webp/E4xUHyAAktY/mqdefault_6s.webp?du=3000&sqp=CJaKmL4G&rs=AOn4CLCmfy1TMOcW4UsjQTgyKRp4TSGZgg"
fallback-thumbnail="/assets/images/dashboard/captain/assistant-popover-light.svg"
fallback-thumbnail-dark="/assets/images/dashboard/captain/assistant-popover-dark.svg"
learn-more-url="https://www.chatwoot.com/hc/user-guide/articles/1738101547-creating-an-assistant-with-captain"
/>
</div>
</div>
</Variant>
</Story>
</template>

View File

@@ -0,0 +1,125 @@
<script setup>
import { ref } from 'vue';
import { useToggle } from '@vueuse/core';
import { vOnClickOutside } from '@vueuse/components';
import Button from 'dashboard/components-next/button/Button.vue';
defineProps({
buttonLabel: { type: String, default: '' },
title: { type: String, default: '' },
note: { type: String, default: '' },
videoUrl: { type: String, default: '' },
thumbnail: { type: String, default: '' },
fallbackThumbnail: { type: String, default: '' },
fallbackThumbnailDark: { type: String, default: '' },
learnMoreUrl: { type: String, default: '' },
});
const imageError = ref(false);
const [isPopupVisible, togglePopup] = useToggle();
const handleImageError = () => {
imageError.value = true;
};
const openLink = link => {
if (link) {
window.open(link, '_blank');
}
};
</script>
<template>
<div class="relative">
<Button
id="togglePopup"
:label="buttonLabel"
slate
ghost
sm
:class="{ 'bg-n-alpha-2': isPopupVisible }"
@click="togglePopup(!isPopupVisible)"
/>
<div
v-if="isPopupVisible"
v-on-click-outside="[
() => isPopupVisible && (isPopupVisible = false),
{ ignore: ['#togglePopup'] },
]"
>
<section
class="absolute top-full mt-6 ltr:left-0 rtl:right-0 outline outline-1 outline-n-weak bg-n-alpha-3 backdrop-blur-[100px] rounded-xl p-4 w-80"
>
<div
class="absolute -top-[0.77rem] ltr:left-12 rtl:right-12 w-6 h-6 ltr:rotate-45 rtl:-rotate-45 rtl:rounded-tr ltr:rounded-tl rtl:border-r ltr:border-l border-t border-n-weak bg-n-alpha-3 z-10"
/>
<div class="relative flex flex-col items-start gap-4 z-20">
<div class="flex-shrink-0 bg-gray-800 w-full h-[7.5rem] rounded-lg">
<img
v-if="!imageError && thumbnail"
:src="thumbnail"
:alt="title"
draggable="false"
loading="lazy"
class="w-full h-full object-cover rounded-lg"
@error="handleImageError"
/>
<template v-else>
<img
v-if="fallbackThumbnailDark"
:src="fallbackThumbnailDark"
:alt="title"
draggable="false"
loading="lazy"
class="w-full h-full object-cover hidden dark:block"
/>
<img
v-if="fallbackThumbnail"
:src="fallbackThumbnail"
:alt="title"
draggable="false"
loading="lazy"
class="w-full h-full object-cover block dark:hidden"
/>
</template>
</div>
<p v-if="note" class="text-n-slate-12 text-start text-sm mb-0">
{{ note }}
</p>
<div class="flex gap-3 justify-between w-full">
<slot name="actions">
<Button
v-if="videoUrl"
:label="$t('FEATURE_SPOTLIGHT.WATCH_VIDEO')"
sm
faded
slate
icon="i-lucide-circle-play"
class="w-full"
@click="openLink(videoUrl)"
/>
<Button
v-if="learnMoreUrl"
:label="$t('FEATURE_SPOTLIGHT.LEARN_MORE')"
sm
faded
slate
trailing-icon
class="w-full"
icon="i-lucide-arrow-up-right"
@click="openLink(learnMoreUrl)"
/>
</slot>
</div>
</div>
</section>
</div>
</div>
</template>