branch:
ShellCommand.tsx
1578 bytesRaw
import { useState } from "react";
import { CheckIcon, CopyIcon } from "@phosphor-icons/react";

const ShellCommand = ({
  command,
  description
}: {
  command: string;
  description?: string;
}) => {
  const [copied, setCopied] = useState(false);
  const [isHovered, setIsHovered] = useState(false);

  const handleCopy = async () => {
    await navigator.clipboard.writeText(command);
    setCopied(true);
    setTimeout(() => setCopied(false), 2000);
  };

  return (
    <div
      className="relative group"
      onMouseEnter={() => setIsHovered(true)}
      onMouseLeave={() => setIsHovered(false)}
    >
      {description && (
        <div className="text-xs text-kumo-secondary mb-1">{description}</div>
      )}
      <div className="relative bg-kumo-control rounded-md py-3 px-3 pr-12 hover:bg-kumo-tint transition-colors">
        <code className="text-sm font-mono text-kumo-default">{command}</code>
        <button
          type="button"
          onClick={handleCopy}
          className={`absolute right-2 top-1/2 -translate-y-1/2 p-1.5 rounded transition-all ${
            isHovered || copied
              ? "opacity-100 translate-x-0"
              : "opacity-0 translate-x-2"
          } ${
            copied
              ? "bg-green-500 text-white"
              : "bg-kumo-inverse text-kumo-inverse hover:opacity-80"
          }`}
          title={copied ? "Copied!" : "Copy to clipboard"}
        >
          {copied ? <CheckIcon size={16} /> : <CopyIcon size={16} />}
        </button>
      </div>
    </div>
  );
};

export default ShellCommand;