← Components/Code

CodeBlock

codeblock-1779378817617.tsx
'use client'
import { useState } from 'react'

const EXAMPLES = {
  tsx: {
    label: 'TypeScript',
    code: `import { useState } from 'react'

interface ButtonProps {
  variant?: 'primary' | 'ghost'
  children: React.ReactNode
  onClick?: () => void
}

export function Button({ variant = 'primary', children, onClick }: ButtonProps) {
  const [active, setActive] = useState(false)

  return (
    <button
      onClick={() => { setActive(true); onClick?.() }}
      className={variant === 'primary' ? 'bg-gold-500 text-black' : 'border border-white/20'}
    >
      {children}
    </button>
  )
}`,
  },
  bash: {
    label: 'Terminal',
    code: `# Install Empire UI MCP
npx empire-ui-mcp --stdio

# Or add to Claude config
{
  "mcpServers": {
    "empire-ui": {
      "command": "npx",
      "args": ["empire-ui-mcp", "--stdio"]
    }
  }
}`,
  },
}

type Lang = keyof typeof EXAMPLES

const KEYWORDS = ['import', 'from', 'interface', 'export', 'function', 'const', 'return', 'useState', 'typeof', 'string', 'boolean', 'React']
const STRINGS = /('.*?'|".*?"|`.*?`)/g
const COMMENTS = /(#.*$|//.*$)/gm

function highlight(code: string, lang: Lang): string {
  if (lang === 'bash') {
    return code.replace(/&/g,'&amp;').replace(/</g,'&lt;')
      .replace(COMMENTS, '<span style="color:#6b7280">$1</span>')
      .replace(/(npx|npm|node|cd|export|echo)/g, '<span style="color:#C9A84C">$1</span>')
  }
  return code.replace(/&/g,'&amp;').replace(/</g,'&lt;')
    .replace(STRINGS, '<span style="color:#86efac">$1</span>')
    .replace(new RegExp(`\\b(${KEYWORDS.join('|')})\\b`, 'g'), '<span style="color:#C9A84C">$1</span>')
    .replace(/([A-Z][a-zA-Z]+)(?=[<(])/g, '<span style="color:#93c5fd">$1</span>')
    .replace(/(/\/.*$)/gm, '<span style="color:#6b7280">$1</span>')
}

export default function CodeBlock() {
  const [lang, setLang] = useState<Lang>('tsx')
  const [copied, setCopied] = useState(false)
  const [lineNums, setLineNums] = useState(true)

  const ex = EXAMPLES[lang]
  const lines = ex.code.split('\n')

  function copy() {
    navigator.clipboard.writeText(ex.code)
    setCopied(true)
    setTimeout(() => setCopied(false), 2000)
  }

  return (
    <div style={{ background: '#0D0D0D', border: '1px solid rgba(255,255,255,0.08)', borderRadius: 14, overflow: 'hidden', fontFamily: 'ui-monospace, monospace' }}>
      {/* Toolbar */}
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: '10px 16px', borderBottom: '1px solid rgba(255,255,255,0.06)', background: '#111' }}>
        <div style={{ display: 'flex', gap: 6 }}>
          {(Object.keys(EXAMPLES) as Lang[]).map(k => (
            <button key={k} onClick={() => setLang(k)} style={{ background: lang === k ? 'rgba(201,168,76,0.15)' : 'rgba(255,255,255,0.04)', border: '1px solid', borderColor: lang === k ? 'rgba(201,168,76,0.3)' : 'rgba(255,255,255,0.08)', color: lang === k ? '#C9A84C' : 'rgba(255,255,255,0.4)', borderRadius: 5, padding: '3px 10px', cursor: 'pointer', fontSize: 11 }}>
              {EXAMPLES[k].label}
            </button>
          ))}
          <button onClick={() => setLineNums(l => !l)} style={{ background: 'rgba(255,255,255,0.04)', border: '1px solid rgba(255,255,255,0.08)', color: 'rgba(255,255,255,0.4)', borderRadius: 5, padding: '3px 8px', cursor: 'pointer', fontSize: 11 }}>
            {lineNums ? '#' : '—'}
          </button>
        </div>
        <button onClick={copy} style={{ background: copied ? 'rgba(34,197,94,0.15)' : 'rgba(255,255,255,0.06)', border: '1px solid', borderColor: copied ? 'rgba(34,197,94,0.3)' : 'rgba(255,255,255,0.1)', color: copied ? '#22c55e' : '#F5F5F0', borderRadius: 6, padding: '5px 12px', cursor: 'pointer', fontSize: 12, transition: 'all 0.2s' }}>
          {copied ? '✓ Copied' : 'Copy'}
        </button>
      </div>
      {/* Code */}
      <div style={{ overflowX: 'auto', padding: '16px 0' }}>
        <table style={{ borderCollapse: 'collapse', width: '100%' }}>
          <tbody>
            {lines.map((line, i) => (
              <tr key={i} style={{ '&:hover': { background: 'rgba(255,255,255,0.02)' } } as any}>
                {lineNums && <td style={{ padding: '0 16px', color: 'rgba(255,255,255,0.2)', fontSize: 12, textAlign: 'right', userSelect: 'none', minWidth: 40, verticalAlign: 'top' }}>{i + 1}</td>}
                <td style={{ padding: lineNums ? '0 20px 0 0' : '0 20px', fontSize: 13, color: '#cdd6f4', whiteSpace: 'pre' }} dangerouslySetInnerHTML={{ __html: highlight(line, lang) || '&nbsp;' }} />
              </tr>
            ))}
          </tbody>
        </table>
      </div>
    </div>
  )
}

Component info

CategoryCode
Frameworkreact
TierFREE
Views0
Copies0

About

Syntax-highlighted code block with copy button, language badge, line numbers, and diff support