Skip to content

Commit

Permalink
Merge pull request #625 from madeindjs/WF-88
Browse files Browse the repository at this point in the history
chore(ui): armonize loading state of `CoreChatBot` - WF-88
  • Loading branch information
ramedina86 authored Nov 19, 2024
2 parents 202406d + 1908d21 commit bfb30f6
Show file tree
Hide file tree
Showing 5 changed files with 296 additions and 163 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<template>
<div class="CoreChatbotAvatar">{{ initials }}</div>
</template>

<script lang="ts" setup>
defineProps({
initials: { type: String, required: true },
});
</script>

<style scoped>
.CoreChatbotAvatar {
border-radius: 50%;
background: var(--avatarBackgroundColor);
color: var(--avatarTextColor);
margin-top: 6px;
height: 32px;
width: 32px;
flex: 0 0 32px;
display: flex;
font-weight: 500;
font-size: 0.75rem;
align-items: center;
justify-content: center;
overflow: hidden;
text-transform: uppercase;
}
</style>
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
<template>
<div class="CoreChatbotLoader" :style="{ '--dotSize': '6px' }">
<span class="CoreChatbotLoader__dot"></span>
<span class="CoreChatbotLoader__dot"></span>
<span class="CoreChatbotLoader__dot"></span>
</div>
</template>

<style scoped>
.CoreChatbotLoader {
width: 100px;
height: 100%;
display: flex;
gap: var(--dotSize);
align-items: center;
justify-content: center;
}
.CoreChatbotLoader__dot {
display: inline-block;
width: var(--dotSize);
height: var(--dotSize);
position: relative;
}
.CoreChatbotLoader__dot::after {
display: inline-block;
content: "";
position: absolute;
background-color: currentColor;
width: calc(var(--dotSize) / 2);
height: calc(var(--dotSize) / 2);
border-radius: 50%;
animation: changeSize 1.5s infinite;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
.CoreChatbotLoader__dot:nth-child(1)::after {
animation-delay: 0s;
}
.CoreChatbotLoader__dot:nth-child(2)::after {
animation-delay: 0.5s;
}
.CoreChatbotLoader__dot:nth-child(3)::after {
animation-delay: 1s;
}
@keyframes changeSize {
0% {
width: calc(var(--dotSize) / 2);
height: calc(var(--dotSize) / 2);
}
50% {
width: var(--dotSize);
height: var(--dotSize);
}
100% {
width: calc(var(--dotSize) / 2);
height: calc(var(--dotSize) / 2);
}
}
</style>
160 changes: 160 additions & 0 deletions src/ui/src/components/core/content/CoreChatBot/CoreChatbotMessage.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
<template>
<div class="CoreChatbotMessage" :aria-busy="isLoading">
<CoreChatbotAvatar :initials="initials" />
<div
class="CoreChatbotMessage__content"
:style="{ background: contentBgColor }"
>
<CoreChatbotLoader v-if="displayLoader" />
<div v-else class="CoreChatbotMessage__content__text">
<BaseMarkdown v-if="useMarkdown" :raw-text="content">
</BaseMarkdown>
<template v-else>
{{ content }}
</template>
</div>
<div
v-if="actions.length"
class="CoreChatbotMessage__content__actions"
>
<button
v-for="(action, actionIndex) in actions"
:key="actionIndex"
class="action"
@click="$emit('actionClick', action)"
>
<div v-if="action.subheading" class="subheading">
{{ action.subheading }}
</div>
<h3 class="name">{{ action.name }}</h3>
<div v-if="action.desc" class="desc">
{{ action.desc }}
</div>
</button>
</div>
</div>
</div>
</template>

<script lang="ts">
export type Action = {
subheading?: string;
name: string;
desc?: string;
data?: string;
};
export type Message = {
role: string;
pending: boolean;
content: string;
actions?: Action[];
};
</script>

<script lang="ts" setup>
import { computed, defineAsyncComponent, PropType } from "vue";
import CoreChatbotAvatar from "./CoreChatbotAvatar.vue";
const BaseMarkdown = defineAsyncComponent(
() => import("../../base/BaseMarkdown.vue"),
);
const CoreChatbotLoader = defineAsyncComponent(
() => import("./CoreChatbotLoader.vue"),
);
const props = defineProps({
initials: { type: String, required: true },
useMarkdown: { type: Boolean, required: false },
message: {
type: Object as PropType<Message>,
required: false,
default: undefined,
},
assistantRoleColor: { type: String, required: false, default: "" },
isLoading: { type: Boolean, required: false },
});
defineEmits({
actionClick: (action: Action) =>
typeof action === "object" && action !== null,
});
const actions = computed<Action[]>(() => props.message?.actions ?? []);
const displayLoader = computed(() => {
return props.isLoading && !content.value;
});
const role = computed(() => {
if (props.isLoading) return "assistant";
return props.message?.role ?? "";
});
const content = computed(() => props.message?.content.trim() ?? "");
const contentBgColor = computed(() => {
switch (role.value) {
case "user":
return "var(--userRoleColor)";
case "assistant":
return (
props.assistantRoleColor ||
"linear-gradient(264deg, #f5ebff 0.71%, #eef1ff 100%)"
);
default:
return "";
}
});
</script>

<style scoped>
.CoreChatbotMessage {
display: flex;
gap: 8px;
}
.CoreChatbotMessage__content {
border-radius: 8px;
width: fit-content;
flex: 0 1 auto;
color: var(--primaryTextColor);
white-space: pre-wrap;
}
.CoreChatbotMessage__content__text {
line-height: 2;
padding: 12px 16px 12px 16px;
}
.CoreChatbotMessage__content__actions {
padding: 16px;
background: rgba(0, 0, 0, 0.02);
display: flex;
gap: 12px;
flex-wrap: wrap;
}
.CoreChatbotMessage__content__actions .action {
padding: 12px;
border-radius: 4px;
background: var(--containerBackgroundColor);
overflow: hidden;
line-height: normal;
display: flex;
gap: 4px;
flex-direction: column;
box-shadow: 0 2px 2px 0px rgba(0, 0, 0, 0.1);
cursor: pointer;
border: 0;
}
.action .subheading {
color: var(--secondaryTextColor);
font-size: 0.7rem;
}
.action .desc {
font-size: 0.7rem;
}
</style>
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<template>
<svg
width="15"
height="12"
viewBox="0 0 15 12"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M14.0712 4.50295C14.2882 4.72002 14.2882 5.07197 14.0712 5.28905L10.5337 8.8265C10.3166 9.04357 9.96468 9.04357 9.7476 8.8265C9.53052 8.60942 9.53052 8.25747 9.7476 8.0404L12.892 4.896L9.7476 1.7516C9.53052 1.53452 9.53052 1.18257 9.7476 0.965495C9.96467 0.74842 10.3166 0.74842 10.5337 0.965495L14.0712 4.50295ZM13.6781 5.45185L3.67268 5.45185L3.67268 4.34014L13.6781 4.34014L13.6781 5.45185ZM2.00511 7.11942L2.00511 8.23114L0.893394 8.23114L0.893394 7.11942L2.00511 7.11942ZM3.67268 9.89871L5.52553 9.89871L5.52553 11.0104L3.67268 11.0104L3.67268 9.89871ZM2.00511 8.23114C2.00511 9.15211 2.7517 9.89871 3.67268 9.89871L3.67268 11.0104C2.13772 11.0104 0.893394 9.76609 0.893394 8.23114L2.00511 8.23114ZM3.67268 5.45185C2.7517 5.45185 2.00511 6.19845 2.00511 7.11942L0.893394 7.11942C0.893394 5.58447 2.13772 4.34014 3.67268 4.34014L3.67268 5.45185Z"
fill="currentColor"
/>
</svg>
</template>
Loading

0 comments on commit bfb30f6

Please sign in to comment.