HextaUI

Tabs: Controlled

Pass value and onValueChange. Changes from outside slide the indicator too.

"use client"

import * as React from "react"

import { Button } from "@/components/ui/button"
import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs"

const steps = ["Cart", "Shipping", "Payment", "Review"]

export function TabsControlled() {
  const [step, setStep] = React.useState("Cart")
  const index = steps.indexOf(step)

  return (
    <div className="flex flex-col items-start gap-4">
      <Tabs value={step} onValueChange={(value) => setStep(String(value))}>
        <TabsList>
          {steps.map((item) => (
            <TabsTrigger key={item} value={item}>
              {item}
            </TabsTrigger>
          ))}
        </TabsList>
      </Tabs>
      <Button
        size="sm"
        variant="outline"
        onClick={() => setStep(steps[(index + 1) % steps.length])}
      >
        Next step
      </Button>
    </div>
  )
}

This adds the example as components/examples/tabs/controlled.tsx, together with the Tabs component and the HextaUI theme tokens it needs.

pnpm dlx shadcn@latest add https://hextaui.com/r/tabs-controlled.json

To add only the component, follow the Tabs installation.

Props in this example

The Tabs props this example sets, from the API reference.

PropTypeDefault
value
any–
onValueChange
(value, details) => void–
PropTypeDefault
value
any–

Every prop is in the Tabs API reference.

See them all, with keyboard support and accessibility notes, on the Tabs page.