feat: add message container

This commit is contained in:
Shivam Mishra
2024-11-21 17:41:02 +05:30
parent 1fe1ace4a0
commit c3327502a1
4 changed files with 112 additions and 16 deletions
@@ -0,0 +1,95 @@
<script setup>
import { computed } from 'vue';
import TextBubble from './bubbles/Text.vue';
import Avatar from 'next/avatar/Avatar.vue';
import Icon from 'next/icon/Icon.vue';
const props = defineProps({
variant: {
type: String,
required: true,
validator: value => ['user', 'agent', 'system', 'private'].includes(value),
},
orientation: {
type: String,
default: 'left',
validator: value => ['left', 'right', 'center'].includes(value),
},
text: {
type: String,
default: 'Hello World',
},
user: {
type: String,
default: '',
},
});
const flexOrientationClass = computed(() => {
const map = {
left: 'justify-start',
right: 'justify-end',
center: 'justify-center',
};
return map[props.orientation];
});
const gridClass = computed(() => {
const map = {
left: 'grid grid-cols-[24px_1fr]',
right: 'grid grid-cols-[1fr_24px]',
};
return map[props.orientation];
});
const gridTemplate = computed(() => {
const map = {
left: `
"avatar bubble"
"spacer meta"
`,
right: `
"bubble avatar"
"meta spacer"
`,
};
return map[props.orientation];
});
</script>
<template>
<div class="flex w-full" :class="flexOrientationClass">
<div v-if="variant === 'system'">
<TextBubble v-bind="props" />
</div>
<div
v-else
:class="gridClass"
class="gap-x-3 gap-y-2 grid-area"
:style="{
gridTemplateAreas: gridTemplate,
gridTemplateColumns:
props.orientation === 'center' ? '1fr' : 'auto 1fr',
}"
>
<div class="[grid-area:avatar] flex items-end">
<Avatar :name="user" src="" size="24" />
</div>
<TextBubble v-bind="props" class="[grid-area:bubble]" />
<div
class="[grid-area:meta] text-xs text-n-slate-11 flex items-center gap-1.5"
:class="flexOrientationClass"
>
<span>{{ user }} {{ '• 1m ago' }}</span>
<Icon
v-if="variant === 'private'"
icon="i-lucide-lock-keyhole"
class="text-n-slate-10 size-3"
/>
</div>
</div>
</div>
</template>
@@ -1,7 +1,13 @@
<script setup>
import MessageBubble from './MessageBubble.vue';
import Message from './Message.vue';
const messages = [
{
variant: 'user',
user: 'Elizabeth',
text: 'Hey, the usual things I order is out of stock.',
orientation: 'left',
},
{
variant: 'system',
text: 'Conversation auto-assigned to Stanley',
@@ -9,31 +15,37 @@ const messages = [
},
{
variant: 'agent',
user: 'Stanley',
text: 'Hello Elizabeth, there was a recent change in our office supplies.',
orientation: 'right',
},
{
variant: 'private',
user: 'Stanley',
text: 'Should we give her a premium discount?',
orientation: 'right',
},
{
variant: 'private',
user: 'Jim',
text: 'They have placed multiple orders already, can go ahead. @Michael thoughts?',
orientation: 'left',
},
{
variant: 'private',
user: 'Michael',
text: 'Yes, lets offer her a 20% discount',
orientation: 'left',
},
{
variant: 'agent',
user: 'Stanley',
text: 'If you want to buy our premium supplies, we can offer you a 20% discount! They come with indices and laser beams! ⚡',
orientation: 'right',
},
{
variant: 'user',
user: 'Elizabeth',
text: 'Thats great!',
orientation: 'left',
},
@@ -46,7 +58,7 @@ const messages = [
:layout="{ type: 'grid', width: '800' }"
>
<div class="p-4 bg-n-background rounded-lg w-full min-w-5xl grid gap-4">
<MessageBubble v-for="message in messages" v-bind="message" />
<Message v-for="message in messages" v-bind="message" />
</div>
</Story>
</template>
@@ -29,16 +29,6 @@ const orientationMap = {
right: 'rounded-xl rounded-br-sm',
};
const containetFlexJustify = computed(() => {
const map = {
left: 'justify-start',
right: 'justify-end',
center: 'justify-center',
};
return map[props.orientation];
});
const messageClass = computed(() => {
const classToApply = [varaintBaseMap[props.variant]];
@@ -53,9 +43,7 @@ const messageClass = computed(() => {
</script>
<template>
<div class="flex w-full" :class="containetFlexJustify">
<div class="max-w-md text-sm" :class="messageClass">
{{ text }}
</div>
<div class="max-w-md text-sm" :class="messageClass">
{{ text }}
</div>
</template>