Code Block
Code Block é um componente de dados para React e Tailwind CSS, da biblioteca UI Layouts, com licença MIT. Copia e cola no teu projeto.
UI Layouts
MIT
data
O que é
Code Block é um componente de dados para React e Tailwind CSS, da biblioteca UI Layouts, com licença MIT. Copia e cola no teu projeto.
Como usar
Abre o componente no catálogo, carrega em copiar, e cola no teu projeto. O prompt copiado leva o código e as regras para o teu agente o reproduzir sem alterar nada.
Cinco cópias grátis por mês. Sem cartão.
Precisa de
npm i shiki
Licença
Este componente vem de UI Layouts e é redistribuído sob a licença MIT, que permite uso comercial. O aviso de copyright viaja com o código.
Code Block
'use client';
import { CopyButton } from '@/components/website/code-components/copy-button';
import { cn } from '@/lib/utils';
import { useEffect, useState } from 'react';
import { codeToHtml } from 'shiki/bundle/web';
export function CodeBlock({
code,
lang = 'tsx',
className,
}: {
code: string;
lang?: string;
className?: string;
}) {
const [html, setHtml] = useState('');
const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
let cancelled = false;
const highlightCode = async () => {
try {
const highlightedHtml = await codeToHtml(code, {
lang,
themes: { light: 'github-light', dark: 'slack-dark' },
});
if (!cancelled) {
setHtml(highlightedHtml);
setIsLoading(false);
}
} catch (error) {
console.error('Error highlighting code:', error);
if (!cancelled) {
setIsLoading(false);
}
}
};
highlightCode();
return () => {
cancelled = true;
};
}, [code, lang]);
if (isLoading) {
return (
<div className={cn('relative', className)}>
<div className='p-6 w-full mx-auto h-[400px] dark:bg-neutral-800 bg-neutral-200 animate-pulse rounded-xl'></div>
</div>
);
}
return (
<div className={cn('relative', className)}>
<CopyButton code={code} classname='right-2 top-2 bg-white dark:bg-neutral-800' />
<div
className='not-prose max-h-[550px] overflow-x-hidden rounded-md text-sm border dark:border-neutral-800'
dangerouslySetInnerHTML={{ __html: html }}
/>
</div>
);
}
'use client';
import { cn } from '@/lib/utils';
import { Check, CheckCheck, Copy } from 'lucide-react';
import { useState } from 'react';
export function CopyButton({ code, classname }: { code: string; classname?: string }) {
const [hasCheckIcon, setHasCheckIcon] = useState(false);
const onCopy = () => {
navigator.clipboard.writeText(code);
setHasCheckIcon(true);
setTimeout(() => {
setHasCheckIcon(false);
}, 1000);
};
return (
<>
<div
className={cn(
'absolute right-2 top-2 cursor-pointer dark:hover:shadow-[0px_1px_10px_5px_#3f7ef3] hover:shadow-[0px_1px_10px_5px_#9abaf7] dark:hover:border-blue-500 hover:border-blue-300 dark:bg-zinc-800 backdrop-blur-2xl bg-white rounded-md border-2',
classname
)}
onClick={onCopy}
>
<div
className={` inset-0 transform transition-all duration-300 w-9 h-8 grid place-content-center ${
hasCheckIcon ? 'scale-0 opacity-0' : 'scale-100 opacity-100'
}`}
>
<Copy className='h-4 w-4 text-foreground/80' />
</div>
<div
className={`absolute inset-0 transform transition-all duration-300 w-8 h-8 grid place-content-center ${
hasCheckIcon ? 'scale-100 opacity-100' : 'scale-0 opacity-0'
}`}
>
<CheckCheck className='h-4 w-4 text-foreground/80' />
</div>
</div>
</>
);
}