Componentes
[animación] · animate-ui / shiki / next-themes

CodeTabs

Tabs de código con highlight via Shiki, tema claro/oscuro automático y botón de copiar.

animate-uishikinext-themes
@/components/animate-ui/components/animate/code-tabs
1'use client';;
2import * as React from 'react';
3import { useTheme } from 'next-themes';
4 
5import { cn } from '@/lib/utils';
6import {
7 Tabs,
8 TabsContent,
9 TabsList,
10 TabsTrigger,
11 TabsContents,
12 TabsHighlight,
13 TabsHighlightItem,
14} from '@/components/animate-ui/primitives/animate/tabs';
15import { CopyButton } from '@/components/animate-ui/components/buttons/copy';
16 
17function CodeTabs({
18 codes,
19 lang = 'bash',
20 
21 themes = {
22 light: 'github-light',
23 dark: 'github-dark',
24 },
25 
26 className,
27 defaultValue,
28 value,
29 onValueChange,
30 copyButton = true,
31 onCopiedChange,
32 ...props
33}) {
34 const { resolvedTheme } = useTheme();
35 
36 const [highlightedCodes, setHighlightedCodes] = React.useState(null);
37 const [selectedCode, setSelectedCode] = React.useState(value ?? defaultValue ?? Object.keys(codes)[0] ?? '');
38 
39 React.useEffect(() => {
40 async function loadHighlightedCode() {
41 try {
42 const { codeToHtml } = await import('shiki');
43 const newHighlightedCodes = {};
44 
45 for (const [command, val] of Object.entries(codes)) {
46 const highlighted = await codeToHtml(val, {
47 lang,
48 themes: {
49 light: themes.light,
50 dark: themes.dark,
51 },
52 defaultColor: resolvedTheme === 'dark' ? 'dark' : 'light',
53 });
54 
55 newHighlightedCodes[command] = highlighted;
56 }
57 
58 setHighlightedCodes(newHighlightedCodes);
59 } catch (error) {
60 console.error('Error highlighting codes', error);
61 setHighlightedCodes(codes);
62 }
63 }
64 loadHighlightedCode();
65 }, [resolvedTheme, lang, themes.light, themes.dark, codes]);
66 
67 return (
68 <Tabs
69 data-slot="install-tabs"
70 className={cn('w-full gap-0 bg-muted/50 rounded-xl border overflow-hidden', className)}
71 {...props}
72 value={selectedCode}
73 onValueChange={(val) => {
74 setSelectedCode(val);
75 onValueChange?.(val);
76 }}>
77 <TabsHighlight
78 className="absolute z-0 inset-0 rounded-none shadow-none bg-transparent after:content-[''] after:absolute after:inset-x-0 after:h-0.5 after:bottom-0 dark:after:bg-white after:bg-black after:rounded-t-full">
79 <TabsList
80 data-slot="install-tabs-list"
81 className="w-full relative flex items-center justify-between rounded-none h-10 bg-muted border-b border-border/75 dark:border-border/50 text-current py-0 px-4">
82 <div className="flex gap-x-3 h-full">
83 {highlightedCodes &&
84 Object.keys(highlightedCodes).map((code) => (
85 <TabsHighlightItem key={code} value={code} className="flex items-center justify-center">
86 <TabsTrigger
87 key={code}
88 value={code}
89 className="text-muted-foreground h-full text-sm font-medium data-[state=active]:text-current px-0">
90 {code}
91 </TabsTrigger>
92 </TabsHighlightItem>
93 ))}
94 </div>
95 
96 {copyButton && highlightedCodes && (
97 <CopyButton
98 content={codes[selectedCode]}
99 size="xs"
100 variant="ghost"
101 className="-me-2.5 bg-transparent hover:bg-black/5 dark:hover:bg-white/10"
102 onCopiedChange={onCopiedChange} />
103 )}
104 </TabsList>
105 </TabsHighlight>
106 
107 <TabsContents data-slot="install-tabs-contents">
108 {highlightedCodes &&
109 Object.entries(highlightedCodes).map(([code, val]) => (
110 <TabsContent
111 data-slot="install-tabs-content"
112 key={code}
113 className="w-full"
114 value={code}>
115 <div
116 className="w-full text-sm overflow-auto flex items-center p-4 [&>pre,_&_code]:!bg-transparent [&_code_.line]:!px-0 [&>pre,_&_code]:[background:transparent_!important] [&>pre,_&_code]:border-none [&_code]:!text-[13px]"
117 dangerouslySetInnerHTML={{ __html: val }} />
118 </TabsContent>
119 ))}
120 </TabsContents>
121 </Tabs>
122 );
123}
124 
125export { CodeTabs };
126 

Uso

Props

PropTipoDefaultDescripción
codesRecord<string, string>—Tab → contenido.
langLangbashLenguaje para Shiki.
themes{light, dark}githubTemas de highlight.
copyButtonbooleantrueBotón copiar.

Acciones del componente

Search for a command to run...

Potenciá tu negocio con SFESS

Software a medida, IA integrada y ciberseguridad avanzada para empresas.

0años de ingeniería
0proyectos entregados
0% uptime
Servicios destacados
  • Consultoría SEO Avanzado & Analítica

    Auditoría técnica profunda para posicionar tu negocio en los primeros resultados de Google.

    SEO TécnicoGA4
  • Páginas Web Corporativas Complejas

    Plataformas empresariales masivas con múltiples secciones y animaciones fluidas.

    Framer MotionMulti-page
  • Integración de Inteligencia Artificial en Negocios

    Automatizamos la atención, las reservas y las ventas de tu negocio con agentes de IA.

    AI AgentsChatbots
Nuestro ecosistema
WORKENTA_OSSFESS_SOLUTIONSPRANALUZ_YOGAREMY_AI
Ver todos los servicios