Sort Dropdown
A compact sort selector card with a small label, current value and animated option list.
Preview and code
index.html
<div class='sd'><button type='button' class='sd-b' id='sdb' aria-haspopup='listbox'><span><small>Sort</small><b id='sdv'>Newest first</b></span><svg width='16' height='16' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><path d='M6 9l6 6 6-6'/></svg></button><ul class='sd-l' id='sdl' role='listbox'></ul></div>
styles.css
.sd{position:relative;width:190px;margin:auto;font-family:Inter,Arial,sans-serif;color:#111}.sd-b{display:flex;justify-content:space-between;align-items:center;width:100%;padding:10px 14px;text-align:left;font:inherit;background:#fff;border:1px solid #e5e5e5;border-radius:12px;cursor:pointer;box-shadow:0 1px 2px rgba(0,0,0,.04);transition:border-color .15s}.sd-b:hover{border-color:#cfcfcf}.sd-b small{display:block;font-size:12px;color:#8a8a8a}.sd-b b{display:block;margin-top:2px;font-size:14.5px;font-weight:400}.sd-b svg{color:#737373;transition:transform .2s}.sd.open .sd-b svg{transform:rotate(180deg)}.sd-l{display:none;position:absolute;left:0;right:0;top:100%;z-index:5;margin:6px 0 0;padding:5px;list-style:none;background:#fff;border:1px solid #e5e5e5;border-radius:12px;box-shadow:0 12px 30px rgba(0,0,0,.12)}.sd.open .sd-l{display:block;animation:sd-in .15s ease}.sd-l li{display:flex;justify-content:space-between;padding:8px 10px;font-size:14px;border-radius:8px;cursor:pointer}.sd-l li:hover{background:#f4f4f4}.sd-l li.on:after{content:'✓';color:#111}@keyframes sd-in{from{opacity:0;transform:translateY(-4px)}}
script.js
const r=document.querySelector('.sd'),b=document.getElementById('sdb'),l=document.getElementById('sdl'),v=document.getElementById('sdv');const O=['Newest first','Oldest first','Name A–Z','Most popular'];let c=0;const d=()=>{l.innerHTML=O.map((x,i)=>'<li role=option class="'+(i===c?'on':'')+'">'+x+'</li>').join('')};d();b.addEventListener('click',()=>r.classList.toggle('open'));l.addEventListener('click',e=>{const i=[...l.children].indexOf(e.target.closest('li'));if(i>-1){c=i;v.textContent=O[i];d();r.classList.remove('open')}});document.addEventListener('mousedown',e=>{if(!r.contains(e.target))r.classList.remove('open')});
About
A two-line trigger showing the label and current choice. Opens a list of sort options with a check on the active one.