Skip to content

Commit

Permalink
[Tabs] Expose width/height state in tabs indicator (#1288)
Browse files Browse the repository at this point in the history
  • Loading branch information
aarongarciah authored Jan 7, 2025
1 parent 2e87d21 commit 576effb
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 3 deletions.
6 changes: 6 additions & 0 deletions packages/react/src/tabs/indicator/TabsIndicator.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,8 @@ describe('<Tabs.Indicator />', () => {
right: tabRight,
top: tabTop,
bottom: tabBottom,
width: tabWidth,
height: tabHeight,
} = activeTab.getBoundingClientRect();

const relativeLeft = tabLeft - listLeft;
Expand All @@ -69,11 +71,15 @@ describe('<Tabs.Indicator />', () => {
const actualRight = bubbleComputedStyle.getPropertyValue('--active-tab-right');
const actualTop = bubbleComputedStyle.getPropertyValue('--active-tab-top');
const actualBottom = bubbleComputedStyle.getPropertyValue('--active-tab-bottom');
const actualWidth = bubbleComputedStyle.getPropertyValue('--active-tab-width');
const actualHeight = bubbleComputedStyle.getPropertyValue('--active-tab-height');

assertSize(actualLeft, relativeLeft);
assertSize(actualRight, relativeRight);
assertSize(actualTop, relativeTop);
assertSize(actualBottom, relativeBottom);
assertSize(actualWidth, tabWidth);
assertSize(actualHeight, tabHeight);
}

it('should set CSS variables corresponding to the active tab', async () => {
Expand Down
13 changes: 10 additions & 3 deletions packages/react/src/tabs/indicator/TabsIndicator.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import type { TabsOrientation, TabsRoot } from '../root/TabsRoot';
import { useTabsRootContext } from '../root/TabsRootContext';
import { tabsStyleHookMapping } from '../root/styleHooks';
import { useTabsListContext } from '../list/TabsListContext';
import { ActiveTabPosition, useTabsIndicator } from './useTabsIndicator';
import { ActiveTabPosition, ActiveTabSize, useTabsIndicator } from './useTabsIndicator';
import { script as prehydrationScript } from './prehydrationScript.min';

const noop = () => null;
Expand All @@ -34,7 +34,11 @@ const TabsIndicator = React.forwardRef<HTMLSpanElement, TabsIndicator.Props>(

useOnMount(() => setIsMounted(true));

const { getRootProps, activeTabPosition: selectedTabPosition } = useTabsIndicator({
const {
getRootProps,
activeTabPosition: selectedTabPosition,
activeTabSize: selectedTabSize,
} = useTabsIndicator({
getTabElementBySelectedValue,
tabsListRef,
value,
Expand All @@ -44,9 +48,10 @@ const TabsIndicator = React.forwardRef<HTMLSpanElement, TabsIndicator.Props>(
() => ({
orientation,
selectedTabPosition,
selectedTabSize,
tabActivationDirection,
}),
[orientation, selectedTabPosition, tabActivationDirection],
[orientation, selectedTabPosition, selectedTabSize, tabActivationDirection],
);

const { renderElement } = useComponentRenderer({
Expand All @@ -62,6 +67,7 @@ const TabsIndicator = React.forwardRef<HTMLSpanElement, TabsIndicator.Props>(
customStyleHookMapping: {
...tabsStyleHookMapping,
selectedTabPosition: noop,
selectedTabSize: noop,
},
ref: forwardedRef,
});
Expand All @@ -88,6 +94,7 @@ const TabsIndicator = React.forwardRef<HTMLSpanElement, TabsIndicator.Props>(
namespace TabsIndicator {
export interface State extends TabsRoot.State {
selectedTabPosition: ActiveTabPosition | null;
selectedTabSize: ActiveTabSize | null;
orientation: TabsOrientation;
}

Expand Down
18 changes: 18 additions & 0 deletions packages/react/src/tabs/indicator/useTabsIndicator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,17 @@ export function useTabsIndicator(
[left, right, top, bottom, isTabSelected],
);

const activeTabSize = React.useMemo(
() =>
isTabSelected
? {
width,
height,
}
: null,
[width, height, isTabSelected],
);

const style = React.useMemo(() => {
if (!isTabSelected) {
return undefined;
Expand Down Expand Up @@ -114,6 +125,7 @@ export function useTabsIndicator(
return {
getRootProps,
activeTabPosition,
activeTabSize,
};
}

Expand All @@ -124,6 +136,11 @@ export interface ActiveTabPosition {
bottom: number;
}

export interface ActiveTabSize {
width: number;
height: number;
}

export namespace useTabsIndicator {
export interface Parameters
extends Pick<TabsRootContext, 'getTabElementBySelectedValue' | 'value'>,
Expand All @@ -137,5 +154,6 @@ export namespace useTabsIndicator {
*/
getRootProps: (externalProps?: GenericHTMLProps) => GenericHTMLProps;
activeTabPosition: ActiveTabPosition | null;
activeTabSize: ActiveTabSize | null;
}
}

0 comments on commit 576effb

Please sign in to comment.