Tabs
Hoja clienteSwitch between related panels.
Vista previa en vivo
Renderizado desde el código fuente instalado de VEXA — los mismos archivos que recibes.
Escritorio
A summary of your workspace and recent usage.
Instalación
Añade el código del componente a tu proyecto. Las dependencias del registry se resuelven automáticamente.
npx shadcn@latest add https://vexa.valfiguer.com/r/tabs.jsonSe instala en components/vexa/tabs.tsx
Dependencias npm
- @radix-ui/react-tabs
Dependencias del registry
- @vexa/utils
Otros items de VEXA que necesita este componente. Instálalos primero — la CLI los resuelve automáticamente.
Código
Cópialo a su ruta destino, o instálalo con el comando de arriba.
components/vexa/tabs.tsx
"use client";
import type * as React from "react";
import * as TabsPrimitive from "@radix-ui/react-tabs";
import { cn } from "@/lib/utils";
/**
* Tabs — switch between related panels.
*
* Client leaf. Radix implements the APG tabs pattern: roving `Tab`/`Shift+Tab`
* focus onto the active trigger, Arrow keys to move between triggers (Home/End
* to jump), and `tab`/`tabpanel` roles with `aria-selected`/`aria-controls`
* wired up. Automatic activation is the default; set `activationMode="manual"`
* for panels whose content is expensive to render.
*/
export function Tabs({
className,
...props
}: React.ComponentProps<typeof TabsPrimitive.Root>) {
return (
<TabsPrimitive.Root
data-slot="tabs"
className={cn("flex flex-col gap-3", className)}
{...props}
/>
);
}
export function TabsList({
className,
...props
}: React.ComponentProps<typeof TabsPrimitive.List>) {
return (
<TabsPrimitive.List
data-slot="tabs-list"
className={cn(
"inline-flex h-10 w-fit items-center justify-center gap-1 rounded-vexa-md bg-vexa-muted p-1 text-vexa-muted-foreground",
className,
)}
{...props}
/>
);
}
export function TabsTrigger({
className,
...props
}: React.ComponentProps<typeof TabsPrimitive.Trigger>) {
return (
<TabsPrimitive.Trigger
data-slot="tabs-trigger"
className={cn(
"inline-flex items-center justify-center gap-1.5 whitespace-nowrap rounded-vexa-sm px-3 py-1.5 text-sm font-medium",
"transition-[color,background-color,box-shadow] duration-[var(--vexa-duration-fast)] ease-[var(--vexa-ease-standard)]",
"outline-none focus-visible:ring-2 focus-visible:ring-vexa-ring focus-visible:ring-offset-2 focus-visible:ring-offset-vexa-background",
"disabled:pointer-events-none disabled:opacity-50",
"data-[state=active]:bg-vexa-surface-raised data-[state=active]:text-vexa-foreground data-[state=active]:shadow-vexa-sm",
"[&_svg]:size-4 [&_svg]:shrink-0",
className,
)}
{...props}
/>
);
}
export function TabsContent({
className,
...props
}: React.ComponentProps<typeof TabsPrimitive.Content>) {
return (
<TabsPrimitive.Content
data-slot="tabs-content"
className={cn(
"outline-none focus-visible:ring-2 focus-visible:ring-vexa-ring focus-visible:ring-offset-2 focus-visible:ring-offset-vexa-background",
className,
)}
{...props}
/>
);
}
JSON del registryr/tabs.json
r/tabs.json
{
"$schema": "https://ui.shadcn.com/schema/registry-item.json",
"name": "tabs",
"type": "registry:ui",
"title": "Tabs",
"description": "Switch between related panels.",
"dependencies": [
"@radix-ui/react-tabs"
],
"registryDependencies": [
"@vexa/utils"
],
"files": [
{
"path": "registry/default/ui/tabs.tsx",
"type": "registry:ui",
"target": "components/vexa/tabs.tsx",
"content": "\"use client\";\n\nimport type * as React from \"react\";\nimport * as TabsPrimitive from \"@radix-ui/react-tabs\";\n\nimport { cn } from \"@/lib/utils\";\n\n/**\n * Tabs — switch between related panels.\n *\n * Client leaf. Radix implements the APG tabs pattern: roving `Tab`/`Shift+Tab`\n * focus onto the active trigger, Arrow keys to move between triggers (Home/End\n * to jump), and `tab`/`tabpanel` roles with `aria-selected`/`aria-controls`\n * wired up. Automatic activation is the default; set `activationMode=\"manual\"`\n * for panels whose content is expensive to render.\n */\nexport function Tabs({\n className,\n ...props\n}: React.ComponentProps<typeof TabsPrimitive.Root>) {\n return (\n <TabsPrimitive.Root\n data-slot=\"tabs\"\n className={cn(\"flex flex-col gap-3\", className)}\n {...props}\n />\n );\n}\n\nexport function TabsList({\n className,\n ...props\n}: React.ComponentProps<typeof TabsPrimitive.List>) {\n return (\n <TabsPrimitive.List\n data-slot=\"tabs-list\"\n className={cn(\n \"inline-flex h-10 w-fit items-center justify-center gap-1 rounded-vexa-md bg-vexa-muted p-1 text-vexa-muted-foreground\",\n className,\n )}\n {...props}\n />\n );\n}\n\nexport function TabsTrigger({\n className,\n ...props\n}: React.ComponentProps<typeof TabsPrimitive.Trigger>) {\n return (\n <TabsPrimitive.Trigger\n data-slot=\"tabs-trigger\"\n className={cn(\n \"inline-flex items-center justify-center gap-1.5 whitespace-nowrap rounded-vexa-sm px-3 py-1.5 text-sm font-medium\",\n \"transition-[color,background-color,box-shadow] duration-[var(--vexa-duration-fast)] ease-[var(--vexa-ease-standard)]\",\n \"outline-none focus-visible:ring-2 focus-visible:ring-vexa-ring focus-visible:ring-offset-2 focus-visible:ring-offset-vexa-background\",\n \"disabled:pointer-events-none disabled:opacity-50\",\n \"data-[state=active]:bg-vexa-surface-raised data-[state=active]:text-vexa-foreground data-[state=active]:shadow-vexa-sm\",\n \"[&_svg]:size-4 [&_svg]:shrink-0\",\n className,\n )}\n {...props}\n />\n );\n}\n\nexport function TabsContent({\n className,\n ...props\n}: React.ComponentProps<typeof TabsPrimitive.Content>) {\n return (\n <TabsPrimitive.Content\n data-slot=\"tabs-content\"\n className={cn(\n \"outline-none focus-visible:ring-2 focus-visible:ring-vexa-ring focus-visible:ring-offset-2 focus-visible:ring-offset-vexa-background\",\n className,\n )}\n {...props}\n />\n );\n}\n"
}
],
"meta": {
"frameworks": [
"react",
"next"
],
"rsc": "client",
"exports": [
"Tabs",
"TabsList",
"TabsTrigger",
"TabsContent"
],
"cssVars": [
"--vexa-muted",
"--vexa-muted-foreground",
"--vexa-surface-raised",
"--vexa-foreground",
"--vexa-ring",
"--vexa-background"
],
"a11y": "APG tabs: roving Tab focus onto the active trigger, Arrow/Home/End to move between triggers, and tab/tabpanel roles with aria-selected/aria-controls.",
"example": "<Tabs defaultValue=\"a\"><TabsList><TabsTrigger value=\"a\">Account</TabsTrigger></TabsList><TabsContent value=\"a\">...</TabsContent></Tabs>",
"tests": "registry/tests/tabs.test.tsx"
}
}Detalles
Accesibilidad
APG tabs: roving Tab focus onto the active trigger, Arrow/Home/End to move between triggers, and tab/tabpanel roles with aria-selected/aria-controls.