mirror of
https://github.com/wahyd4/links.git
synced 2026-08-08 21:04:53 +10:00
Update dropdown style
This commit is contained in:
@@ -6,18 +6,29 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
const languageOptions = document.getElementById('language-options');
|
||||
|
||||
const isMobile = () => window.innerWidth < 768; // matches Tailwind's md breakpoint
|
||||
const reduceMotion = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
||||
const ANIM_MS = reduceMotion ? 0 : 320;
|
||||
|
||||
function isOpen(dropdown) {
|
||||
return dropdown ? dropdown.classList.contains('menu-open') : false;
|
||||
}
|
||||
|
||||
function openDropdown(dropdown) {
|
||||
dropdown.classList.remove('hidden');
|
||||
dropdown.classList.add('menu-open');
|
||||
if (isMobile()) {
|
||||
document.body.style.overflow = 'hidden';
|
||||
}
|
||||
}
|
||||
|
||||
function closeDropdown(dropdown) {
|
||||
dropdown.classList.add('hidden');
|
||||
dropdown.classList.remove('menu-open');
|
||||
if (isMobile()) {
|
||||
document.body.style.overflow = '';
|
||||
// Release body scroll only after the slide-up animation finishes
|
||||
setTimeout(() => {
|
||||
if (!isOpen(moreMenuDropdown) && !isOpen(languageOptions)) {
|
||||
document.body.style.overflow = '';
|
||||
}
|
||||
}, ANIM_MS);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,12 +36,12 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
button.addEventListener('click', function(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
if (dropdown.classList.contains('hidden')) {
|
||||
if (!isOpen(dropdown)) {
|
||||
// Close other dropdown first
|
||||
if (dropdown === moreMenuDropdown && languageOptions && !languageOptions.classList.contains('hidden')) {
|
||||
if (dropdown === moreMenuDropdown && isOpen(languageOptions)) {
|
||||
closeDropdown(languageOptions);
|
||||
}
|
||||
if (dropdown === languageOptions && moreMenuDropdown && !moreMenuDropdown.classList.contains('hidden')) {
|
||||
if (dropdown === languageOptions && isOpen(moreMenuDropdown)) {
|
||||
closeDropdown(moreMenuDropdown);
|
||||
}
|
||||
openDropdown(dropdown);
|
||||
@@ -58,31 +69,25 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
// Close dropdowns when clicking outside
|
||||
document.addEventListener('click', function(e) {
|
||||
if (moreMenuDropdown && !moreMenuButton.contains(e.target) && !moreMenuDropdown.contains(e.target)) {
|
||||
closeDropdown(moreMenuDropdown);
|
||||
if (isOpen(moreMenuDropdown)) closeDropdown(moreMenuDropdown);
|
||||
}
|
||||
if (languageOptions && !languageSelectorButton.contains(e.target) && !languageOptions.contains(e.target)) {
|
||||
closeDropdown(languageOptions);
|
||||
if (isOpen(languageOptions)) closeDropdown(languageOptions);
|
||||
}
|
||||
});
|
||||
|
||||
// Close dropdowns on Escape key
|
||||
document.addEventListener('keydown', function(e) {
|
||||
if (e.key === 'Escape') {
|
||||
if (moreMenuDropdown && !moreMenuDropdown.classList.contains('hidden')) {
|
||||
closeDropdown(moreMenuDropdown);
|
||||
}
|
||||
if (languageOptions && !languageOptions.classList.contains('hidden')) {
|
||||
closeDropdown(languageOptions);
|
||||
}
|
||||
if (isOpen(moreMenuDropdown)) closeDropdown(moreMenuDropdown);
|
||||
if (isOpen(languageOptions)) closeDropdown(languageOptions);
|
||||
}
|
||||
});
|
||||
|
||||
// Handle window resize: close mobile overlay if resizing to desktop
|
||||
window.addEventListener('resize', function() {
|
||||
if (!isMobile()) {
|
||||
if (moreMenuDropdown && !moreMenuDropdown.classList.contains('hidden')) {
|
||||
document.body.style.overflow = '';
|
||||
}
|
||||
document.body.style.overflow = '';
|
||||
}
|
||||
});
|
||||
|
||||
@@ -112,4 +117,4 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
lastScrollTop = scrollTop;
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
+35
-2
@@ -46,6 +46,39 @@
|
||||
transition: top 0.3s ease-in-out;
|
||||
}
|
||||
|
||||
/* Animated nav dropdowns.
|
||||
We toggle a `.menu-open` class instead of `hidden` so that CSS
|
||||
opacity/transform transitions run on open and close. */
|
||||
#more-menu-dropdown,
|
||||
#language-options {
|
||||
opacity: 0;
|
||||
pointer-events: none;
|
||||
transform: translateY(-10px);
|
||||
transition: opacity 0.22s ease, transform 0.22s cubic-bezier(0.28, 0.11, 0.32, 1);
|
||||
}
|
||||
#more-menu-dropdown.menu-open,
|
||||
#language-options.menu-open {
|
||||
opacity: 1;
|
||||
pointer-events: auto;
|
||||
transform: translateY(0);
|
||||
}
|
||||
/* Mobile: full-screen overlay slides down from the top */
|
||||
@media (max-width: 767px) {
|
||||
#more-menu-dropdown {
|
||||
transform: translateY(-12px);
|
||||
transition: opacity 0.28s ease, transform 0.32s cubic-bezier(0.28, 0.11, 0.32, 1);
|
||||
}
|
||||
}
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
#more-menu-dropdown,
|
||||
#language-options,
|
||||
#more-menu-dropdown.menu-open,
|
||||
#language-options.menu-open {
|
||||
transition: none;
|
||||
transform: none;
|
||||
}
|
||||
}
|
||||
|
||||
/* Line clamp utilities for truncating text */
|
||||
.line-clamp-2 {
|
||||
display: -webkit-box;
|
||||
@@ -71,7 +104,7 @@
|
||||
<i class="fas fa-bars mr-2"></i>
|
||||
{% trans "Menu" %}
|
||||
</button>
|
||||
<div id="more-menu-dropdown" class="fixed inset-0 top-[57px] w-full rounded-none overflow-y-auto md:absolute md:inset-auto md:top-auto md:right-0 md:mt-2 md:w-48 md:rounded-md md:overflow-visible bg-white shadow-xl z-20 hidden">
|
||||
<div id="more-menu-dropdown" class="fixed inset-0 top-[57px] w-full rounded-none overflow-y-auto md:absolute md:inset-auto md:top-auto md:right-0 md:mt-2 md:w-48 md:rounded-md md:overflow-visible bg-white shadow-xl z-20">
|
||||
<div class="grid grid-cols-3 gap-0.5 p-1.5 md:grid-cols-1 md:gap-0 md:p-0">
|
||||
<a href="{% url 'search' %}" class="flex flex-col items-center justify-center p-2.5 rounded-lg md:flex-row md:justify-start md:px-4 md:py-2 md:rounded-none transition-colors text-gray-700 hover:bg-gray-100">
|
||||
<svg class="w-6 h-6 mb-1 md:w-5 md:h-5 md:mr-2 md:mb-0 shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
@@ -233,7 +266,7 @@
|
||||
{% get_language_info for LANGUAGE_CODE as current_language %}
|
||||
{{ current_language.code|upper }}
|
||||
</button>
|
||||
<div id="language-options" class="absolute right-0 mt-2 py-2 w-48 bg-white rounded-md shadow-xl z-20 hidden">
|
||||
<div id="language-options" class="absolute right-0 mt-2 py-2 w-48 bg-white rounded-md shadow-xl z-20">
|
||||
<form action="{% url 'set_language' %}" method="post" id="language-form">
|
||||
{% csrf_token %}
|
||||
<input name="next" type="hidden" value="{{ request.path }}">
|
||||
|
||||
Reference in New Issue
Block a user