8pt

Segmented Control

Segmented Control•Navigation
Overview

Equal-width segments with a slider that springs into place; the content below fades in. Arrow keys switch segments.

Plain HTML, CSS and a little vanilla JS, with no framework dependency. Copy the prompt into Claude Code, Cursor, Trae or Codex and the model adds Segmented Control to your project in your colors.

Where to use it

Site headers, tab switches, segmented controls, side navigation and footers.

Install

With Builder, install it with the 8pt CLI or call it directly from an editor connected to 8pt MCP.

$ npm i -g @8pt-dev/cli && 8pt add segmented-control
mcp › Use 8pt MCP to call get_component("segmented-control")

Code

Source for Segmented Control. Motion uses only transform and opacity and respects the Reduce motion setting.

<div class="x-seg">
  <div class="x-seg__bar" role="tablist" aria-label="View">
    <span class="x-seg__thumb" aria-hidden="true"></span>
    <button type="button" role="tab" aria-selected="true">D</button>
    <button type="button" role="tab" aria-selected="false">W</button>
    <button type="button" role="tab" aria-selected="false">M</button>
    <button type="button" role="tab" aria-selected="false">year</button>
  </div>
  <div class="x-seg__out"><b>2,481</b><span>Visits today</span></div>
</div>
.x-seg{display:grid;justify-items:center;gap:18px;color:var(--d-fg,#fff)}
.x-seg__bar{--n:4;--w:62px;position:relative;display:grid;grid-template-columns:repeat(var(--n),var(--w));padding:4px;border-radius:12px;background:var(--d-card,#14141c);border:1px solid var(--d-line,rgba(255,255,255,.1))}
.x-seg__bar button{position:relative;z-index:1;height:34px;border:0;background:transparent;color:var(--d-muted,#9b9ba8);font:600 13px/1 var(--d-font,system-ui,sans-serif);cursor:pointer;transition:color .25s}
.x-seg__bar button[aria-selected=true]{color:var(--d-fg,#fff)}
.x-seg__thumb{position:absolute;left:4px;top:4px;width:var(--w);height:34px;border-radius:9px;background:color-mix(in srgb,var(--d-fg,#fff) 10%,var(--d-card,#14141c));border:1px solid var(--d-line,rgba(255,255,255,.14));box-shadow:0 6px 16px -8px rgba(0,0,0,.5);transition:transform .45s cubic-bezier(.3,1.3,.5,1)}
.x-seg__out{display:grid;justify-items:center;gap:4px;transition:opacity .25s,transform .25s}
.x-seg__out.swap{opacity:0;transform:translateY(6px)}
.x-seg__out b{font:700 34px/1 var(--d-font,system-ui,sans-serif);letter-spacing:-.03em;font-variant-numeric:tabular-nums}
.x-seg__out span{font:12px/1 var(--d-font,system-ui,sans-serif);color:var(--d-muted,#9b9ba8)}
const init = (root) => {
  const bar = root.querySelector('.x-seg__bar'), tabs = [...bar.querySelectorAll('[role=tab]')], thumb = bar.querySelector('.x-seg__thumb');
  const out = root.querySelector('.x-seg__out'), b = out.querySelector('b'), s = out.querySelector('span');
  const data = [['2,481', 'Visits today'], ['16,920', 'Visits this week'], ['71,305', 'Visits this month'], ['842,117', 'Visits this year']];
  let cur = 0, t;
  const go = (i) => { if (i === cur) return; cur = i;
    thumb.style.transform = `translateX(${i * 100}%)`;
    tabs.forEach((x, j) => { x.setAttribute('aria-selected', String(j === i)); x.tabIndex = j === i ? 0 : -1; });
    out.classList.add('swap'); clearTimeout(t); t = setTimeout(() => { b.textContent = data[i][0]; s.textContent = data[i][1]; out.classList.remove('swap'); }, 200); };
  tabs.forEach((x, i) => { x.tabIndex = i ? -1 : 0; x.addEventListener('click', () => go(i)); });
  bar.addEventListener('keydown', e => { if (e.key === 'ArrowRight' || e.key === 'ArrowLeft') { const n = (cur + (e.key === 'ArrowRight' ? 1 : 3)) % 4; go(n); tabs[n].focus(); } });
  return () => clearTimeout(t);
…
Subscribe to Builder to see the full source.See pricing

More navigation components

View all

Animated Tabs

Stepper

More components

View all

AI Prompt Composer

Film Strip Carousel

Auto Tab Showcase

Media Bento Grid

Agent Chat Window

Model Pill Marquee

Director Art Cards

Mac File Window

Keep exploring