mirror of
https://github.com/Frooodle/Stirling-PDF.git
synced 2025-09-08 17:51:20 +02:00
started fresh, much better now
This commit is contained in:
parent
d17d10b240
commit
8bcdb4cf9e
@ -290,6 +290,21 @@ span.icon-text::after {
|
||||
color: var(--md-sys-color-on-surface-variant);
|
||||
}
|
||||
|
||||
.nav-link {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
max-width: 95vw;
|
||||
}
|
||||
|
||||
.chevron-icon {
|
||||
margin-left: auto;
|
||||
transition: transform 0.3s ease;
|
||||
}
|
||||
|
||||
[aria-expanded="true"] > .chevron-icon {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
|
||||
.nav-item {
|
||||
position: relative;
|
||||
}
|
||||
@ -484,27 +499,88 @@ html[dir="rtl"] .dropdown-menu {
|
||||
display: inline-flex;
|
||||
}
|
||||
|
||||
@media (min-width:992px) {
|
||||
@media (max-width:1199.98px) {
|
||||
.navbar-collapse .dropdown-menu {
|
||||
width: 100%;
|
||||
}
|
||||
.navbar-collapse .dropdown-menu-wrapper {
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
.navbar-collapse .dropdown-mw-28 {
|
||||
min-width: 0;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width:1200px) {
|
||||
/* This CSS-based hover is disabled because it conflicts with Bootstrap's JavaScript.
|
||||
Hover functionality is now handled in navbar.js and search.js */
|
||||
/*
|
||||
.dropdown:hover .dropdown-menu {
|
||||
display: block;
|
||||
margin-top: 0;
|
||||
}
|
||||
*/
|
||||
|
||||
/* .icon-hide {
|
||||
display: none;
|
||||
} */
|
||||
}
|
||||
|
||||
@media (max-width:1199px) {
|
||||
.icon-hide {
|
||||
display: inline-flex;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width:1200px) {
|
||||
.icon-hide {
|
||||
display: none;
|
||||
}
|
||||
.chevron-icon {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 1199.98px) {
|
||||
.navbar-collapse .dropdown-menu {
|
||||
width: 100vw !important;
|
||||
max-width: 100vw !important;
|
||||
left: 0 !important;
|
||||
}
|
||||
|
||||
.navbar-collapse .dropdown-mega .dropdown-menu {
|
||||
max-height: 60vh;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.navbar-collapse .dropdown-mega .dropdown-menu-wrapper {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
#favoritesDropdown,
|
||||
#languageDropdown + .dropdown-menu .dropdown-menu-wrapper,
|
||||
#searchDropdown + .dropdown-menu .dropdown-menu-wrapper {
|
||||
padding: 1.5rem 1rem;
|
||||
}
|
||||
|
||||
#favoritesDropdown, #languageSelection, #searchResults {
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
#languageSelection {
|
||||
grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
|
||||
}
|
||||
|
||||
.navbar-collapse .dropdown-menu-wrapper {
|
||||
width: 95vw;
|
||||
box-sizing: border-box;
|
||||
margin-left: 0 !important;
|
||||
padding: 0 !important;
|
||||
}
|
||||
.navbar-collapse .dropdown-mw-28 {
|
||||
min-width: 0;
|
||||
}
|
||||
.icon-hide {
|
||||
display: inline-flex;
|
||||
}
|
||||
|
||||
.navbar-collapse .dropdown-item {
|
||||
margin-left: 0 !important;
|
||||
}
|
||||
|
||||
.container {
|
||||
margin-left: 0px !important;
|
||||
padding-left: 4px !important;
|
||||
}
|
||||
}
|
||||
|
||||
.go-pro-link {
|
||||
@ -558,6 +634,12 @@ html[dir="rtl"] .dropdown-menu {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.feature-group {
|
||||
min-width: 10rem;
|
||||
}
|
||||
}
|
||||
|
||||
.feature-rows {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
@ -42,6 +42,58 @@ function toolsManager() {
|
||||
});
|
||||
}
|
||||
|
||||
function setupDropdownHovers() {
|
||||
const dropdowns = document.querySelectorAll('.navbar-nav > .nav-item.dropdown');
|
||||
|
||||
dropdowns.forEach(dropdown => {
|
||||
const toggle = dropdown.querySelector('[data-bs-toggle="dropdown"]');
|
||||
if (!toggle) return;
|
||||
|
||||
// Skip search dropdown, it has its own logic
|
||||
if (toggle.id === 'searchDropdown') {
|
||||
return;
|
||||
}
|
||||
|
||||
let timeout;
|
||||
const instance = bootstrap.Dropdown.getOrCreateInstance(toggle);
|
||||
|
||||
dropdown.addEventListener('mouseenter', () => {
|
||||
if (window.innerWidth >= 1200) {
|
||||
clearTimeout(timeout);
|
||||
if (!instance._isShown()) {
|
||||
instance.show();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
dropdown.addEventListener('mouseleave', () => {
|
||||
if (window.innerWidth >= 1200) {
|
||||
timeout = setTimeout(() => {
|
||||
if (instance._isShown()) {
|
||||
instance.hide();
|
||||
}
|
||||
}, 200);
|
||||
}
|
||||
});
|
||||
|
||||
toggle.addEventListener('click', (e) => {
|
||||
if (window.innerWidth >= 1200) {
|
||||
// On desktop, prevent Bootstrap's default click toggle
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
// Still allow navigation if it's a link
|
||||
const href = toggle.getAttribute('href');
|
||||
if (href && href !== '#') {
|
||||
window.location.href = href;
|
||||
}
|
||||
}
|
||||
// On mobile (< 1200px), this listener does nothing, allowing default click behavior.
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
window.tooltipSetup = () => {
|
||||
const tooltipElements = document.querySelectorAll('[title]');
|
||||
|
||||
@ -56,23 +108,27 @@ window.tooltipSetup = () => {
|
||||
document.body.appendChild(customTooltip);
|
||||
|
||||
element.addEventListener('mouseenter', (event) => {
|
||||
customTooltip.style.display = 'block';
|
||||
customTooltip.style.left = `${event.pageX + 10}px`; // Position tooltip slightly away from the cursor
|
||||
customTooltip.style.top = `${event.pageY + 10}px`;
|
||||
if (window.innerWidth >= 1200) {
|
||||
customTooltip.style.display = 'block';
|
||||
customTooltip.style.left = `${event.pageX + 10}px`;
|
||||
customTooltip.style.top = `${event.pageY + 10}px`;
|
||||
}
|
||||
});
|
||||
|
||||
// Update the position of the tooltip as the user moves the mouse
|
||||
element.addEventListener('mousemove', (event) => {
|
||||
customTooltip.style.left = `${event.pageX + 10}px`;
|
||||
customTooltip.style.top = `${event.pageY + 10}px`;
|
||||
if (window.innerWidth >= 1200) {
|
||||
customTooltip.style.left = `${event.pageX + 10}px`;
|
||||
customTooltip.style.top = `${event.pageY + 10}px`;
|
||||
}
|
||||
});
|
||||
|
||||
// Hide the tooltip when the mouse leaves
|
||||
element.addEventListener('mouseleave', () => {
|
||||
customTooltip.style.display = 'none';
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
tooltipSetup();
|
||||
setupDropdownHovers();
|
||||
});
|
||||
|
@ -79,33 +79,67 @@ const searchDropdown = document.getElementById('searchDropdown');
|
||||
const searchInput = document.getElementById('navbarSearchInput');
|
||||
const dropdownMenu = searchDropdown.querySelector('.dropdown-menu');
|
||||
|
||||
// Handle dropdown shown event
|
||||
searchDropdown.addEventListener('shown.bs.dropdown', function () {
|
||||
searchInput.focus();
|
||||
// Create a single dropdown instance
|
||||
const dropdownInstance = new bootstrap.Dropdown(searchDropdown);
|
||||
|
||||
// Function to handle showing the dropdown
|
||||
function showSearchDropdown() {
|
||||
if (!dropdownInstance._isShown()) {
|
||||
dropdownInstance.show();
|
||||
}
|
||||
setTimeout(() => searchInput.focus(), 150); // Focus after animation
|
||||
}
|
||||
|
||||
// Handle click for mobile
|
||||
searchDropdown.addEventListener('click', function (e) {
|
||||
if (window.innerWidth < 1200) {
|
||||
// Let Bootstrap's default toggling handle it, but ensure focus
|
||||
if (!dropdownInstance._isShown()) {
|
||||
// Use a small delay to allow the dropdown to open before focusing
|
||||
setTimeout(() => searchInput.focus(), 150);
|
||||
}
|
||||
} else {
|
||||
// On desktop, hover opens the dropdown, so a click shouldn't toggle it.
|
||||
e.preventDefault();
|
||||
}
|
||||
});
|
||||
|
||||
// Handle hover opening
|
||||
// Handle hover for desktop
|
||||
searchDropdown.addEventListener('mouseenter', function () {
|
||||
const dropdownInstance = new bootstrap.Dropdown(searchDropdown);
|
||||
dropdownInstance.show();
|
||||
|
||||
setTimeout(() => {
|
||||
searchInput.focus();
|
||||
}, 100);
|
||||
});
|
||||
|
||||
// Handle mouse leave
|
||||
searchDropdown.addEventListener('mouseleave', function () {
|
||||
// Check if current value is empty (including if user typed and then deleted)
|
||||
if (searchInput.value.trim().length === 0) {
|
||||
searchInput.blur();
|
||||
const dropdownInstance = new bootstrap.Dropdown(searchDropdown);
|
||||
dropdownInstance.hide();
|
||||
if (window.innerWidth >= 1200) {
|
||||
showSearchDropdown();
|
||||
}
|
||||
});
|
||||
|
||||
searchDropdown.addEventListener('hidden.bs.dropdown', function () {
|
||||
if (searchInput.value.trim().length === 0) {
|
||||
searchInput.blur();
|
||||
// Handle mouse leave for desktop
|
||||
searchDropdown.addEventListener('mouseleave', function (e) {
|
||||
if (window.innerWidth >= 1200) {
|
||||
// A short delay to allow moving mouse from button to menu
|
||||
setTimeout(() => {
|
||||
const dropdownMenu = searchDropdown.querySelector('.dropdown-menu');
|
||||
if (!dropdownMenu) return;
|
||||
|
||||
// Check if either the button or the menu is still hovered
|
||||
const isHoveringButton = searchDropdown.matches(':hover');
|
||||
const isHoveringMenu = dropdownMenu.matches(':hover');
|
||||
|
||||
if (!isHoveringButton && !isHoveringMenu && searchInput.value.trim().length === 0) {
|
||||
dropdownInstance.hide();
|
||||
}
|
||||
}, 200);
|
||||
}
|
||||
});
|
||||
|
||||
// Hide dropdown if it's open and user clicks outside
|
||||
document.addEventListener('click', function(e) {
|
||||
if (!searchDropdown.contains(e.target) && dropdownInstance._isShown()) {
|
||||
if (searchInput.value.trim().length === 0) {
|
||||
dropdownInstance.hide();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Keep dropdown open if search input is clicked
|
||||
searchInput.addEventListener('click', function (e) {
|
||||
e.stopPropagation();
|
||||
});
|
||||
|
@ -31,6 +31,10 @@
|
||||
const isHighDPI = systemDPR > 1.4;
|
||||
|
||||
function scaleNav() {
|
||||
if (window.innerWidth < 1200) {
|
||||
// Don't scale nav on mobile
|
||||
return;
|
||||
}
|
||||
const currentDPR = window.devicePixelRatio || 1;
|
||||
const browserZoom = currentDPR / systemDPR;
|
||||
|
||||
|
@ -45,9 +45,10 @@
|
||||
apps
|
||||
</span>
|
||||
<span class="icon-text" th:data-text="#{navbar.allTools}" th:text="#{navbar.allTools}"></span>
|
||||
<span class="material-symbols-rounded chevron-icon">expand_more</span>
|
||||
</a>
|
||||
<div class="dropdown-menu dropdown-menu-tp" aria-labelledby="navbarDropdown-1">
|
||||
<div class="dropdown-menu-wrapper" style="justify-content: center; display:flex">
|
||||
<div class="dropdown-menu-wrapper" style="max-width: 95vw !important;">
|
||||
<div class="feature-rows">
|
||||
|
||||
<th:block th:insert="~{fragments/navElements.html :: navElements}"></th:block>
|
||||
@ -117,9 +118,10 @@
|
||||
star
|
||||
</span>
|
||||
<span class="icon-text icon-hide" th:data-text="#{navbar.favorite}" th:text="#{navbar.favorite}"></span>
|
||||
<span class="material-symbols-rounded chevron-icon">expand_more</span>
|
||||
</a>
|
||||
<div class="dropdown-menu dropdown-menu-tp dropdown-mw-28" aria-labelledby="navbarDropdown-5">
|
||||
<div class="dropdown-menu-wrapper px-xl-2 px-2" id="favoritesDropdown">
|
||||
<div class="dropdown-menu dropdown-menu-tp dropdown-mw-28" role="menu" aria-labelledby="navbarDropdown-5">
|
||||
<div class="dropdown-menu-wrapper px-xl-2 px-2" id="favoritesDropdown" style="max-width: 95vw !important; ">
|
||||
<!-- Dropdown items will be added here by JavaScript -->
|
||||
</div>
|
||||
</div>
|
||||
@ -140,9 +142,10 @@
|
||||
language
|
||||
</span>
|
||||
<span class="icon-text icon-hide" th:data-text="#{navbar.language}" th:text="#{navbar.language}"></span>
|
||||
<span class="material-symbols-rounded chevron-icon">expand_more</span>
|
||||
</a>
|
||||
<div class="dropdown-menu dropdown-menu-tp" aria-labelledby="languageDropdown">
|
||||
<div class="dropdown-menu-wrapper px-xl-2 px-2">
|
||||
<div class="dropdown-menu-wrapper px-xl-2 px-2" style="max-width: 95vw !important;">
|
||||
<div id="languageSelection" class="scrollable-y lang_dropdown-mw scalable-languages-container">
|
||||
<th:block th:insert="~{fragments/languages :: langs}"></th:block>
|
||||
</div>
|
||||
@ -157,9 +160,10 @@
|
||||
search
|
||||
</span>
|
||||
<span class="icon-text icon-hide">Search</span>
|
||||
<span class="material-symbols-rounded chevron-icon">expand_more</span>
|
||||
</a>
|
||||
<div class="dropdown-menu dropdown-menu-tp" aria-labelledby="searchDropdown">
|
||||
<div class="dropdown-menu-wrapper px-xl-2 px-2">
|
||||
<div class="dropdown-menu-wrapper px-xl-2 px-2" style="max-width: 95vw !important;">
|
||||
<form th:action="@{''}" class="d-flex p-2 search-form" id="searchForm">
|
||||
<input class="form-control search-input" type="search" th:placeholder="#{navbar.search}"
|
||||
aria-label="Search" id="navbarSearchInput">
|
||||
@ -172,7 +176,7 @@
|
||||
|
||||
<li class="nav-item" th:if="${!@runningProOrHigher}">
|
||||
<a href="https://stirlingpdf.com/pricing" class="nav-link go-pro-link" target="_blank"
|
||||
rel="noopener noreferrer">
|
||||
rel="noopener noreferrer" aria-label="Upgrade to PRO" title="Upgrade to PRO">
|
||||
<span class="go-pro-badge" th:text="#{enterpriseEdition.button}"></span>
|
||||
</a>
|
||||
</li>
|
||||
|
Loading…
Reference in New Issue
Block a user