chore: Update reply editor design (#10575)

# Pull Request Template

## Description

This PR will update the reply message editor’s design.

**Screen recording**


https://github.com/user-attachments/assets/40f61903-6bf7-4031-9a36-9027dffc46aa

---------

Co-authored-by: Pranav <pranavrajs@gmail.com>
Co-authored-by: Shivam Mishra <scm.mymail@gmail.com>
This commit is contained in:
Sivin Varghese
2025-01-08 17:49:53 +05:30
committed by GitHub
parent fa8f1d9b6f
commit dd595675bc
14 changed files with 216 additions and 164 deletions

View File

@@ -80,7 +80,7 @@ const toggleConversationLayout = () => {
<template> <template>
<div <div
class="flex items-center justify-between gap-2 px-4 pb-0" class="flex items-center justify-between gap-2 px-4 pb-0 mb-2"
:class="{ :class="{
'pb-3 border-b border-n-strong': hasAppliedFiltersOrActiveFolders, 'pb-3 border-b border-n-strong': hasAppliedFiltersOrActiveFolders,
'pt-2.5': showV4View, 'pt-2.5': showV4View,

View File

@@ -10,9 +10,11 @@ import AIAssistanceModal from './AIAssistanceModal.vue';
import { CMD_AI_ASSIST } from 'dashboard/helper/commandbar/events'; import { CMD_AI_ASSIST } from 'dashboard/helper/commandbar/events';
import AIAssistanceCTAButton from './AIAssistanceCTAButton.vue'; import AIAssistanceCTAButton from './AIAssistanceCTAButton.vue';
import { emitter } from 'shared/helpers/mitt'; import { emitter } from 'shared/helpers/mitt';
import NextButton from 'dashboard/components-next/button/Button.vue';
export default { export default {
components: { components: {
NextButton,
AIAssistanceModal, AIAssistanceModal,
AICTAModal, AICTAModal,
AIAssistanceCTAButton, AIAssistanceCTAButton,
@@ -128,13 +130,13 @@ export default {
v-if="shouldShowAIAssistCTAButton" v-if="shouldShowAIAssistCTAButton"
@open="openAIAssist" @open="openAIAssist"
/> />
<woot-button <NextButton
v-else v-else
v-tooltip.top-end="$t('INTEGRATION_SETTINGS.OPEN_AI.AI_ASSIST')" v-tooltip.top-end="$t('INTEGRATION_SETTINGS.OPEN_AI.AI_ASSIST')"
icon="wand" icon="i-ph-magic-wand"
color-scheme="secondary" slate
variant="smooth" faded
size="small" sm
@click="openAIAssist" @click="openAIAssist"
/> />
<woot-modal <woot-modal

View File

@@ -1,27 +1,22 @@
<script> <script setup>
export default { import NextButton from 'dashboard/components-next/button/Button.vue';
emits: ['open'],
methods: { const emit = defineEmits(['open']);
onClick() {
this.$emit('open'); const onClick = () => {
}, emit('open');
},
}; };
</script> </script>
<template> <template>
<div class="relative"> <div class="relative">
<woot-button <NextButton
icon="wand" class="cta-btn cta-btn-light dark:cta-btn-dark hover:cta-btn-light-hover dark:hover:cta-btn-dark-hover"
color-scheme="secondary" :label="$t('INTEGRATION_SETTINGS.OPEN_AI.AI_ASSIST')"
variant="smooth" icon="i-ph-magic-wand"
size="small" sm
class-names="cta-btn cta-btn-light dark:cta-btn-dark hover:cta-btn-light-hover dark:hover:cta-btn-dark-hover"
@click="onClick" @click="onClick"
> />
{{ $t('INTEGRATION_SETTINGS.OPEN_AI.AI_ASSIST') }}
</woot-button>
<div <div
class="radar-ping-animation absolute top-0 right-0 -mt-1 -mr-1 rounded-full w-3 h-3 bg-woot-500 dark:bg-woot-500" class="radar-ping-animation absolute top-0 right-0 -mt-1 -mr-1 rounded-full w-3 h-3 bg-woot-500 dark:bg-woot-500"
@@ -34,22 +29,26 @@ export default {
<style scoped> <style scoped>
@tailwind components; @tailwind components;
@layer components { @layer components {
/* Gradient animation */ /* Gradient animation */
@keyframes gradient { @keyframes gradient {
0% { 0% {
background-position: 0% 50%; background-position: 0% 50%;
} }
50% { 50% {
background-position: 100% 50%; background-position: 100% 50%;
} }
100% { 100% {
background-position: 0% 50%; background-position: 0% 50%;
} }
} }
.cta-btn { .cta-btn {
animation: gradient 5s ease infinite; animation: gradient 5s ease infinite;
border: 0; @apply text-n-slate-12 border-0 text-xs;
} }
.cta-btn-light { .cta-btn-light {
@@ -96,6 +95,7 @@ export default {
opacity: 0; opacity: 0;
} }
} }
.radar-ping-animation { .radar-ping-animation {
animation: ping 1s ease infinite; animation: ping 1s ease infinite;
} }

View File

@@ -2,8 +2,12 @@
import { mapGetters } from 'vuex'; import { mapGetters } from 'vuex';
import DyteAPI from 'dashboard/api/integrations/dyte'; import DyteAPI from 'dashboard/api/integrations/dyte';
import { useAlert } from 'dashboard/composables'; import { useAlert } from 'dashboard/composables';
import NextButton from 'dashboard/components-next/button/Button.vue';
export default { export default {
components: {
NextButton,
},
props: { props: {
conversationId: { conversationId: {
type: Number, type: Number,
@@ -43,16 +47,15 @@ export default {
<!-- eslint-disable-next-line vue/no-root-v-if --> <!-- eslint-disable-next-line vue/no-root-v-if -->
<template> <template>
<woot-button <NextButton
v-if="isVideoIntegrationEnabled" v-if="isVideoIntegrationEnabled"
v-tooltip.top-end=" v-tooltip.top-end="
$t('INTEGRATION_SETTINGS.DYTE.START_VIDEO_CALL_HELP_TEXT') $t('INTEGRATION_SETTINGS.DYTE.START_VIDEO_CALL_HELP_TEXT')
" "
icon="video" icon="i-ph-video-camera"
:is-loading="isLoading" slate
color-scheme="secondary" faded
variant="smooth" sm
size="small"
@click="onClick" @click="onClick"
/> />
</template> </template>

View File

@@ -735,7 +735,7 @@ useEmitter(BUS_EVENTS.INSERT_INTO_RICH_EDITOR, insertContentIntoEditor);
.ProseMirror-menubar { .ProseMirror-menubar {
min-height: var(--space-two) !important; min-height: var(--space-two) !important;
@apply -ml-2.5 pb-0 bg-white dark:bg-slate-900 text-slate-700 dark:text-slate-100; @apply -ml-2.5 pb-0 bg-transparent text-n-slate-11;
.ProseMirror-menu-active { .ProseMirror-menu-active {
@apply bg-slate-75 dark:bg-slate-800; @apply bg-slate-75 dark:bg-slate-800;
@@ -787,10 +787,6 @@ useEmitter(BUS_EVENTS.INSERT_INTO_RICH_EDITOR, insertContentIntoEditor);
} }
.ProseMirror-menubar-wrapper { .ProseMirror-menubar-wrapper {
.ProseMirror-menubar {
@apply bg-yellow-100 dark:bg-yellow-800 text-slate-700 dark:text-slate-25;
}
> .ProseMirror { > .ProseMirror {
@apply text-slate-800 dark:text-slate-25; @apply text-slate-800 dark:text-slate-25;

View File

@@ -0,0 +1,64 @@
<script setup>
import { computed } from 'vue';
import { REPLY_EDITOR_MODES } from './constants';
import Icon from 'dashboard/components-next/icon/Icon.vue';
const props = defineProps({
mode: {
type: String,
default: REPLY_EDITOR_MODES.REPLY,
},
});
defineEmits(['toggleMode']);
const isPrivate = computed(() => props.mode === REPLY_EDITOR_MODES.NOTE);
</script>
<template>
<button
class="flex items-center h-8 p-1 transition-all border rounded-full duration-600 bg-n-alpha-2 dark:bg-n-alpha-2 hover:bg-n-alpha-1 dark:hover:brightness-105 group relative transition-all duration-300 ease-in-out"
:class="[
isPrivate
? 'border-n-amber-12/10 dark:border-n-amber-3/30 w-[128px]'
: 'border-n-weak dark:border-n-weak ',
]"
@click="$emit('toggleMode')"
>
<div
class="flex absolute items-center justify-center w-6 transition-all duration-200 rounded-full bg-n-alpha-black1 size-6 transition-all duration-300 ease-in-out"
:class="[
isPrivate
? 'ltr:translate-x-[94px] rtl:-translate-x-[94px]'
: 'translate-x-0',
]"
>
<Icon
:icon="
isPrivate
? 'i-material-symbols-lock'
: 'i-material-symbols-lock-open-rounded'
"
class="flex-shrink-0 size-3.5"
:class="[
isPrivate ? 'dark:text-n-amber-9 text-n-amber-11' : 'text-n-slate-10',
]"
/>
</div>
<span
class="flex items-center text-sm font-medium transition-all duration-200 w-fit whitespace-nowrap"
:class="[
isPrivate
? 'text-n-amber-12 ltr:mr-7 ltr:ml-1.5 rtl:ml-7 rtl:mr-1.5'
: 'text-n-slate-12 ltr:ml-7 ltr:mr-1.5 rtl:mr-7 rtl:ml-1.5',
]"
>
{{
isPrivate
? $t('CONVERSATION.REPLYBOX.PRIVATE_NOTE')
: $t('CONVERSATION.REPLYBOX.REPLY')
}}
</span>
</button>
</template>

View File

@@ -15,10 +15,11 @@ import VideoCallButton from '../VideoCallButton.vue';
import AIAssistanceButton from '../AIAssistanceButton.vue'; import AIAssistanceButton from '../AIAssistanceButton.vue';
import { REPLY_EDITOR_MODES } from './constants'; import { REPLY_EDITOR_MODES } from './constants';
import { mapGetters } from 'vuex'; import { mapGetters } from 'vuex';
import NextButton from 'dashboard/components-next/button/Button.vue';
export default { export default {
name: 'ReplyBottomPanel', name: 'ReplyBottomPanel',
components: { FileUpload, VideoCallButton, AIAssistanceButton }, components: { NextButton, FileUpload, VideoCallButton, AIAssistanceButton },
mixins: [inboxMixin], mixins: [inboxMixin],
props: { props: {
mode: { mode: {
@@ -207,13 +208,13 @@ export default {
switch (this.recordingAudioState) { switch (this.recordingAudioState) {
// playing paused recording stopped inactive destroyed // playing paused recording stopped inactive destroyed
case 'playing': case 'playing':
return 'microphone-pause'; return 'i-ph-pause';
case 'paused': case 'paused':
return 'microphone-play'; return 'i-ph-play';
case 'stopped': case 'stopped':
return 'microphone-play'; return 'i-ph-play';
default: default:
return 'microphone-stop'; return 'i-ph-stop';
} }
}, },
showMessageSignatureButton() { showMessageSignatureButton() {
@@ -253,15 +254,14 @@ export default {
</script> </script>
<template> <template>
<div class="bottom-box" :class="wrapClass"> <div class="flex justify-between p-3" :class="wrapClass">
<div class="left-wrap"> <div class="left-wrap">
<woot-button <NextButton
v-tooltip.top-end="$t('CONVERSATION.REPLYBOX.TIP_EMOJI_ICON')" v-tooltip.top-end="$t('CONVERSATION.REPLYBOX.TIP_EMOJI_ICON')"
:title="$t('CONVERSATION.REPLYBOX.TIP_EMOJI_ICON')" icon="i-ph-smiley-sticker"
icon="emoji" slate
color-scheme="secondary" faded
variant="smooth" sm
size="small"
@click="toggleEmojiPicker" @click="toggleEmojiPicker"
/> />
<FileUpload <FileUpload
@@ -279,62 +279,59 @@ export default {
}" }"
@input-file="onFileUpload" @input-file="onFileUpload"
> >
<woot-button <NextButton
v-if="showAttachButton" v-if="showAttachButton"
class-names="button--upload" v-tooltip.top-end="$t('CONVERSATION.REPLYBOX.TIP_ATTACH_ICON')"
:title="$t('CONVERSATION.REPLYBOX.TIP_ATTACH_ICON')" icon="i-ph-paperclip"
icon="attach" slate
color-scheme="secondary" faded
variant="smooth" sm
size="small"
/> />
</FileUpload> </FileUpload>
<woot-button <NextButton
v-if="showAudioRecorderButton" v-if="showAudioRecorderButton"
v-tooltip.top-end="$t('CONVERSATION.REPLYBOX.TIP_AUDIORECORDER_ICON')" v-tooltip.top-end="$t('CONVERSATION.REPLYBOX.TIP_AUDIORECORDER_ICON')"
:icon="!isRecordingAudio ? 'microphone' : 'microphone-off'" :icon="!isRecordingAudio ? 'i-ph-microphone' : 'i-ph-microphone-slash'"
:color-scheme="!isRecordingAudio ? 'secondary' : 'alert'" slate
variant="smooth" faded
size="small" sm
@click="toggleAudioRecorder" @click="toggleAudioRecorder"
/> />
<woot-button <NextButton
v-if="showEditorToggle" v-if="showEditorToggle"
v-tooltip.top-end="$t('CONVERSATION.REPLYBOX.TIP_FORMAT_ICON')" v-tooltip.top-end="$t('CONVERSATION.REPLYBOX.TIP_FORMAT_ICON')"
icon="quote" icon="i-ph-quotes"
color-scheme="secondary" slate
variant="smooth" faded
size="small" sm
@click="$emit('toggleEditor')" @click="$emit('toggleEditor')"
/> />
<woot-button <NextButton
v-if="showAudioPlayStopButton" v-if="showAudioPlayStopButton"
v-tooltip.top-end="$t('CONVERSATION.REPLYBOX.TIP_FORMAT_ICON')"
:icon="audioRecorderPlayStopIcon" :icon="audioRecorderPlayStopIcon"
color-scheme="secondary" slate
variant="smooth" faded
size="small" sm
:label="recordingAudioDurationText"
@click="toggleAudioRecorderPlayPause" @click="toggleAudioRecorderPlayPause"
> />
<span>{{ recordingAudioDurationText }}</span> <NextButton
</woot-button>
<woot-button
v-if="showMessageSignatureButton" v-if="showMessageSignatureButton"
v-tooltip.top-end="signatureToggleTooltip" v-tooltip.top-end="signatureToggleTooltip"
icon="signature" icon="i-ph-signature"
color-scheme="secondary" slate
variant="smooth" faded
size="small" sm
:title="signatureToggleTooltip"
@click="toggleMessageSignature" @click="toggleMessageSignature"
/> />
<woot-button <NextButton
v-if="hasWhatsappTemplates" v-if="hasWhatsappTemplates"
v-tooltip.top-end="$t('CONVERSATION.FOOTER.WHATSAPP_TEMPLATES')" v-tooltip.top-end="$t('CONVERSATION.FOOTER.WHATSAPP_TEMPLATES')"
icon="whatsapp" icon="i-ph-whatsapp"
color-scheme="secondary" slate
variant="smooth" faded
size="small" sm
:title="$t('CONVERSATION.FOOTER.WHATSAPP_TEMPLATES')"
@click="$emit('selectWhatsappTemplate')" @click="$emit('selectWhatsappTemplate')"
/> />
<VideoCallButton <VideoCallButton
@@ -359,14 +356,13 @@ export default {
</h4> </h4>
</div> </div>
</transition> </transition>
<woot-button <NextButton
v-if="enableInsertArticleInReply" v-if="enableInsertArticleInReply"
v-tooltip.top-end="$t('HELP_CENTER.ARTICLE_SEARCH.OPEN_ARTICLE_SEARCH')" v-tooltip.top-end="$t('HELP_CENTER.ARTICLE_SEARCH.OPEN_ARTICLE_SEARCH')"
icon="document-text-link" icon="i-ph-article-ny-times"
color-scheme="secondary" slate
variant="smooth" faded
size="small" sm
:title="$t('HELP_CENTER.ARTICLE_SEARCH.OPEN_ARTICLE_SEARCH')"
@click="toggleInsertArticle" @click="toggleInsertArticle"
/> />
</div> </div>
@@ -384,14 +380,6 @@ export default {
</template> </template>
<style lang="scss" scoped> <style lang="scss" scoped>
.bottom-box {
@apply flex justify-between py-3 px-4;
&.is-note-mode {
@apply bg-yellow-100 dark:bg-yellow-800;
}
}
.left-wrap { .left-wrap {
@apply items-center flex gap-2; @apply items-center flex gap-2;
} }

View File

@@ -1,9 +1,15 @@
<script> <script>
import { useKeyboardEvents } from 'dashboard/composables/useKeyboardEvents'; import { useKeyboardEvents } from 'dashboard/composables/useKeyboardEvents';
import { REPLY_EDITOR_MODES, CHAR_LENGTH_WARNING } from './constants'; import { REPLY_EDITOR_MODES, CHAR_LENGTH_WARNING } from './constants';
import NextButton from 'dashboard/components-next/button/Button.vue';
import EditorModeToggle from './EditorModeToggle.vue';
export default { export default {
name: 'ReplyTopPanel', name: 'ReplyTopPanel',
components: {
NextButton,
EditorModeToggle,
},
props: { props: {
mode: { mode: {
type: String, type: String,
@@ -17,10 +23,6 @@ export default {
type: Number, type: Number,
default: () => 0, default: () => 0,
}, },
popoutReplyBox: {
type: Boolean,
default: false,
},
}, },
emits: ['setReplyMode', 'togglePopout'], emits: ['setReplyMode', 'togglePopout'],
setup(props, { emit }) { setup(props, { emit }) {
@@ -33,6 +35,13 @@ export default {
const handleNoteClick = () => { const handleNoteClick = () => {
setReplyMode(REPLY_EDITOR_MODES.NOTE); setReplyMode(REPLY_EDITOR_MODES.NOTE);
}; };
const handleModeToggle = () => {
const newMode =
props.mode === REPLY_EDITOR_MODES.REPLY
? REPLY_EDITOR_MODES.NOTE
: REPLY_EDITOR_MODES.REPLY;
setReplyMode(newMode);
};
const keyboardEvents = { const keyboardEvents = {
'Alt+KeyP': { 'Alt+KeyP': {
action: () => handleNoteClick(), action: () => handleNoteClick(),
@@ -46,8 +55,10 @@ export default {
useKeyboardEvents(keyboardEvents); useKeyboardEvents(keyboardEvents);
return { return {
handleModeToggle,
handleReplyClick, handleReplyClick,
handleNoteClick, handleNoteClick,
REPLY_EDITOR_MODES,
}; };
}, },
computed: { computed: {
@@ -74,27 +85,12 @@ export default {
</script> </script>
<template> <template>
<div class="flex justify-between bg-black-50 dark:bg-slate-800"> <div class="flex justify-between h-[52px] gap-2 ltr:pl-3 rtl:pr-3">
<div class="button-group"> <EditorModeToggle
<woot-button :mode="mode"
variant="clear" class="mt-3"
class="button--reply" @toggle-mode="handleModeToggle"
:class="replyButtonClass" />
@click="handleReplyClick"
>
{{ $t('CONVERSATION.REPLYBOX.REPLY') }}
</woot-button>
<woot-button
class="button--note"
variant="clear"
color-scheme="warning"
:class="noteButtonClass"
@click="handleNoteClick"
>
{{ $t('CONVERSATION.REPLYBOX.PRIVATE_NOTE') }}
</woot-button>
</div>
<div class="flex items-center mx-4 my-0"> <div class="flex items-center mx-4 my-0">
<div v-if="isMessageLengthReachingThreshold" class="text-xs"> <div v-if="isMessageLengthReachingThreshold" class="text-xs">
<span :class="charLengthClass"> <span :class="charLengthClass">
@@ -102,20 +98,10 @@ export default {
</span> </span>
</div> </div>
</div> </div>
<woot-button <NextButton
v-if="popoutReplyBox" ghost
variant="clear" class="ltr:rounded-bl-md rtl:rounded-br-md ltr:rounded-br-none rtl:rounded-bl-none ltr:rounded-tl-none rtl:rounded-tr-none text-n-slate-11 ltr:rounded-tr-[11px] rtl:rounded-tl-[11px]"
icon="dismiss" icon="i-lucide-maximize-2"
color-scheme="secondary"
class-names="popout-button"
@click="$emit('togglePopout')"
/>
<woot-button
v-else
variant="clear"
icon="resize-large"
color-scheme="secondary"
class-names="popout-button"
@click="$emit('togglePopout')" @click="$emit('togglePopout')"
/> />
</div> </div>
@@ -127,28 +113,35 @@ export default {
.button { .button {
@apply text-sm font-medium py-2.5 px-4 m-0 relative z-10; @apply text-sm font-medium py-2.5 px-4 m-0 relative z-10;
&.is-active { &.is-active {
@apply bg-white dark:bg-slate-900; @apply bg-white dark:bg-slate-900;
} }
} }
.button--reply { .button--reply {
@apply border-r rounded-none border-b-0 border-l-0 border-t-0 border-slate-50 dark:border-slate-700; @apply border-r rounded-none border-b-0 border-l-0 border-t-0 border-slate-50 dark:border-slate-700;
&:hover, &:hover,
&:focus { &:focus {
@apply border-r border-slate-50 dark:border-slate-700; @apply border-r border-slate-50 dark:border-slate-700;
} }
} }
.button--note { .button--note {
@apply border-l-0 rounded-none; @apply border-l-0 rounded-none;
&.is-active { &.is-active {
@apply border-r border-b-0 bg-yellow-100 dark:bg-yellow-800 border-t-0 border-slate-50 dark:border-slate-700; @apply border-r border-b-0 bg-yellow-100 dark:bg-yellow-800 border-t-0 border-slate-50 dark:border-slate-700;
} }
&:hover, &:hover,
&:active { &:active {
@apply text-yellow-700 dark:text-yellow-700; @apply text-yellow-700 dark:text-yellow-700;
} }
} }
} }
.button--note { .button--note {
@apply text-yellow-600 dark:text-yellow-600 bg-transparent dark:bg-transparent; @apply text-yellow-600 dark:text-yellow-600 bg-transparent dark:bg-transparent;
} }

View File

@@ -623,7 +623,11 @@ export default {
} }
.reply-box { .reply-box {
@apply border border-solid border-slate-75 dark:border-slate-600 max-w-[75rem] w-[70%]; @apply border border-n-weak max-w-[75rem] w-[70%];
&.is-private {
@apply dark:border-n-amber-3/30 border-n-amber-12/5;
}
} }
.reply-box .reply-box__top { .reply-box .reply-box__top {

View File

@@ -1242,28 +1242,12 @@ export default {
} }
.reply-box { .reply-box {
transition: transition: height 2s cubic-bezier(0.37, 0, 0.63, 1);
box-shadow 0.35s cubic-bezier(0.37, 0, 0.63, 1),
height 2s cubic-bezier(0.37, 0, 0.63, 1);
@apply relative border-t border-slate-50 dark:border-slate-700 bg-white dark:bg-slate-900; @apply relative mb-2 mx-2 border border-n-weak rounded-xl bg-n-solid-1;
&.is-focused {
box-shadow:
0 1px 3px 0 rgba(0, 0, 0, 0.1),
0 1px 2px 0 rgba(0, 0, 0, 0.06);
}
&.is-private { &.is-private {
@apply bg-yellow-100 dark:bg-yellow-800; @apply bg-n-solid-amber dark:border-n-amber-3/10 border-n-amber-12/5;
.reply-box__top {
@apply bg-yellow-100 dark:bg-yellow-800;
> input {
@apply bg-yellow-100 dark:bg-yellow-800;
}
}
} }
} }
@@ -1272,7 +1256,7 @@ export default {
} }
.reply-box__top { .reply-box__top {
@apply relative py-0 px-4 -mt-px border-t border-solid border-slate-50 dark:border-slate-700; @apply relative py-0 px-4 -mt-px;
textarea { textarea {
@apply shadow-none border-transparent bg-transparent m-0 max-h-60 min-h-[3rem] pt-4 pb-0 px-0 resize-none; @apply shadow-none border-transparent bg-transparent m-0 max-h-60 min-h-[3rem] pt-4 pb-0 px-0 resize-none;

View File

@@ -89,11 +89,11 @@ export default {
<label class="input-group-label"> <label class="input-group-label">
{{ $t('CONVERSATION.REPLYBOX.EMAIL_HEAD.TO') }} {{ $t('CONVERSATION.REPLYBOX.EMAIL_HEAD.TO') }}
</label> </label>
<div class="rounded-none flex-1 min-w-0 m-0 whitespace-nowrap"> <div class="flex-1 min-w-0 m-0 rounded-none whitespace-nowrap">
<woot-input <woot-input
v-model="v$.toEmailsVal.$model" v-model="v$.toEmailsVal.$model"
type="text" type="text"
class="[&>input]:!mb-0 [&>input]:border-transparent [&>input]:h-8 [&>input]:text-sm [&>input]:!border-0 [&>input]:border-none" class="[&>input]:!mb-0 [&>input]:border-transparent [&>input]:h-8 [&>input]:text-sm [&>input]:!border-0 [&>input]:border-none [&>input]:!bg-transparent dark:[&>input]:!bg-transparent"
:class="{ error: v$.toEmailsVal.$error }" :class="{ error: v$.toEmailsVal.$error }"
:placeholder="$t('CONVERSATION.REPLYBOX.EMAIL_HEAD.CC.PLACEHOLDER')" :placeholder="$t('CONVERSATION.REPLYBOX.EMAIL_HEAD.CC.PLACEHOLDER')"
@blur="onBlur" @blur="onBlur"
@@ -106,10 +106,10 @@ export default {
<label class="input-group-label"> <label class="input-group-label">
{{ $t('CONVERSATION.REPLYBOX.EMAIL_HEAD.CC.LABEL') }} {{ $t('CONVERSATION.REPLYBOX.EMAIL_HEAD.CC.LABEL') }}
</label> </label>
<div class="rounded-none flex-1 min-w-0 m-0 whitespace-nowrap"> <div class="flex-1 min-w-0 m-0 rounded-none whitespace-nowrap">
<woot-input <woot-input
v-model="v$.ccEmailsVal.$model" v-model="v$.ccEmailsVal.$model"
class="[&>input]:!mb-0 [&>input]:border-transparent [&>input]:h-8 [&>input]:text-sm [&>input]:!border-0 [&>input]:border-none" class="[&>input]:!mb-0 [&>input]:border-transparent [&>input]:h-8 [&>input]:text-sm [&>input]:!border-0 [&>input]:border-none [&>input]:!bg-transparent dark:[&>input]:!bg-transparent"
type="text" type="text"
:class="{ error: v$.ccEmailsVal.$error }" :class="{ error: v$.ccEmailsVal.$error }"
:placeholder="$t('CONVERSATION.REPLYBOX.EMAIL_HEAD.CC.PLACEHOLDER')" :placeholder="$t('CONVERSATION.REPLYBOX.EMAIL_HEAD.CC.PLACEHOLDER')"
@@ -134,11 +134,11 @@ export default {
<label class="input-group-label"> <label class="input-group-label">
{{ $t('CONVERSATION.REPLYBOX.EMAIL_HEAD.BCC.LABEL') }} {{ $t('CONVERSATION.REPLYBOX.EMAIL_HEAD.BCC.LABEL') }}
</label> </label>
<div class="rounded-none flex-1 min-w-0 m-0 whitespace-nowrap"> <div class="flex-1 min-w-0 m-0 rounded-none whitespace-nowrap">
<woot-input <woot-input
v-model="v$.bccEmailsVal.$model" v-model="v$.bccEmailsVal.$model"
type="text" type="text"
class="[&>input]:!mb-0 [&>input]:border-transparent [&>input]:h-8 [&>input]:text-sm [&>input]:!border-0 [&>input]:border-none" class="[&>input]:!mb-0 [&>input]:border-transparent [&>input]:h-8 [&>input]:text-sm [&>input]:!border-0 [&>input]:border-none [&>input]:!bg-transparent dark:[&>input]:!bg-transparent"
:class="{ error: v$.bccEmailsVal.$error }" :class="{ error: v$.bccEmailsVal.$error }"
:placeholder=" :placeholder="
$t('CONVERSATION.REPLYBOX.EMAIL_HEAD.BCC.PLACEHOLDER') $t('CONVERSATION.REPLYBOX.EMAIL_HEAD.BCC.PLACEHOLDER')

View File

@@ -39,6 +39,7 @@
"@formkit/vue": "^1.6.7", "@formkit/vue": "^1.6.7",
"@hcaptcha/vue3-hcaptcha": "^1.3.0", "@hcaptcha/vue3-hcaptcha": "^1.3.0",
"@highlightjs/vue-plugin": "^2.1.0", "@highlightjs/vue-plugin": "^2.1.0",
"@iconify-json/material-symbols": "^1.2.10",
"@june-so/analytics-next": "^2.0.0", "@june-so/analytics-next": "^2.0.0",
"@lk77/vue3-color": "^3.0.6", "@lk77/vue3-color": "^3.0.6",
"@radix-ui/colors": "^3.0.0", "@radix-ui/colors": "^3.0.0",

10
pnpm-lock.yaml generated
View File

@@ -40,6 +40,9 @@ importers:
'@highlightjs/vue-plugin': '@highlightjs/vue-plugin':
specifier: ^2.1.0 specifier: ^2.1.0
version: 2.1.0(highlight.js@11.10.0)(vue@3.5.12(typescript@5.6.2)) version: 2.1.0(highlight.js@11.10.0)(vue@3.5.12(typescript@5.6.2))
'@iconify-json/material-symbols':
specifier: ^1.2.10
version: 1.2.10
'@june-so/analytics-next': '@june-so/analytics-next':
specifier: ^2.0.0 specifier: ^2.0.0
version: 2.0.0 version: 2.0.0
@@ -890,6 +893,9 @@ packages:
'@iconify-json/lucide@1.2.11': '@iconify-json/lucide@1.2.11':
resolution: {integrity: sha512-dqpbV7+g1qqxtZOHCZKwdKhtYYqEUjFhYiOg/+PcADbjtapoL+bwa1Brn12gAHq5r2K7Mf29xRHOTmZ3UHHOrw==} resolution: {integrity: sha512-dqpbV7+g1qqxtZOHCZKwdKhtYYqEUjFhYiOg/+PcADbjtapoL+bwa1Brn12gAHq5r2K7Mf29xRHOTmZ3UHHOrw==}
'@iconify-json/material-symbols@1.2.10':
resolution: {integrity: sha512-GcZxhOFStM7Dk/oZvJSaW0tR/k6NwTq+KDzYgCNBDg52ktZuRa/gkjRiYooJm/8PAe9NBYxIx8XjS/wi4sasdQ==}
'@iconify-json/ph@1.2.1': '@iconify-json/ph@1.2.1':
resolution: {integrity: sha512-x0DNfwWrS18dbsBYOq3XGiZnGz4CgRyC+YSl/TZvMQiKhIUl1woWqUbMYqqfMNUBzjyk7ulvaRovpRsIlqIf8g==} resolution: {integrity: sha512-x0DNfwWrS18dbsBYOq3XGiZnGz4CgRyC+YSl/TZvMQiKhIUl1woWqUbMYqqfMNUBzjyk7ulvaRovpRsIlqIf8g==}
@@ -5784,6 +5790,10 @@ snapshots:
dependencies: dependencies:
'@iconify/types': 2.0.0 '@iconify/types': 2.0.0
'@iconify-json/material-symbols@1.2.10':
dependencies:
'@iconify/types': 2.0.0
'@iconify-json/ph@1.2.1': '@iconify-json/ph@1.2.1':
dependencies: dependencies:
'@iconify/types': 2.0.0 '@iconify/types': 2.0.0

View File

@@ -227,7 +227,14 @@ const tailwindConfig = {
iconsPlugin({ iconsPlugin({
collections: { collections: {
woot: { icons }, woot: { icons },
...getIconCollections(['lucide', 'logos', 'ri', 'ph', 'teenyicons']), ...getIconCollections([
'lucide',
'logos',
'ri',
'ph',
'material-symbols',
'teenyicons',
]),
}, },
}), }),
], ],