Files
opencrm/frontend/src/components/ui/Tabs.tsx
T
duffyduck 84cbf01706 Kunden-Tabs: ExternalLink-Icon neben jedem Reiter
Tabs-Komponente bekommt optionalen tabHrefBuilder(tabId)-Prop.
Wenn gesetzt, erscheint neben jedem Tab-Label ein kleines
ExternalLink-Icon, das den Tab via ?tab=<id> in einem neuen
Browser-Tab öffnet.

CustomerDetail übergibt den Builder. URL-Param wird eh schon
für den Tab-Sync genutzt – Anhängen reicht.

Click-stopPropagation verhindert, dass der Klick auf das Icon
gleichzeitig den Tab-Wechsel auslöst.
2026-06-03 18:15:23 +02:00

83 lines
2.4 KiB
TypeScript

import { ReactNode, useState, useEffect } from 'react';
import { ExternalLink } from 'lucide-react';
interface Tab {
id: string;
label: string;
content: ReactNode;
}
interface TabsProps {
tabs: Tab[];
defaultTab?: string;
activeTab?: string;
onTabChange?: (tabId: string) => void;
/**
* Optional: liefert die URL, unter der ein einzelner Tab in einem
* neuen Tab geöffnet werden kann. Wenn gesetzt, erscheint neben jedem
* Tab-Label ein kleines „im neuen Tab öffnen"-Icon.
*/
tabHrefBuilder?: (tabId: string) => string;
}
export default function Tabs({
tabs,
defaultTab,
activeTab: controlledTab,
onTabChange,
tabHrefBuilder,
}: TabsProps) {
const [internalTab, setInternalTab] = useState(defaultTab || tabs[0]?.id);
const activeTab = controlledTab ?? internalTab;
useEffect(() => {
if (controlledTab !== undefined) {
setInternalTab(controlledTab);
}
}, [controlledTab]);
const handleTabChange = (tabId: string) => {
setInternalTab(tabId);
onTabChange?.(tabId);
};
return (
<div>
<div className="border-b border-gray-200">
<nav className="flex -mb-px space-x-6">
{tabs.map((tab) => (
<div key={tab.id} className="flex items-center gap-1">
<button
onClick={() => handleTabChange(tab.id)}
className={`py-4 px-1 border-b-2 font-medium text-sm whitespace-nowrap ${
activeTab === tab.id
? 'border-blue-500 text-blue-600'
: 'border-transparent text-gray-500 hover:text-gray-700 hover:border-gray-300'
}`}
>
{tab.label}
</button>
{tabHrefBuilder && (
<a
href={tabHrefBuilder(tab.id)}
target="_blank"
rel="noopener noreferrer"
onClick={(e) => e.stopPropagation()}
className="text-gray-400 hover:text-blue-600 p-0.5"
title={`${tab.label} in neuem Tab öffnen`}
aria-label={`${tab.label} in neuem Tab öffnen`}
>
<ExternalLink className="w-3.5 h-3.5" />
</a>
)}
</div>
))}
</nav>
</div>
<div className="mt-4">
{tabs.find((tab) => tab.id === activeTab)?.content}
</div>
</div>
);
}