Preline JS Collapse Fix
March 29, 2025 · AI Conversations
<script>
import { ref, onMounted } from 'vue';
import { Link,usePage } from '@inertiajs/vue3';
import LanguageSwitcher from '@/Components/LanguageSwitcher.vue';
</script>
Sign in
Hire us
Work
Services
About
Careers
Blog
About
Services
Blog
in laravel vue interia js
above tailwind css Hamburg mobile menu not collasping not work
You're using the `hs-collapse-toggle` and `data-hs-collapse` attributes, which are part of **Preline UI** or **HSUI (HyperStack)** — these require **JavaScript initialization** for the collapse functionality to work.
### ✅ Here's how to fix the mobile collapse toggle:
—
### ✅ **Step 1: Ensure Preline JS is Loaded**
Make sure you **import Preline's JS** in your main JavaScript entry file, typically `resources/js/app.js` or `main.js`.
import 'preline'; // Ensure this is added
Also, ensure Preline is installed:
yarn add preline
# OR
npm install preline
—
### ✅ **Step 2: Initialize Preline After Mounting**
Add this inside your “ block in your layout or component where the nav exists:
import { onMounted } from 'vue';
import 'preline';
onMounted(() => {
import('preline').then(({ default: HS }) => {
window.HSStaticMethods.autoInit(); // Initializes all HS components including collapse
});
});
—
### ✅ **Step 3: Check HTML Attributes**
You're already using the correct attributes:
<button
class="hs-collapse-toggle ..."
data-hs-collapse="#hs-navbar-hcail"
...
>
And the corresponding collapse target:
<div id="hs-navbar-hcail" class="hs-collapse hidden ..." >
✅ That’s correct.
—
### ⚠️ Common Issue
Make sure **no JavaScript errors** occur in your console. If `autoInit` fails to run, Preline won’t know to attach collapse logic.
—
### Optional: Try Alpine.js (If You Want Simpler Control)
If you’re not using full Preline JS and want simple toggling, you could use Alpine.js instead for lightweight interaction.
—
Let me know if you want a version using **Alpine.js** or **native Vue state toggle** instead of Preline.
const isMenuOpen=ref(false);
function toggleMenu() {
isMenuOpen.value = !isMenuOpen.value;
}
—
### ✅ **Update Your “ block:**
<script setup>
import { ref } from 'vue';
import { Link, usePage } from '@inertiajs/vue3';
import LanguageSwitcher from '@/Components/LanguageSwitcher.vue';
const isMenuOpen = ref(false);
const toggleMenu = () => {
isMenuOpen.value = !isMenuOpen.value;
};
</script>
—
### ✅ **Update Your Button and Collapse Menu in the Template:**
#### 🟢 Toggle Button:
Replace your current toggle button with:
<!-- Toggle Button -->
<button
@click="toggleMenu"
class="size-9.5 flex justify-center items-center text-sm font-semibold rounded-xl border border-gray-200 text-black hover:bg-gray-100 dark:text-white dark:border-neutral-700 dark:hover:bg-neutral-700"
aria-label="Toggle navigation"
>
<svg
v-if="!isMenuOpen"
class="shrink-0 size-4"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
stroke-width="2"
>
<line x1="3" x2="21" y1="6" y2="6" />
<line x1="3" x2="21" y1="12" y2="12" />
<line x1="3" x2="21" y1="18" y2="18" />
</svg>
<svg
v-else
class="shrink-0 size-4"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
stroke-width="2"
>
<path d="M18 6L6 18" />
<path d="M6 6l12 12" />
</svg>
</button>
—
#### 🟢 Collapsible Menu Section:
Replace your collapsible menu div with:
<!-- Mobile Collapse -->
<div
:class="[
'transition-all duration-300 overflow-hidden lg:block lg:w-auto lg:basis-auto lg:order-2 lg:col-span-6',
isMenuOpen ? 'block' : 'hidden'
]"
>
<div class="flex flex-col gap-y-4 mt-5 lg:flex-row lg:justify-center lg:items-center lg:gap-x-7 lg:mt-0">
<div><a class="relative inline-block text-black dark:text-white" href="#">Work</a></div>
<div><a class="inline-block text-black dark:text-white" href="#">Services</a></div>
<div><a class="inline-block text-black dark:text-white" href="#">About</a></div>
<div><a class="inline-block text-black dark:text-white" href="#">Careers</a></div>
<div><a class="inline-block text-black dark:text-white" href="#">Blog</a></div>
</div>
</div>
—
### 🔄 Summary
– `isMenuOpen` controls the open/close state.
– Toggle button uses Vue's `@click` to flip the state.
– Menu `div` shows/hides using conditional classes.
This is lightweight, Vue-native, and does **not** depend on Preline or Alpine.js. Let me know if you want it animated too!
<script>
import { ref, onMounted } from 'vue';
import { Link,usePage } from '@inertiajs/vue3';
import LanguageSwitcher from '@/Components/LanguageSwitcher.vue';
const isMenuOpen = ref(false);
const toggleMenu = () => {
isMenuOpen.value = !isMenuOpen.value;
};
</script>
Sign in
Hire us
Work
Services
About
Careers
Blog
About
Services
Blog
now above code work just display
button when menu collapspe
—
### ✅ Replace This Section:
<svg class="hs-collapse-open:hidden shrink-0 size-4" ...>...</svg>
<svg class="hs-collapse-open:block hidden shrink-0 size-4" ...>...</svg>
—
### ✅ With This Vue Condition:
<!-- Hamburger Icon -->
<svg
v-if="!isMenuOpen"
class="shrink-0 size-4"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
stroke-width="2"
>
<line x1="3" x2="21" y1="6" y2="6" />
<line x1="3" x2="21" y1="12" y2="12" />
<line x1="3" x2="21" y1="18" y2="18" />
</svg>
<!-- Close Icon -->
<svg
v-else
class="shrink-0 size-4"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
stroke-width="2"
>
<path d="M18 6L6 18" />
<path d="M6 6l12 12" />
</svg>
—
### ✅ Final Result
Your toggle button block should look like this now:
<button
type="button"
@click="toggleMenu"
class="size-9.5 flex justify-center items-center text-sm font-semibold rounded-xl border border-gray-200 text-black hover:bg-gray-100 focus:outline-hidden focus:bg-gray-100 disabled:opacity-50 disabled:pointer-events-none dark:text-white dark:border-neutral-700 dark:hover:bg-neutral-700 dark:focus:bg-neutral-700"
aria-label="Toggle navigation"
>
<svg
v-if="!isMenuOpen"
class="shrink-0 size-4"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
stroke-width="2"
>
<line x1="3" x2="21" y1="6" y2="6" />
<line x1="3" x2="21" y1="12" y2="12" />
<line x1="3" x2="21" y1="18" y2="18" />
</svg>
<svg
v-else
class="shrink-0 size-4"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke="currentColor"
stroke-width="2"
>
<path d="M18 6L6 18" />
<path d="M6 6l12 12" />
</svg>
</button>
Now it’ll visually switch between the burger and close icon when toggling `isMenuOpen`. 🎉
Let me know if you want it animated or with smooth transitions!
class="hs-collapse-open:block hidden ..."
That class combo is from Preline and uses its JS behavior to toggle visibility, which you’re no longer using — you're managing state with Vue now. So `v-else` is working **but `hidden` is overriding it**, making the `X` icon invisible even though it’s technically rendered.
—
### ✅ ✅ Fix: **Remove Preline classes from the “**
Update the **close (X) icon SVG** like this:
<svg
v-else
class="shrink-0 size-4"
xmlns="http://www.w3.org/2000/svg"
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
stroke="currentColor"
stroke-width="2"
stroke-linecap="round"
stroke-linejoin="round"
>
<path d="M18 6L6 18" />
<path d="M6 6l12 12" />
</svg>
—
### ✅ Summary
– `v-if="!isMenuOpen"` for the hamburger icon.
– `v-else` for the X icon.
– **No `hidden` class**, because Vue’s conditional rendering handles visibility.
—
Let me know if you want the toggle button to animate with a smooth icon transition too!
—
### ✅ Step 1: Wrap the collapsible menu with “
Update your collapse menu like this:
<Transition
enter-active-class="transition ease-out duration-300"
enter-from-class="opacity-0 -translate-y-4"
enter-to-class="opacity-100 translate-y-0"
leave-active-class="transition ease-in duration-200"
leave-from-class="opacity-100 translate-y-0"
leave-to-class="opacity-0 -translate-y-4"
>
<div
v-if="isMenuOpen"
class="basis-full grow lg:block lg:w-auto lg:basis-auto lg:order-2 lg:col-span-6"
>
<div class="flex flex-col gap-y-4 gap-x-0 mt-5 lg:flex-row lg:justify-center lg:items-center lg:gap-y-0 lg:gap-x-7 lg:mt-0">
<div><a class="relative inline-block text-black dark:text-white" href="#">Work</a></div>
<div><a class="inline-block text-black dark:text-white" href="#">Services</a></div>
<div><a class="inline-block text-black dark:text-white" href="#">About</a></div>
<div><a class="inline-block text-black dark:text-white" href="#">Careers</a></div>
<div><a class="inline-block text-black dark:text-white" href="#">Blog</a></div>
</div>
</div>
</Transition>
—
### ✅ Step 2: Remove `:class` with `isMenuOpen ? 'block' : 'hidden'`
Since “ with `v-if` controls rendering and visibility, you don’t need to manually toggle classes anymore.
—
### 💡 Result:
– When the menu opens: it slides down with a fade.
– When it closes: it slides up and fades out.
—
Let me know if you’d like a different animation style like **slide from left/right**, or **scale/pop** effect!