fix: Dropdown menu issues (#10364)
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
<script setup>
|
||||
import { computed, ref } from 'vue';
|
||||
import { computed } from 'vue';
|
||||
import { useToggle } from '@vueuse/core';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { dynamicTime } from 'shared/helpers/timeHelper';
|
||||
import {
|
||||
@@ -49,7 +50,7 @@ const emit = defineEmits(['openArticle', 'articleAction']);
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
const isOpen = ref(false);
|
||||
const [showActionsDropdown, toggleDropdown] = useToggle();
|
||||
|
||||
const articleMenuItems = computed(() => {
|
||||
const commonItems = Object.entries(ARTICLE_MENU_ITEMS).reduce(
|
||||
@@ -112,7 +113,7 @@ const lastUpdatedAt = computed(() => {
|
||||
});
|
||||
|
||||
const handleArticleAction = ({ action, value }) => {
|
||||
isOpen.value = false;
|
||||
toggleDropdown(false);
|
||||
emit('articleAction', { action, value, id: props.id });
|
||||
};
|
||||
|
||||
@@ -139,19 +140,18 @@ const handleClick = id => {
|
||||
{{ statusText }}
|
||||
</span>
|
||||
<div
|
||||
v-on-clickaway="() => (isOpen = false)"
|
||||
v-on-clickaway="() => toggleDropdown(false)"
|
||||
class="relative flex items-center group"
|
||||
@click.stop
|
||||
>
|
||||
<Button
|
||||
icon="i-lucide-ellipsis-vertical"
|
||||
color="slate"
|
||||
size="xs"
|
||||
class="group-hover:bg-n-solid-2 !p-0.5 rounded-md"
|
||||
@click="isOpen = !isOpen"
|
||||
class="rounded-md group-hover:bg-n-alpha-2"
|
||||
@click="toggleDropdown()"
|
||||
/>
|
||||
<DropdownMenu
|
||||
v-if="isOpen"
|
||||
v-if="showActionsDropdown"
|
||||
:menu-items="articleMenuItems"
|
||||
class="mt-1 ltr:right-0 rtl:left-0 xl:ltr:left-0 xl:rtl:right-0 top-full"
|
||||
@action="handleArticleAction($event)"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script setup>
|
||||
import { ref, computed } from 'vue';
|
||||
import { OnClickOutside } from '@vueuse/components';
|
||||
import { computed } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useToggle } from '@vueuse/core';
|
||||
|
||||
import CardLayout from 'dashboard/components-next/CardLayout.vue';
|
||||
import Button from 'dashboard/components-next/button/Button.vue';
|
||||
@@ -38,20 +38,20 @@ const emit = defineEmits(['click', 'action']);
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
const isOpen = ref(false);
|
||||
const [showActionsDropdown, toggleDropdown] = useToggle();
|
||||
|
||||
const categoryMenuItems = [
|
||||
{
|
||||
label: 'Edit',
|
||||
action: 'edit',
|
||||
value: 'edit',
|
||||
icon: 'edit',
|
||||
icon: 'i-lucide-pencil',
|
||||
},
|
||||
{
|
||||
label: 'Delete',
|
||||
action: 'delete',
|
||||
value: 'delete',
|
||||
icon: 'delete',
|
||||
icon: 'i-lucide-trash',
|
||||
},
|
||||
];
|
||||
|
||||
@@ -73,7 +73,7 @@ const handleClick = slug => {
|
||||
|
||||
const handleAction = ({ action, value }) => {
|
||||
emit('action', { action, value, id: props.id });
|
||||
isOpen.value = false;
|
||||
toggleDropdown(false);
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -81,16 +81,16 @@ const handleAction = ({ action, value }) => {
|
||||
<CardLayout>
|
||||
<template #header>
|
||||
<div class="flex gap-2">
|
||||
<div class="flex justify-between w-full gap-1">
|
||||
<div class="flex items-center justify-start gap-2">
|
||||
<div class="flex justify-between w-full gap-2">
|
||||
<div class="flex items-center justify-start w-full min-w-0 gap-2">
|
||||
<span
|
||||
class="text-base cursor-pointer hover:underline underline-offset-2 hover:text-n-blue-text text-n-slate-12 line-clamp-1"
|
||||
class="text-base truncate cursor-pointer hover:underline underline-offset-2 hover:text-n-blue-text text-n-slate-12"
|
||||
@click="handleClick(slug)"
|
||||
>
|
||||
{{ categoryTitleWithIcon }}
|
||||
</span>
|
||||
<span
|
||||
class="inline-flex items-center justify-center h-6 px-2 py-1 text-xs text-center truncate border rounded-lg min-w-fit text-slate-500 w-fit border-slate-200 dark:border-slate-800 dark:text-slate-400"
|
||||
class="inline-flex items-center justify-center h-6 px-2 py-1 text-xs text-center border rounded-lg bg-n-slate-1 whitespace-nowrap shrink-0 text-n-slate-11 border-n-slate-4"
|
||||
>
|
||||
{{
|
||||
t('HELP_CENTER.CATEGORY_PAGE.CATEGORY_CARD.ARTICLES_COUNT', {
|
||||
@@ -99,22 +99,24 @@ const handleAction = ({ action, value }) => {
|
||||
}}
|
||||
</span>
|
||||
</div>
|
||||
<div class="relative group" @click.stop>
|
||||
<OnClickOutside @trigger="isOpen = false">
|
||||
<Button
|
||||
icon="i-lucide-ellipsis-vertical"
|
||||
color="slate"
|
||||
size="xs"
|
||||
class="rounded-md group-hover:bg-n-solid-2"
|
||||
@click="isOpen = !isOpen"
|
||||
/>
|
||||
<DropdownMenu
|
||||
v-if="isOpen"
|
||||
:menu-items="categoryMenuItems"
|
||||
class="mt-1 ltr:right-0 rtl:left-0 xl:ltr:left-0 xl:rtl:right-0 top-full z-60"
|
||||
@action="handleAction"
|
||||
/>
|
||||
</OnClickOutside>
|
||||
<div
|
||||
v-on-clickaway="() => toggleDropdown(false)"
|
||||
class="relative group"
|
||||
>
|
||||
<Button
|
||||
icon="i-lucide-ellipsis-vertical"
|
||||
color="slate"
|
||||
size="xs"
|
||||
variant="ghost"
|
||||
class="rounded-md group-hover:bg-n-alpha-2"
|
||||
@click="toggleDropdown()"
|
||||
/>
|
||||
<DropdownMenu
|
||||
v-if="showActionsDropdown"
|
||||
:menu-items="categoryMenuItems"
|
||||
class="mt-1 ltr:right-0 rtl:left-0 xl:ltr:left-0 xl:rtl:right-0 top-full z-60"
|
||||
@action="handleAction"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script setup>
|
||||
import { ref, computed } from 'vue';
|
||||
import { OnClickOutside } from '@vueuse/components';
|
||||
import { computed } from 'vue';
|
||||
import { useI18n } from 'vue-i18n';
|
||||
import { useToggle } from '@vueuse/core';
|
||||
import { LOCALE_MENU_ITEMS } from 'dashboard/helper/portalHelper';
|
||||
|
||||
import CardLayout from 'dashboard/components-next/CardLayout.vue';
|
||||
@@ -35,7 +35,7 @@ const emit = defineEmits(['action']);
|
||||
|
||||
const { t } = useI18n();
|
||||
|
||||
const showDropdownMenu = ref(false);
|
||||
const [showDropdownMenu, toggleDropdown] = useToggle();
|
||||
|
||||
const localeMenuItems = computed(() =>
|
||||
LOCALE_MENU_ITEMS.map(item => ({
|
||||
@@ -47,7 +47,7 @@ const localeMenuItems = computed(() =>
|
||||
|
||||
const handleAction = ({ action, value }) => {
|
||||
emit('action', { action, value });
|
||||
showDropdownMenu.value = false;
|
||||
toggleDropdown(false);
|
||||
};
|
||||
</script>
|
||||
|
||||
@@ -92,23 +92,24 @@ const handleAction = ({ action, value }) => {
|
||||
}}
|
||||
</span>
|
||||
</div>
|
||||
<div class="relative group">
|
||||
<OnClickOutside @trigger="showDropdownMenu = false">
|
||||
<Button
|
||||
icon="i-lucide-ellipsis-vertical"
|
||||
color="slate"
|
||||
size="xs"
|
||||
class="rounded-md group-hover:bg-n-solid-2"
|
||||
@click="showDropdownMenu = !showDropdownMenu"
|
||||
/>
|
||||
<div
|
||||
v-on-clickaway="() => toggleDropdown(false)"
|
||||
class="relative group"
|
||||
>
|
||||
<Button
|
||||
icon="i-lucide-ellipsis-vertical"
|
||||
color="slate"
|
||||
size="xs"
|
||||
class="rounded-md group-hover:bg-n-alpha-2"
|
||||
@click="toggleDropdown()"
|
||||
/>
|
||||
|
||||
<DropdownMenu
|
||||
v-if="showDropdownMenu"
|
||||
:menu-items="localeMenuItems"
|
||||
class="ltr:right-0 rtl:left-0 mt-1 xl:ltr:left-0 xl:rtl:right-0 top-full z-60 min-w-[150px]"
|
||||
@action="handleAction"
|
||||
/>
|
||||
</OnClickOutside>
|
||||
<DropdownMenu
|
||||
v-if="showDropdownMenu"
|
||||
:menu-items="localeMenuItems"
|
||||
class="ltr:right-0 rtl:left-0 mt-1 xl:ltr:left-0 xl:rtl:right-0 top-full z-60 min-w-[150px]"
|
||||
@action="handleAction"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -52,7 +52,7 @@ onMounted(() => {
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="flex flex-col absolute w-[400px] bg-n-alpha-3 backdrop-blur-[100px] shadow-lg gap-6 rounded-xl p-6"
|
||||
class="flex flex-col absolute w-[400px] bg-n-alpha-3 outline outline-1 outline-n-container backdrop-blur-[100px] shadow-lg gap-6 rounded-xl p-6"
|
||||
>
|
||||
<div class="flex items-center justify-between">
|
||||
<h3>
|
||||
|
||||
@@ -147,7 +147,9 @@ const handleBreadcrumbClick = () => {
|
||||
</OnClickOutside>
|
||||
</div>
|
||||
<div class="w-px h-3.5 rounded my-auto bg-slate-75 dark:bg-slate-800" />
|
||||
<span class="text-sm font-medium text-slate-800 dark:text-slate-100">
|
||||
<span
|
||||
class="min-w-0 text-sm font-medium truncate text-slate-800 dark:text-slate-100"
|
||||
>
|
||||
{{
|
||||
t('HELP_CENTER.CATEGORY_PAGE.CATEGORY_HEADER.CATEGORIES_COUNT', {
|
||||
n: categoriesCount,
|
||||
|
||||
@@ -106,7 +106,7 @@ const redirectToPortalHomePage = () => {
|
||||
{{ t('HELP_CENTER.PORTAL_SWITCHER.PORTALS') }}
|
||||
</h2>
|
||||
<Button
|
||||
icon="arrow-up-right-lucide"
|
||||
icon="i-lucide-arrow-up-right"
|
||||
variant="ghost"
|
||||
icon-lib="lucide"
|
||||
size="sm"
|
||||
|
||||
@@ -45,7 +45,7 @@ const slots = useSlots();
|
||||
const STYLE_CONFIG = {
|
||||
colors: {
|
||||
blue: {
|
||||
solid: 'bg-n-brand text-white hover:bg-n-blue-text outline-transparent',
|
||||
solid: 'bg-n-brand text-white hover:brightness-110 outline-transparent',
|
||||
faded:
|
||||
'bg-n-brand/10 text-n-slate-12 hover:bg-n-brand/20 outline-transparent',
|
||||
outline: 'text-n-blue-text hover:bg-n-brand/10 outline-n-blue-border',
|
||||
@@ -67,7 +67,7 @@ const STYLE_CONFIG = {
|
||||
},
|
||||
slate: {
|
||||
solid:
|
||||
'bg-n-solid-3 hover:bg-n-solid-2 text-n-slate-12 outline-n-container',
|
||||
'bg-n-solid-3 dark:hover:bg-n-solid-2 hover:bg-n-alpha-2 text-n-slate-12 outline-n-container',
|
||||
faded:
|
||||
'bg-n-slate-9/10 text-n-slate-12 hover:bg-n-slate-9/20 outline-transparent',
|
||||
outline: 'text-n-slate-11 outline-n-strong hover:bg-n-slate-9/10',
|
||||
|
||||
@@ -128,9 +128,9 @@ watch(
|
||||
<li
|
||||
v-for="option in filteredOptions"
|
||||
:key="option.value"
|
||||
class="flex items-center justify-between !text-n-slate-12 w-full gap-2 px-3 py-2 text-sm transition-colors duration-150 cursor-pointer hover:bg-n-solid-2"
|
||||
class="flex items-center justify-between !text-n-slate-12 w-full gap-2 px-3 py-2 text-sm transition-colors duration-150 cursor-pointer hover:bg-n-alpha-2"
|
||||
:class="{
|
||||
'bg-n-solid-2': option.value === selectedValue,
|
||||
'bg-n-alpha-2': option.value === selectedValue,
|
||||
}"
|
||||
role="option"
|
||||
:aria-selected="option.value === selectedValue"
|
||||
|
||||
@@ -27,7 +27,7 @@ const handleAction = (action, value) => {
|
||||
|
||||
<template>
|
||||
<div
|
||||
class="bg-n-alpha-3 backdrop-blur-[100px] absolute rounded-xl z-50 py-2 px-2 gap-2 flex flex-col min-w-[136px] shadow-lg"
|
||||
class="bg-n-alpha-3 backdrop-blur-[100px] border-0 outline outline-1 outline-n-container absolute rounded-xl z-50 py-2 px-2 gap-2 flex flex-col min-w-[136px] shadow-lg"
|
||||
>
|
||||
<button
|
||||
v-for="item in menuItems"
|
||||
@@ -48,9 +48,11 @@ const handleAction = (action, value) => {
|
||||
:size="thumbnailSize"
|
||||
:src="item.thumbnail.src"
|
||||
/>
|
||||
<Icon v-if="item.icon" :icon="item.icon" />
|
||||
<span v-if="item.emoji">{{ item.emoji }}</span>
|
||||
<span v-if="item.label" class="text-sm">{{ item.label }}</span>
|
||||
<Icon v-if="item.icon" :icon="item.icon" class="flex-shrink-0" />
|
||||
<span v-if="item.emoji" class="flex-shrink-0">{{ item.emoji }}</span>
|
||||
<span v-if="item.label" class="min-w-0 text-sm truncate">{{
|
||||
item.label
|
||||
}}</span>
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
Reference in New Issue
Block a user