

Finally fixed the horrible default style for the Glossary panel in the Articulate Storyline player.
What this new style gives you:
• Click any term → definition expands with an animated chevron
• Live search filtering across both terms and definitions
• Zero changes to your existing Glossary panel setup — same panel, same tab, just restyled
Add one trigger: On the first slide → When: Timeline starts → Action: Execute JavaScript.
The JavaScript code is below.
(function(){
// Guard against duplicate execution (fixes the double-toggle bug)
if (window.__csGlossaryPatched) return;
window.__csGlossaryPatched = true;
function injectStyles(){
var style = document.createElement('style');
style.id = 'cg-glossary-style';
style.textContent = `
.glossary-content{padding:0 16px 24px;}
.glossary-search-wrap{position:sticky;top:0;background:#FFFFFF;padding:10px 0;z-index:5;border-bottom:1px solid #E8E8E8;margin-bottom:2px;}
.glossary-search-wrap input{width:100%;box-sizing:border-box;border:1px solid #E8E8E8;border-radius:6px;padding:7px 10px;font-size:12.5px;font-family:'Montserrat',sans-serif;outline:none;}
.glossary-search-wrap input:focus{border-color:#DB8353;box-shadow:0 0 0 2px rgba(219,131,83,0.18);}
dt.glossary-term{cursor:pointer;font-weight:600;font-size:13.5px;color:#1E1E1E;padding:11px 22px 11px 0;margin:0;border-bottom:1px solid #F0F0F0;position:relative;transition:color .12s ease;}
dt.glossary-term:hover{color:#DB8353;}
dt.glossary-term.code-term{font-family:'Courier New',monospace;font-size:12.5px;background:#F7F7F7;border-radius:4px;padding:9px 22px 9px 8px;margin-top:8px;border-bottom:none;}
dt.glossary-term::after{content:'';position:absolute;right:3px;top:50%;width:7px;height:7px;border-right:2px solid #BBBBBB;border-bottom:2px solid #BBBBBB;transform:translateY(-65%) rotate(45deg);transition:transform .18s ease, border-color .18s ease;}
dt.glossary-term.is-open::after{transform:translateY(-35%) rotate(-135deg);border-color:#DB8353;}
dd.glossary-desc{display:none;margin:0 0 4px 0;padding:0 0 14px 0;font-size:12.5px;line-height:1.55;color:#555555;}
dd.glossary-desc.is-open{display:block;border-left:3px solid #DB8353;padding-left:12px;margin-top:2px;}
dd.glossary-desc p{margin:0;}
`;
document.head.appendChild(style);
}
function markCodeTerms(container){
container.querySelectorAll('dt.glossary-term:not(.cg-marked)').forEach(function(dt){
dt.classList.add('cg-marked');
var label = dt.textContent.trim();
if(/^[\$_]/.test(label) || /^issue\./.test(label) || label === 'search.mode'){
dt.classList.add('code-term');
}
});
}
function ensureSearchBox(container){
var dl = container.querySelector('dl');
if(dl && !container.querySelector('.glossary-search-wrap')){
var wrap = document.createElement('div');
wrap.className = 'glossary-search-wrap';
wrap.innerHTML = '<input type="text" placeholder="Search glossary…" aria-label="Search glossary">';
container.insertBefore(wrap, dl);
}
}
function init(){
injectStyles();
var container = document.querySelector('#glossary-content [data-ref="terms"]');
if(!container){ setTimeout(init, 400); return; }
markCodeTerms(container);
ensureSearchBox(container);
// Re-apply formatting if Storyline rebuilds the term list later
new MutationObserver(function(){
markCodeTerms(container);
ensureSearchBox(container);
}).observe(container, {childList:true, subtree:true});
}
// ONE delegated listener — survives node replacement, never double-fires
document.addEventListener('click', function(e){
var dt = e.target.closest('dt.glossary-term');
if(!dt) return;
var dd = dt.nextElementSibling;
if(!dd || !dd.classList.contains('glossary-desc')) return;
var isOpen = dd.classList.contains('is-open');
dd.classList.toggle('is-open', !isOpen);
dt.classList.toggle('is-open', !isOpen);
});
document.addEventListener('input', function(e){
if(!e.target.matches('.glossary-search-wrap input')) return;
var container = e.target.closest('.glossary-search-wrap').parentElement;
var q = e.target.value.trim().toLowerCase();
container.querySelectorAll('dt.glossary-term').forEach(function(dt){
var dd = dt.nextElementSibling;
var match = !q || dt.textContent.toLowerCase().indexOf(q) > -1 ||
(dd && dd.textContent.toLowerCase().indexOf(q) > -1);
dt.style.display = match ? '' : 'none';
if(dd) dd.style.display = !match ? 'none' : (dd.classList.contains('is-open') ? 'block' : '');
});
});
init();
})();




