chore: Update buttons in conversation screens - 2 (#11134)

This commit is contained in:
Sivin Varghese 2025-03-21 21:54:54 +05:30 committed by GitHub
parent 280bc58963
commit e4ea078e52
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
25 changed files with 363 additions and 471 deletions

View File

@ -190,7 +190,7 @@ const STYLE_CONFIG = {
const variantClasses = computed(() => { const variantClasses = computed(() => {
const variantMap = { const variantMap = {
ghost: `${STYLE_CONFIG.colors[computedColor.value].ghost}`, ghost: `${STYLE_CONFIG.colors[computedColor.value].ghost}`,
link: `${STYLE_CONFIG.colors[computedColor.value].link} p-0 font-medium underline-offset-4`, link: `${STYLE_CONFIG.colors[computedColor.value].link} p-0 font-medium underline-offset-2`,
outline: STYLE_CONFIG.colors[computedColor.value].outline, outline: STYLE_CONFIG.colors[computedColor.value].outline,
faded: STYLE_CONFIG.colors[computedColor.value].faded, faded: STYLE_CONFIG.colors[computedColor.value].faded,
solid: STYLE_CONFIG.colors[computedColor.value].solid, solid: STYLE_CONFIG.colors[computedColor.value].solid,

View File

@ -11,6 +11,8 @@ import {
} from 'dashboard/helper/routeHelpers'; } from 'dashboard/helper/routeHelpers';
import { useEventListener } from '@vueuse/core'; import { useEventListener } from '@vueuse/core';
import Button from 'dashboard/components-next/button/Button.vue';
const { t } = useI18n(); const { t } = useI18n();
const route = useRoute(); const route = useRoute();
@ -107,34 +109,31 @@ onBeforeUnmount(() => {
<template> <template>
<transition name="network-notification-fade" tag="div"> <transition name="network-notification-fade" tag="div">
<div v-show="showNotification" class="fixed z-50 top-4 left-2 group"> <div v-show="showNotification" class="fixed z-50 top-2 left-2 group">
<div <div
class="relative flex items-center justify-between w-full px-2 py-1 bg-yellow-200 rounded-lg shadow-lg dark:bg-yellow-700" class="relative flex items-center justify-between w-full px-2 py-1 bg-n-amber-4 dark:bg-n-amber-8 rounded-lg shadow-lg"
> >
<fluent-icon <fluent-icon :icon="iconName" class="text-n-amber-12" size="18" />
:icon="iconName" <span class="px-2 text-xs font-medium tracking-wide text-n-amber-12">
class="text-yellow-700/50 dark:text-yellow-50"
size="18"
/>
<span
class="px-2 text-xs font-medium tracking-wide text-yellow-700/70 dark:text-yellow-50"
>
{{ bannerText }} {{ bannerText }}
</span> </span>
<woot-button <Button
v-if="canRefresh" v-if="canRefresh"
ghost
sm
amber
icon="i-lucide-refresh-ccw"
:title="$t('NETWORK.BUTTON.REFRESH')" :title="$t('NETWORK.BUTTON.REFRESH')"
variant="clear" class="!text-n-amber-12 dark:!text-n-amber-9"
size="small"
color-scheme="warning"
icon="arrow-clockwise"
@click="refreshPage" @click="refreshPage"
/> />
<woot-button
variant="clear" <Button
size="small" ghost
color-scheme="warning" sm
icon="dismiss" amber
icon="i-lucide-x"
class="!text-n-amber-12 dark:!text-n-amber-9"
@click="closeNotification" @click="closeNotification"
/> />
</div> </div>

View File

@ -157,12 +157,7 @@ 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"
> >
<NextButton <NextButton link slate @click.prevent="$emit('contactPanelToggle')">
link
slate
class="!underline-offset-1"
@click.prevent="$emit('contactPanelToggle')"
>
<span <span
class="text-base font-medium truncate leading-tight text-n-slate-12" class="text-base font-medium truncate leading-tight text-n-slate-12"
> >
@ -190,7 +185,6 @@ export default {
xs xs
blue blue
:label="contactPanelToggleText" :label="contactPanelToggleText"
class="!underline-offset-1"
@click="$emit('contactPanelToggle')" @click="$emit('contactPanelToggle')"
/> />
</div> </div>

View File

@ -1,10 +1,11 @@
<script> <script setup>
export default { import { useRouter } from 'vue-router';
methods: { import Button from 'dashboard/components-next/button/Button.vue';
openProfileSettings() {
return this.$router.push({ name: 'profile_settings_index' }); const router = useRouter();
},
}, const openProfileSettings = () => {
return router.push({ name: 'profile_settings_index' });
}; };
</script> </script>
@ -14,13 +15,12 @@ export default {
> >
<p class="w-fit !m-0"> <p class="w-fit !m-0">
{{ $t('CONVERSATION.FOOTER.MESSAGE_SIGNATURE_NOT_CONFIGURED') }} {{ $t('CONVERSATION.FOOTER.MESSAGE_SIGNATURE_NOT_CONFIGURED') }}
<woot-button
color-scheme="primary" <Button
variant="link" link
:label="$t('CONVERSATION.FOOTER.CLICK_HERE')"
@click="openProfileSettings" @click="openProfileSettings"
> />
{{ $t('CONVERSATION.FOOTER.CLICK_HERE') }}
</woot-button>
</p> </p>
</div> </div>
</template> </template>

View File

@ -37,6 +37,8 @@ import wootConstants from 'dashboard/constants/globals';
import { LOCAL_STORAGE_KEYS } from 'dashboard/constants/localStorage'; import { LOCAL_STORAGE_KEYS } from 'dashboard/constants/localStorage';
import { FEATURE_FLAGS } from '../../../featureFlags'; import { FEATURE_FLAGS } from '../../../featureFlags';
import NextButton from 'dashboard/components-next/button/Button.vue';
export default { export default {
components: { components: {
Message, Message,
@ -44,6 +46,7 @@ export default {
ReplyBox, ReplyBox,
Banner, Banner,
ConversationLabelSuggestion, ConversationLabelSuggestion,
NextButton,
}, },
mixins: [inboxMixin], mixins: [inboxMixin],
props: { props: {
@ -488,13 +491,15 @@ export default {
:href-link-text="replyWindowLinkText" :href-link-text="replyWindowLinkText"
/> />
<div class="flex justify-end"> <div class="flex justify-end">
<woot-button <NextButton
variant="smooth" faded
size="tiny" xs
color-scheme="secondary" slate
class="box-border fixed z-10 bg-white border border-r-0 border-solid rounded-bl-calc rtl:rotate-180 rounded-tl-calc border-n-weak" class="!rounded-r-none rtl:rotate-180 !rounded-2xl !fixed z-10"
:icon="
isContactPanelOpen ? 'i-ph-caret-right-fill' : 'i-ph-caret-left-fill'
"
:class="isInboxView ? 'top-52 md:top-40' : 'top-32'" :class="isInboxView ? 'top-52 md:top-40' : 'top-32'"
:icon="isRightOrLeftIcon"
@click="onToggleContactPanel" @click="onToggleContactPanel"
/> />
</div> </div>
@ -614,20 +619,6 @@ export default {
</div> </div>
</template> </template>
<style scoped>
@tailwind components;
@layer components {
.rounded-bl-calc {
border-bottom-left-radius: calc(1.5rem + 1px);
}
.rounded-tl-calc {
border-top-left-radius: calc(1.5rem + 1px);
}
}
</style>
<style scoped lang="scss"> <style scoped lang="scss">
.modal-mask { .modal-mask {
@apply absolute; @apply absolute;

View File

@ -1,21 +1,20 @@
<script> <script setup>
import MessagePreview from 'dashboard/components/widgets/conversation/MessagePreview.vue'; import MessagePreview from 'dashboard/components/widgets/conversation/MessagePreview.vue';
import Button from 'dashboard/components-next/button/Button.vue';
export default { defineProps({
components: { MessagePreview }, message: {
props: { type: Object,
message: { required: true,
type: Object,
required: true,
},
}, },
emits: ['dismiss'], });
};
const emit = defineEmits(['dismiss']);
</script> </script>
<template> <template>
<div <div
class="reply-editor bg-slate-50 dark:bg-slate-800 rounded-md py-1 pl-2 pr-1 text-xs tracking-wide mt-2 flex items-center gap-1.5 -mx-2" class="reply-editor bg-n-slate-9/10 rounded-md py-1 pl-2 pr-1 text-xs tracking-wide mt-2 flex items-center gap-1.5 -mx-2"
> >
<fluent-icon class="flex-shrink-0 icon" icon="arrow-reply" size="14" /> <fluent-icon class="flex-shrink-0 icon" icon="arrow-reply" size="14" />
<div class="flex-grow gap-1 mt-px text-xs truncate"> <div class="flex-grow gap-1 mt-px text-xs truncate">
@ -27,14 +26,13 @@ export default {
class="inline" class="inline"
/> />
</div> </div>
<woot-button <Button
v-tooltip="$t('CONVERSATION.REPLYBOX.DISMISS_REPLY')" v-tooltip="$t('CONVERSATION.REPLYBOX.DISMISS_REPLY')"
color-scheme="secondary" ghost
icon="dismiss" xs
variant="clear" slate
size="tiny" icon="i-lucide-x"
class="flex-shrink-0" @click.stop="emit('dismiss')"
@click.stop="$emit('dismiss')"
/> />
</div> </div>
</template> </template>

View File

@ -12,7 +12,12 @@ import { ref, computed, onMounted } from 'vue';
import { useVuelidate } from '@vuelidate/core'; import { useVuelidate } from '@vuelidate/core';
import { requiredIf } from '@vuelidate/validators'; import { requiredIf } from '@vuelidate/validators';
import NextButton from 'dashboard/components-next/button/Button.vue';
export default { export default {
components: {
NextButton,
},
props: { props: {
template: { template: {
type: Object, type: Object,
@ -114,78 +119,47 @@ export default {
readonly readonly
class="template-input" class="template-input"
/> />
<div v-if="variables" class="template__variables-container"> <div v-if="variables" class="p-2.5">
<p class="variables-label"> <p class="text-sm font-semibold mb-2.5">
{{ $t('WHATSAPP_TEMPLATES.PARSER.VARIABLES_LABEL') }} {{ $t('WHATSAPP_TEMPLATES.PARSER.VARIABLES_LABEL') }}
</p> </p>
<div <div
v-for="(variable, key) in processedParams" v-for="(variable, key) in processedParams"
:key="key" :key="key"
class="template__variable-item" class="items-center flex mb-2.5"
> >
<span class="variable-label"> <span
class="bg-n-alpha-black2 text-n-slate-12 inline-block rounded-md text-xs py-2.5 px-6"
>
{{ key }} {{ key }}
</span> </span>
<woot-input <woot-input
v-model="processedParams[key]" v-model="processedParams[key]"
type="text" type="text"
class="variable-input" class="flex-1 text-sm ml-2.5"
:styles="{ marginBottom: 0 }" :styles="{ marginBottom: 0 }"
/> />
</div> </div>
<p v-if="v$.$dirty && v$.$invalid" class="error"> <p
v-if="v$.$dirty && v$.$invalid"
class="bg-n-ruby-9/20 rounded-md text-n-ruby-9 p-2.5 text-center"
>
{{ $t('WHATSAPP_TEMPLATES.PARSER.FORM_ERROR_MESSAGE') }} {{ $t('WHATSAPP_TEMPLATES.PARSER.FORM_ERROR_MESSAGE') }}
</p> </p>
</div> </div>
<footer> <footer class="flex justify-end gap-2">
<woot-button variant="smooth" @click="resetTemplate"> <NextButton
{{ $t('WHATSAPP_TEMPLATES.PARSER.GO_BACK_LABEL') }} faded
</woot-button> slate
<woot-button type="button" @click="sendMessage"> type="reset"
{{ $t('WHATSAPP_TEMPLATES.PARSER.SEND_MESSAGE_LABEL') }} :label="$t('WHATSAPP_TEMPLATES.PARSER.GO_BACK_LABEL')"
</woot-button> @click="resetTemplate"
/>
<NextButton
type="button"
:label="$t('WHATSAPP_TEMPLATES.PARSER.SEND_MESSAGE_LABEL')"
@click="sendMessage"
/>
</footer> </footer>
</div> </div>
</template> </template>
<style scoped lang="scss">
.template__variables-container {
@apply p-2.5;
}
.variables-label {
@apply text-sm font-semibold mb-2.5;
}
.template__variable-item {
@apply items-center flex mb-2.5;
.label {
@apply text-xs;
}
.variable-input {
@apply flex-1 text-sm ml-2.5;
}
.variable-label {
@apply bg-slate-75 dark:bg-slate-700 text-slate-700 dark:text-slate-100 inline-block rounded-md text-xs py-2.5 px-6;
}
}
footer {
@apply flex justify-end;
button {
@apply ml-2.5;
}
}
.error {
@apply bg-red-100 dark:bg-red-100 rounded-md text-red-800 dark:text-red-800 p-2.5 text-center;
}
.template-input {
@apply bg-slate-25 dark:bg-slate-900 text-slate-700 dark:text-slate-100;
}
</style>

View File

@ -43,48 +43,56 @@ export default {
<template> <template>
<div class="w-full"> <div class="w-full">
<div class="gap-1 templates__list-search"> <div
<fluent-icon icon="search" class="search-icon" size="16" /> class="gap-1 bg-n-alpha-black2 items-center flex mb-2.5 py-0 px-2.5 rounded-lg outline outline-1 outline-n-weak hover:outline-n-slate-6 dark:hover:outline-n-slate-6 focus-within:outline-n-brand dark:focus-within:outline-n-brand"
>
<fluent-icon icon="search" class="text-n-slate-12" size="16" />
<input <input
v-model="query" v-model="query"
type="search" type="search"
:placeholder="$t('WHATSAPP_TEMPLATES.PICKER.SEARCH_PLACEHOLDER')" :placeholder="$t('WHATSAPP_TEMPLATES.PICKER.SEARCH_PLACEHOLDER')"
class="templates__search-input" class="reset-base w-full h-9 bg-transparent text-n-slate-12 !text-sm !outline-0"
/> />
</div> </div>
<div class="template__list-container"> <div
class="bg-n-background outline-n-container outline outline-1 rounded-lg max-h-[18.75rem] overflow-y-auto p-2.5"
>
<div v-for="(template, i) in filteredTemplateMessages" :key="template.id"> <div v-for="(template, i) in filteredTemplateMessages" :key="template.id">
<button <button
class="template__list-item" class="rounded-lg cursor-pointer block p-2.5 text-left w-full hover:bg-n-alpha-2 dark:hover:bg-n-solid-2"
@click="$emit('onSelect', template)" @click="$emit('onSelect', template)"
> >
<div> <div>
<div class="flex items-center justify-between mb-2.5"> <div class="flex items-center justify-between mb-2.5">
<p class="label-title"> <p class="text-sm">
{{ template.name }} {{ template.name }}
</p> </p>
<span <span
class="inline-block px-2 py-1 text-xs leading-none bg-white rounded-sm cursor-default dark:bg-slate-700 text-slate-800 dark:text-slate-100" class="inline-block px-2 py-1 text-xs leading-none bg-n-slate-3 rounded-lg cursor-default text-n-slate-12"
> >
{{ $t('WHATSAPP_TEMPLATES.PICKER.LABELS.LANGUAGE') }} : {{ $t('WHATSAPP_TEMPLATES.PICKER.LABELS.LANGUAGE') }} :
{{ template.language }} {{ template.language }}
</span> </span>
</div> </div>
<div> <div>
<p class="strong"> <p class="font-medium">
{{ $t('WHATSAPP_TEMPLATES.PICKER.LABELS.TEMPLATE_BODY') }} {{ $t('WHATSAPP_TEMPLATES.PICKER.LABELS.TEMPLATE_BODY') }}
</p> </p>
<p class="label-body">{{ getTemplatebody(template) }}</p> <p class="label-body">{{ getTemplatebody(template) }}</p>
</div> </div>
<div class="label-category"> <div class="mt-5">
<p class="strong"> <p class="font-medium">
{{ $t('WHATSAPP_TEMPLATES.PICKER.LABELS.CATEGORY') }} {{ $t('WHATSAPP_TEMPLATES.PICKER.LABELS.CATEGORY') }}
</p> </p>
<p>{{ template.category }}</p> <p>{{ template.category }}</p>
</div> </div>
</div> </div>
</button> </button>
<hr v-if="i != filteredTemplateMessages.length - 1" :key="`hr-${i}`" /> <hr
v-if="i != filteredTemplateMessages.length - 1"
:key="`hr-${i}`"
class="border-b border-solid border-n-weak my-2.5 mx-auto max-w-[95%]"
/>
</div> </div>
<div v-if="!filteredTemplateMessages.length"> <div v-if="!filteredTemplateMessages.length">
<p> <p>
@ -97,46 +105,7 @@ export default {
</template> </template>
<style scoped lang="scss"> <style scoped lang="scss">
.templates__list-search { .label-body {
@apply items-center flex bg-slate-25 dark:bg-slate-900 mb-2.5 py-0 px-2.5 rounded-md border border-solid border-slate-100 dark:border-slate-700; font-family: monospace;
.search-icon {
@apply text-slate-400 dark:text-slate-300;
}
.templates__search-input {
@apply bg-transparent border-0 text-xs h-9 m-0;
}
}
.template__list-container {
@apply bg-slate-25 dark:bg-slate-900 rounded-md max-h-[18.75rem] overflow-y-auto p-2.5;
.template__list-item {
@apply rounded-lg cursor-pointer block p-2.5 text-left w-full hover:bg-woot-50 dark:hover:bg-slate-800;
.label-title {
@apply text-sm;
}
.label-category {
@apply mt-5;
span {
@apply text-sm font-semibold;
}
}
.label-body {
font-family: monospace;
}
}
}
.strong {
@apply text-xs font-semibold;
}
hr {
@apply border-b border-solid border-slate-100 dark:border-slate-700 my-2.5 mx-auto max-w-[95%];
} }
</style> </style>

View File

@ -3,6 +3,7 @@ import { ref, computed } from 'vue';
import wootConstants from 'dashboard/constants/globals'; import wootConstants from 'dashboard/constants/globals';
import SLAEventItem from './SLAEventItem.vue'; import SLAEventItem from './SLAEventItem.vue';
import Button from 'dashboard/components-next/button/Button.vue';
const props = defineProps({ const props = defineProps({
slaMissedEvents: { slaMissedEvents: {
@ -60,20 +61,19 @@ const toggleShowAllNRT = () => {
v-if="shouldShowMoreNRTButton" v-if="shouldShowMoreNRTButton"
class="flex flex-col items-end w-full" class="flex flex-col items-end w-full"
> >
<woot-button <Button
size="small" link
:icon="!shouldShowAllNrts ? 'plus-sign' : ''" xs
variant="link" slate
color-scheme="secondary" class="hover:!no-underline"
class="hover:!no-underline !gap-1 hover:!bg-transparent dark:hover:!bg-transparent" :icon="!shouldShowAllNrts ? 'i-lucide-plus' : ''"
@click="toggleShowAllNRT" :label="
>
{{
shouldShowAllNrts shouldShowAllNrts
? $t('SLA.EVENTS.HIDE', { count: nrtMisses.length }) ? $t('SLA.EVENTS.HIDE', { count: nrtMisses.length })
: $t('SLA.EVENTS.SHOW_MORE', { count: nrtMisses.length }) : $t('SLA.EVENTS.SHOW_MORE', { count: nrtMisses.length })
}} "
</woot-button> @click="toggleShowAllNRT"
/>
</div> </div>
</template> </template>
</SLAEventItem> </SLAEventItem>

View File

@ -2,11 +2,13 @@
import { mapGetters } from 'vuex'; import { mapGetters } from 'vuex';
import Thumbnail from 'dashboard/components/widgets/Thumbnail.vue'; import Thumbnail from 'dashboard/components/widgets/Thumbnail.vue';
import Spinner from 'shared/components/Spinner.vue'; import Spinner from 'shared/components/Spinner.vue';
import NextButton from 'dashboard/components-next/button/Button.vue';
export default { export default {
components: { components: {
Thumbnail, Thumbnail,
Spinner, Spinner,
NextButton,
}, },
props: { props: {
selectedInboxes: { selectedInboxes: {
@ -94,13 +96,7 @@ export default {
</div> </div>
<div class="flex items-center justify-between header"> <div class="flex items-center justify-between header">
<span>{{ $t('BULK_ACTION.AGENT_SELECT_LABEL') }}</span> <span>{{ $t('BULK_ACTION.AGENT_SELECT_LABEL') }}</span>
<woot-button <NextButton ghost xs slate icon="i-lucide-x" @click="onClose" />
size="tiny"
variant="clear"
color-scheme="secondary"
icon="dismiss"
@click="onClose"
/>
</div> </div>
<div class="container"> <div class="container">
<div <div
@ -121,7 +117,7 @@ export default {
v-model="query" v-model="query"
type="search" type="search"
:placeholder="$t('BULK_ACTION.SEARCH_INPUT_PLACEHOLDER')" :placeholder="$t('BULK_ACTION.SEARCH_INPUT_PLACEHOLDER')"
class="agent--search_input" class="reset-base !outline-0 !text-sm agent--search_input"
/> />
</div> </div>
</li> </li>
@ -161,21 +157,21 @@ export default {
}} }}
</p> </p>
<div class="agent-confirmation-actions"> <div class="agent-confirmation-actions">
<woot-button <NextButton
color-scheme="primary" faded
variant="smooth" sm
slate
type="reset"
:label="$t('BULK_ACTION.GO_BACK_LABEL')"
@click="goBack" @click="goBack"
> />
{{ $t('BULK_ACTION.GO_BACK_LABEL') }} <NextButton
</woot-button> sm
<woot-button type="submit"
color-scheme="primary" :label="$t('BULK_ACTION.YES')"
variant="flat"
:is-loading="uiFlags.isUpdating" :is-loading="uiFlags.isUpdating"
@click="submit" @click="submit"
> />
{{ $t('BULK_ACTION.YES') }}
</woot-button>
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,7 +1,11 @@
<script> <script>
import { mapGetters } from 'vuex'; import { mapGetters } from 'vuex';
import NextButton from 'dashboard/components-next/button/Button.vue';
export default { export default {
components: {
NextButton,
},
emits: ['update', 'close', 'assign'], emits: ['update', 'close', 'assign'],
data() { data() {
return { return {
@ -40,13 +44,7 @@ export default {
</div> </div>
<div class="flex items-center justify-between header"> <div class="flex items-center justify-between header">
<span>{{ $t('BULK_ACTION.LABELS.ASSIGN_LABELS') }}</span> <span>{{ $t('BULK_ACTION.LABELS.ASSIGN_LABELS') }}</span>
<woot-button <NextButton ghost xs slate icon="i-lucide-x" @click="onClose" />
size="tiny"
variant="clear"
color-scheme="secondary"
icon="dismiss"
@click="onClose"
/>
</div> </div>
<div class="labels-list"> <div class="labels-list">
<header class="labels-list__header"> <header class="labels-list__header">
@ -58,7 +56,7 @@ export default {
v-model="query" v-model="query"
type="search" type="search"
:placeholder="$t('BULK_ACTION.SEARCH_INPUT_PLACEHOLDER')" :placeholder="$t('BULK_ACTION.SEARCH_INPUT_PLACEHOLDER')"
class="label--search_input" class="reset-base !outline-0 !text-sm label--search_input"
/> />
</div> </div>
</header> </header>
@ -91,15 +89,13 @@ export default {
</li> </li>
</ul> </ul>
<footer class="labels-list__footer"> <footer class="labels-list__footer">
<woot-button <NextButton
size="small" sm
is-expanded type="submit"
color-scheme="primary" :label="$t('BULK_ACTION.LABELS.ASSIGN_SELECTED_LABELS')"
:disabled="!selectedLabels.length" :disabled="!selectedLabels.length"
@click="$emit('assign', selectedLabels)" @click="$emit('assign', selectedLabels)"
> />
<span>{{ $t('BULK_ACTION.LABELS.ASSIGN_SELECTED_LABELS') }}</span>
</woot-button>
</footer> </footer>
</div> </div>
</div> </div>

View File

@ -1,6 +1,11 @@
<script> <script>
import { mapGetters } from 'vuex'; import { mapGetters } from 'vuex';
import NextButton from 'dashboard/components-next/button/Button.vue';
export default { export default {
components: {
NextButton,
},
emits: ['assignTeam', 'close'], emits: ['assignTeam', 'close'],
data() { data() {
@ -40,13 +45,7 @@ export default {
</div> </div>
<div class="flex items-center justify-between header"> <div class="flex items-center justify-between header">
<span>{{ $t('BULK_ACTION.TEAMS.TEAM_SELECT_LABEL') }}</span> <span>{{ $t('BULK_ACTION.TEAMS.TEAM_SELECT_LABEL') }}</span>
<woot-button <NextButton ghost xs slate icon="i-lucide-x" @click="onClose" />
size="tiny"
variant="clear"
color-scheme="secondary"
icon="dismiss"
@click="onClose"
/>
</div> </div>
<div class="container"> <div class="container">
<div class="team__list-container"> <div class="team__list-container">
@ -60,7 +59,7 @@ export default {
v-model="query" v-model="query"
type="search" type="search"
:placeholder="$t('BULK_ACTION.SEARCH_INPUT_PLACEHOLDER')" :placeholder="$t('BULK_ACTION.SEARCH_INPUT_PLACEHOLDER')"
class="agent--search_input" class="reset-base !outline-0 !text-sm agent--search_input"
/> />
</div> </div>
</li> </li>

View File

@ -4,6 +4,7 @@ import { ref } from 'vue';
import WootDropdownItem from 'shared/components/ui/dropdown/DropdownItem.vue'; import WootDropdownItem from 'shared/components/ui/dropdown/DropdownItem.vue';
import WootDropdownMenu from 'shared/components/ui/dropdown/DropdownMenu.vue'; import WootDropdownMenu from 'shared/components/ui/dropdown/DropdownMenu.vue';
import Button from 'dashboard/components-next/button/Button.vue';
const props = defineProps({ const props = defineProps({
showResolve: { showResolve: {
@ -25,9 +26,9 @@ const emit = defineEmits(['update', 'close']);
const { t } = useI18n(); const { t } = useI18n();
const actions = ref([ const actions = ref([
{ icon: 'checkmark', key: 'resolved' }, { icon: 'i-lucide-check', key: 'resolved' },
{ icon: 'arrow-redo', key: 'open' }, { icon: 'i-lucide-redo', key: 'open' },
{ icon: 'send-clock', key: 'snoozed' }, { icon: 'i-lucide-alarm-clock', key: 'snoozed' },
]); ]);
const updateConversations = key => { const updateConversations = key => {
@ -85,28 +86,21 @@ const actionLabel = key => {
<span class="text-sm font-medium text-slate-600 dark:text-slate-100"> <span class="text-sm font-medium text-slate-600 dark:text-slate-100">
{{ $t('BULK_ACTION.UPDATE.CHANGE_STATUS') }} {{ $t('BULK_ACTION.UPDATE.CHANGE_STATUS') }}
</span> </span>
<woot-button <Button ghost xs slate icon="i-lucide-x" @click="onClose" />
size="tiny"
variant="clear"
color-scheme="secondary"
icon="dismiss"
@click="onClose"
/>
</div> </div>
<div class="px-2.5 pt-0 pb-2.5"> <div class="px-2.5 pt-0 pb-2.5">
<WootDropdownMenu class="m-0 list-none"> <WootDropdownMenu class="m-0 list-none">
<template v-for="action in actions"> <template v-for="action in actions">
<WootDropdownItem v-if="showAction(action.key)" :key="action.key"> <WootDropdownItem v-if="showAction(action.key)" :key="action.key">
<woot-button <Button
variant="clear" ghost
color-scheme="secondary" sm
size="small" slate
class="!w-full ltr:!justify-start rtl:!justify-end"
:icon="action.icon" :icon="action.icon"
class="hover:!bg-n-slate-3 dark:hover:!bg-n-solid-3" :label="actionLabel(action.key)"
@click="updateConversations(action.key)" @click="updateConversations(action.key)"
> />
{{ actionLabel(action.key) }}
</woot-button>
</WootDropdownItem> </WootDropdownItem>
</template> </template>
</WootDropdownMenu> </WootDropdownMenu>

View File

@ -9,6 +9,7 @@ import validations from './validations';
import { parseLinearAPIErrorResponse } from 'dashboard/store/utils/api'; import { parseLinearAPIErrorResponse } from 'dashboard/store/utils/api';
import SearchableDropdown from './SearchableDropdown.vue'; import SearchableDropdown from './SearchableDropdown.vue';
import { LINEAR_EVENTS } from 'dashboard/helper/AnalyticsHelper/events'; import { LINEAR_EVENTS } from 'dashboard/helper/AnalyticsHelper/events';
import Button from 'dashboard/components-next/button/Button.vue';
const props = defineProps({ const props = defineProps({
conversationId: { conversationId: {
@ -248,20 +249,20 @@ onMounted(getTeams);
/> />
</div> </div>
<div class="flex items-center justify-end w-full gap-2 mt-8"> <div class="flex items-center justify-end w-full gap-2 mt-8">
<woot-button <Button
class="px-4 rounded-xl button clear outline-woot-200/50 outline" faded
slate
type="reset"
:label="$t('INTEGRATION_SETTINGS.LINEAR.ADD_OR_LINK.CANCEL')"
@click.prevent="onClose" @click.prevent="onClose"
> />
{{ $t('INTEGRATION_SETTINGS.LINEAR.ADD_OR_LINK.CANCEL') }} <Button
</woot-button> type="submit"
<woot-button :label="$t('INTEGRATION_SETTINGS.LINEAR.ADD_OR_LINK.CREATE')"
:is-disabled="isSubmitDisabled" :disabled="isSubmitDisabled"
class="px-4 rounded-xl"
:is-loading="isCreating" :is-loading="isCreating"
@click.prevent="createIssue" @click.prevent="createIssue"
> />
{{ $t('INTEGRATION_SETTINGS.LINEAR.ADD_OR_LINK.CREATE') }}
</woot-button>
</div> </div>
</div> </div>
</template> </template>

View File

@ -1,5 +1,7 @@
<script setup> <script setup>
import { inject } from 'vue'; import { inject } from 'vue';
import Button from 'dashboard/components-next/button/Button.vue';
const props = defineProps({ const props = defineProps({
identifier: { identifier: {
type: String, type: String,
@ -37,30 +39,24 @@ const openIssue = () => {
/> />
<span class="text-xs font-medium text-ash-900">{{ identifier }}</span> <span class="text-xs font-medium text-ash-900">{{ identifier }}</span>
</div> </div>
<div class="flex items-center gap-0.5"> <div class="flex items-center gap-1">
<woot-button <Button
variant="clear" ghost
color-scheme="secondary" xs
class="h-[24px]" slate
icon="i-lucide-unlink"
class="!transition-none"
:is-loading="isUnlinking" :is-loading="isUnlinking"
@click="unlinkIssue" @click="unlinkIssue"
> />
<fluent-icon <Button
v-if="!isUnlinking" ghost
icon="unlink" xs
size="12" slate
type="outline" class="!transition-none"
icon-lib="lucide" icon="i-lucide-arrow-up-right"
/>
</woot-button>
<woot-button
variant="clear"
class="h-[24px]"
color-scheme="secondary"
@click="openIssue" @click="openIssue"
> />
<fluent-icon icon="arrow-up-right" size="14" />
</woot-button>
</div> </div>
</div> </div>
</template> </template>

View File

@ -8,6 +8,7 @@ import FilterButton from 'dashboard/components/ui/Dropdown/DropdownButton.vue';
import FilterListDropdown from 'dashboard/components/ui/Dropdown/DropdownList.vue'; import FilterListDropdown from 'dashboard/components/ui/Dropdown/DropdownList.vue';
import { parseLinearAPIErrorResponse } from 'dashboard/store/utils/api'; import { parseLinearAPIErrorResponse } from 'dashboard/store/utils/api';
import { LINEAR_EVENTS } from 'dashboard/helper/AnalyticsHelper/events'; import { LINEAR_EVENTS } from 'dashboard/helper/AnalyticsHelper/events';
import Button from 'dashboard/components-next/button/Button.vue';
const props = defineProps({ const props = defineProps({
conversationId: { conversationId: {
@ -129,20 +130,20 @@ const linkIssue = async () => {
</template> </template>
</FilterButton> </FilterButton>
<div class="flex items-center justify-end w-full gap-2 mt-2"> <div class="flex items-center justify-end w-full gap-2 mt-2">
<woot-button <Button
class="px-4 rounded-xl button clear outline-woot-200/50 outline" faded
slate
type="reset"
:label="$t('INTEGRATION_SETTINGS.LINEAR.ADD_OR_LINK.CANCEL')"
@click.prevent="onClose" @click.prevent="onClose"
> />
{{ $t('INTEGRATION_SETTINGS.LINEAR.ADD_OR_LINK.CANCEL') }} <Button
</woot-button> type="submit"
<woot-button :label="$t('INTEGRATION_SETTINGS.LINEAR.LINK.TITLE')"
:is-disabled="isSubmitDisabled" :disabled="isSubmitDisabled"
class="px-4 rounded-xl"
:is-loading="isLinking" :is-loading="isLinking"
@click.prevent="linkIssue" @click.prevent="linkIssue"
> />
{{ $t('INTEGRATION_SETTINGS.LINEAR.LINK.TITLE') }}
</woot-button>
</div> </div>
</div> </div>
</template> </template>

View File

@ -9,6 +9,7 @@ import Issue from './Issue.vue';
import { useTrack } from 'dashboard/composables'; import { useTrack } from 'dashboard/composables';
import { LINEAR_EVENTS } from 'dashboard/helper/AnalyticsHelper/events'; import { LINEAR_EVENTS } from 'dashboard/helper/AnalyticsHelper/events';
import { parseLinearAPIErrorResponse } from 'dashboard/store/utils/api'; import { parseLinearAPIErrorResponse } from 'dashboard/store/utils/api';
import Button from 'dashboard/components-next/button/Button.vue';
const props = defineProps({ const props = defineProps({
conversationId: { conversationId: {
@ -100,23 +101,25 @@ onMounted(() => {
<template> <template>
<div class="relative" :class="{ group: linkedIssue }"> <div class="relative" :class="{ group: linkedIssue }">
<woot-button <Button
v-on-clickaway="closeIssue" v-on-clickaway="closeIssue"
v-tooltip="tooltipText" v-tooltip="tooltipText"
variant="clear" sm
color-scheme="secondary" ghost
slate
class="!gap-1"
@click="openIssue" @click="openIssue"
> >
<fluent-icon <fluent-icon
icon="linear" icon="linear"
size="19" size="19"
class="text-[#5E6AD2]" class="text-[#5E6AD2] flex-shrink-0"
view-box="0 0 19 19" view-box="0 0 19 19"
/> />
<span v-if="linkedIssue" class="text-xs font-medium text-ash-800"> <span v-if="linkedIssue" class="text-xs font-medium text-n-slate-11">
{{ linkedIssue.issue.identifier }} {{ linkedIssue.issue.identifier }}
</span> </span>
</woot-button> </Button>
<Issue <Issue
v-if="linkedIssue" v-if="linkedIssue"
:issue="linkedIssue.issue" :issue="linkedIssue.issue"

View File

@ -3,9 +3,12 @@ import { required } from '@vuelidate/validators';
import { useVuelidate } from '@vuelidate/core'; import { useVuelidate } from '@vuelidate/core';
import Modal from '../../Modal.vue'; import Modal from '../../Modal.vue';
import NextButton from 'dashboard/components-next/button/Button.vue';
export default { export default {
components: { components: {
Modal, Modal,
NextButton,
}, },
props: { props: {
show: { type: Boolean, default: false }, show: { type: Boolean, default: false },
@ -66,13 +69,20 @@ export default {
:placeholder="confirmPlaceHolderText" :placeholder="confirmPlaceHolderText"
@blur="v$.value.$touch" @blur="v$.value.$touch"
/> />
<div class="button-wrapper"> <div class="flex items-center justify-end gap-2">
<woot-button color-scheme="alert" :is-disabled="v$.value.$invalid"> <NextButton
{{ confirmText }} faded
</woot-button> slate
<woot-button class="clear" @click.prevent="closeModal"> type="reset"
{{ rejectText }} :label="rejectText"
</woot-button> @click.prevent="closeModal"
/>
<NextButton
ruby
type="submit"
:label="confirmText"
:disabled="v$.value.$invalid"
/>
</div> </div>
</form> </form>
</Modal> </Modal>

View File

@ -1,9 +1,11 @@
<script> <script>
import Modal from '../../Modal.vue'; import Modal from '../../Modal.vue';
import NextButton from 'dashboard/components-next/button/Button.vue';
export default { export default {
components: { components: {
Modal, Modal,
NextButton,
}, },
props: { props: {
title: { title: {
@ -55,12 +57,8 @@ export default {
<div class="h-auto overflow-auto flex flex-col"> <div class="h-auto overflow-auto flex flex-col">
<woot-modal-header :header-title="title" :header-content="description" /> <woot-modal-header :header-title="title" :header-content="description" />
<div class="flex flex-row justify-end gap-2 py-4 px-6 w-full"> <div class="flex flex-row justify-end gap-2 py-4 px-6 w-full">
<woot-button variant="clear" @click="cancel"> <NextButton faded type="reset" :label="cancelLabel" @click="cancel" />
{{ cancelLabel }} <NextButton type="submit" :label="confirmLabel" @click="confirm" />
</woot-button>
<woot-button @click="confirm">
{{ confirmLabel }}
</woot-button>
</div> </div>
</div> </div>
</Modal> </Modal>

View File

@ -1,5 +1,6 @@
<script setup> <script setup>
import Modal from '../../Modal.vue'; import Modal from '../../Modal.vue';
import Button from 'dashboard/components-next/button/Button.vue';
defineProps({ defineProps({
onClose: { type: Function, default: () => {} }, onClose: { type: Function, default: () => {} },
@ -22,23 +23,8 @@ const show = defineModel('show', { type: Boolean, default: false });
:header-content-value="messageValue" :header-content-value="messageValue"
/> />
<div class="flex items-center justify-end gap-2 p-8"> <div class="flex items-center justify-end gap-2 p-8">
<woot-button variant="clear" class="action-button" @click="onClose"> <Button faded slate type="reset" :label="rejectText" @click="onClose" />
{{ rejectText }} <Button ruby type="submit" :label="confirmText" @click="onConfirm" />
</woot-button>
<woot-button
color-scheme="alert"
class="action-button"
variant="smooth"
@click="onConfirm"
>
{{ confirmText }}
</woot-button>
</div> </div>
</Modal> </Modal>
</template> </template>
<style lang="scss" scoped>
.action-button {
max-width: var(--space-giga);
}
</style>

View File

@ -4,9 +4,10 @@ import { useVuelidate } from '@vuelidate/core';
import MergeContactSummary from 'dashboard/modules/contact/components/MergeContactSummary.vue'; import MergeContactSummary from 'dashboard/modules/contact/components/MergeContactSummary.vue';
import ContactDropdownItem from './ContactDropdownItem.vue'; import ContactDropdownItem from './ContactDropdownItem.vue';
import NextButton from 'dashboard/components-next/button/Button.vue';
export default { export default {
components: { MergeContactSummary, ContactDropdownItem }, components: { MergeContactSummary, ContactDropdownItem, NextButton },
props: { props: {
primaryContact: { primaryContact: {
type: Object, type: Object,
@ -173,12 +174,18 @@ export default {
:parent-contact-name="parentContactName" :parent-contact-name="parentContactName"
/> />
<div class="flex justify-end gap-2 mt-6"> <div class="flex justify-end gap-2 mt-6">
<woot-button variant="clear" @click.prevent="onCancel"> <NextButton
{{ $t('MERGE_CONTACTS.FORM.CANCEL') }} faded
</woot-button> slate
<woot-button type="submit" :is-loading="isMerging"> type="reset"
{{ $t('MERGE_CONTACTS.FORM.SUBMIT') }} :label="$t('MERGE_CONTACTS.FORM.CANCEL')"
</woot-button> @click.prevent="onCancel"
/>
<NextButton
type="submit"
:is-loading="isMerging"
:label="$t('MERGE_CONTACTS.FORM.SUBMIT')"
/>
</div> </div>
</form> </form>
</template> </template>

View File

@ -1,47 +1,50 @@
<script> <script setup>
import { useAlert } from 'dashboard/composables'; import { useAlert } from 'dashboard/composables';
import { useI18n } from 'vue-i18n';
import { copyTextToClipboard } from 'shared/helpers/clipboard'; import { copyTextToClipboard } from 'shared/helpers/clipboard';
import Button from 'dashboard/components-next/button/Button.vue';
export default { const props = defineProps({
name: 'ArticleSearchResultItem', id: {
props: { type: Number,
id: { default: 0,
type: Number,
default: 0,
},
title: {
type: String,
default: 'Untitled',
},
url: {
type: String,
default: '',
},
category: {
type: String,
default: '',
},
locale: {
type: String,
default: '',
},
}, },
emits: ['insert', 'preview'], title: {
methods: { type: String,
handleInsert(e) { default: 'Untitled',
e.stopPropagation();
this.$emit('insert', this.id);
},
handlePreview(e) {
e.stopPropagation();
this.$emit('preview', this.id);
},
async handleCopy(e) {
e.stopPropagation();
await copyTextToClipboard(this.url);
useAlert(this.$t('CONTACT_PANEL.COPY_SUCCESSFUL'));
},
}, },
url: {
type: String,
default: '',
},
category: {
type: String,
default: '',
},
locale: {
type: String,
default: '',
},
});
const emit = defineEmits(['insert', 'preview']);
const { t } = useI18n();
const handleInsert = e => {
e.stopPropagation();
emit('insert', props.id);
};
const handlePreview = e => {
e.stopPropagation();
emit('preview', props.id);
};
const handleCopy = async e => {
e.stopPropagation();
await copyTextToClipboard(props.url);
useAlert(t('CONTACT_PANEL.COPY_SUCCESSFUL'));
}; };
</script> </script>
@ -65,24 +68,23 @@ export default {
{{ category || $t('HELP_CENTER.ARTICLE_SEARCH_RESULT.UNCATEGORIZED') }} {{ category || $t('HELP_CENTER.ARTICLE_SEARCH_RESULT.UNCATEGORIZED') }}
</p> </p>
<div class="flex gap-0.5"> <div class="flex gap-0.5">
<woot-button <Button
:title="$t('HELP_CENTER.ARTICLE_SEARCH_RESULT.COPY_LINK')" :title="$t('HELP_CENTER.ARTICLE_SEARCH_RESULT.COPY_LINK')"
variant="hollow" faded
color-scheme="secondary" slate
size="tiny" xs
icon="copy" type="reset"
icon="i-lucide-copy"
class="invisible group-hover:visible" class="invisible group-hover:visible"
@click="handleCopy" @click="handleCopy"
/> />
<woot-button <Button
class="insert-button" xs
variant="smooth" faded
color-scheme="secondary" slate
size="tiny" :label="$t('HELP_CENTER.ARTICLE_SEARCH_RESULT.INSERT_ARTICLE')"
@click="handleInsert" @click="handleInsert"
> />
{{ $t('HELP_CENTER.ARTICLE_SEARCH_RESULT.INSERT_ARTICLE') }}
</woot-button>
</div> </div>
</div> </div>
</button> </button>

View File

@ -1,42 +1,37 @@
<script> <script setup>
import IframeLoader from 'shared/components/IframeLoader.vue'; import IframeLoader from 'shared/components/IframeLoader.vue';
import Button from 'dashboard/components-next/button/Button.vue';
export default { defineProps({
name: 'ArticleView', url: {
components: { type: String,
IframeLoader, default: '',
},
props: {
url: {
type: String,
default: '',
},
},
emits: ['back', 'insert'],
methods: {
onBack(e) {
e.stopPropagation();
this.$emit('back');
},
onInsert(e) {
e.stopPropagation();
this.$emit('insert');
},
}, },
});
const emit = defineEmits(['back', 'insert']);
const onBack = e => {
e.stopPropagation();
emit('back');
};
const onInsert = e => {
e.stopPropagation();
emit('insert');
}; };
</script> </script>
<template> <template>
<div class="h-full w-full flex flex-col flex-1 overflow-hidden"> <div class="h-full w-full flex flex-col flex-1 overflow-hidden">
<div class="py-1"> <div class="py-1">
<woot-button <Button
variant="link" link
size="small" xs
icon="chevron-left" :label="$t('HELP_CENTER.ARTICLE_SEARCH.BACK_RESULTS')"
icon="i-lucide-chevron-left"
@click="onBack" @click="onBack"
> />
{{ $t('HELP_CENTER.ARTICLE_SEARCH.BACK_RESULTS') }}
</woot-button>
</div> </div>
<div class="-ml-4 h-full overflow-y-auto"> <div class="-ml-4 h-full overflow-y-auto">
<div class="w-full h-full min-h-0"> <div class="w-full h-full min-h-0">
@ -45,24 +40,22 @@ export default {
</div> </div>
<div class="flex justify-end gap-2 py-2"> <div class="flex justify-end gap-2 py-2">
<woot-button <Button
variant="hollow" faded
size="small" slate
is-expanded sm
color-scheme="secondary" type="reset"
icon="chevron-left" icon="i-lucide-chevron-left"
:label="$t('HELP_CENTER.ARTICLE_SEARCH.BACK')"
@click="onBack" @click="onBack"
> />
{{ $t('HELP_CENTER.ARTICLE_SEARCH.BACK') }} <Button
</woot-button> sm
<woot-button type="submit"
size="small" icon="i-lucide-arrow-down-to-dot"
is-expanded :label="$t('HELP_CENTER.ARTICLE_SEARCH.INSERT_ARTICLE')"
icon="arrow-download"
@click="onInsert" @click="onInsert"
> />
{{ $t('HELP_CENTER.ARTICLE_SEARCH.INSERT_ARTICLE') }}
</woot-button>
</div> </div>
</div> </div>
</template> </template>

View File

@ -1,6 +1,7 @@
<script setup> <script setup>
import { ref, onMounted } from 'vue'; import { ref, onMounted } from 'vue';
import { useKeyboardEvents } from 'dashboard/composables/useKeyboardEvents'; import { useKeyboardEvents } from 'dashboard/composables/useKeyboardEvents';
import Button from 'dashboard/components-next/button/Button.vue';
defineProps({ defineProps({
title: { title: {
@ -49,13 +50,7 @@ useKeyboardEvents(keyboardEvents);
<h3 class="text-base text-slate-900 dark:text-slate-25"> <h3 class="text-base text-slate-900 dark:text-slate-25">
{{ title }} {{ title }}
</h3> </h3>
<woot-button <Button ghost xs slate icon="i-lucide-x" @click="onClose" />
variant="clear"
size="tiny"
color-scheme="secondary"
icon="dismiss"
@click="onClose"
/>
</div> </div>
<div class="relative"> <div class="relative">

View File

@ -1,30 +1,20 @@
<script> <script setup>
export default { import Button from 'dashboard/components-next/button/Button.vue';
emits: ['add'],
methods: { const emit = defineEmits(['add']);
addLabel() {
this.$emit('add'); const addLabel = () => {
}, emit('add');
},
}; };
</script> </script>
<template> <template>
<woot-button <Button
variant="smooth" faded
class="label--add" xs
icon="add" icon="i-lucide-plus"
size="tiny" class="mb-0.5 ltr:mr-0.5 rtl:ml-0.5 !rounded-[4px]"
:label="$t('CONTACT_PANEL.LABELS.CONVERSATION.ADD_BUTTON')"
@click="addLabel" @click="addLabel"
> />
{{ $t('CONTACT_PANEL.LABELS.CONVERSATION.ADD_BUTTON') }}
</woot-button>
</template> </template>
<style lang="scss" scoped>
.label--add {
margin-bottom: var(--space-micro);
margin-right: var(--space-micro);
}
</style>