diff --git a/src/components/Tabs.stories.tsx b/src/components/Tabs.stories.tsx
index 669adc120..cb3658986 100644
--- a/src/components/Tabs.stories.tsx
+++ b/src/components/Tabs.stories.tsx
@@ -132,7 +132,7 @@ function TestComponent() {
name: "Disabled Tab",
href: "/ce:2/disabled",
path: "/:ceId/disabled",
- disabled: true,
+ disabled: "Disabled reason",
render: () => ,
},
];
diff --git a/src/components/Tabs.tsx b/src/components/Tabs.tsx
index 4db1d95f2..01d3e8bc0 100644
--- a/src/components/Tabs.tsx
+++ b/src/components/Tabs.tsx
@@ -3,8 +3,7 @@ import { HTMLAttributes, KeyboardEvent, ReactNode, useEffect, useMemo, useRef, u
import { mergeProps, useFocusRing, useHover } from "react-aria";
import { matchPath, Route } from "react-router";
import { Link, useLocation } from "react-router-dom";
-import type { IconKey } from "src/components";
-import { FullBleed } from "src/components";
+import { FullBleed, IconKey, maybeTooltip, resolveTooltip } from "src/components";
import { Css, Margin, Only, Padding, Xss } from "src/Css";
import { BeamFocusableProps } from "src/interfaces";
import { AnyObject } from "src/types";
@@ -19,7 +18,8 @@ export interface Tab {
icon?: IconKey;
// Suffixes label with specified node. Expected to be used for cases where the decoration is not just an icon.
endAdornment?: ReactNode;
- disabled?: boolean;
+ /** Whether the Tab is disabled. If a ReactNode, it's treated as a "disabled reason" that's shown in a tooltip. */
+ disabled?: boolean | ReactNode;
}
type TabsContentXss = Xss;
@@ -205,7 +205,8 @@ interface TabImplProps extends BeamFocusableProps {
function TabImpl(props: TabImplProps) {
const { tab, onClick, active, onKeyUp, onBlur, focusProps, isFocusVisible = false, ...others } = props;
- const { disabled: isDisabled = false, name: label, icon, endAdornment } = tab;
+ const { disabled = false, name: label, icon, endAdornment } = tab;
+ const isDisabled = !!disabled;
const { hoverProps, isHovered } = useHover({ isDisabled });
const { baseStyles, activeStyles, focusRingStyles, hoverStyles, disabledStyles, activeHoverStyles } = useMemo(
() => getTabStyles(),
@@ -244,7 +245,11 @@ function TabImpl(props: TabImplProps) {
);
return isDisabled ? (
- {tabLabel}
+ maybeTooltip({
+ title: resolveTooltip(disabled),
+ placement: "top",
+ children: {tabLabel}
,
+ })
) : isRouteTab(tab) ? (
{tabLabel}