Replies: 4 comments 2 replies
-
Hey @SHVM-09 maybe you have some ideas regarding with this issue please leave some here, Thanks man. |
Beta Was this translation helpful? Give feedback.
-
Update: I manage to work the dropdown in my bulletin board component alongside testing with the tooltip component. But I put those dropdown alongside with test tooltip component on a separate component. bulletin-board.vue <script setup>
import { storeToRefs } from "pinia"
import { useAuthStore } from "@/stores/authStore"
import { useArticleStore } from "@/stores/articles/articleStore"
import { useConfirmDialogStore } from '@/stores/dialogs/confirmDialogStore'
definePageMeta({
pageTransition: true,
middleware: ["auth"],
})
const authStore = useAuthStore()
const articleStore = useArticleStore()
const confirmDialogStore = useConfirmDialogStore()
const { user } = storeToRefs(authStore)
const { articles } = storeToRefs(articleStore)
const route = useRoute()
const loading = ref(false)
watch(
() => route.name,
(val) => {
if (!articles.length) {
init()
}
},
{
immediate: true,
}
);
async function init() {
loading.value = true
await articleStore.getArticles()
loading.value = false
}
function showArticleDetails (id) {
navigateTo(`/bulletin-board/${id}`)
}
async function deleteArticle (id) {
let confirmed = await confirmDialogStore
.show('Are you sure you want to delete this article?', {
title: 'Deleting Selected Article'
})
if (confirmed) {
try {
await articleStore.removeArticle(data)
await init()
} catch (e) {
alertStore.show({
type: 'error',
message: 'Something went wrong while deleting article.'
})
}
}
}
</script>
<template>
<div>
<div class="container mt-3 mb-6">
<div class="my-3 flex justify-between items-center">
<div clas="text-xl font-light">Latest Articles</div>
<div class="float-right">
<NuxtLink
type="button"
class="py-3 px-4 inline-flex items-center gap-x-2 text-sm font-semibold rounded-lg border border-transparent bg-blue-100 text-blue-800 hover:bg-blue-200 disabled:opacity-50 disabled:pointer-events-none dark:hover:bg-blue-900 dark:text-blue-400 dark:focus:outline-none dark:focus:ring-1 dark:focus:ring-gray-600"
:to="'/bulletin-board/add'"
>
<span
class="flex-shrink-0 size-4 z-0 text-blue-800 dark:text-blue-400 i-[mdi--plus]"
></span>
<span class="md:block hidden">Create New Article</span>
</NuxtLink>
</div>
</div>
<!-- TODO: Dropdown and tooltip working on v-show, but not on v-if. -->
<!-- and need to trigger modal-related components before the dropdown and tooltip working -->
<div
v-show="!loading && articles.length"
class="grid grid-cols-1 gap-4"
>
<div
v-for="article in articles"
:key="article.id"
class="p-4 flex flex-col bg-white border shadow-sm rounded-xl cursor-pointer hover:shadow-lg transition dark:bg-slate-900 dark:border-gray-700 dark:shadow-slate-700/[.7]"
>
<div class="flex justify-between items-center">
<h3 @click="showArticleDetails(article.id)" class="text-lg font-bold text-gray-800 dark:text-white">
Card action
</h3>
<ActionButton
v-if="article.user_id === user.id"
:key="article.id"
:article="article"
@deleteArticle="deleteArticle"
/>
</div>
<div @click="showArticleDetails(article.id)" class="py-2">
<div class="mt-1 text-gray-500 dark:text-gray-400">
<div class="truncate-content" v-html="article.content"></div>
</div>
<p class="mt-5 text-xs text-gray-500 dark:text-gray-500">
{{
article.updated_at && article.created_at !== article.updated_at
? 'updated on ' + $dayjs(article.updated_at).format('MMM DD, YYYY hh:mm a')
: $dayjs(article.created_at).format('MMM DD, YYYY hh:mm a')
}}
</p>
</div>
</div>
</div>
<div
v-if="loading"
class="flex flex-col bg-white border border-gray-200 shadow-sm rounded-xl p-4 md:p-5 dark:bg-slate-900 dark:border-gray-700 dark:text-gray-400"
>
<div class="flex animate-pulse">
<div class="ms-4 mt-2 w-full">
<h3
class="h-4 bg-gray-200 rounded-full dark:bg-gray-700"
style="width: 40%"
>
</h3>
<ul class="mt-5 space-y-3 list-none">
<li
class="w-full h-4 bg-gray-200 rounded-full dark:bg-gray-700"
></li>
</ul>
</div>
</div>
</div>
<div v-if="!loading && !articles.length" class="p-3 text-center">
Empty article data
</div>
</div>
<NuxtPage />
</div>
</template>
<style lang="scss"></style> ArticleListActionButton.vue <script setup>
const props = defineProps({
article: {
type: Object,
default: null
}
})
const emit = defineEmits(['deleteArticle'])
function removeArticle (id) {
emit('deleteArticle', id)
}
</script>
<template>
<div class="hs-dropdown relative inline-flex [--trigger:hover]">
<button
:id="`hsArticleActionDropdown${article?.id ?? ''}`"
type="button"
class="hs-dropdown-toggle flex justify-center items-center size-9 text-sm font-semibold rounded-full bg-white text-gray-800 hover:shadow-sm hover:bg-gray-50 disabled:opacity-50 disabled:pointer-events-none dark:bg-slate-900 dark:border-gray-700 dark:text-white dark:hover:bg-gray-800"
>
<span
class="flex-none size-4 text-gray-600 i-[fe--elipsis-v]"
></span>
</button>
<div
class="hs-dropdown-menu transition-[opacity,margin] duration hs-dropdown-open:opacity-100 opacity-0 hidden min-w-60 bg-white shadow-md rounded-lg p-2 mt-2 border border-neutral-100 dark:bg-neutral-800 dark:border-neutral-700 dark:divide-neutral-700 after:h-4 after:absolute after:-bottom-4 after:start-0 after:w-full before:h-4 before:absolute before:-top-4 before:start-0 before:w-full"
:aria-labelledby="`hsArticleActionDropdown${article?.id ?? ''}`"
>
<div class="py-2 first:pt-0 last:pb-0">
<span
class="block py-2 px-3 text-xs font-medium uppercase text-gray-400 dark:text-gray-500"
>
Actions
</span>
<NuxtLink
class="flex items-center gap-x-3.5 py-2 px-3 rounded-lg text-sm text-gray-800 cursor-pointer hover:bg-gray-100 focus:outline-none focus:bg-gray-100 dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-gray-300 dark:focus:bg-gray-700"
:to="`/bulletin-board/${article?.id || ''}`"
>
<span class="mr-1 flex-none size-4 text-sky-600 i-[mdi--pencil]"></span>
Edit
</NuxtLink>
<button
class="w-full flex items-center gap-x-3.5 py-2 px-3 rounded-lg text-sm text-gray-800 cursor-pointer hover:bg-gray-100 focus:outline-none focus:bg-gray-100 dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-gray-300 dark:focus:bg-gray-700"
@click="removeArticle(article?.id)"
>
<span class="mr-1 flex-none size-4 text-red-600 i-[mdi--delete]"></span>
Delete
</button>
</div>
</div>
</div>
<!-- Tooltip sample action buttons -->
<!-- <div class="flex items-center gap-x-1 z-[100]">
<div class="hs-tooltip inline-block">
<NuxtLink
class="hs-tooltip-toggle size-8 inline-flex justify-center items-center gap-x-2 text-sm font-semibold rounded-full border border-transparent text-sky-700 hover:text-sky-500 disabled:opacity-50 disabled:pointer-events-none dark:text-neutral-400"
:to="article?.id ? `/bulletin-board/${article.id}/edit` : `#`"
>
<span class="flex-shrink-0 size-4 i-[mdi--pencil]"></span>
<span class="hs-tooltip-content hs-tooltip-shown:opacity-100 hs-tooltip-shown:visible opacity-0 transition-opacity inline-block absolute invisible z-10 py-1 px-2 bg-gray-900 text-xs font-medium text-white rounded shadow-sm dark:bg-neutral-700" role="tooltip">
Edit
</span>
</NuxtLink>
</div>
<div class="hs-tooltip inline-block">
<button
type="button"
class="hs-tooltip-toggle size-8 inline-flex justify-center items-center gap-x-2 text-sm font-semibold rounded-full border border-transparent text-red-700 hover:text-red-500 disabled:opacity-50 disabled:pointer-events-none dark:text-neutral-400"
@click="removeArticle(article?.id ?? '')"
>
<span class="flex-shrink-0 size-4 i-[mdi--delete]"></span>
<span class="hs-tooltip-content hs-tooltip-shown:opacity-100 hs-tooltip-shown:visible opacity-0 transition-opacity inline-block absolute invisible z-10 py-1 px-2 bg-gray-900 text-xs font-medium text-white rounded shadow-sm dark:bg-neutral-700" role="tooltip">
Delete
</span>
</button>
</div>
</div> -->
</template>
<style scoped></style> Now, the issue is, it is needed to trigger the modal-related components in order to show the dropdowns and tooltips, in which is some kind of weird on my end, or something I did wrong. AppHeader.vue <script setup>
import { storeToRefs } from "pinia";
import { useAuthStore } from "@/stores/authStore";
const route = useRoute();
const authStore = useAuthStore();
const { user } = storeToRefs(authStore);
async function logout() {
await authStore.logout();
}
</script>
<template>
<header class="bg-blue-500 sticky top-0 z-50">
<nav
class="relative flex flex-wrap sm:justify-start sm:flex-nowrap w-full bg-white text-sm py-4 shadow-lg dark:bg-gray-800"
>
<div
class="max-w-[85rem] w-full mx-auto px-4 sm:flex sm:items-center sm:justify-between"
>
<div class="flex items-center justify-between">
<NuxtLink
class="mx-2 my-1 flex items-center text-neutral-900 hover:text-neutral-900 focus:text-neutral-900 lg:mb-0 lg:mt-0"
:to="'/'"
>
<img
class="mr-2"
src="@/assets/img/bulletin-board.svg"
style="height: 32px"
alt="Bulletin Board Logo"
loading="lazy"
/>
</NuxtLink>
<div class="sm:hidden">
<button
type="button"
class="hs-collapse-toggle p-2 inline-flex justify-center items-center gap-x-2 rounded-lg border border-gray-200 bg-white text-gray-800 shadow-sm hover:bg-gray-50 disabled:opacity-50 disabled:pointer-events-none dark:bg-transparent dark:border-gray-700 dark:text-white dark:hover:bg-white/10 dark:focus:outline-none dark:focus:ring-1 dark:focus:ring-gray-600"
data-hs-collapse="#navbar-with-mega-menu"
aria-controls="navbar-with-mega-menu"
aria-label="Toggle navigation"
>
<span
class="hs-collapse-open:hidden flex-shrink-0 size-4 i-[mdi--menu]"
></span>
<span
class="hs-collapse-open:block hidden flex-shrink-0 size-4 i-[mdi--close]"
></span>
</button>
</div>
</div>
<div
id="navbar-with-mega-menu"
class="hs-collapse hidden overflow-hidden transition-all duration-300 basis-full grow sm:block"
>
<div
class="flex flex-col gap-5 mt-5 sm:flex-row sm:items-center sm:justify-end sm:mt-0 sm:ps-5"
>
<div v-if="!authStore.isAuthenticated">
<NuxtLink
v-if="route.name === 'index'"
class="font-medium text-gray-600 hover:text-gray-400 dark:text-gray-400 dark:hover:text-gray-500 dark:focus:outline-none dark:focus:ring-1 dark:focus:ring-gray-600"
:to="'/register'"
>
Register
</NuxtLink>
<NuxtLink
v-if="route.name === 'register'"
class="font-medium text-gray-600 hover:text-gray-400 dark:text-gray-400 dark:hover:text-gray-500 dark:focus:outline-none dark:focus:ring-1 dark:focus:ring-gray-600"
:to="'/'"
>
Login
</NuxtLink>
</div>
<div
v-if="authStore.isAuthenticated"
class="hs-dropdown [--strategy:static] sm:[--strategy:fixed] [--adaptive:none]"
>
<button
id="hs-mega-menu-basic-dr"
type="button"
class="flex items-center w-full text-gray-600 hover:text-gray-400 font-medium dark:text-gray-400 dark:hover:text-gray-500"
>
{{ user.name }}
<span
class="ms-1 flex-shrink-0 size-4 i-[mdi--chevron-down]"
></span>
</button>
<div
class="hs-dropdown-menu transition-[opacity,margin] duration-[0.1ms] sm:duration-[150ms] hs-dropdown-open:opacity-100 opacity-0 sm:w-48 z-10 bg-white sm:shadow-md rounded-lg p-2 dark:bg-gray-800 sm:dark:border dark:border-gray-700 dark:divide-gray-700 before:absolute top-full sm:border before:-top-5 before:start-0 before:w-full before:h-5 hidden"
>
<NuxtLink
class="flex items-center gap-x-3.5 py-2 px-3 rounded-lg text-sm text-gray-800 hover:bg-gray-100 focus:ring-2 focus:ring-blue-500 dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-gray-300"
@click="logout"
>
Logout
</NuxtLink>
</div>
</div>
</div>
</div>
</div>
</nav>
</header>
</template> Kindly look further with the files under this repo: Hoping from the dev team and other who encounter the same issue to share with their thoughts, leave a suggestion or help on this issue. TIA. |
Beta Was this translation helpful? Give feedback.
-
You may find simple integration example here. |
Beta Was this translation helpful? Give feedback.
-
Hi @jahaganiev , I temporarily resolve this issue by following the proposed solution in the comment here although the implementation is somewhat like an React. It is tweak from the plugin file and somewhat delayed the instance of the preline static methods. plugins/preline.client.ts import "preline/preline";
import { type IStaticMethods } from "preline/preline";
declare global {
interface Window {
HSStaticMethods: IStaticMethods;
}
}
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.hook("page:finish", () => {
setTimeout(() => {
window.HSStaticMethods.autoInit();
}, 500)
});
}); At first I tried it in around .5 secs. delay. But I decide to put it in a lowest delay possible. I haven't tried with the lowest point based on the implementation above but I tried around .1 sec and sometimes the dropdown is sometimes working when I fast refresh the page. I hope this helps for the other devs out there who is encounter the same issue as I am. Thank you for the support and effort for this issue. |
Beta Was this translation helpful? Give feedback.
-
Context
I'm creating an simple bulletin board where you can able to post an article with title and its content.
Issue
I'm trying to put an Action dropdown beside the Card title to be able to delete or edit the selected article, but the Dropdown component is not working.
Setup
I'm following the Preline's installation guide on Nuxt and I'm current on Nuxt 3.
Code
I'm creating an different component called ActionButton.vue to try if it is needed to separate its component to a single file component approach
pages/bulletin-board.vue - where the article cards is shown with the Action button inside of it
for more reference, please see this repository for the overall setup and implementation and look up for the file name I declared above to easily locate my issue.
Any help, guide and suggestion is welcome. Hoping for the resolution for this.
TIA.
Beta Was this translation helpful? Give feedback.
All reactions