bolt.diy/app/components/ui/CodeBlock.tsx
Stijnus 870bfc58ee
Some checks are pending
Docker Publish / docker-build-publish (push) Waiting to run
Update Stable Branch / prepare-release (push) Waiting to run
feat: github fix and ui improvements (#1685)
* feat: Add reusable UI components and fix GitHub repository display

* style: Fix linting issues in UI components

* fix: Add close icon to GitHub Connection Required dialog

* fix: Add CloseButton component to fix white background issue in dialog close icons

* Fix close button styling in dialog components to address ghost white issue in dark mode

* fix: update icon color to tertiary for consistency

The icon color was changed from `text-bolt-elements-icon-info` to `text-bolt-elements-icon-tertiary`

* fix: improve repository selection dialog tab styling for dark mode

- Update tab menu styling to prevent white background in dark mode
- Use explicit color values for better dark/light mode compatibility
- Improve hover and active states for better visual hierarchy
- Remove unused Tabs imports

---------

Co-authored-by: KevIsDev <zennerd404@gmail.com>
2025-05-09 15:23:20 +02:00

104 lines
3.9 KiB
TypeScript

import React, { useState } from 'react';
import { classNames } from '~/utils/classNames';
import { motion } from 'framer-motion';
import { FileIcon } from './FileIcon';
import { Tooltip } from './Tooltip';
interface CodeBlockProps {
code: string;
language?: string;
filename?: string;
showLineNumbers?: boolean;
highlightLines?: number[];
maxHeight?: string;
className?: string;
onCopy?: () => void;
}
export function CodeBlock({
code,
language,
filename,
showLineNumbers = true,
highlightLines = [],
maxHeight = '400px',
className,
onCopy,
}: CodeBlockProps) {
const [copied, setCopied] = useState(false);
const handleCopy = () => {
navigator.clipboard.writeText(code);
setCopied(true);
setTimeout(() => setCopied(false), 2000);
onCopy?.();
};
const lines = code.split('\n');
return (
<div
className={classNames(
'rounded-lg overflow-hidden border border-bolt-elements-borderColor dark:border-bolt-elements-borderColor-dark',
'bg-bolt-elements-background-depth-2 dark:bg-bolt-elements-background-depth-3',
className,
)}
>
{/* Header */}
<div className="flex items-center justify-between px-4 py-2 bg-bolt-elements-background-depth-3 dark:bg-bolt-elements-background-depth-4 border-b border-bolt-elements-borderColor dark:border-bolt-elements-borderColor-dark">
<div className="flex items-center gap-2">
{filename && (
<>
<FileIcon filename={filename} size="sm" />
<span className="text-xs font-medium text-bolt-elements-textSecondary dark:text-bolt-elements-textSecondary-dark">
{filename}
</span>
</>
)}
{language && !filename && (
<span className="text-xs font-medium text-bolt-elements-textSecondary dark:text-bolt-elements-textSecondary-dark uppercase">
{language}
</span>
)}
</div>
<Tooltip content={copied ? 'Copied!' : 'Copy code'}>
<motion.button
onClick={handleCopy}
className="p-1.5 rounded-md text-bolt-elements-textTertiary hover:text-bolt-elements-textSecondary dark:text-bolt-elements-textTertiary-dark dark:hover:text-bolt-elements-textSecondary-dark hover:bg-bolt-elements-background-depth-2 dark:hover:bg-bolt-elements-background-depth-3 transition-colors"
whileHover={{ scale: 1.05 }}
whileTap={{ scale: 0.95 }}
>
{copied ? <span className="i-ph:check w-4 h-4 text-green-500" /> : <span className="i-ph:copy w-4 h-4" />}
</motion.button>
</Tooltip>
</div>
{/* Code content */}
<div className={classNames('overflow-auto', 'font-mono text-sm', 'custom-scrollbar')} style={{ maxHeight }}>
<table className="min-w-full border-collapse">
<tbody>
{lines.map((line, index) => (
<tr
key={index}
className={classNames(
highlightLines.includes(index + 1) ? 'bg-purple-500/10 dark:bg-purple-500/20' : '',
'hover:bg-bolt-elements-background-depth-3 dark:hover:bg-bolt-elements-background-depth-4',
)}
>
{showLineNumbers && (
<td className="py-1 pl-4 pr-2 text-right select-none text-bolt-elements-textTertiary dark:text-bolt-elements-textTertiary-dark border-r border-bolt-elements-borderColor dark:border-bolt-elements-borderColor-dark">
<span className="inline-block min-w-[1.5rem] text-xs">{index + 1}</span>
</td>
)}
<td className="py-1 pl-4 pr-4 text-bolt-elements-textPrimary dark:text-bolt-elements-textPrimary-dark whitespace-pre">
{line || ' '}
</td>
</tr>
))}
</tbody>
</table>
</div>
</div>
);
}