Top level hortizontal tab can now be loaded using the #tab id in the url

This commit is contained in:
Colin Dawson 2026-01-31 23:46:08 +00:00
parent c95d7b469c
commit c7428be21b
3 changed files with 20 additions and 11 deletions

View File

@ -1,4 +1,5 @@
import React, { useEffect, useState, useCallback, useMemo } from "react";
import { useLocation } from "react-router-dom";
import TabHeader from "./TabHeader";
interface HorizontalTabsProps {
@ -10,22 +11,25 @@ const HorizontalTabs: React.FC<HorizontalTabsProps> = ({
children,
initialTab,
}) => {
const location = useLocation();
const [activeTab, setActiveTab] = useState<string>("");
// Set initial tab on mount
useEffect(() => {
if (children.length > 0) {
const tabToSelect = initialTab || children[0].props.label;
// Check for hash in URL first, then fall back to initialTab prop
const hashTab = location.hash.slice(1); // Remove the # character
const tabToSelect = hashTab || initialTab || children[0].props.id;
setActiveTab(tabToSelect);
}
}, [children, initialTab]);
}, [children, initialTab, location.hash]);
const onClickTabItem = useCallback((tab: string) => {
setActiveTab((prev) => (prev !== tab ? tab : prev));
}, []);
const activeTabChildren = useMemo(() => {
const match = children.find((child) => child.props.label === activeTab);
const match = children.find((child) => child.props.id === activeTab);
return match ? match.props.children : <></>;
}, [children, activeTab]);
@ -38,13 +42,13 @@ const HorizontalTabs: React.FC<HorizontalTabsProps> = ({
<div className="horizionalTabs">
<ul className="tab-list">
{children.map((child) => {
const { label } = child.props;
const { id, label } = child.props;
return (
<TabHeader
key={label}
label={label}
isActive={label === activeTab}
onClick={onClickTabItem}
isActive={id === activeTab}
onClick={() => onClickTabItem(id)}
/>
);
})}

View File

@ -1,10 +1,15 @@
import React from "react";
interface TabProps {
id?: string;
label: string;
children: React.ReactNode;
}
export default function Tab({ label, children }: TabProps): JSX.Element {
return <div data-tab-label={label}>{children}</div>;
export default function Tab({ id, label, children }: TabProps): JSX.Element {
return (
<div data-tab-id={id} data-tab-label={label}>
{children}
</div>
);
}

View File

@ -28,7 +28,7 @@ const DomainsDetails: React.FC<DomainsDetailsProps> = ({ isEditMode }) => {
const tabs: JSX.Element[] = [];
tabs.push(
<Tab key={1} label={t("General")}>
<Tab id="general" key="general" label={t("General")}>
<GeneralTab isEditMode={isEditMode} />
</Tab>,
);
@ -36,14 +36,14 @@ const DomainsDetails: React.FC<DomainsDetailsProps> = ({ isEditMode }) => {
if (isEditMode) {
if (canViewMailTemplates) {
tabs.push(
<Tab key={2} label={t("MailTemplates")}>
<Tab id="mailTemplates" key="mailTemplates" label={t("MailTemplates")}>
<MailTemplatesTab />
</Tab>,
);
}
if (canViewSecurityRoles) {
tabs.push(
<Tab key={3} label={t("SecurityRoles")}>
<Tab id="securityRoles" key="securityRoles" label={t("SecurityRoles")}>
<SecurityRolesTab initialRoleId={roleId} initialInnerTab={innerTab} />
</Tab>,
);