Files
MotionSimulator/components/IOPanel.tsx
2025-12-21 22:35:36 +09:00

72 lines
2.5 KiB
TypeScript

import React from 'react';
interface IOPanelProps {
inputs: boolean[];
outputs: boolean[];
inputNames: string[];
outputNames: string[];
onToggleInput: (index: number) => void;
onToggleOutput: (index: number) => void;
}
export const IOPanel: React.FC<IOPanelProps> = ({
inputs,
outputs,
inputNames,
outputNames,
onToggleInput,
onToggleOutput
}) => {
const renderBits = (
bits: boolean[],
names: string[],
colorClass: string,
label: string,
onToggle: (i: number) => void
) => (
<div className="mb-6">
<h3 className="text-xs font-bold text-gray-400 mb-2 uppercase tracking-wider">{label}</h3>
<div className="grid grid-cols-4 gap-2">
{bits.map((isActive, i) => (
<div key={i} className="flex flex-col items-center group relative">
<button
onClick={() => onToggle(i)}
title={`${label} ${i}: ${names[i] || 'Unnamed'}`}
className={`w-7 h-7 rounded-md border border-gray-700 flex items-center justify-center text-[10px] font-mono transition-all duration-150 active:scale-90 ${
isActive
? `${colorClass} shadow-[0_0_10px_rgba(255,255,255,0.3)] border-transparent text-black font-bold`
: 'bg-gray-850 text-gray-500 hover:bg-gray-700'
}`}
>
{i}
</button>
{/* Tooltip on hover */}
<div className="absolute bottom-full mb-1 hidden group-hover:block z-50 bg-black text-white text-[9px] px-2 py-1 rounded border border-gray-700 whitespace-nowrap pointer-events-none">
{names[i] || `Port ${i}`}
</div>
</div>
))}
</div>
</div>
);
return (
<div className="w-48 bg-gray-900 border-r border-gray-800 flex flex-col h-full p-4 z-10 shadow-xl select-none custom-scrollbar overflow-y-auto">
<h2 className="text-sm font-bold text-white mb-4 border-b border-gray-800 pb-2 flex items-center gap-2">
<div className="w-2 h-2 rounded-full bg-blue-500 animate-pulse" />
I/O Monitor
</h2>
{renderBits(inputs, inputNames, 'bg-green-500', 'Inputs', onToggleInput)}
<hr className="border-gray-800 my-4" />
{renderBits(outputs, outputNames, 'bg-red-500', 'Outputs', onToggleOutput)}
<div className="mt-auto pt-4 text-[9px] text-gray-600 border-t border-gray-800">
<p className="font-bold mb-1">Interactive Panel</p>
<p> Click bits to toggle state</p>
<p> Hover to see port names</p>
</div>
</div>
);
};