Searchable Workspace Combobox
A labelled combobox with a search icon that filters options as you type, opens with a soft animation and supports arrow keys and enter.
Preview and code
index.html
<div class="cb"><label>Workspace</label><div class="fd"><svg class="s" viewBox="0 0 24 24"><circle cx="11" cy="11" r="6"/><path d="M20 20l-4-4"/></svg><input value="Design studio" autocomplete="off" spellcheck="false"><svg class="u" viewBox="0 0 24 24"><path d="M8 10l4-4 4 4M8 14l4 4 4-4"/></svg></div><ul class="ls"></ul></div>
styles.css
.cb{position:relative;width:290px;height:260px;font-family:system-ui,-apple-system,sans-serif;color:#f1f1f1}.cb label{display:block;font-size:12.5px;color:#7f8aa0;margin-bottom:8px}.fd{display:flex;align-items:center;gap:10px;height:46px;padding:0 14px;border-radius:14px;border:1px solid #2a2a2a;background:#161616;transition:border-color .2s,box-shadow .2s}.fd:focus-within{border-color:#0a84ff;box-shadow:0 0 0 3px rgba(10,132,255,.18)}.fd svg{width:16px;height:16px;flex:none;fill:none;stroke:#8f8f8f;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round}.fd input{flex:1;min-width:0;border:0;outline:0;background:none;color:#fff;font:600 15px/1 inherit}.ls{position:absolute;left:0;right:0;top:82px;margin:0;padding:5px;list-style:none;border-radius:14px;border:1px solid #2a2a2a;background:#1a1a1a;box-shadow:0 18px 40px rgba(0,0,0,.5);max-height:170px;overflow:auto;opacity:0;transform:translateY(-6px) scale(.98);pointer-events:none;transition:opacity .2s,transform .3s cubic-bezier(.3,1.3,.5,1)}.ls.open{opacity:1;transform:none;pointer-events:auto}.ls li{padding:10px 12px;border-radius:9px;font-size:14px;color:#cfcfcf;cursor:pointer}.ls li.hv,.ls li:hover{background:#262626;color:#fff}.ls .no{color:#777;cursor:default}
script.js
(function(){var A=['Design studio','Engineering','Marketing','Customer success','Finance','Operations','Product'],r=document.querySelector('.cb'),i=r.querySelector('input'),l=r.querySelector('.ls'),h=0,cur=A[0],vis=A;function draw(q){vis=A.filter(function(a){return a.toLowerCase().indexOf((q||'').toLowerCase())>-1});h=0;l.innerHTML=vis.length?vis.map(function(a,n){return '<li class="'+(n===0?'hv':'')+'">'+a+'</li>'}).join(''):'<li class="no">No matches</li>';[].slice.call(l.children).forEach(function(e,n){e.onclick=function(){pick(n)}})}function pick(n){if(!vis[n])return;cur=vis[n];i.value=cur;l.classList.remove('open')}function mark(){[].slice.call(l.children).forEach(function(e,n){e.classList.toggle('hv',n===h)})}i.onfocus=function(){i.select();draw('');l.classList.add('open')};i.oninput=function(){draw(i.value);l.classList.add('open')};i.onkeydown=function(e){if(e.key==='ArrowDown'){e.preventDefault();h=Math.min(vis.length-1,h+1);mark()}else if(e.key==='ArrowUp'){e.preventDefault();h=Math.max(0,h-1);mark()}else if(e.key==='Enter'){e.preventDefault();pick(h);i.blur()}else if(e.key==='Escape'){l.classList.remove('open');i.value=cur;i.blur()}};i.onblur=function(){setTimeout(function(){l.classList.remove('open');i.value=cur},150)};draw('')})();