Toolbar
A toolbar groups related controls — buttons, toggles, inputs, menus — into a single navigable region. You will find them in rich-text editors, media players, IDEs, and data tables. This guide covers production-ready toolbar patterns in plain HTML/CSS, Tailwind CSS, and Bootstrap, including roving tabindex, separators, overflow menus, and ARIA.
info
A horizontal formatting toolbar with toggle buttons for bold, italic, underline, and a link action separated by a visual divider.
| 1 | <div class="toolbar" role="toolbar" aria-label="Text formatting" aria-orientation="horizontal"> |
| 2 | <button class="btn toggle" aria-pressed="false"> |
| 3 | B |
| 4 | </button> |
| 5 | <button class="btn toggle" aria-pressed="false"> |
| 6 | I |
| 7 | </button> |
| 8 | <button class="btn toggle" aria-pressed="false"> |
| 9 | U |
| 10 | </button> |
| 11 | <div role="separator" aria-orientation="vertical" class="sep"> |
| 12 | </div> |
| 13 | <button class="btn"> |
| 14 | Link |
| 15 | </button> |
| 16 | </div> |
| 1 | .toolbar { |
| 2 | display:inline-flex; |
| 3 | align-items:center; |
| 4 | gap:6px; |
| 5 | padding:10px 12px; |
| 6 | background:#151515; |
| 7 | border:1px solid #2A2A3E; |
| 8 | border-radius:10px |
| 9 | } |
| 10 | .btn { |
| 11 | display:inline-flex; |
| 12 | align-items:center; |
| 13 | justify-content:center; |
| 14 | min-width:36px; |
| 15 | height:36px; |
| 16 | padding:0 10px; |
| 17 | border-radius:6px; |
| 18 | font-size:13px; |
| 19 | font-weight:600; |
| 20 | font-family:system-ui, |
| 21 | sans-serif; |
| 22 | color:#E0E0E0; |
| 23 | background:#1A1A2E; |
| 24 | border:1px solid transparent; |
| 25 | cursor:pointer; |
| 26 | transition:all .2s ease |
| 27 | } |
| 28 | .btn:hover { |
| 29 | border-color:#3A3A4E; |
| 30 | background:#22223A |
| 31 | } |
| 32 | .btn[aria-pressed="true"] { |
| 33 | background:#00FF41; |
| 34 | color:#0A0A0A; |
| 35 | border-color:#00FF41 |
| 36 | } |
| 37 | .sep { |
| 38 | width:1px; |
| 39 | height:22px; |
| 40 | background:#2A2A3E; |
| 41 | margin:0 4px |
| 42 | } |
| 1 | document.querySelectorAll('.toolbar .toggle').forEach(b=>{b.addEventListener('click',()=>{const pressed=b.getAttribute('aria-pressed')==='true';b.setAttribute('aria-pressed',String(!pressed));b.classList.toggle('active',!pressed)})}) |
| 1 | <div class="inline-flex items-center gap-1.5 p-2.5 bg-[#151515] border border-[#2A2A3E] rounded-xl" role="toolbar" aria-label="Text formatting" aria-orientation="horizontal"> |
| 2 | <button class="t min-w-[36px] h-9 px-2.5 rounded-md text-[13px] font-semibold bg-[#1A1A2E] text-[#E0E0E0] border border-transparent hover:border-[#3A3A4E] hover:bg-[#22223A] transition-all" aria-pressed="false"> |
| 3 | B |
| 4 | </button> |
| 5 | <button class="t min-w-[36px] h-9 px-2.5 rounded-md text-[13px] font-semibold bg-[#1A1A2E] text-[#E0E0E0] border border-transparent hover:border-[#3A3A4E] hover:bg-[#22223A] transition-all" aria-pressed="false"> |
| 6 | I |
| 7 | </button> |
| 8 | <button class="t min-w-[36px] h-9 px-2.5 rounded-md text-[13px] font-semibold bg-[#1A1A2E] text-[#E0E0E0] border border-transparent hover:border-[#3A3A4E] hover:bg-[#22223A] transition-all" aria-pressed="false"> |
| 9 | U |
| 10 | </button> |
| 11 | <div role="separator" aria-orientation="vertical" class="w-px h-5 bg-[#2A2A3E] mx-1"> |
| 12 | </div> |
| 13 | <button class="min-w-[36px] h-9 px-2.5 rounded-md text-[13px] font-semibold bg-[#1A1A2E] text-[#E0E0E0] border border-transparent hover:border-[#3A3A4E] hover:bg-[#22223A] transition-all"> |
| 14 | Link |
| 15 | </button> |
| 16 | </div> |
| 1 | <div class="btn-group" role="toolbar" aria-label="Text formatting"> |
| 2 | <button class="btn btn-dark border-secondary fw-semibold t" style="width:40px" aria-pressed="false"> |
| 3 | B |
| 4 | </button> |
| 5 | <button class="btn btn-dark border-secondary fw-semibold t" style="width:40px" aria-pressed="false"> |
| 6 | I |
| 7 | </button> |
| 8 | <button class="btn btn-dark border-secondary fw-semibold t" style="width:40px" aria-pressed="false"> |
| 9 | U |
| 10 | </button> |
| 11 | <button class="btn btn-dark border-secondary fw-semibold" style="--bs-btn-bg:#1A1A2E"> |
| 12 | Link |
| 13 | </button> |
| 14 | </div> |
Compact icon-only controls are common in IDEs and media players. Every icon button must carry an aria-label.
| 1 | <div class="toolbar" role="toolbar" aria-label="Editor actions"> |
| 2 | <button class="icon" aria-label="Undo"> |
| 3 | <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="18" height="18"> |
| 4 | <path d="M3 7v6h6"/> |
| 5 | <path d="M21 17a9 9 0 0 0-9-9 9 9 0 0 0-6 2.3L3 13"/> |
| 6 | </svg> |
| 7 | </button> |
| 8 | <button class="icon" aria-label="Redo"> |
| 9 | <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="18" height="18"> |
| 10 | <path d="M21 7v6h-6"/> |
| 11 | <path d="M3 17a9 9 0 0 1 9-9 9 9 0 0 1 6 2.3L21 13"/> |
| 12 | </svg> |
| 13 | </button> |
| 14 | <button class="icon" aria-label="Cut"> |
| 15 | <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="18" height="18"> |
| 16 | <circle cx="6" cy="6" r="3"/> |
| 17 | <circle cx="6" cy="18" r="3"/> |
| 18 | <line x1="20" y1="4" x2="8.12" y2="15.88"/> |
| 19 | <line x1="14.47" y1="14.48" x2="20" y2="20"/> |
| 20 | <line x1="8.12" y1="8.12" x2="12" y2="12"/> |
| 21 | </svg> |
| 22 | </button> |
| 23 | <button class="icon" aria-label="Copy"> |
| 24 | <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="18" height="18"> |
| 25 | <rect x="9" y="9" width="13" height="13" rx="2" ry="2"/> |
| 26 | <path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/> |
| 27 | </svg> |
| 28 | </button> |
| 29 | <button class="icon" aria-label="Paste"> |
| 30 | <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="18" height="18"> |
| 31 | <path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"/> |
| 32 | <rect x="8" y="2" width="8" height="4" rx="1" ry="1"/> |
| 33 | </svg> |
| 34 | </button> |
| 35 | </div> |
| 1 | .toolbar { |
| 2 | display:inline-flex; |
| 3 | align-items:center; |
| 4 | gap:6px; |
| 5 | padding:10px; |
| 6 | background:#151515; |
| 7 | border:1px solid #2A2A3E; |
| 8 | border-radius:10px |
| 9 | } |
| 10 | .icon { |
| 11 | display:inline-flex; |
| 12 | align-items:center; |
| 13 | justify-content:center; |
| 14 | width:38px; |
| 15 | height:38px; |
| 16 | border-radius:8px; |
| 17 | color:#A0A0A0; |
| 18 | background:#1A1A2E; |
| 19 | border:1px solid transparent; |
| 20 | cursor:pointer; |
| 21 | transition:all .2s ease |
| 22 | } |
| 23 | .icon:hover { |
| 24 | background:#22223A; |
| 25 | border-color:#3A3A4E; |
| 26 | color:#E0E0E0 |
| 27 | } |
| 28 | .icon:active { |
| 29 | background:#00FF41; |
| 30 | color:#0A0A0A |
| 31 | } |
| 1 | <div class="inline-flex items-center gap-1.5 p-2.5 bg-[#151515] border border-[#2A2A3E] rounded-xl" role="toolbar" aria-label="Editor actions"> |
| 2 | <button aria-label="Undo" class="w-10 h-10 rounded-lg inline-flex items-center justify-center bg-[#1A1A2E] text-[#A0A0A0] border border-transparent hover:bg-[#22223A] hover:border-[#3A3A4E] hover:text-[#E0E0E0] active:bg-[#00FF41] active:text-[#0A0A0A] transition-all"> |
| 3 | <svg class="w-[18px] h-[18px]" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> |
| 4 | <path d="M3 7v6h6"/> |
| 5 | <path d="M21 17a9 9 0 0 0-9-9 9 9 0 0 0-6 2.3L3 13"/> |
| 6 | </svg> |
| 7 | </button> |
| 8 | <button aria-label="Redo" class="w-10 h-10 rounded-lg inline-flex items-center justify-center bg-[#1A1A2E] text-[#A0A0A0] border border-transparent hover:bg-[#22223A] hover:border-[#3A3A4E] hover:text-[#E0E0E0] active:bg-[#00FF41] active:text-[#0A0A0A] transition-all"> |
| 9 | <svg class="w-[18px] h-[18px]" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> |
| 10 | <path d="M21 7v6h-6"/> |
| 11 | <path d="M3 17a9 9 0 0 1 9-9 9 9 0 0 1 6 2.3L21 13"/> |
| 12 | </svg> |
| 13 | </button> |
| 14 | <button aria-label="Cut" class="w-10 h-10 rounded-lg inline-flex items-center justify-center bg-[#1A1A2E] text-[#A0A0A0] border border-transparent hover:bg-[#22223A] hover:border-[#3A3A4E] hover:text-[#E0E0E0] active:bg-[#00FF41] active:text-[#0A0A0A] transition-all"> |
| 15 | <svg class="w-[18px] h-[18px]" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> |
| 16 | <circle cx="6" cy="6" r="3"/> |
| 17 | <circle cx="6" cy="18" r="3"/> |
| 18 | <line x1="20" y1="4" x2="8.12" y2="15.88"/> |
| 19 | <line x1="14.47" y1="14.48" x2="20" y2="20"/> |
| 20 | <line x1="8.12" y1="8.12" x2="12" y2="12"/> |
| 21 | </svg> |
| 22 | </button> |
| 23 | <button aria-label="Copy" class="w-10 h-10 rounded-lg inline-flex items-center justify-center bg-[#1A1A2E] text-[#A0A0A0] border border-transparent hover:bg-[#22223A] hover:border-[#3A3A4E] hover:text-[#E0E0E0] active:bg-[#00FF41] active:text-[#0A0A0A] transition-all"> |
| 24 | <svg class="w-[18px] h-[18px]" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> |
| 25 | <rect x="9" y="9" width="13" height="13" rx="2" ry="2"/> |
| 26 | <path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/> |
| 27 | </svg> |
| 28 | </button> |
| 29 | <button aria-label="Paste" class="w-10 h-10 rounded-lg inline-flex items-center justify-center bg-[#1A1A2E] text-[#A0A0A0] border border-transparent hover:bg-[#22223A] hover:border-[#3A3A4E] hover:text-[#E0E0E0] active:bg-[#00FF41] active:text-[#0A0A0A] transition-all"> |
| 30 | <svg class="w-[18px] h-[18px]" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> |
| 31 | <path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"/> |
| 32 | <rect x="8" y="2" width="8" height="4" rx="1" ry="1"/> |
| 33 | </svg> |
| 34 | </button> |
| 35 | </div> |
| 1 | <div class="btn-group" role="toolbar" aria-label="Editor actions"> |
| 2 | <button aria-label="Undo" class="btn btn-dark border-secondary" style="width:42px;height:42px"> |
| 3 | <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> |
| 4 | <path d="M3 7v6h6"/> |
| 5 | <path d="M21 17a9 9 0 0 0-9-9 9 9 0 0 0-6 2.3L3 13"/> |
| 6 | </svg> |
| 7 | </button> |
| 8 | <button aria-label="Redo" class="btn btn-dark border-secondary" style="width:42px;height:42px"> |
| 9 | <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> |
| 10 | <path d="M21 7v6h-6"/> |
| 11 | <path d="M3 17a9 9 0 0 1 9-9 9 9 0 0 1 6 2.3L21 13"/> |
| 12 | </svg> |
| 13 | </button> |
| 14 | <button aria-label="Cut" class="btn btn-dark border-secondary" style="width:42px;height:42px"> |
| 15 | <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> |
| 16 | <circle cx="6" cy="6" r="3"/> |
| 17 | <circle cx="6" cy="18" r="3"/> |
| 18 | <line x1="20" y1="4" x2="8.12" y2="15.88"/> |
| 19 | <line x1="14.47" y1="14.48" x2="20" y2="20"/> |
| 20 | <line x1="8.12" y1="8.12" x2="12" y2="12"/> |
| 21 | </svg> |
| 22 | </button> |
| 23 | <button aria-label="Copy" class="btn btn-dark border-secondary" style="width:42px;height:42px"> |
| 24 | <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> |
| 25 | <rect x="9" y="9" width="13" height="13" rx="2" ry="2"/> |
| 26 | <path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"/> |
| 27 | </svg> |
| 28 | </button> |
| 29 | <button aria-label="Paste" class="btn btn-dark border-secondary" style="width:42px;height:42px"> |
| 30 | <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> |
| 31 | <path d="M16 4h2a2 2 0 0 1 2 2v14a2 2 0 0 1-2 2H6a2 2 0 0 1-2-2V6a2 2 0 0 1 2-2h2"/> |
| 32 | <rect x="8" y="2" width="8" height="4" rx="1" ry="1"/> |
| 33 | </svg> |
| 34 | </button> |
| 35 | </div> |
A segmented control toolbar. Only one option is active; the rest are inactive but still focusable via arrow keys.
| 1 | <div class="toolbar" role="toolbar" aria-label="View layout"> |
| 2 | <button class="seg active"> |
| 3 | List |
| 4 | </button> |
| 5 | <button class="seg"> |
| 6 | Grid |
| 7 | </button> |
| 8 | <button class="seg"> |
| 9 | Board |
| 10 | </button> |
| 11 | </div> |
| 1 | .toolbar { |
| 2 | display:inline-flex; |
| 3 | align-items:center; |
| 4 | padding:4px; |
| 5 | background:#151515; |
| 6 | border:1px solid #2A2A3E; |
| 7 | border-radius:10px |
| 8 | } |
| 9 | .seg { |
| 10 | padding:8px 18px; |
| 11 | font-size:12px; |
| 12 | font-weight:600; |
| 13 | font-family:system-ui, |
| 14 | sans-serif; |
| 15 | color:#808080; |
| 16 | background:transparent; |
| 17 | border:none; |
| 18 | border-radius:6px; |
| 19 | cursor:pointer; |
| 20 | transition:all .2s ease |
| 21 | } |
| 22 | .seg:hover { |
| 23 | color:#E0E0E0; |
| 24 | background:rgba(255, |
| 25 | 255, |
| 26 | 255, |
| 27 | .03) |
| 28 | } |
| 29 | .seg.active { |
| 30 | background:#00FF41; |
| 31 | color:#0A0A0A |
| 32 | } |
| 1 | document.querySelectorAll('.seg').forEach(b=>{b.addEventListener('click',()=>{document.querySelectorAll('.seg').forEach(x=>x.classList.remove('active'));b.classList.add('active')})}) |
| 1 | <div class="inline-flex items-center p-1 bg-[#151515] border border-[#2A2A3E] rounded-xl" role="toolbar" aria-label="View layout"> |
| 2 | <button class="seg px-5 py-2 text-xs font-semibold rounded-lg text-[#0A0A0A] bg-[#00FF41]"> |
| 3 | List |
| 4 | </button> |
| 5 | <button class="seg px-5 py-2 text-xs font-semibold rounded-lg text-[#808080] hover:text-[#E0E0E0] hover:bg-white/[0.03] transition-all"> |
| 6 | Grid |
| 7 | </button> |
| 8 | <button class="seg px-5 py-2 text-xs font-semibold rounded-lg text-[#808080] hover:text-[#E0E0E0] hover:bg-white/[0.03] transition-all"> |
| 9 | Board |
| 10 | </button> |
| 11 | </div> |
| 1 | <div class="btn-group" role="toolbar" aria-label="View layout"> |
| 2 | <button class="btn btn-success active fw-semibold" style="--bs-btn-bg:#00FF41;--bs-btn-color:#0A0A0A;--bs-btn-border-color:#00FF41;--bs-btn-hover-bg:#00E63A"> |
| 3 | List |
| 4 | </button> |
| 5 | <button class="btn btn-dark border-secondary fw-semibold"> |
| 6 | Grid |
| 7 | </button> |
| 8 | <button class="btn btn-dark border-secondary fw-semibold"> |
| 9 | Board |
| 10 | </button> |
| 11 | </div> |
Set aria-orientation="vertical" and use Up/Down arrows for roving focus in narrow sidebars.
| 1 | <div class="toolbar" role="toolbar" aria-label="Tools" aria-orientation="vertical"> |
| 2 | <button class="icon" aria-label="Select"> |
| 3 | <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="18" height="18"> |
| 4 | <path d="M3 3l7.07 16.97 2.51-7.39 7.39-2.51L3 3z"/> |
| 5 | </svg> |
| 6 | </button> |
| 7 | <button class="icon" aria-label="Brush"> |
| 8 | <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="18" height="18"> |
| 9 | <path d="M18 11.5V9a2 2 0 0 0-2-2v0a2 2 0 0 0-2 2v1.5"/> |
| 10 | <path d="M14 10V8a2 2 0 0 0-2-2v0a2 2 0 0 0-2 2v2"/> |
| 11 | <path d="M10 9.5V12a2 2 0 0 0 2 2v0"/> |
| 12 | <path d="M16 12a2 2 0 0 1-2 2v0"/> |
| 13 | <path d="M20 18a2 2 0 1 1-4 0c0-1.5 2-2 2-4 0 2 2 2.5 2 4z"/> |
| 14 | </svg> |
| 15 | </button> |
| 16 | <button class="icon" aria-label="Eraser"> |
| 17 | <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="18" height="18"> |
| 18 | <path d="M7 21l-4.3-4.3c-1-1-1-2.5 0-3.4l9.6-9.6c1-1 2.5-1 3.4 0l5.6 5.6c1 1 1 2.5 0 3.4L13 21"/> |
| 19 | <path d="M22 21H7"/> |
| 20 | <path d="M5 11l9 9"/> |
| 21 | </svg> |
| 22 | </button> |
| 23 | <button class="icon" aria-label="Text"> |
| 24 | <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" width="18" height="18"> |
| 25 | <path d="M4 7V5h16v2"/> |
| 26 | <path d="M9 20h6"/> |
| 27 | <path d="M12 5v14"/> |
| 28 | </svg> |
| 29 | </button> |
| 30 | </div> |
| 1 | .toolbar { |
| 2 | display:inline-flex; |
| 3 | flex-direction:column; |
| 4 | align-items:center; |
| 5 | gap:6px; |
| 6 | padding:10px; |
| 7 | background:#151515; |
| 8 | border:1px solid #2A2A3E; |
| 9 | border-radius:10px |
| 10 | } |
| 11 | .icon { |
| 12 | display:inline-flex; |
| 13 | align-items:center; |
| 14 | justify-content:center; |
| 15 | width:40px; |
| 16 | height:40px; |
| 17 | border-radius:8px; |
| 18 | color:#A0A0A0; |
| 19 | background:#1A1A2E; |
| 20 | border:1px solid transparent; |
| 21 | cursor:pointer; |
| 22 | transition:all .2s ease |
| 23 | } |
| 24 | .icon:hover { |
| 25 | background:#22223A; |
| 26 | border-color:#3A3A4E; |
| 27 | color:#E0E0E0 |
| 28 | } |
| 29 | .icon.active { |
| 30 | background:#00FF41; |
| 31 | color:#0A0A0A |
| 32 | } |
| 1 | document.querySelectorAll('.icon').forEach(b=>{b.addEventListener('click',()=>{document.querySelectorAll('.icon').forEach(x=>x.classList.remove('active'));b.classList.add('active')})}) |
| 1 | <div class="inline-flex flex-col items-center gap-1.5 p-2.5 bg-[#151515] border border-[#2A2A3E] rounded-xl" role="toolbar" aria-label="Tools" aria-orientation="vertical"> |
| 2 | <button aria-label="Select" class="icon w-10 h-10 rounded-lg inline-flex items-center justify-center bg-[#1A1A2E] text-[#A0A0A0] border border-transparent hover:bg-[#22223A] hover:border-[#3A3A4E] hover:text-[#E0E0E0] transition-all"> |
| 3 | <svg class="w-[18px] h-[18px]" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> |
| 4 | <path d="M3 3l7.07 16.97 2.51-7.39 7.39-2.51L3 3z"/> |
| 5 | </svg> |
| 6 | </button> |
| 7 | <button aria-label="Brush" class="icon w-10 h-10 rounded-lg inline-flex items-center justify-center bg-[#1A1A2E] text-[#A0A0A0] border border-transparent hover:bg-[#22223A] hover:border-[#3A3A4E] hover:text-[#E0E0E0] transition-all"> |
| 8 | <svg class="w-[18px] h-[18px]" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> |
| 9 | <path d="M18 11.5V9a2 2 0 0 0-2-2v0a2 2 0 0 0-2 2v1.5"/> |
| 10 | <path d="M14 10V8a2 2 0 0 0-2-2v0a2 2 0 0 0-2 2v2"/> |
| 11 | <path d="M10 9.5V12a2 2 0 0 0 2 2v0"/> |
| 12 | <path d="M16 12a2 2 0 0 1-2 2v0"/> |
| 13 | <path d="M20 18a2 2 0 1 1-4 0c0-1.5 2-2 2-4 0 2 2 2.5 2 4z"/> |
| 14 | </svg> |
| 15 | </button> |
| 16 | <button aria-label="Eraser" class="icon w-10 h-10 rounded-lg inline-flex items-center justify-center bg-[#1A1A2E] text-[#A0A0A0] border border-transparent hover:bg-[#22223A] hover:border-[#3A3A4E] hover:text-[#E0E0E0] transition-all"> |
| 17 | <svg class="w-[18px] h-[18px]" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> |
| 18 | <path d="M7 21l-4.3-4.3c-1-1-1-2.5 0-3.4l9.6-9.6c1-1 2.5-1 3.4 0l5.6 5.6c1 1 1 2.5 0 3.4L13 21"/> |
| 19 | <path d="M22 21H7"/> |
| 20 | <path d="M5 11l9 9"/> |
| 21 | </svg> |
| 22 | </button> |
| 23 | <button aria-label="Text" class="icon w-10 h-10 rounded-lg inline-flex items-center justify-center bg-[#1A1A2E] text-[#A0A0A0] border border-transparent hover:bg-[#22223A] hover:border-[#3A3A4E] hover:text-[#E0E0E0] transition-all"> |
| 24 | <svg class="w-[18px] h-[18px]" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> |
| 25 | <path d="M4 7V5h16v2"/> |
| 26 | <path d="M9 20h6"/> |
| 27 | <path d="M12 5v14"/> |
| 28 | </svg> |
| 29 | </button> |
| 30 | </div> |
| 1 | <div class="btn-group-vertical" role="toolbar" aria-label="Tools" aria-orientation="vertical"> |
| 2 | <button aria-label="Select" class="btn btn-dark border-secondary" style="width:42px;height:42px"> |
| 3 | <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> |
| 4 | <path d="M3 3l7.07 16.97 2.51-7.39 7.39-2.51L3 3z"/> |
| 5 | </svg> |
| 6 | </button> |
| 7 | <button aria-label="Brush" class="btn btn-dark border-secondary" style="width:42px;height:42px"> |
| 8 | <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> |
| 9 | <path d="M18 11.5V9a2 2 0 0 0-2-2v0a2 2 0 0 0-2 2v1.5"/> |
| 10 | <path d="M14 10V8a2 2 0 0 0-2-2v0a2 2 0 0 0-2 2v2"/> |
| 11 | <path d="M10 9.5V12a2 2 0 0 0 2 2v0"/> |
| 12 | <path d="M16 12a2 2 0 0 1-2 2v0"/> |
| 13 | <path d="M20 18a2 2 0 1 1-4 0c0-1.5 2-2 2-4 0 2 2 2.5 2 4z"/> |
| 14 | </svg> |
| 15 | </button> |
| 16 | <button aria-label="Eraser" class="btn btn-dark border-secondary" style="width:42px;height:42px"> |
| 17 | <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> |
| 18 | <path d="M7 21l-4.3-4.3c-1-1-1-2.5 0-3.4l9.6-9.6c1-1 2.5-1 3.4 0l5.6 5.6c1 1 1 2.5 0 3.4L13 21"/> |
| 19 | <path d="M22 21H7"/> |
| 20 | <path d="M5 11l9 9"/> |
| 21 | </svg> |
| 22 | </button> |
| 23 | <button aria-label="Text" class="btn btn-dark border-secondary" style="width:42px;height:42px"> |
| 24 | <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"> |
| 25 | <path d="M4 7V5h16v2"/> |
| 26 | <path d="M9 20h6"/> |
| 27 | <path d="M12 5v14"/> |
| 28 | </svg> |
| 29 | </button> |
| 30 | </div> |
Toolbars can include non-button controls such as a search field. The input remains a regular tab stop while buttons use roving focus.
| 1 | <div class="toolbar" role="toolbar" aria-label="File search"> |
| 2 | <button class="btn"> |
| 3 | New |
| 4 | </button> |
| 5 | <button class="btn"> |
| 6 | Open |
| 7 | </button> |
| 8 | <div role="separator" aria-orientation="vertical" class="sep"> |
| 9 | </div> |
| 10 | <input type="text" class="search" placeholder="Search files..." aria-label="Search files" /> |
| 11 | </div> |
| 1 | .toolbar { |
| 2 | display:inline-flex; |
| 3 | align-items:center; |
| 4 | gap:6px; |
| 5 | padding:10px 12px; |
| 6 | background:#151515; |
| 7 | border:1px solid #2A2A3E; |
| 8 | border-radius:10px |
| 9 | } |
| 10 | .btn { |
| 11 | display:inline-flex; |
| 12 | align-items:center; |
| 13 | justify-content:center; |
| 14 | height:36px; |
| 15 | padding:0 14px; |
| 16 | border-radius:6px; |
| 17 | font-size:13px; |
| 18 | font-weight:600; |
| 19 | font-family:system-ui, |
| 20 | sans-serif; |
| 21 | color:#E0E0E0; |
| 22 | background:#1A1A2E; |
| 23 | border:1px solid transparent; |
| 24 | cursor:pointer; |
| 25 | transition:all .2s ease |
| 26 | } |
| 27 | .btn:hover { |
| 28 | border-color:#3A3A4E; |
| 29 | background:#22223A |
| 30 | } |
| 31 | .sep { |
| 32 | width:1px; |
| 33 | height:22px; |
| 34 | background:#2A2A3E; |
| 35 | margin:0 4px |
| 36 | } |
| 37 | .search { |
| 38 | width:180px; |
| 39 | height:36px; |
| 40 | padding:0 12px; |
| 41 | border-radius:6px; |
| 42 | font-size:13px; |
| 43 | font-family:system-ui, |
| 44 | sans-serif; |
| 45 | color:#E0E0E0; |
| 46 | background:#0A0A0A; |
| 47 | border:1px solid #2A2A3E; |
| 48 | outline:none |
| 49 | } |
| 50 | .search::placeholder { |
| 51 | color:#808080 |
| 52 | } |
| 53 | .search:focus { |
| 54 | border-color:#00FF41; |
| 55 | box-shadow:0 0 0 2px rgba(0, |
| 56 | 255, |
| 57 | 65, |
| 58 | .15) |
| 59 | } |
| 1 | <div class="inline-flex items-center gap-1.5 p-2.5 bg-[#151515] border border-[#2A2A3E] rounded-xl" role="toolbar" aria-label="File search"> |
| 2 | <button class="h-9 px-3 rounded-md text-[13px] font-semibold bg-[#1A1A2E] text-[#E0E0E0] border border-transparent hover:border-[#3A3A4E] hover:bg-[#22223A] transition-all"> |
| 3 | New |
| 4 | </button> |
| 5 | <button class="h-9 px-3 rounded-md text-[13px] font-semibold bg-[#1A1A2E] text-[#E0E0E0] border border-transparent hover:border-[#3A3A4E] hover:bg-[#22223A] transition-all"> |
| 6 | Open |
| 7 | </button> |
| 8 | <div role="separator" aria-orientation="vertical" class="w-px h-5 bg-[#2A2A3E] mx-1"> |
| 9 | </div> |
| 10 | <input type="text" placeholder="Search files..." aria-label="Search files" class="h-9 w-44 px-3 rounded-md text-[13px] bg-[#0A0A0A] text-[#E0E0E0] border border-[#2A2A3E] placeholder:text-[#808080] focus:border-[#00FF41] focus:outline-none focus:ring-2 focus:ring-[#00FF41]/15" /> |
| 11 | </div> |
| 1 | <div class="btn-group" role="toolbar" aria-label="File search"> |
| 2 | <button class="btn btn-dark border-secondary fw-semibold"> |
| 3 | New |
| 4 | </button> |
| 5 | <button class="btn btn-dark border-secondary fw-semibold"> |
| 6 | Open |
| 7 | </button> |
| 8 | <input type="text" class="form-control bg-dark text-light border-secondary" placeholder="Search files..." aria-label="Search files" style="width:180px;background:#0A0A0A;color:#E0E0E0" /> |
| 9 | </div> |
Toolbars are composite widgets, so keyboard behavior and screen-reader semantics matter as much as visual styling.
- Apply role="toolbar" to the container and a descriptive aria-label.
- Use aria-orientation to declare horizontal or vertical layout.
- Implement roving tabIndex: only the active control has tabIndex="0"; siblings have tabIndex="-1".
- Move focus with Left/Right in horizontal toolbars and Up/Down in vertical toolbars.
- Mark toggle buttons with aria-pressed and update it when state changes.
- Icon-only buttons must include an aria-label or visually hidden text.
- Place role="separator" between logical groups and give it an orientation.
- Keep focus indicators visible; never remove focus rings without a replacement.
Community
Get help on Slack, Discord or VIP
Stuck on a guide? Join the community and ask.