Ship assistant answers, contact moods, voice dictation, and the related CRM UI so these can be deployed to production. Co-authored-by: Cursor <cursoragent@cursor.com>
222 lines
3.8 KiB
Vue
222 lines
3.8 KiB
Vue
<script setup lang="ts">
|
|
import type { PersonMood } from '@mento/shared';
|
|
|
|
withDefaults(
|
|
defineProps<{
|
|
mood?: PersonMood | null;
|
|
size?: number;
|
|
}>(),
|
|
{ mood: 'newcomer', size: 48 },
|
|
);
|
|
</script>
|
|
|
|
<template>
|
|
<span
|
|
class="face"
|
|
:class="mood || 'newcomer'"
|
|
:style="{ width: `${size}px`, height: `${size}px` }"
|
|
aria-hidden="true"
|
|
>
|
|
<svg viewBox="0 0 64 64" fill="none">
|
|
<circle class="skin" cx="32" cy="34" r="22" />
|
|
<g class="shine">
|
|
<ellipse cx="24" cy="26" rx="6" ry="3.2" />
|
|
</g>
|
|
|
|
<g class="eyes">
|
|
<g class="eye left">
|
|
<ellipse class="open" cx="24" cy="33" rx="3.1" ry="3.6" />
|
|
<path class="happy" d="M21 33c1.4-2.2 4.6-2.2 6 0" />
|
|
<path class="sad" d="M21.4 34.6c1.2-2 4-2 5.2 0" />
|
|
</g>
|
|
<g class="eye right">
|
|
<ellipse class="open" cx="40" cy="33" rx="3.1" ry="3.6" />
|
|
<path class="happy" d="M37 33c1.4-2.2 4.6-2.2 6 0" />
|
|
<path class="sad" d="M37.4 34.6c1.2-2 4-2 5.2 0" />
|
|
</g>
|
|
</g>
|
|
|
|
<path class="mouth smile" d="M24 42c2.6 4.4 13.4 4.4 16 0" />
|
|
<path class="mouth grin" d="M22 40.5c3.4 7 16.6 7 20 0" />
|
|
<path class="mouth frown" d="M25 46c2.8-3.6 11.2-3.6 14 0" />
|
|
|
|
<g class="tears">
|
|
<ellipse class="tear t1" cx="18" cy="40" rx="2.1" ry="3.2" />
|
|
<ellipse class="tear t2" cx="46" cy="42" rx="2.1" ry="3.2" />
|
|
</g>
|
|
|
|
<g class="crown">
|
|
<path d="M16 18.5 22 26l10-9 10 9 6-7.5-2 12H18l-2-12Z" />
|
|
<rect x="18" y="26" width="28" height="3.4" rx="1" />
|
|
<circle class="gem" cx="32" cy="20" r="2.1" />
|
|
<circle class="gem side" cx="22.5" cy="23" r="1.5" />
|
|
<circle class="gem side" cx="41.5" cy="23" r="1.5" />
|
|
</g>
|
|
</svg>
|
|
</span>
|
|
</template>
|
|
|
|
<style scoped>
|
|
.face {
|
|
display: inline-grid;
|
|
place-items: center;
|
|
flex-shrink: 0;
|
|
border-radius: 50%;
|
|
background: #fff7d6;
|
|
box-shadow: inset 0 -3px 0 rgba(180, 120, 20, 0.08);
|
|
overflow: visible;
|
|
}
|
|
|
|
svg {
|
|
width: 100%;
|
|
height: 100%;
|
|
overflow: visible;
|
|
}
|
|
|
|
.skin {
|
|
fill: #f5c542;
|
|
}
|
|
|
|
.shine ellipse {
|
|
fill: rgba(255, 255, 255, 0.35);
|
|
}
|
|
|
|
.eye .open {
|
|
fill: #3b2415;
|
|
}
|
|
|
|
.eye .happy,
|
|
.eye .sad,
|
|
.mouth,
|
|
.tears,
|
|
.crown {
|
|
display: none;
|
|
}
|
|
|
|
.eye .happy,
|
|
.eye .sad,
|
|
.mouth {
|
|
stroke: #3b2415;
|
|
stroke-width: 2.4;
|
|
stroke-linecap: round;
|
|
fill: none;
|
|
}
|
|
|
|
.face.newcomer .mouth.smile {
|
|
display: block;
|
|
}
|
|
|
|
.face.happy {
|
|
animation: bounce 1.6s ease-in-out infinite;
|
|
}
|
|
|
|
.face.happy .eye .open {
|
|
display: none;
|
|
}
|
|
|
|
.face.happy .eye .happy,
|
|
.face.happy .mouth.grin {
|
|
display: block;
|
|
}
|
|
|
|
.face.unhappy .eye .open {
|
|
display: none;
|
|
}
|
|
|
|
.face.unhappy .eye .sad,
|
|
.face.unhappy .mouth.frown,
|
|
.face.unhappy .tears {
|
|
display: block;
|
|
}
|
|
|
|
.tear {
|
|
fill: #5bb7ff;
|
|
}
|
|
|
|
.t1 {
|
|
animation: drop 1.4s ease-in infinite;
|
|
}
|
|
|
|
.t2 {
|
|
animation: drop 1.4s ease-in 0.35s infinite;
|
|
}
|
|
|
|
.face.special .mouth.smile,
|
|
.face.special .crown {
|
|
display: block;
|
|
}
|
|
|
|
.face.special .crown {
|
|
transform-origin: 32px 22px;
|
|
animation: bob 1.8s ease-in-out infinite;
|
|
}
|
|
|
|
.crown path,
|
|
.crown rect {
|
|
fill: #f0b429;
|
|
stroke: #c48414;
|
|
stroke-width: 1;
|
|
}
|
|
|
|
.gem {
|
|
fill: #ef4444;
|
|
}
|
|
|
|
.gem.side {
|
|
fill: #22c55e;
|
|
}
|
|
|
|
.face.newcomer .eye .open,
|
|
.face.special .eye .open {
|
|
transform-box: fill-box;
|
|
transform-origin: center;
|
|
animation: blink 3.4s ease-in-out infinite;
|
|
}
|
|
|
|
@keyframes blink {
|
|
0%,
|
|
42%,
|
|
48%,
|
|
100% {
|
|
transform: scaleY(1);
|
|
}
|
|
45% {
|
|
transform: scaleY(0.12);
|
|
}
|
|
}
|
|
|
|
@keyframes bounce {
|
|
0%,
|
|
100% {
|
|
transform: translateY(0);
|
|
}
|
|
50% {
|
|
transform: translateY(-2px);
|
|
}
|
|
}
|
|
|
|
@keyframes drop {
|
|
0% {
|
|
opacity: 0;
|
|
transform: translateY(-4px);
|
|
}
|
|
25% {
|
|
opacity: 1;
|
|
}
|
|
100% {
|
|
opacity: 0;
|
|
transform: translateY(10px);
|
|
}
|
|
}
|
|
|
|
@keyframes bob {
|
|
0%,
|
|
100% {
|
|
transform: translateY(0) rotate(-4deg);
|
|
}
|
|
50% {
|
|
transform: translateY(-2px) rotate(4deg);
|
|
}
|
|
}
|
|
</style>
|