Forms segmentedswitch

Segmented Control

Radio-based mode switcher.

Preview

Usage

Copy the full block below to use this component with its imports.

astro
---
import { SegmentedControl } from 'astro-component-kit';
---

<SegmentedControl name="view" options={[{label: "Day", value: "d", checked: true}, {label: "Week", value: "w"}]} />
--- import { SegmentedControl } from 'astro-component-kit'; --- <SegmentedControl name="view" options={[{label: "Day", value: "d", checked: true}, {label: "Week", value: "w"}]} />

Manual Installation

If you are not using the npm package, create a new file src/components/lib/SegmentedControl.astro and paste the following code:

astro
---
/**
 * SegmentedControl — A horizontal group of button-like radio choices for switching views or modes.
 * 
 * @param {string} name - Shared HTML name for the internal radio inputs.
 * @param {Array<{label: string, value: string, checked?: boolean}>} options - Selectable segments.
 * @param {string} idPrefix - Prefix for auto-generating input IDs.
 */
interface Props {
  name: string;
  options: Array<{ label: string; value: string; checked?: boolean }>;
  idPrefix?: string;
}

const { name, options = [], idPrefix = "seg" } = Astro.props;
---

<div class="segmented">
  {options.map((opt, i) => (
    <div class="segmented-item">
      <input 
        type="radio" 
        name={name} 
        id={`${idPrefix}-${i}`} 
        value={opt.value} 
        checked={opt.checked} 
        class="segmented-input"
      />
      <label for={`${idPrefix}-${i}`} class="segmented-label">{opt.label}</label>
    </div>
  ))}
</div>

<style>
  .segmented { 
    display: flex; position: relative; 
    background: var(--c-bg-elev, rgba(255,255,255,0.05)); 
    padding: 4px; border-radius: var(--r-md, 12px); 
    width: fit-content; border: 1px solid var(--c-border, rgba(255,255,255,0.05));
    box-shadow: inset 0 2px 4px rgba(0,0,0,0.1);
  }
  
  .segmented-item { display: flex; }
  
  .segmented-label { 
    padding: 0.5rem 1.4rem; cursor: pointer; z-index: 1; 
    font-size: 0.85rem; transition: all 0.25s ease; 
    color: var(--c-text-2, #94a3b8); 
    border-radius: var(--r-sm, 8px);
    font-weight: 500;
    user-select: none;
  }
  
  .segmented-input { display: none; }
  
  .segmented-input:checked + .segmented-label { 
    color: var(--c-text-1, #fff); 
    font-weight: 700; 
    background: var(--c-primary, #6366f1); 
    box-shadow: 0 4px 12px rgba(99, 102, 241, 0.3);
  }
  
  .segmented-label:hover:not(.segmented-input:checked + .segmented-label) {
    color: var(--c-text-1);
    background: rgba(255,255,255,0.03);
  }
</style>
--- /** * SegmentedControl — A horizontal group of button-like radio choices for switching views or modes. * * @param {string} name - Shared HTML name for the internal radio inputs. * @param {Array<{label: string, value: string, checked?: boolean}>} options - Selectable segments. * @param {string} idPrefix - Prefix for auto-generating input IDs. */ interface Props { name: string; options: Array<{ label: string; value: string; checked?: boolean }>; idPrefix?: string; } const { name, options = [], idPrefix = "seg" } = Astro.props; --- <div class="segmented"> {options.map((opt, i) => ( <div class="segmented-item"> <input type="radio" name={name} id={`${idPrefix}-${i}`} value={opt.value} checked={opt.checked} class="segmented-input" /> <label for={`${idPrefix}-${i}`} class="segmented-label">{opt.label}</label> </div> ))} </div> <style> .segmented { display: flex; position: relative; background: var(--c-bg-elev, rgba(255,255,255,0.05)); padding: 4px; border-radius: var(--r-md, 12px); width: fit-content; border: 1px solid var(--c-border, rgba(255,255,255,0.05)); box-shadow: inset 0 2px 4px rgba(0,0,0,0.1); } .segmented-item { display: flex; } .segmented-label { padding: 0.5rem 1.4rem; cursor: pointer; z-index: 1; font-size: 0.85rem; transition: all 0.25s ease; color: var(--c-text-2, #94a3b8); border-radius: var(--r-sm, 8px); font-weight: 500; user-select: none; } .segmented-input { display: none; } .segmented-input:checked + .segmented-label { color: var(--c-text-1, #fff); font-weight: 700; background: var(--c-primary, #6366f1); box-shadow: 0 4px 12px rgba(99, 102, 241, 0.3); } .segmented-label:hover:not(.segmented-input:checked + .segmented-label) { color: var(--c-text-1); background: rgba(255,255,255,0.03); } </style>

Quick Info

Category
Forms
Filename
SegmentedControl.astro
Dependencies
None — pure Astro + CSS
Tags
segmentedswitch