I wanted dropdown submenus for Source, similar to what is accomplished with Add Dropdowns to Main Menu Through the Site Admin (Copy & Paste into Site Header/Footer Injections)
That code relies on jQuery, which is not included in Source, and does not take into account that Source collapses menu items into a dropdown on its own.
This code should be put into your header injections
<style>
li.menu-item-has-children {
position: relative;
padding-right: 15px!important;
display: inline;
}
.menu-item-has-children svg {
position: absolute;
right: 0px;
top: 35%;
transform: scale(1.1);
}
div.gh-dropdown {
right: -100px;
margin-top: 24px;
top: 0px;
border-bottom: 3px solid var(--ghost-accent-color);
}
li.menu-item-has-children:hover div.gh-dropdown, div.gh-dropdown:hover {
opacity: 1;
transform: translateY(0);
visibility: visible;
}
div.gh-dropdown ul {
padding: 0;
}
div.gh-dropdown li {
list-style: none;
white-space: nowrap;
}
div.gh-dropdown li:hover {
background-color: var(--ghost-accent-color);
}
div.gh-dropdown li:hover a {
color: var(--color-darker-gray)!important;
opacity: 0.8;
}
</style>
This goes into footer injections:
<script>
"use strict";
function ghost_dropdown(options) {
let defultOptions = {
targetElement: ".gh-navigation-menu ul li",
hasChildrenClasses: "menu-item-has-children",
hasChildrenIcon: "<svg xmlns='http://www.w3.org/2000/svg' width='11' height='7' fill='currentColor' class='bi bi-caret-down' viewBox='0 0 11 7'><path d='M5.4999 6.20003L0.649902 1.35003L1.3499 0.650024L5.4999 4.80002L9.6499 0.650024L10.3499 1.35003L5.4999 6.20003Z'/></svg>",
hasChildDetectText: "[has_child]",
submenuUlClasses: "gh-dropdown",
subitemDetectText: "[subitem]",
subitemLiClasses: "subitem"
}
options = {
...defultOptions,
...options
}
// Target Element
let targetElement = options.targetElement
let hasChildrenClasses = options.hasChildrenClasses
let hasChildrenIcon = options.hasChildrenIcon
let hasChildDetectText = options.hasChildDetectText
let submenuUlClasses = options.submenuUlClasses
let subitemDetectText = options.subitemDetectText
let subitemLiClasses = options.subitemLiClasses
let navigation = document.querySelector('#gh-navigation')
// This bit can be removed if used for themes other than Source
if (navigation?.classList?.contains('is-dropdown-loaded')) {
navigation.classList.remove('is-dropdown-mega')
let menu = navigation.querySelector('nav.gh-navigation-menu')
let ul = menu?.querySelector('ul.nav')
let button = ul?.querySelector('button.gh-more-toggle')
if (button) {
ul.removeChild(button)
button.querySelector('div.gh-dropdown')?.querySelectorAll('li').forEach(function (element, index) {
element.parentElement.removeChild(element)
ul.appendChild(element)
})
}
}
let parentEl = document.querySelectorAll(targetElement)
let parentIndex = []
parentEl.forEach(function (element, index) {
element.parentElement.classList.add('ghost-dropdown-menu')
if (element.textContent.indexOf(hasChildDetectText) >= 0) {
parentIndex.push(index)
element.innerHTML = element.innerHTML.replaceAll(hasChildDetectText, '')
element.classList.add(hasChildrenClasses)
element.innerHTML = element.innerHTML + hasChildrenIcon + (`<div class='${submenuUlClasses}'><ul></ul></div>`)
element.style.opacity = '1'
}
})
parentIndex.forEach(function (i) {
let collecting = true
parentEl.forEach(function (element, index) {
if (index > i) {
if (element.textContent.indexOf(subitemDetectText) < 0) {
collecting = false
}
if (collecting) {
element.innerHTML = element.innerHTML.replaceAll(subitemDetectText, '')
element.classList.add(subitemLiClasses)
element.parentElement.removeChild(element)
parentEl[i].querySelector(`div.${submenuUlClasses}`).querySelector('ul').appendChild(element)
}
}
})
})
}
window.addEventListener("load", function() {
ghost_dropdown();
})
// This bit can be removed if used for themes other than Source
window.addEventListener('resize', function () {
setTimeout(() => {
ghost_dropdown();
}, 1);
});
</script>
The code is fairly generic Javascript and should work for themes without external dependencies. The CSS relies on Source CSS for displaying the menu, so you likely need something like
<style>
.gh-dropdown {
background-color: #fff;
border-radius: 5px;
box-shadow: 0 0 0 1px rgba(0,0,0,.04),0 7px 20px -5px rgba(0,0,0,.15);
margin-top: 24px;
opacity: 0;
padding: 12px 0;
position: absolute;
right: -16px;
text-align: left;
top: 100%;
transform: translate3d(0,6px,0);
transition: opacity .3s,transform .2s;
visibility: hidden;
width: 200px;
z-index: 90;
}
</style>
before the rest of the styles if used with other themes.
Note that this will potentially cause problems if the main menu is so long after introducing submenus that the Source menu collapse script kicks in – the existing menu collapse is hard to disable, so I just undo its work, which works for short top menus only.
See original thread for usage; this is what the result looks like on my site: