chore: Update buttons in conversation screens(#11132)

# Pull Request Template

### Changes includes
* Update send message and add note button
<img width="151" alt="image"
src="https://github.com/user-attachments/assets/646d1d22-07be-4f2f-9090-6642556aa761"
/>
<img width="151" alt="image"
src="https://github.com/user-attachments/assets/b5651420-c48b-4932-aff9-911788b9eabc"
/>
<img width="165" alt="image"
src="https://github.com/user-attachments/assets/f1ace171-2115-4eba-9055-e568d1b73c5e"
/>
<img width="165" alt="image"
src="https://github.com/user-attachments/assets/0c818461-ccdb-46ab-b7d3-3917e4ee4e74"
/>
<img width="165" alt="image"
src="https://github.com/user-attachments/assets/eef1545b-1bed-47a1-8b83-ed5d5da3f24f"
/>
<img width="165" alt="image"
src="https://github.com/user-attachments/assets/429de6e6-1263-4216-9222-4eaece95da81"
/>
<img width="165" alt="image"
src="https://github.com/user-attachments/assets/59a69867-4da1-4695-b88c-329142a693a8"
/>
<img width="165" alt="image"
src="https://github.com/user-attachments/assets/7114745c-836f-4c5a-b5d6-e200e1343a73"
/>

* Remove Unused component `AnnouncementPopup.vue`
* Updated button for custom attributes in conversation sidebar.
<img width="225" alt="image"
src="https://github.com/user-attachments/assets/a71f6c31-aca9-4e1b-bf63-6b9d5ed183c8"
/>
<img width="310" alt="image"
src="https://github.com/user-attachments/assets/8d847e1b-4a13-4108-a487-ce3d36257afa"
/>

* Update button in custom snooze modal buttons
<img width="207" alt="image"
src="https://github.com/user-attachments/assets/78315ce6-9734-467b-a4d3-e753d3eca384"
/>

* Update modal component close button
<img width="80" alt="image"
src="https://github.com/user-attachments/assets/643e9ef0-b781-47ce-a66b-a9ee4760c952"
/>

* Update AI assistant modal and AICTA modal
<img width="319" alt="image"
src="https://github.com/user-attachments/assets/8d0986ec-ec7a-4abb-9327-f73df8b4d942"
/>
<img width="565" alt="image"
src="https://github.com/user-attachments/assets/1e02ddd1-7f51-4d8a-bb57-558b9a50c938"
/>

* Update remove attachment button
<img width="301" alt="image"
src="https://github.com/user-attachments/assets/90c93eee-0b4d-4839-9db5-edc4b023df4b"
/>

* Update the conversation header buttons
<img width="256" alt="image"
src="https://github.com/user-attachments/assets/abac5d7e-dd83-40ae-b548-76bbafaa2231"
/>

* Update the retry button in old message bubbles.

---------

Co-authored-by: Pranav <pranav@chatwoot.com>
This commit is contained in:
Sivin Varghese
2025-03-21 14:47:28 +05:30
committed by GitHub
parent 5745ffbcb0
commit 280bc58963
12 changed files with 145 additions and 179 deletions

View File

@@ -9,12 +9,15 @@ import { getRegexp } from 'shared/helpers/Validators';
import { useVuelidate } from '@vuelidate/core'; import { useVuelidate } from '@vuelidate/core';
import { emitter } from 'shared/helpers/mitt'; import { emitter } from 'shared/helpers/mitt';
import NextButton from 'dashboard/components-next/button/Button.vue';
const DATE_FORMAT = 'yyyy-MM-dd'; const DATE_FORMAT = 'yyyy-MM-dd';
export default { export default {
components: { components: {
MultiselectDropdown, MultiselectDropdown,
HelperTextPopup, HelperTextPopup,
NextButton,
}, },
props: { props: {
label: { type: String, required: true }, label: { type: String, required: true },
@@ -219,14 +222,13 @@ export default {
class="mt-0.5" class="mt-0.5"
/> />
</span> </span>
<woot-button <NextButton
v-if="showActions && value" v-if="showActions && value"
v-tooltip.left="$t('CUSTOM_ATTRIBUTES.ACTIONS.DELETE')" v-tooltip.left="$t('CUSTOM_ATTRIBUTES.ACTIONS.DELETE')"
variant="link" slate
size="medium" sm
color-scheme="secondary" link
icon="delete" icon="i-lucide-trash-2"
class-names="flex justify-end !w-fit"
@click="onDelete" @click="onDelete"
/> />
</div> </div>
@@ -246,10 +248,10 @@ export default {
@keyup.enter="onUpdate" @keyup.enter="onUpdate"
/> />
<div> <div>
<woot-button <NextButton
size="small" sm
icon="checkmark" icon="i-lucide-check"
class="ltr:rounded-l-none rtl:rounded-r-none" class="ltr:rounded-l-none rtl:rounded-r-none h-[34px]"
@click="onUpdate" @click="onUpdate"
/> />
</div> </div>
@@ -281,25 +283,27 @@ export default {
> >
{{ displayValue || '---' }} {{ displayValue || '---' }}
</p> </p>
<div class="flex max-w-[2rem] gap-1 ml-1 rtl:mr-1 rtl:ml-0"> <div
<woot-button class="flex items-center max-w-[2rem] gap-1 ml-1 rtl:mr-1 rtl:ml-0"
>
<NextButton
v-if="showActions && value" v-if="showActions && value"
v-tooltip="$t('CUSTOM_ATTRIBUTES.ACTIONS.COPY')" v-tooltip="$t('CUSTOM_ATTRIBUTES.ACTIONS.COPY')"
variant="link" xs
size="small" slate
color-scheme="secondary" ghost
icon="clipboard" icon="i-lucide-clipboard"
class-names="hidden group-hover:flex !w-6 flex-shrink-0" class="hidden group-hover:flex flex-shrink-0"
@click="onCopy" @click="onCopy"
/> />
<woot-button <NextButton
v-if="showActions" v-if="showActions"
v-tooltip.right="$t('CUSTOM_ATTRIBUTES.ACTIONS.EDIT')" v-tooltip.right="$t('CUSTOM_ATTRIBUTES.ACTIONS.EDIT')"
variant="link" xs
size="small" slate
color-scheme="secondary" ghost
icon="edit" icon="i-lucide-pen"
class-names="hidden group-hover:flex !w-6 flex-shrink-0" class="hidden group-hover:flex flex-shrink-0"
@click="onEdit" @click="onEdit"
/> />
</div> </div>

View File

@@ -1,9 +1,11 @@
<script> <script>
import DatePicker from 'vue-datepicker-next'; import DatePicker from 'vue-datepicker-next';
import NextButton from 'dashboard/components-next/button/Button.vue';
export default { export default {
components: { components: {
DatePicker, DatePicker,
NextButton,
}, },
emits: ['close', 'chooseTime'], emits: ['close', 'chooseTime'],
@@ -52,18 +54,23 @@ export default {
v-model:value="snoozeTime" v-model:value="snoozeTime"
type="datetime" type="datetime"
inline inline
input-class="mx-input reset-base" input-class="mx-input "
:lang="lang" :lang="lang"
:disabled-date="disabledDate" :disabled-date="disabledDate"
:disabled-time="disabledTime" :disabled-time="disabledTime"
/> />
<div class="flex flex-row justify-end w-full gap-2 px-0 py-2"> <div class="flex flex-row justify-end w-full gap-2 px-0 py-2">
<woot-button variant="clear" @click.prevent="onClose"> <NextButton
{{ $t('CONVERSATION.CUSTOM_SNOOZE.CANCEL') }} faded
</woot-button> slate
<woot-button> type="reset"
{{ $t('CONVERSATION.CUSTOM_SNOOZE.APPLY') }} :label="$t('CONVERSATION.CUSTOM_SNOOZE.CANCEL')"
</woot-button> @click.prevent="onClose"
/>
<NextButton
type="submit"
:label="$t('CONVERSATION.CUSTOM_SNOOZE.APPLY')"
/>
</div> </div>
</form> </form>
</div> </div>

View File

@@ -2,6 +2,7 @@
// [TODO] Use Teleport to move the modal to the end of the body // [TODO] Use Teleport to move the modal to the end of the body
import { ref, computed, defineEmits, onMounted } from 'vue'; import { ref, computed, defineEmits, onMounted } from 'vue';
import { useEventListener } from '@vueuse/core'; import { useEventListener } from '@vueuse/core';
import Button from 'dashboard/components-next/button/Button.vue';
const { modalType, closeOnBackdropClick, onClose } = defineProps({ const { modalType, closeOnBackdropClick, onClose } = defineProps({
closeOnBackdropClick: { type: Boolean, default: true }, closeOnBackdropClick: { type: Boolean, default: true },
@@ -85,11 +86,11 @@ onMounted(() => {
@mouse.stop @mouse.stop
@mousedown="event => event.stopPropagation()" @mousedown="event => event.stopPropagation()"
> >
<woot-button <Button
v-if="showCloseButton" v-if="showCloseButton"
color-scheme="secondary" ghost
icon="dismiss" slate
variant="clear" icon="i-lucide-x"
class="absolute z-10 ltr:right-2 rtl:left-2 top-2" class="absolute z-10 ltr:right-2 rtl:left-2 top-2"
@click="close" @click="close"
/> />

View File

@@ -1,90 +0,0 @@
<script>
export default {
props: {
popupMessage: {
type: String,
default: '',
},
routeText: {
type: String,
default: '',
},
hasCloseButton: {
type: Boolean,
default: true,
},
closeButtonText: {
type: String,
default: '',
},
},
emits: ['open', 'close'],
methods: {
onClickOpenPath() {
this.$emit('open');
},
onClickClose(e) {
this.$emit('close', e);
},
},
};
</script>
<template>
<div class="announcement-popup">
<span v-if="popupMessage" class="popup-content">
{{ popupMessage }}
<span v-if="routeText" class="route-url" @click="onClickOpenPath">
{{ routeText }}
</span>
</span>
<div v-if="hasCloseButton" class="popup-close">
<woot-button
v-if="hasCloseButton"
color-scheme="primary"
variant="link"
size="small"
@click="onClickClose"
>
{{ closeButtonText }}
</woot-button>
</div>
</div>
</template>
<style lang="scss">
.announcement-popup {
max-width: 15rem;
min-width: 10rem;
display: flex;
position: absolute;
flex-direction: column;
align-items: flex-start;
height: fit-content;
background: var(--white);
padding: 0 var(--space-normal);
z-index: var(--z-index-much-higher);
box-shadow: var(--b-200) 4px 4px 16px 4px;
border-radius: var(--border-radius-normal);
.popup-content {
font-size: var(--font-size-mini);
color: var(--s-700);
padding: var(--space-one) 0;
.route-url {
font-size: var(--font-size-mini);
color: var(--s-600);
cursor: pointer;
text-decoration: underline;
}
}
.popup-close {
width: 100%;
display: flex;
align-items: center;
padding: var(--space-one) 0;
border-top: 1px solid var(--color-border-light);
}
}
</style>

View File

@@ -2,10 +2,12 @@
import { useMessageFormatter } from 'shared/composables/useMessageFormatter'; import { useMessageFormatter } from 'shared/composables/useMessageFormatter';
import { useAI } from 'dashboard/composables/useAI'; import { useAI } from 'dashboard/composables/useAI';
import AILoader from './AILoader.vue'; import AILoader from './AILoader.vue';
import NextButton from 'dashboard/components-next/button/Button.vue';
export default { export default {
components: { components: {
AILoader, AILoader,
NextButton,
}, },
props: { props: {
aiOption: { aiOption: {
@@ -84,16 +86,22 @@ export default {
</div> </div>
<div class="flex flex-row justify-end w-full gap-2 px-0 py-2"> <div class="flex flex-row justify-end w-full gap-2 px-0 py-2">
<woot-button variant="clear" @click.prevent="onClose"> <NextButton
{{ faded
slate
type="reset"
:label="
$t('INTEGRATION_SETTINGS.OPEN_AI.ASSISTANCE_MODAL.BUTTONS.CANCEL') $t('INTEGRATION_SETTINGS.OPEN_AI.ASSISTANCE_MODAL.BUTTONS.CANCEL')
}} "
</woot-button> @click.prevent="onClose"
<woot-button :disabled="!generatedContent"> />
{{ <NextButton
type="submit"
:disabled="!generatedContent"
:label="
$t('INTEGRATION_SETTINGS.OPEN_AI.ASSISTANCE_MODAL.BUTTONS.APPLY') $t('INTEGRATION_SETTINGS.OPEN_AI.ASSISTANCE_MODAL.BUTTONS.APPLY')
}} "
</woot-button> />
</div> </div>
</form> </form>
</div> </div>

View File

@@ -6,7 +6,12 @@ import { useUISettings } from 'dashboard/composables/useUISettings';
import { useAI } from 'dashboard/composables/useAI'; import { useAI } from 'dashboard/composables/useAI';
import { OPEN_AI_EVENTS } from 'dashboard/helper/AnalyticsHelper/events'; import { OPEN_AI_EVENTS } from 'dashboard/helper/AnalyticsHelper/events';
import NextButton from 'dashboard/components-next/button/Button.vue';
export default { export default {
components: {
NextButton,
},
emits: ['close'], emits: ['close'],
setup() { setup() {
@@ -94,16 +99,30 @@ export default {
/> />
</div> </div>
<div class="flex flex-row justify-between w-full gap-2 px-0 py-2"> <div class="flex flex-row justify-between w-full gap-2 px-0 py-2">
<woot-button variant="link" @click.prevent="openOpenAIDoc"> <NextButton
{{ $t('INTEGRATION_SETTINGS.OPEN_AI.CTA_MODAL.BUTTONS.NEED_HELP') }} ghost
</woot-button> type="button"
class="!px-3"
:label="
$t('INTEGRATION_SETTINGS.OPEN_AI.CTA_MODAL.BUTTONS.NEED_HELP')
"
@click.prevent="openOpenAIDoc"
/>
<div class="flex items-center gap-1"> <div class="flex items-center gap-1">
<woot-button variant="clear" @click.prevent="onDismiss"> <NextButton
{{ $t('INTEGRATION_SETTINGS.OPEN_AI.CTA_MODAL.BUTTONS.DISMISS') }} faded
</woot-button> slate
<woot-button :is-disabled="v$.value.$invalid"> type="reset"
{{ $t('INTEGRATION_SETTINGS.OPEN_AI.CTA_MODAL.BUTTONS.FINISH') }} :label="
</woot-button> $t('INTEGRATION_SETTINGS.OPEN_AI.CTA_MODAL.BUTTONS.DISMISS')
"
@click.prevent="onDismiss"
/>
<NextButton
type="submit"
:disabled="v$.value.$invalid"
:label="$t('INTEGRATION_SETTINGS.OPEN_AI.CTA_MODAL.BUTTONS.FINISH')"
/>
</div> </div>
</div> </div>
</form> </form>

View File

@@ -2,6 +2,8 @@
import { computed } from 'vue'; import { computed } from 'vue';
import { formatBytes } from 'shared/helpers/FileHelper'; import { formatBytes } from 'shared/helpers/FileHelper';
import Button from 'dashboard/components-next/button/Button.vue';
const props = defineProps({ const props = defineProps({
attachments: { attachments: {
type: Array, type: Array,
@@ -73,9 +75,11 @@ const fileName = file => {
</span> </span>
</div> </div>
<div class="flex items-center justify-center"> <div class="flex items-center justify-center">
<woot-button <Button
class="!w-6 !h-6 text-sm rounded-md hover:bg-slate-50 dark:hover:bg-slate-800 clear secondary" ghost
icon="dismiss" slate
xs
icon="i-lucide-x"
@click="onRemoveAttachment(index)" @click="onRemoveAttachment(index)"
/> />
</div> </div>

View File

@@ -2,11 +2,14 @@
import AutomationActionTeamMessageInput from './AutomationActionTeamMessageInput.vue'; import AutomationActionTeamMessageInput from './AutomationActionTeamMessageInput.vue';
import AutomationActionFileInput from './AutomationFileInput.vue'; import AutomationActionFileInput from './AutomationFileInput.vue';
import WootMessageEditor from 'dashboard/components/widgets/WootWriter/Editor.vue'; import WootMessageEditor from 'dashboard/components/widgets/WootWriter/Editor.vue';
import NextButton from 'dashboard/components-next/button/Button.vue';
export default { export default {
components: { components: {
AutomationActionTeamMessageInput, AutomationActionTeamMessageInput,
AutomationActionFileInput, AutomationActionFileInput,
WootMessageEditor, WootMessageEditor,
NextButton,
}, },
props: { props: {
modelValue: { modelValue: {
@@ -172,11 +175,11 @@ export default {
/> />
</div> </div>
</div> </div>
<woot-button <NextButton
v-if="!isMacro" v-if="!isMacro"
icon="dismiss" icon="i-lucide-x"
variant="clear" slate
color-scheme="secondary" ghost
class="flex-shrink-0" class="flex-shrink-0"
@click="removeAction" @click="removeAction"
/> />

View File

@@ -247,7 +247,13 @@ export default {
:placeholder="$t('FILTER.INPUT_PLACEHOLDER')" :placeholder="$t('FILTER.INPUT_PLACEHOLDER')"
/> />
</div> </div>
<NextButton icon="i-lucide-x" slate ghost @click="removeFilter" /> <NextButton
icon="i-lucide-x"
slate
ghost
class="flex-shrink-0"
@click="removeFilter"
/>
</div> </div>
<p v-if="errorMessage" class="filter-error"> <p v-if="errorMessage" class="filter-error">
{{ errorMessage }} {{ errorMessage }}

View File

@@ -164,11 +164,6 @@ export default {
'is-note-mode': this.isNote, 'is-note-mode': this.isNote,
}; };
}, },
buttonClass() {
return {
warning: this.isNote,
};
},
showAttachButton() { showAttachButton() {
return this.showFileUpload || this.isNote; return this.showFileUpload || this.isNote;
}, },
@@ -367,14 +362,15 @@ export default {
/> />
</div> </div>
<div class="right-wrap"> <div class="right-wrap">
<woot-button <NextButton
size="small" :label="sendButtonText"
:class-names="buttonClass" type="submit"
:is-disabled="isSendDisabled" sm
:color="isNote ? 'amber' : 'blue'"
:disabled="isSendDisabled"
class="flex-shrink-0"
@click="onSend" @click="onSend"
> />
{{ sendButtonText }}
</woot-button>
</div> </div>
</div> </div>
</template> </template>

View File

@@ -13,6 +13,8 @@ import { snoozedReopenTime } from 'dashboard/helper/snoozeHelpers';
import { FEATURE_FLAGS } from 'dashboard/featureFlags'; import { FEATURE_FLAGS } from 'dashboard/featureFlags';
import Linear from './linear/index.vue'; import Linear from './linear/index.vue';
import NextButton from 'dashboard/components-next/button/Button.vue';
export default { export default {
components: { components: {
BackButton, BackButton,
@@ -21,6 +23,7 @@ export default {
Thumbnail, Thumbnail,
SLACardLabel, SLACardLabel,
Linear, Linear,
NextButton,
}, },
mixins: [inboxMixin], mixins: [inboxMixin],
props: { props: {
@@ -154,16 +157,18 @@ export default {
<div <div
class="flex flex-row items-center max-w-full gap-1 p-0 m-0 w-fit" class="flex flex-row items-center max-w-full gap-1 p-0 m-0 w-fit"
> >
<woot-button <NextButton
variant="link" link
color-scheme="secondary" slate
class="[&>span]:overflow-hidden [&>span]:whitespace-nowrap [&>span]:text-ellipsis min-w-0" class="!underline-offset-1"
@click.prevent="$emit('contactPanelToggle')" @click.prevent="$emit('contactPanelToggle')"
> >
<span class="text-base font-medium leading-tight text-n-slate-12"> <span
class="text-base font-medium truncate leading-tight text-n-slate-12"
>
{{ currentContact.name }} {{ currentContact.name }}
</span> </span>
</woot-button> </NextButton>
<fluent-icon <fluent-icon
v-if="!isHMACVerified" v-if="!isHMACVerified"
v-tooltip="$t('CONVERSATION.UNVERIFIED_SESSION')" v-tooltip="$t('CONVERSATION.UNVERIFIED_SESSION')"
@@ -180,14 +185,14 @@ export default {
<span v-if="isSnoozed" class="font-medium text-n-amber-10"> <span v-if="isSnoozed" class="font-medium text-n-amber-10">
{{ snoozedDisplayText }} {{ snoozedDisplayText }}
</span> </span>
<woot-button <NextButton
class="p-0" link
size="small" xs
variant="link" blue
:label="contactPanelToggleText"
class="!underline-offset-1"
@click="$emit('contactPanelToggle')" @click="$emit('contactPanelToggle')"
> />
{{ contactPanelToggleText }}
</woot-button>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -25,6 +25,8 @@ import * as Sentry from '@sentry/vue';
import { useTrack } from 'dashboard/composables'; import { useTrack } from 'dashboard/composables';
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: {
BubbleActions, BubbleActions,
@@ -40,6 +42,7 @@ export default {
InstagramStory, InstagramStory,
InstagramStoryReply, InstagramStoryReply,
Spinner, Spinner,
NextButton,
}, },
props: { props: {
data: { data: {
@@ -452,12 +455,12 @@ export default {
v-if="isFailed && !hasOneDayPassed && !isAnEmailInbox" v-if="isFailed && !hasOneDayPassed && !isAnEmailInbox"
class="message-failed--alert" class="message-failed--alert"
> >
<woot-button <NextButton
v-tooltip.top-end="$t('CONVERSATION.TRY_AGAIN')" v-tooltip.top-end="$t('CONVERSATION.TRY_AGAIN')"
size="tiny" ghost
color-scheme="alert" xs
variant="clear" ruby
icon="arrow-clockwise" icon="i-lucide-refresh-ccw"
@click="retrySendMessage" @click="retrySendMessage"
/> />
</div> </div>