Simplifies Vertical and Horizontal tabs
This commit is contained in:
@@ -8,8 +8,7 @@ import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import { Dialog, DialogClose, DialogContent } from "@calcom/ui/Dialog";
|
||||
import { Icon } from "@calcom/ui/Icon";
|
||||
import { InputLeading, Label, TextArea, TextField } from "@calcom/ui/form/fields";
|
||||
import { HorizontalTabs, showToast } from "@calcom/ui/v2";
|
||||
import { Button, Switch } from "@calcom/ui/v2";
|
||||
import { Button, HorizontalTabs, showToast, Switch } from "@calcom/ui/v2";
|
||||
|
||||
import { EMBED_LIB_URL, WEBAPP_URL } from "@lib/config/constants";
|
||||
|
||||
@@ -452,7 +451,7 @@ const embeds: {
|
||||
const tabs = [
|
||||
{
|
||||
name: "HTML",
|
||||
embedTabName: "embed-code",
|
||||
href: "embedTabName=embed-code",
|
||||
icon: Icon.FiCode,
|
||||
type: "code",
|
||||
Component: forwardRef<
|
||||
@@ -503,7 +502,7 @@ ${getEmbedTypeSpecificString({ embedFramework: "HTML", embedType, calLink, previ
|
||||
},
|
||||
{
|
||||
name: "React",
|
||||
embedTabName: "embed-react",
|
||||
href: "embedTabName=embed-react",
|
||||
icon: Icon.FiCode,
|
||||
type: "code",
|
||||
Component: forwardRef<
|
||||
@@ -543,7 +542,7 @@ ${getEmbedTypeSpecificString({ embedFramework: "react", embedType, calLink, prev
|
||||
},
|
||||
{
|
||||
name: "Preview",
|
||||
embedTabName: "embed-preview",
|
||||
href: "embedTabName=embed-preview",
|
||||
icon: Icon.FiEye,
|
||||
type: "iframe",
|
||||
Component: forwardRef<
|
||||
@@ -606,12 +605,9 @@ const ChooseEmbedTypesDialogContent = () => {
|
||||
key={index}
|
||||
data-testid={embed.type}
|
||||
onClick={() => {
|
||||
router.push({
|
||||
query: {
|
||||
...router.query,
|
||||
embedType: embed.type,
|
||||
},
|
||||
});
|
||||
const newQuery = new URLSearchParams(router.asPath);
|
||||
newQuery.set("embedType", embed.type);
|
||||
router.push(`${router.asPath.split("?")[0]}?${newQuery.toString()}`);
|
||||
}}>
|
||||
<div className="order-none box-border flex-none rounded-sm border border-solid bg-white">
|
||||
{embed.illustration}
|
||||
@@ -635,6 +631,13 @@ const EmbedTypeCodeAndPreviewDialogContent = ({
|
||||
const { t } = useLocale();
|
||||
const router = useRouter();
|
||||
const iframeRef = useRef<HTMLIFrameElement>(null);
|
||||
const s = (href: string) => {
|
||||
const searchParams = new URLSearchParams(router.asPath);
|
||||
const [a, b] = href.split("=");
|
||||
searchParams.set(a, b);
|
||||
return `${router.asPath.split("?")[0]}?${searchParams.toString()}`;
|
||||
};
|
||||
const parsedTabs = tabs.map((t) => ({ ...t, href: s(t.href) }));
|
||||
const embedCodeRefs: Record<typeof tabs[0]["name"], RefObject<HTMLTextAreaElement>> = {};
|
||||
tabs
|
||||
.filter((tab) => tab.type === "code")
|
||||
@@ -676,16 +679,6 @@ const EmbedTypeCodeAndPreviewDialogContent = ({
|
||||
});
|
||||
};
|
||||
|
||||
// Use embed-code as default tab
|
||||
if (!router.query.embedTabName) {
|
||||
router.query.embedTabName = "embed-code";
|
||||
router.push({
|
||||
query: {
|
||||
...router.query,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
if (!embed || !embedUrl) {
|
||||
close();
|
||||
return null;
|
||||
@@ -785,14 +778,10 @@ const EmbedTypeCodeAndPreviewDialogContent = ({
|
||||
<h3 className="mb-2 flex text-xl font-bold leading-6 text-gray-900" id="modal-title">
|
||||
<button
|
||||
onClick={() => {
|
||||
const newQuery = { ...router.query };
|
||||
delete newQuery.embedType;
|
||||
delete newQuery.embedTabName;
|
||||
router.push({
|
||||
query: {
|
||||
...newQuery,
|
||||
},
|
||||
});
|
||||
const newQuery = new URLSearchParams(router.asPath);
|
||||
newQuery.delete("embedType");
|
||||
newQuery.delete("embedTabName");
|
||||
router.push(`${router.asPath.split("?")[0]}?${newQuery.toString()}`);
|
||||
}}>
|
||||
<Icon.FiArrowLeft className="mr-4 w-4" />
|
||||
</button>
|
||||
@@ -1041,14 +1030,12 @@ const EmbedTypeCodeAndPreviewDialogContent = ({
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex w-2/3 flex-col p-6">
|
||||
<HorizontalTabs tabNameKey="embedTabName" data-testid="embed-tabs" tabs={tabs} />
|
||||
<HorizontalTabs data-testid="embed-tabs" tabs={parsedTabs} linkProps={{ shallow: true }} />
|
||||
{tabs.map((tab) => {
|
||||
return (
|
||||
<div
|
||||
key={tab.embedTabName}
|
||||
className={classNames(
|
||||
router.query.embedTabName === tab.embedTabName ? "flex flex-grow flex-col" : "hidden"
|
||||
)}>
|
||||
key={tab.href}
|
||||
className={classNames(router.asPath === tab.href ? "flex flex-grow flex-col" : "hidden")}>
|
||||
<div className="flex h-[55vh] flex-grow flex-col">
|
||||
{tab.type === "code" ? (
|
||||
<tab.Component
|
||||
@@ -1133,19 +1120,10 @@ export const EmbedButton = <T extends React.ElementType>({
|
||||
const router = useRouter();
|
||||
className = classNames(className, "hidden lg:inline-flex");
|
||||
const openEmbedModal = () => {
|
||||
const query = {
|
||||
...router.query,
|
||||
dialog: "embed",
|
||||
embedUrl,
|
||||
};
|
||||
router.push(
|
||||
{
|
||||
pathname: router.pathname,
|
||||
query,
|
||||
},
|
||||
undefined,
|
||||
{ shallow: true }
|
||||
);
|
||||
const searchParams = new URLSearchParams(router.asPath);
|
||||
searchParams.set("dialog", "embed");
|
||||
searchParams.set("embedUrl", embedUrl);
|
||||
router.push(`${router.asPath.split("?")[0]}?${searchParams.toString()}`, undefined, { shallow: true });
|
||||
};
|
||||
const Component = as ?? Button;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useRouter } from "next/router";
|
||||
import { TFunction } from "next-i18next";
|
||||
import { EventTypeSetupInfered, FormValues } from "pages/v2/event-types/[type]";
|
||||
import { useEffect, useMemo, useState } from "react";
|
||||
import { useMemo, useState } from "react";
|
||||
import { Loader } from "react-feather";
|
||||
import { UseFormReturn } from "react-hook-form";
|
||||
|
||||
@@ -9,20 +9,18 @@ import { CAL_URL } from "@calcom/lib/constants";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import { HttpError } from "@calcom/lib/http-error";
|
||||
import { trpc, TRPCClientError } from "@calcom/trpc/react";
|
||||
import ConfirmationDialogContent from "@calcom/ui/ConfirmationDialogContent";
|
||||
import { Icon } from "@calcom/ui/Icon";
|
||||
import {
|
||||
Button,
|
||||
ButtonGroup,
|
||||
Tooltip,
|
||||
showToast,
|
||||
VerticalTabItemProps,
|
||||
VerticalTabs,
|
||||
HorizontalTabs,
|
||||
Switch,
|
||||
Label,
|
||||
HorizontalTabItemProps,
|
||||
showToast,
|
||||
Switch,
|
||||
Tooltip,
|
||||
VerticalTabs,
|
||||
} from "@calcom/ui/v2";
|
||||
import ConfirmationDialogContent from "@calcom/ui/v2/core/ConfirmationDialogContent";
|
||||
import { Dialog } from "@calcom/ui/v2/core/Dialog";
|
||||
import Dropdown, {
|
||||
DropdownMenuContent,
|
||||
@@ -46,6 +44,59 @@ type Props = {
|
||||
formMethods: UseFormReturn<FormValues>;
|
||||
};
|
||||
|
||||
function getNavigation(props: {
|
||||
t: TFunction;
|
||||
eventType: Props["eventType"];
|
||||
enabledAppsNumber: number;
|
||||
enabledWorkflowsNumber: number;
|
||||
}) {
|
||||
const { eventType, t, enabledAppsNumber, enabledWorkflowsNumber } = props;
|
||||
return [
|
||||
{
|
||||
name: "event_setup_tab_title",
|
||||
href: `/event-types/${eventType.id}?tabName=setup`,
|
||||
icon: Icon.FiLink,
|
||||
info: `${eventType.length} Mins`, // TODO: Get this from props
|
||||
},
|
||||
{
|
||||
name: "availability",
|
||||
href: `/event-types/${eventType.id}?tabName=availability`,
|
||||
icon: Icon.FiCalendar,
|
||||
info: `Working Hours`, // TODO: Get this from props
|
||||
},
|
||||
{
|
||||
name: "event_limit_tab_title",
|
||||
href: `/event-types/${eventType.id}?tabName=limits`,
|
||||
icon: Icon.FiClock,
|
||||
info: `event_limit_tab_description`,
|
||||
},
|
||||
{
|
||||
name: "event_advanced_tab_title",
|
||||
href: `/event-types/${eventType.id}?tabName=advanced`,
|
||||
icon: Icon.FiSliders,
|
||||
info: `event_advanced_tab_description`,
|
||||
},
|
||||
{
|
||||
name: "recurring",
|
||||
href: `/event-types/${eventType.id}?tabName=recurring`,
|
||||
icon: Icon.FiRepeat,
|
||||
info: `recurring_event_tab_description`,
|
||||
},
|
||||
{
|
||||
name: "apps",
|
||||
href: `/event-types/${eventType.id}?tabName=apps`,
|
||||
icon: Icon.FiGrid,
|
||||
info: `${enabledAppsNumber} ${t("active")}`,
|
||||
},
|
||||
{
|
||||
name: "workflows",
|
||||
href: `/event-types/${eventType.id}?tabName=workflows`,
|
||||
icon: Icon.FiZap,
|
||||
info: `${enabledWorkflowsNumber} ${t("active")}`,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
function EventTypeSingleLayout({
|
||||
children,
|
||||
eventType,
|
||||
@@ -57,7 +108,6 @@ function EventTypeSingleLayout({
|
||||
formMethods,
|
||||
}: Props) {
|
||||
const utils = trpc.useContext();
|
||||
const router = useRouter();
|
||||
const { t } = useLocale();
|
||||
const [deleteDialogOpen, setDeleteDialogOpen] = useState(false);
|
||||
|
||||
@@ -82,73 +132,17 @@ function EventTypeSingleLayout({
|
||||
|
||||
// Define tab navigation here
|
||||
const EventTypeTabs = useMemo(() => {
|
||||
const navigation: (VerticalTabItemProps & HorizontalTabItemProps)[] = [
|
||||
{
|
||||
name: "event_setup_tab_title",
|
||||
tabName: "setup",
|
||||
icon: Icon.FiLink,
|
||||
info: `${eventType.length} Mins`, // TODO: Get this from props
|
||||
},
|
||||
{
|
||||
name: "availability",
|
||||
tabName: "availability",
|
||||
icon: Icon.FiCalendar,
|
||||
info: `Working Hours`, // TODO: Get this from props
|
||||
},
|
||||
{
|
||||
name: "event_limit_tab_title",
|
||||
tabName: "limits",
|
||||
icon: Icon.FiClock,
|
||||
info: `event_limit_tab_description`,
|
||||
},
|
||||
{
|
||||
name: "event_advanced_tab_title",
|
||||
tabName: "advanced",
|
||||
icon: Icon.FiSliders,
|
||||
info: `event_advanced_tab_description`,
|
||||
},
|
||||
{
|
||||
name: "recurring",
|
||||
tabName: "recurring",
|
||||
icon: Icon.FiRepeat,
|
||||
info: `recurring_event_tab_description`,
|
||||
},
|
||||
{
|
||||
name: "apps",
|
||||
tabName: "apps",
|
||||
icon: Icon.FiGrid,
|
||||
info: `${enabledAppsNumber} ${t("active")}`,
|
||||
},
|
||||
{
|
||||
name: "workflows",
|
||||
tabName: "workflows",
|
||||
icon: Icon.FiZap,
|
||||
info: `${enabledWorkflowsNumber} ${t("active")}`,
|
||||
},
|
||||
];
|
||||
|
||||
const navigation = getNavigation({ t, eventType, enabledAppsNumber, enabledWorkflowsNumber });
|
||||
// If there is a team put this navigation item within the tabs
|
||||
if (team)
|
||||
navigation.splice(2, 0, {
|
||||
name: "scheduling_type",
|
||||
tabName: "team",
|
||||
href: `team`,
|
||||
icon: Icon.FiUsers,
|
||||
info: eventType.schedulingType === "COLLECTIVE" ? "collective" : "round_robin",
|
||||
});
|
||||
return navigation;
|
||||
}, [eventType, enabledAppsNumber, team]);
|
||||
|
||||
useEffect(() => {
|
||||
// Default to the first in the list
|
||||
if (!router.query.tabName) {
|
||||
router.push({
|
||||
query: {
|
||||
...router.query,
|
||||
tabName: EventTypeTabs[0].tabName,
|
||||
},
|
||||
});
|
||||
}
|
||||
}, [EventTypeTabs, router]);
|
||||
}, [t, eventType, enabledAppsNumber, enabledWorkflowsNumber, team]);
|
||||
|
||||
const permalink = `${CAL_URL}/${team ? `team/${team.slug}` : eventType.users[0].username}/${
|
||||
eventType.slug
|
||||
@@ -265,10 +259,15 @@ function EventTypeSingleLayout({
|
||||
<ClientSuspense fallback={<Loader />}>
|
||||
<div className="-mt-2 flex flex-col xl:flex-row xl:space-x-8">
|
||||
<div className="hidden xl:block">
|
||||
<VerticalTabs className="primary-navigation" tabs={EventTypeTabs} sticky />
|
||||
<VerticalTabs
|
||||
className="primary-navigation"
|
||||
tabs={EventTypeTabs}
|
||||
sticky
|
||||
linkProps={{ shallow: true }}
|
||||
/>
|
||||
</div>
|
||||
<div className="p-2 md:mx-0 md:p-0 xl:hidden">
|
||||
<HorizontalTabs tabNameKey="tabName" tabs={EventTypeTabs} />
|
||||
<HorizontalTabs tabs={EventTypeTabs} linkProps={{ shallow: true }} />
|
||||
</div>
|
||||
<div className="w-full ltr:mr-2 rtl:ml-2">
|
||||
<div
|
||||
@@ -292,7 +291,7 @@ function EventTypeSingleLayout({
|
||||
e.preventDefault();
|
||||
deleteMutation.mutate({ id: eventType.id });
|
||||
}}>
|
||||
{t("delete_event_type_description") as string}
|
||||
{t("delete_event_type_description")}
|
||||
</ConfirmationDialogContent>
|
||||
</Dialog>
|
||||
<EmbedDialog />
|
||||
|
||||
@@ -16,10 +16,10 @@ import { v5 as uuidv5 } from "uuid";
|
||||
import { z } from "zod";
|
||||
|
||||
import { SelectGifInput } from "@calcom/app-store/giphy/components";
|
||||
import { getEventLocationType, EventLocationType } from "@calcom/app-store/locations";
|
||||
import { EventLocationType, getEventLocationType } from "@calcom/app-store/locations";
|
||||
import { StripeData } from "@calcom/app-store/stripepayment/lib/server";
|
||||
import getApps, { getLocationOptions } from "@calcom/app-store/utils";
|
||||
import { LocationObject, LocationType } from "@calcom/core/location";
|
||||
import { LocationObject } from "@calcom/core/location";
|
||||
import { parseRecurringEvent } from "@calcom/lib";
|
||||
import { CAL_URL, WEBAPP_URL } from "@calcom/lib/constants";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
|
||||
@@ -45,10 +45,10 @@ export default function BookingLayout({
|
||||
<Shell {...rest}>
|
||||
<div className="flex flex-col sm:space-x-2 xl:flex-row">
|
||||
<div className="hidden xl:block">
|
||||
<VerticalTabs tabNameKey="tabName" tabs={tabs} sticky />
|
||||
<VerticalTabs tabs={tabs} sticky />
|
||||
</div>
|
||||
<div className="block xl:hidden">
|
||||
<HorizontalTabs tabNameKey="tabName" tabs={tabs} />
|
||||
<HorizontalTabs tabs={tabs} />
|
||||
</div>
|
||||
<main className="w-full max-w-6xl">{children}</main>
|
||||
</div>
|
||||
|
||||
@@ -49,10 +49,10 @@ export default function InstalledAppsLayout({
|
||||
<Shell {...rest}>
|
||||
<div className="flex flex-col p-2 md:p-0 xl:flex-row">
|
||||
<div className="hidden xl:block">
|
||||
<VerticalTabs tabs={actualTabs} sticky />
|
||||
<VerticalTabs tabs={actualTabs} sticky linkProps={{ shallow: true }} />
|
||||
</div>
|
||||
<div className="block xl:hidden">
|
||||
<HorizontalTabs tabNameKey="tabName" tabs={actualTabs} />
|
||||
<HorizontalTabs tabs={actualTabs} linkProps={{ shallow: true }} />
|
||||
</div>
|
||||
<main className="w-full xl:mx-5 xl:w-4/5 xl:pr-5">{children}</main>
|
||||
</div>
|
||||
|
||||
@@ -1,65 +1,28 @@
|
||||
import noop from "lodash/noop";
|
||||
import Link from "next/link";
|
||||
import { useRouter } from "next/router";
|
||||
import { MouseEventHandler } from "react";
|
||||
import { ComponentProps } from "react";
|
||||
|
||||
import classNames from "@calcom/lib/classNames";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
|
||||
import { SkeletonText } from "../../skeleton";
|
||||
|
||||
export type HorizontalTabItemProps<T extends string = "tabName"> = {
|
||||
export type HorizontalTabItemProps = {
|
||||
name: string;
|
||||
disabled?: boolean;
|
||||
className?: string;
|
||||
} & (
|
||||
| {
|
||||
href: string;
|
||||
}
|
||||
| ({
|
||||
href?: never;
|
||||
} & Partial<Record<T, string>>)
|
||||
);
|
||||
href: string;
|
||||
linkProps?: Omit<ComponentProps<typeof Link>, "href">;
|
||||
};
|
||||
|
||||
const HorizontalTabItem = function <T extends string>({
|
||||
name,
|
||||
href,
|
||||
tabNameKey,
|
||||
...props
|
||||
}: HorizontalTabItemProps<T> & {
|
||||
tabNameKey?: T;
|
||||
}) {
|
||||
const router = useRouter();
|
||||
const HorizontalTabItem = function ({ name, href, linkProps, ...props }: HorizontalTabItemProps) {
|
||||
const { t, isLocaleReady } = useLocale();
|
||||
let newHref = "";
|
||||
let isCurrent;
|
||||
const _tabNameKey = tabNameKey || "tabName";
|
||||
const tabName = props[tabNameKey as keyof typeof props];
|
||||
|
||||
if (href) {
|
||||
newHref = href;
|
||||
isCurrent = router.asPath.startsWith(href);
|
||||
} else if (tabName) {
|
||||
newHref = "";
|
||||
isCurrent = router.query[_tabNameKey] === tabName;
|
||||
}
|
||||
|
||||
const onClick: MouseEventHandler = tabName
|
||||
? (e) => {
|
||||
e.preventDefault();
|
||||
router.push({
|
||||
query: {
|
||||
...router.query,
|
||||
[_tabNameKey]: tabName,
|
||||
},
|
||||
});
|
||||
}
|
||||
: noop;
|
||||
const { asPath } = useRouter();
|
||||
const isCurrent = asPath.startsWith(href);
|
||||
|
||||
return (
|
||||
<Link key={name} href={props.disabled ? "#" : newHref}>
|
||||
<Link key={name} href={href} {...linkProps}>
|
||||
<a
|
||||
onClick={onClick}
|
||||
className={classNames(
|
||||
isCurrent ? "bg-gray-200 text-gray-900" : " text-gray-600 hover:bg-gray-100 hover:text-gray-900 ",
|
||||
"mb-2 inline-flex items-center justify-center whitespace-nowrap rounded-md py-[10px] px-4 text-sm font-medium leading-4 md:mb-0",
|
||||
|
||||
@@ -2,13 +2,12 @@ import HorizontalTabItem, { HorizontalTabItemProps } from "./HorizontalTabItem";
|
||||
|
||||
export { HorizontalTabItem };
|
||||
|
||||
export interface NavTabProps<T extends string> {
|
||||
tabs: HorizontalTabItemProps<T>[];
|
||||
tabNameKey?: T;
|
||||
export interface NavTabProps {
|
||||
tabs: HorizontalTabItemProps[];
|
||||
linkProps?: HorizontalTabItemProps["linkProps"];
|
||||
}
|
||||
|
||||
const HorizontalTabs = function <T extends string>({ tabs, tabNameKey, ...props }: NavTabProps<T>) {
|
||||
const _tabNameKey = tabNameKey || "tabName";
|
||||
const HorizontalTabs = function ({ tabs, linkProps, ...props }: NavTabProps) {
|
||||
return (
|
||||
<div className="-mx-6 mb-2 w-[calc(100%+40px)]">
|
||||
<nav
|
||||
@@ -16,7 +15,7 @@ const HorizontalTabs = function <T extends string>({ tabs, tabNameKey, ...props
|
||||
aria-label="Tabs"
|
||||
{...props}>
|
||||
{tabs.map((tab, idx) => (
|
||||
<HorizontalTabItem tabNameKey={_tabNameKey} {...tab} key={idx} />
|
||||
<HorizontalTabItem {...tab} key={idx} {...linkProps} />
|
||||
))}
|
||||
</nav>
|
||||
</div>
|
||||
|
||||
@@ -1,80 +1,46 @@
|
||||
import noop from "lodash/noop";
|
||||
import Link from "next/link";
|
||||
import { useRouter } from "next/router";
|
||||
import { Fragment, MouseEventHandler } from "react";
|
||||
import { ComponentProps, Fragment } from "react";
|
||||
|
||||
// import { ChevronRight } from "react-feather";
|
||||
import classNames from "@calcom/lib/classNames";
|
||||
import { useLocale } from "@calcom/lib/hooks/useLocale";
|
||||
import { SVGComponent } from "@calcom/types/SVGComponent";
|
||||
import { Icon } from "@calcom/ui/Icon";
|
||||
|
||||
export type VerticalTabItemProps<T extends string = "tabName"> = {
|
||||
export type VerticalTabItemProps = {
|
||||
name: string;
|
||||
info?: string;
|
||||
icon?: SVGComponent;
|
||||
disabled?: boolean;
|
||||
children?: VerticalTabItemProps<T>[];
|
||||
children?: VerticalTabItemProps[];
|
||||
textClassNames?: string;
|
||||
className?: string;
|
||||
isChild?: boolean;
|
||||
hidden?: boolean;
|
||||
disableChevron?: boolean;
|
||||
} & (
|
||||
| {
|
||||
/** If you want to change query param tabName as per current tab */
|
||||
href: string;
|
||||
tabName?: never;
|
||||
}
|
||||
| ({
|
||||
href?: never;
|
||||
} & Partial<Record<T, string>>)
|
||||
);
|
||||
href: string;
|
||||
linkProps?: Omit<ComponentProps<typeof Link>, "href">;
|
||||
};
|
||||
|
||||
const VerticalTabItem = function <T extends string>({
|
||||
const VerticalTabItem = function ({
|
||||
name,
|
||||
href,
|
||||
tabNameKey,
|
||||
info,
|
||||
isChild,
|
||||
disableChevron,
|
||||
linkProps,
|
||||
...props
|
||||
}: VerticalTabItemProps<T> & {
|
||||
tabNameKey?: T;
|
||||
}) {
|
||||
const router = useRouter();
|
||||
}: VerticalTabItemProps) {
|
||||
const { t } = useLocale();
|
||||
let newHref = "";
|
||||
let isCurrent;
|
||||
const tabName = props[tabNameKey as keyof typeof props] as string;
|
||||
const _tabNameKey = tabNameKey || "tabName";
|
||||
if (href) {
|
||||
newHref = href;
|
||||
isCurrent = router.asPath.startsWith(href);
|
||||
} else if (tabName) {
|
||||
newHref = "";
|
||||
isCurrent = router.query[_tabNameKey] === tabName;
|
||||
}
|
||||
|
||||
const onClick: MouseEventHandler = tabName
|
||||
? (e) => {
|
||||
e.preventDefault();
|
||||
router.push({
|
||||
query: {
|
||||
...router.query,
|
||||
[_tabNameKey]: tabName,
|
||||
},
|
||||
});
|
||||
}
|
||||
: noop;
|
||||
const { asPath } = useRouter();
|
||||
const isCurrent = asPath.startsWith(href);
|
||||
|
||||
return (
|
||||
<Fragment key={name}>
|
||||
{!props.hidden && (
|
||||
<>
|
||||
<Link key={name} href={props.disabled ? "#" : newHref}>
|
||||
<Link key={name} href={href} {...linkProps}>
|
||||
<a
|
||||
onClick={onClick}
|
||||
className={classNames(
|
||||
props.textClassNames || "text-sm font-medium leading-none text-gray-600",
|
||||
"group flex w-64 flex-row items-center rounded-md px-3 py-[10px] hover:bg-gray-100 group-hover:text-gray-700 [&[aria-current='page']]:bg-gray-200 [&[aria-current='page']]:text-gray-900",
|
||||
@@ -86,8 +52,6 @@ const VerticalTabItem = function <T extends string>({
|
||||
data-testid={`vertical-tab-${name}`}
|
||||
aria-current={isCurrent ? "page" : undefined}>
|
||||
{props.icon && (
|
||||
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
||||
//@ts-ignore
|
||||
<props.icon className="mr-[10px] h-[16px] w-[16px] self-start stroke-[2px] md:mt-0" />
|
||||
)}
|
||||
<div>
|
||||
@@ -106,7 +70,7 @@ const VerticalTabItem = function <T extends string>({
|
||||
</a>
|
||||
</Link>
|
||||
{props.children?.map((child) => (
|
||||
<VerticalTabItem tabNameKey={tabNameKey} key={child.name} {...child} isChild />
|
||||
<VerticalTabItem key={child.name} {...child} isChild />
|
||||
))}
|
||||
</>
|
||||
)}
|
||||
|
||||
@@ -4,23 +4,15 @@ import VerticalTabItem, { VerticalTabItemProps } from "./VerticalTabItem";
|
||||
|
||||
export { VerticalTabItem };
|
||||
|
||||
export interface NavTabProps<T extends string> {
|
||||
tabs: VerticalTabItemProps<T>[];
|
||||
export interface NavTabProps {
|
||||
tabs: VerticalTabItemProps[];
|
||||
children?: React.ReactNode;
|
||||
className?: string;
|
||||
sticky?: boolean;
|
||||
tabNameKey?: T;
|
||||
linkProps?: VerticalTabItemProps["linkProps"];
|
||||
}
|
||||
|
||||
const NavTabs = function <T extends string>({
|
||||
tabs,
|
||||
tabNameKey,
|
||||
className = "",
|
||||
sticky,
|
||||
...props
|
||||
}: NavTabProps<T>) {
|
||||
const _tabNameKey = tabNameKey || "tabName";
|
||||
|
||||
const NavTabs = function ({ tabs, className = "", sticky, linkProps, ...props }: NavTabProps) {
|
||||
return (
|
||||
<nav
|
||||
className={classNames(
|
||||
@@ -33,7 +25,7 @@ const NavTabs = function <T extends string>({
|
||||
{sticky && <div className="pt-6" />}
|
||||
{props.children}
|
||||
{tabs.map((tab, idx) => (
|
||||
<VerticalTabItem tabNameKey={_tabNameKey} {...tab} key={idx} />
|
||||
<VerticalTabItem {...tab} key={idx} linkProps={linkProps} />
|
||||
))}
|
||||
</nav>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user