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);
|
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 {
|
.nav-item {
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
@ -484,27 +499,88 @@ html[dir="rtl"] .dropdown-menu {
|
|||||||
display: inline-flex;
|
display: inline-flex;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width:992px) {
|
@media (max-width:1199.98px) {
|
||||||
.dropdown:hover .dropdown-menu {
|
.navbar-collapse .dropdown-menu {
|
||||||
display: block;
|
width: 100%;
|
||||||
margin-top: 0;
|
|
||||||
}
|
}
|
||||||
|
.navbar-collapse .dropdown-menu-wrapper {
|
||||||
/* .icon-hide {
|
width: 100%;
|
||||||
display: none;
|
box-sizing: border-box;
|
||||||
} */
|
}
|
||||||
}
|
.navbar-collapse .dropdown-mw-28 {
|
||||||
|
min-width: 0;
|
||||||
@media (max-width:1199px) {
|
|
||||||
.icon-hide {
|
|
||||||
display: inline-flex;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (min-width:1200px) {
|
@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 {
|
.icon-hide {
|
||||||
display: none;
|
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 {
|
.go-pro-link {
|
||||||
@ -558,6 +634,12 @@ html[dir="rtl"] .dropdown-menu {
|
|||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@media (max-width: 768px) {
|
||||||
|
.feature-group {
|
||||||
|
min-width: 10rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.feature-rows {
|
.feature-rows {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
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 = () => {
|
window.tooltipSetup = () => {
|
||||||
const tooltipElements = document.querySelectorAll('[title]');
|
const tooltipElements = document.querySelectorAll('[title]');
|
||||||
|
|
||||||
@ -56,23 +108,27 @@ window.tooltipSetup = () => {
|
|||||||
document.body.appendChild(customTooltip);
|
document.body.appendChild(customTooltip);
|
||||||
|
|
||||||
element.addEventListener('mouseenter', (event) => {
|
element.addEventListener('mouseenter', (event) => {
|
||||||
|
if (window.innerWidth >= 1200) {
|
||||||
customTooltip.style.display = 'block';
|
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`;
|
|
||||||
});
|
|
||||||
|
|
||||||
// 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.left = `${event.pageX + 10}px`;
|
||||||
customTooltip.style.top = `${event.pageY + 10}px`;
|
customTooltip.style.top = `${event.pageY + 10}px`;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
element.addEventListener('mousemove', (event) => {
|
||||||
|
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', () => {
|
element.addEventListener('mouseleave', () => {
|
||||||
customTooltip.style.display = 'none';
|
customTooltip.style.display = 'none';
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
tooltipSetup();
|
tooltipSetup();
|
||||||
|
setupDropdownHovers();
|
||||||
});
|
});
|
||||||
|
@ -79,33 +79,67 @@ const searchDropdown = document.getElementById('searchDropdown');
|
|||||||
const searchInput = document.getElementById('navbarSearchInput');
|
const searchInput = document.getElementById('navbarSearchInput');
|
||||||
const dropdownMenu = searchDropdown.querySelector('.dropdown-menu');
|
const dropdownMenu = searchDropdown.querySelector('.dropdown-menu');
|
||||||
|
|
||||||
// Handle dropdown shown event
|
// Create a single dropdown instance
|
||||||
searchDropdown.addEventListener('shown.bs.dropdown', function () {
|
const dropdownInstance = new bootstrap.Dropdown(searchDropdown);
|
||||||
searchInput.focus();
|
|
||||||
});
|
|
||||||
|
|
||||||
// Handle hover opening
|
// Function to handle showing the dropdown
|
||||||
searchDropdown.addEventListener('mouseenter', function () {
|
function showSearchDropdown() {
|
||||||
const dropdownInstance = new bootstrap.Dropdown(searchDropdown);
|
if (!dropdownInstance._isShown()) {
|
||||||
dropdownInstance.show();
|
dropdownInstance.show();
|
||||||
|
}
|
||||||
|
setTimeout(() => searchInput.focus(), 150); // Focus after animation
|
||||||
|
}
|
||||||
|
|
||||||
setTimeout(() => {
|
// Handle click for mobile
|
||||||
searchInput.focus();
|
searchDropdown.addEventListener('click', function (e) {
|
||||||
}, 100);
|
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 mouse leave
|
// Handle hover for desktop
|
||||||
searchDropdown.addEventListener('mouseleave', function () {
|
searchDropdown.addEventListener('mouseenter', function () {
|
||||||
// Check if current value is empty (including if user typed and then deleted)
|
if (window.innerWidth >= 1200) {
|
||||||
if (searchInput.value.trim().length === 0) {
|
showSearchDropdown();
|
||||||
searchInput.blur();
|
}
|
||||||
const dropdownInstance = new bootstrap.Dropdown(searchDropdown);
|
});
|
||||||
|
|
||||||
|
// 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();
|
dropdownInstance.hide();
|
||||||
}
|
}
|
||||||
});
|
}, 200);
|
||||||
|
|
||||||
searchDropdown.addEventListener('hidden.bs.dropdown', function () {
|
|
||||||
if (searchInput.value.trim().length === 0) {
|
|
||||||
searchInput.blur();
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// 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;
|
const isHighDPI = systemDPR > 1.4;
|
||||||
|
|
||||||
function scaleNav() {
|
function scaleNav() {
|
||||||
|
if (window.innerWidth < 1200) {
|
||||||
|
// Don't scale nav on mobile
|
||||||
|
return;
|
||||||
|
}
|
||||||
const currentDPR = window.devicePixelRatio || 1;
|
const currentDPR = window.devicePixelRatio || 1;
|
||||||
const browserZoom = currentDPR / systemDPR;
|
const browserZoom = currentDPR / systemDPR;
|
||||||
|
|
||||||
|
@ -45,9 +45,10 @@
|
|||||||
apps
|
apps
|
||||||
</span>
|
</span>
|
||||||
<span class="icon-text" th:data-text="#{navbar.allTools}" th:text="#{navbar.allTools}"></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>
|
</a>
|
||||||
<div class="dropdown-menu dropdown-menu-tp" aria-labelledby="navbarDropdown-1">
|
<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">
|
<div class="feature-rows">
|
||||||
|
|
||||||
<th:block th:insert="~{fragments/navElements.html :: navElements}"></th:block>
|
<th:block th:insert="~{fragments/navElements.html :: navElements}"></th:block>
|
||||||
@ -117,9 +118,10 @@
|
|||||||
star
|
star
|
||||||
</span>
|
</span>
|
||||||
<span class="icon-text icon-hide" th:data-text="#{navbar.favorite}" th:text="#{navbar.favorite}"></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>
|
</a>
|
||||||
<div class="dropdown-menu dropdown-menu-tp dropdown-mw-28" aria-labelledby="navbarDropdown-5">
|
<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">
|
<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 -->
|
<!-- Dropdown items will be added here by JavaScript -->
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -140,9 +142,10 @@
|
|||||||
language
|
language
|
||||||
</span>
|
</span>
|
||||||
<span class="icon-text icon-hide" th:data-text="#{navbar.language}" th:text="#{navbar.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>
|
</a>
|
||||||
<div class="dropdown-menu dropdown-menu-tp" aria-labelledby="languageDropdown">
|
<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">
|
<div id="languageSelection" class="scrollable-y lang_dropdown-mw scalable-languages-container">
|
||||||
<th:block th:insert="~{fragments/languages :: langs}"></th:block>
|
<th:block th:insert="~{fragments/languages :: langs}"></th:block>
|
||||||
</div>
|
</div>
|
||||||
@ -157,9 +160,10 @@
|
|||||||
search
|
search
|
||||||
</span>
|
</span>
|
||||||
<span class="icon-text icon-hide">Search</span>
|
<span class="icon-text icon-hide">Search</span>
|
||||||
|
<span class="material-symbols-rounded chevron-icon">expand_more</span>
|
||||||
</a>
|
</a>
|
||||||
<div class="dropdown-menu dropdown-menu-tp" aria-labelledby="searchDropdown">
|
<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">
|
<form th:action="@{''}" class="d-flex p-2 search-form" id="searchForm">
|
||||||
<input class="form-control search-input" type="search" th:placeholder="#{navbar.search}"
|
<input class="form-control search-input" type="search" th:placeholder="#{navbar.search}"
|
||||||
aria-label="Search" id="navbarSearchInput">
|
aria-label="Search" id="navbarSearchInput">
|
||||||
@ -172,7 +176,7 @@
|
|||||||
|
|
||||||
<li class="nav-item" th:if="${!@runningProOrHigher}">
|
<li class="nav-item" th:if="${!@runningProOrHigher}">
|
||||||
<a href="https://stirlingpdf.com/pricing" class="nav-link go-pro-link" target="_blank"
|
<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>
|
<span class="go-pro-badge" th:text="#{enterpriseEdition.button}"></span>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
Loading…
Reference in New Issue
Block a user