headplane/app/components/Attribute.tsx

87 lines
2 KiB
TypeScript
Raw Normal View History

import { Check, Copy, Info } from 'lucide-react';
2025-02-01 18:11:33 -05:00
import cn from '~/utils/cn';
2025-01-28 16:06:41 -05:00
import toast from '~/utils/toast';
import Tooltip from './Tooltip';
2024-03-26 09:28:52 -04:00
2025-02-01 18:11:33 -05:00
export interface AttributeProps {
2024-12-31 10:30:14 +05:30
name: string;
value: string;
tooltip?: string;
2024-12-31 10:30:14 +05:30
isCopyable?: boolean;
2024-03-26 09:28:52 -04:00
}
export default function Attribute({
name,
value,
tooltip,
isCopyable,
}: AttributeProps) {
2024-03-26 09:28:52 -04:00
return (
2025-04-23 11:08:50 -04:00
<dl className="flex gap-1 items-center text-sm">
<dt
className={cn(
'w-1/3 sm:w-1/4 lg:w-1/3 shrink-0 min-w-0',
2025-04-23 11:08:50 -04:00
'text-headplane-500 dark:text-headplane-400',
tooltip ? 'flex items-center gap-1' : undefined,
2024-12-31 10:30:14 +05:30
)}
2025-04-23 11:08:50 -04:00
>
{name}
{tooltip ? (
<Tooltip>
<Info className="size-4" />
<Tooltip.Body>{tooltip}</Tooltip.Body>
</Tooltip>
) : undefined}
2024-03-26 09:28:52 -04:00
</dt>
2025-02-01 18:11:33 -05:00
<dd
className={cn(
2025-04-23 11:08:50 -04:00
'min-w-0 px-1.5 py-1 rounded-lg border border-transparent',
...(isCopyable
? [
2025-05-29 09:45:47 -04:00
'cursor-pointer hover:shadow-xs',
2025-04-23 11:08:50 -04:00
'hover:bg-headplane-50 dark:hover:bg-headplane-800',
'hover:border-headplane-100 dark:hover:border-headplane-700',
]
: []),
2025-02-01 18:11:33 -05:00
)}
>
{isCopyable ? (
<button
type="button"
2025-04-23 11:08:50 -04:00
className="flex items-center gap-1.5 relative min-w-0 w-full"
2025-02-01 18:11:33 -05:00
onClick={async (event) => {
const svgs = event.currentTarget.querySelectorAll('svg');
for (const svg of svgs) {
svg.toggleAttribute('data-copied', true);
}
await navigator.clipboard.writeText(value);
2025-04-23 11:08:50 -04:00
toast(`Copied ${name} to clipboard`);
2024-03-26 09:28:52 -04:00
2025-02-01 18:11:33 -05:00
setTimeout(() => {
for (const svg of svgs) {
svg.toggleAttribute('data-copied', false);
}
}, 1000);
}}
>
2025-04-23 11:08:50 -04:00
<div suppressHydrationWarning className="truncate">
{value}
2025-04-23 11:08:50 -04:00
</div>
{isCopyable ? (
<div>
2025-05-29 09:45:47 -04:00
<Check className="size-4 hidden data-copied:block" />
<Copy className="size-4 block data-copied:hidden" />
2025-04-23 11:08:50 -04:00
</div>
) : undefined}
2025-02-01 18:11:33 -05:00
</button>
) : (
2025-04-23 11:08:50 -04:00
<div className="relative min-w-0 truncate" suppressHydrationWarning>
{value}
</div>
2025-02-01 18:11:33 -05:00
)}
</dd>
2024-03-26 09:28:52 -04:00
</dl>
2024-12-31 10:30:14 +05:30
);
2024-03-26 09:28:52 -04:00
}