feat: Add support for feature spotlight components (#11012)
This commit is contained in:
@@ -72,10 +72,18 @@ const handlePageChange = event => {
|
||||
<div
|
||||
class="flex items-start lg:items-center justify-between w-full py-6 lg:py-0 lg:h-20 gap-4 lg:gap-2 flex-col lg:flex-row"
|
||||
>
|
||||
<span class="text-xl font-medium text-n-slate-12">
|
||||
{{ headerTitle }}
|
||||
<slot name="headerTitle" />
|
||||
</span>
|
||||
<div class="flex gap-4 items-center">
|
||||
<slot name="headerTitle">
|
||||
<span class="text-xl font-medium text-n-slate-12">
|
||||
{{ headerTitle }}
|
||||
</span>
|
||||
</slot>
|
||||
<div v-if="!isEmpty" class="flex items-center gap-2">
|
||||
<div class="w-0.5 h-4 rounded-2xl bg-n-weak" />
|
||||
<slot name="knowMore" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
v-if="!showPaywall"
|
||||
v-on-clickaway="() => emit('close')"
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
import EmptyStateLayout from 'dashboard/components-next/EmptyStateLayout.vue';
|
||||
import Button from 'dashboard/components-next/button/Button.vue';
|
||||
import AssistantCard from 'dashboard/components-next/captain/assistant/AssistantCard.vue';
|
||||
import FeatureSpotlight from 'dashboard/components-next/feature-spotlight/FeatureSpotlight.vue';
|
||||
import { assistantsList } from 'dashboard/components-next/captain/pageComponents/emptyStates/captainEmptyStateContent.js';
|
||||
|
||||
const emit = defineEmits(['click']);
|
||||
@@ -12,6 +13,14 @@ const onClick = () => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<FeatureSpotlight
|
||||
:title="$t('CAPTAIN.ASSISTANTS.EMPTY_STATE.FEATURE_SPOTLIGHT.TITLE')"
|
||||
:note="$t('CAPTAIN.ASSISTANTS.EMPTY_STATE.FEATURE_SPOTLIGHT.NOTE')"
|
||||
fallback-thumbnail="/assets/images/dashboard/captain/assistant-light.svg"
|
||||
fallback-thumbnail-dark="/assets/images/dashboard/captain/assistant-dark.svg"
|
||||
learn-more-url="https://chwt.app/captain-assistant"
|
||||
class="mb-8"
|
||||
/>
|
||||
<EmptyStateLayout
|
||||
:title="$t('CAPTAIN.ASSISTANTS.EMPTY_STATE.TITLE')"
|
||||
:subtitle="$t('CAPTAIN.ASSISTANTS.EMPTY_STATE.SUBTITLE')"
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
import EmptyStateLayout from 'dashboard/components-next/EmptyStateLayout.vue';
|
||||
import Button from 'dashboard/components-next/button/Button.vue';
|
||||
import DocumentCard from 'dashboard/components-next/captain/assistant/DocumentCard.vue';
|
||||
import FeatureSpotlight from 'dashboard/components-next/feature-spotlight/FeatureSpotlight.vue';
|
||||
import { documentsList } from 'dashboard/components-next/captain/pageComponents/emptyStates/captainEmptyStateContent.js';
|
||||
|
||||
const emit = defineEmits(['click']);
|
||||
@@ -12,6 +13,14 @@ const onClick = () => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<FeatureSpotlight
|
||||
:title="$t('CAPTAIN.DOCUMENTS.EMPTY_STATE.FEATURE_SPOTLIGHT.TITLE')"
|
||||
:note="$t('CAPTAIN.DOCUMENTS.EMPTY_STATE.FEATURE_SPOTLIGHT.NOTE')"
|
||||
fallback-thumbnail="/assets/images/dashboard/captain/document-light.svg"
|
||||
fallback-thumbnail-dark="/assets/images/dashboard/captain/document-dark.svg"
|
||||
learn-more-url="https://chwt.app/captain-document"
|
||||
class="mb-8"
|
||||
/>
|
||||
<EmptyStateLayout
|
||||
:title="$t('CAPTAIN.DOCUMENTS.EMPTY_STATE.TITLE')"
|
||||
:subtitle="$t('CAPTAIN.DOCUMENTS.EMPTY_STATE.SUBTITLE')"
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
import EmptyStateLayout from 'dashboard/components-next/EmptyStateLayout.vue';
|
||||
import Button from 'dashboard/components-next/button/Button.vue';
|
||||
import ResponseCard from 'dashboard/components-next/captain/assistant/ResponseCard.vue';
|
||||
import FeatureSpotlight from 'dashboard/components-next/feature-spotlight/FeatureSpotlight.vue';
|
||||
import { responsesList } from 'dashboard/components-next/captain/pageComponents/emptyStates/captainEmptyStateContent.js';
|
||||
|
||||
const emit = defineEmits(['click']);
|
||||
@@ -12,6 +13,14 @@ const onClick = () => {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<FeatureSpotlight
|
||||
:title="$t('CAPTAIN.RESPONSES.EMPTY_STATE.FEATURE_SPOTLIGHT.TITLE')"
|
||||
:note="$t('CAPTAIN.RESPONSES.EMPTY_STATE.FEATURE_SPOTLIGHT.NOTE')"
|
||||
fallback-thumbnail="/assets/images/dashboard/captain/faqs-light.svg"
|
||||
fallback-thumbnail-dark="/assets/images/dashboard/captain/faqs-dark.svg"
|
||||
learn-more-url="https://chwt.app/captain-faq"
|
||||
class="mb-8"
|
||||
/>
|
||||
<EmptyStateLayout
|
||||
:title="$t('CAPTAIN.RESPONSES.EMPTY_STATE.TITLE')"
|
||||
:subtitle="$t('CAPTAIN.RESPONSES.EMPTY_STATE.SUBTITLE')"
|
||||
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
Reference in New Issue
Block a user