diff --git a/docs/data/api/tabs-root.json b/docs/data/api/tabs-root.json
index e3d5d1f5c8..0a6fd74aaa 100644
--- a/docs/data/api/tabs-root.json
+++ b/docs/data/api/tabs-root.json
@@ -2,10 +2,6 @@
"props": {
"className": { "type": { "name": "union", "description": "func
| string" } },
"defaultValue": { "type": { "name": "any" }, "default": "0" },
- "direction": {
- "type": { "name": "enum", "description": "'ltr'
| 'rtl'" },
- "default": "'ltr'"
- },
"onValueChange": { "type": { "name": "func" } },
"orientation": {
"type": { "name": "enum", "description": "'horizontal'
| 'vertical'" },
diff --git a/docs/data/components/tabs/tabs.mdx b/docs/data/components/tabs/tabs.mdx
index d24bd1efa7..7704c427f5 100644
--- a/docs/data/components/tabs/tabs.mdx
+++ b/docs/data/components/tabs/tabs.mdx
@@ -154,6 +154,18 @@ Base UI Tabs follow the [Tabs WAI-ARIA design pattern](https://www.w3.org/WAI/A
| Down Arrow | Moves focus to the next tab (when `orientation="vertical"`) and activates it if `activateOnFocus` is set. |
| Space, Enter | Activates the focused tab. |
+## RTL
+
+Place horizontal tabs inside an HTML element or component with the HTML `dir="rtl"` attribute to reverse arrow key navigation for right-to-left languages:
+
+```jsx
+
+
+ {/* RTL keyboard behavior*/}
+
+
+```
+
### Labeling
To make the Tabs component suite accessible to assistive technology, label the `` element with `aria-label`.
diff --git a/docs/data/translations/api-docs/tabs-root/tabs-root.json b/docs/data/translations/api-docs/tabs-root/tabs-root.json
index 27020d8d4f..d6bf5a38ed 100644
--- a/docs/data/translations/api-docs/tabs-root/tabs-root.json
+++ b/docs/data/translations/api-docs/tabs-root/tabs-root.json
@@ -7,7 +7,6 @@
"defaultValue": {
"description": "The default value. Use when the component is not controlled. When the value is null
, no Tab will be selected."
},
- "direction": { "description": "The direction of the text." },
"onValueChange": { "description": "Callback invoked when new value is being set." },
"orientation": { "description": "The component orientation (layout flow direction)." },
"render": { "description": "A function to customize rendering of the component." },
diff --git a/docs/reference/generated/tabs-root.json b/docs/reference/generated/tabs-root.json
index 33998d6c74..b953ac03c1 100644
--- a/docs/reference/generated/tabs-root.json
+++ b/docs/reference/generated/tabs-root.json
@@ -11,11 +11,6 @@
"default": "0",
"description": "The default value. Use when the component is not controlled.\nWhen the value is `null`, no Tab will be selected."
},
- "direction": {
- "type": "'ltr' | 'rtl'",
- "default": "'ltr'",
- "description": "The direction of the text."
- },
"onValueChange": {
"type": "(value, event) => void",
"description": "Callback invoked when new value is being set."
diff --git a/packages/react/src/tabs/root/TabsRoot.test.tsx b/packages/react/src/tabs/root/TabsRoot.test.tsx
index 823173819b..3daea2ebc0 100644
--- a/packages/react/src/tabs/root/TabsRoot.test.tsx
+++ b/packages/react/src/tabs/root/TabsRoot.test.tsx
@@ -286,19 +286,20 @@ describe('', () => {
const handleChange = spy();
const handleKeyDown = spy();
const { getAllByRole } = await render(
-
-
-
-
-
-
- ,
+
+
+
+
+
+
+
+
+
,
);
const [firstTab, , lastTab] = getAllByRole('tab');
await act(async () => {
@@ -318,19 +319,20 @@ describe('', () => {
const handleChange = spy();
const handleKeyDown = spy();
const { getAllByRole } = await render(
-
-
-
-
-
-
- ,
+
+
+
+
+
+
+
+
+
,
);
const [firstTab, secondTab] = getAllByRole('tab');
await act(async () => {
@@ -352,19 +354,20 @@ describe('', () => {
const handleChange = spy();
const handleKeyDown = spy();
const { getAllByRole } = await render(
-
-
-
-
-
-
- ,
+
+
+
+
+
+
+
+
+
,
);
const [firstTab, , lastTab] = getAllByRole('tab');
await act(async () => {
@@ -385,19 +388,20 @@ describe('', () => {
const handleChange = spy();
const handleKeyDown = spy();
const { getAllByRole } = await render(
-
-
-
-
-
-
- ,
+
+
+
+
+
+
+
+
+
,
);
const [firstTab, secondTab] = getAllByRole('tab');
await act(async () => {
@@ -418,18 +422,19 @@ describe('', () => {
it('skips over disabled tabs', async () => {
const handleKeyDown = spy();
const { getAllByRole } = await render(
-
-
-
-
-
-
- ,
+
+
+
+
+
+
+
+
+
,
);
const [firstTab, , lastTab] = getAllByRole('tab');
await act(async () => {
@@ -451,19 +456,20 @@ describe('', () => {
const handleChange = spy();
const handleKeyDown = spy();
const { getAllByRole } = await render(
-
-
-
-
-
-
- ,
+
+
+
+
+
+
+
+
+
,
);
const [firstTab, , lastTab] = getAllByRole('tab');
await act(async () => {
@@ -483,19 +489,20 @@ describe('', () => {
const handleChange = spy();
const handleKeyDown = spy();
const { getAllByRole } = await render(
-
-
-
-
-
-
- ,
+
+
+
+
+
+
+
+
+
,
);
const [, secondTab, lastTab] = getAllByRole('tab');
await act(async () => {
@@ -517,19 +524,20 @@ describe('', () => {
const handleChange = spy();
const handleKeyDown = spy();
const { getAllByRole } = await render(
-
-
-
-
-
-
- ,
+
+
+
+
+
+
+
+
+
,
);
const [firstTab, , lastTab] = getAllByRole('tab');
await act(async () => {
@@ -550,19 +558,20 @@ describe('', () => {
const handleChange = spy();
const handleKeyDown = spy();
const { getAllByRole } = await render(
-
-
-
-
-
-
- ,
+
+
+
+
+
+
+
+
+
,
);
const [, secondTab, lastTab] = getAllByRole('tab');
await act(async () => {
@@ -583,18 +592,19 @@ describe('', () => {
it('skips over disabled tabs', async () => {
const handleKeyDown = spy();
const { getAllByRole } = await render(
-
-
-
-
-
-
- ,
+
+
+
+
+
+
+
+
+
,
);
const [firstTab, , lastTab] = getAllByRole('tab');
await act(async () => {
diff --git a/packages/react/src/tabs/root/TabsRoot.tsx b/packages/react/src/tabs/root/TabsRoot.tsx
index f9bcf00f11..18983cb370 100644
--- a/packages/react/src/tabs/root/TabsRoot.tsx
+++ b/packages/react/src/tabs/root/TabsRoot.tsx
@@ -26,7 +26,6 @@ const TabsRoot = React.forwardRef(function TabsRoot(
const {
className,
defaultValue = 0,
- direction: directionProp = 'ltr',
onValueChange: onValueChangeProp,
orientation = 'horizontal',
render,
@@ -35,8 +34,6 @@ const TabsRoot = React.forwardRef(function TabsRoot(
} = props;
const {
- getRootProps,
- direction,
getTabElementBySelectedValue,
getTabIdByPanelValueOrIndex,
getTabPanelIdByTabValueOrIndex,
@@ -50,12 +47,10 @@ const TabsRoot = React.forwardRef(function TabsRoot(
value: valueProp,
defaultValue,
onValueChange: onValueChangeProp,
- direction: directionProp,
});
const tabsContextValue: TabsRootContext = React.useMemo(
() => ({
- direction,
getTabElementBySelectedValue,
getTabIdByPanelValueOrIndex,
getTabPanelIdByTabValueOrIndex,
@@ -66,7 +61,6 @@ const TabsRoot = React.forwardRef(function TabsRoot(
value,
}),
[
- direction,
getTabElementBySelectedValue,
getTabIdByPanelValueOrIndex,
getTabPanelIdByTabValueOrIndex,
@@ -80,12 +74,10 @@ const TabsRoot = React.forwardRef(function TabsRoot(
const state: TabsRoot.State = {
orientation,
- direction,
tabActivationDirection,
};
const { renderElement } = useComponentRenderer({
- propGetter: getRootProps,
render: render ?? 'div',
className,
state,
@@ -104,14 +96,12 @@ const TabsRoot = React.forwardRef(function TabsRoot(
});
export type TabsOrientation = 'horizontal' | 'vertical';
-export type TabsDirection = 'ltr' | 'rtl';
export type TabActivationDirection = 'left' | 'right' | 'up' | 'down' | 'none';
export type TabValue = any | null;
namespace TabsRoot {
export type State = {
orientation: TabsOrientation;
- direction: TabsDirection;
tabActivationDirection: TabActivationDirection;
};
@@ -132,11 +122,6 @@ namespace TabsRoot {
* @default 'horizontal'
*/
orientation?: TabsOrientation;
- /**
- * The direction of the text.
- * @default 'ltr'
- */
- direction?: TabsDirection;
/**
* Callback invoked when new value is being set.
*/
@@ -165,11 +150,6 @@ TabsRoot.propTypes /* remove-proptypes */ = {
* @default 0
*/
defaultValue: PropTypes.any,
- /**
- * The direction of the text.
- * @default 'ltr'
- */
- direction: PropTypes.oneOf(['ltr', 'rtl']),
/**
* Callback invoked when new value is being set.
*/
diff --git a/packages/react/src/tabs/root/TabsRootContext.ts b/packages/react/src/tabs/root/TabsRootContext.ts
index 9fe68c4458..8e567a38c3 100644
--- a/packages/react/src/tabs/root/TabsRootContext.ts
+++ b/packages/react/src/tabs/root/TabsRootContext.ts
@@ -20,10 +20,6 @@ export interface TabsRootContext {
* The component orientation (layout flow direction).
*/
orientation: 'horizontal' | 'vertical';
- /**
- * The direction of the tabs.
- */
- direction: 'ltr' | 'rtl';
/**
* Gets the element of the Tab with the given value.
* @param {any | undefined} value Value to find the tab for.
diff --git a/packages/react/src/tabs/root/styleHooks.ts b/packages/react/src/tabs/root/styleHooks.ts
index 4929d153ae..87481b41d2 100644
--- a/packages/react/src/tabs/root/styleHooks.ts
+++ b/packages/react/src/tabs/root/styleHooks.ts
@@ -2,7 +2,6 @@ import type { TabsRoot } from './TabsRoot';
import type { CustomStyleHookMapping } from '../../utils/getStyleHookProps';
export const tabsStyleHookMapping: CustomStyleHookMapping = {
- direction: () => null,
tabActivationDirection: (dir) => ({
'data-activation-direction': dir,
}),
diff --git a/packages/react/src/tabs/root/useTabsRoot.ts b/packages/react/src/tabs/root/useTabsRoot.ts
index 2938c5f1f1..18ce3dc3ea 100644
--- a/packages/react/src/tabs/root/useTabsRoot.ts
+++ b/packages/react/src/tabs/root/useTabsRoot.ts
@@ -1,7 +1,5 @@
'use client';
import * as React from 'react';
-import { mergeReactProps } from '../../utils/mergeReactProps';
-import { GenericHTMLProps } from '../../utils/types';
import { useControlled } from '../../utils/useControlled';
import type { CompositeMetadata } from '../../composite/list/CompositeList';
import type { TabPanelMetadata } from '../tab-panel/useTabPanel';
@@ -9,12 +7,7 @@ import type { TabMetadata } from '../tab/useTab';
import type { TabActivationDirection, TabValue } from './TabsRoot';
function useTabsRoot(parameters: useTabsRoot.Parameters): useTabsRoot.ReturnValue {
- const {
- value: valueProp,
- defaultValue,
- onValueChange: onValueChangeProp,
- direction = 'ltr',
- } = parameters;
+ const { value: valueProp, defaultValue, onValueChange: onValueChangeProp } = parameters;
const tabPanelRefs = React.useRef<(HTMLElement | null)[]>([]);
@@ -122,17 +115,7 @@ function useTabsRoot(parameters: useTabsRoot.Parameters): useTabsRoot.ReturnValu
[tabMap],
);
- const getRootProps: useTabsRoot.ReturnValue['getRootProps'] = React.useCallback(
- (otherProps = {}) =>
- mergeReactProps<'div'>(otherProps, {
- dir: direction,
- }),
- [direction],
- );
-
return {
- getRootProps,
- direction,
getTabElementBySelectedValue,
getTabIdByPanelValueOrIndex,
getTabPanelIdByTabValueOrIndex,
@@ -157,11 +140,6 @@ namespace useTabsRoot {
* The default value. Use when the component is not controlled.
*/
defaultValue?: TabValue;
- /**
- * The direction of the text.
- * @default 'ltr'
- */
- direction?: 'ltr' | 'rtl';
/**
* Callback invoked when new value is being set.
*/
@@ -169,16 +147,6 @@ namespace useTabsRoot {
}
export interface ReturnValue {
- /**
- * Resolver for the Root component's props.
- * @param externalProps additional props for Tabs.Root
- * @returns props that should be spread on Tabs.Root
- */
- getRootProps: (externalProps?: GenericHTMLProps) => GenericHTMLProps;
- /**
- * The direction of the text.
- */
- direction: 'ltr' | 'rtl';
/**
* Gets the element of the Tab with the given value.
* @param {any | undefined} value Value to find the tab for.
diff --git a/packages/react/src/tabs/tab-indicator/TabIndicator.tsx b/packages/react/src/tabs/tab-indicator/TabIndicator.tsx
index f1c13b2f84..de24e2da6a 100644
--- a/packages/react/src/tabs/tab-indicator/TabIndicator.tsx
+++ b/packages/react/src/tabs/tab-indicator/TabIndicator.tsx
@@ -4,7 +4,7 @@ import PropTypes from 'prop-types';
import { useComponentRenderer } from '../../utils/useComponentRenderer';
import { useOnMount } from '../../utils/useOnMount';
import type { BaseUIComponentProps } from '../../utils/types';
-import type { TabsDirection, TabsOrientation, TabsRoot } from '../root/TabsRoot';
+import type { TabsOrientation, TabsRoot } from '../root/TabsRoot';
import { useTabsRootContext } from '../root/TabsRootContext';
import { tabsStyleHookMapping } from '../root/styleHooks';
import { useTabsListContext } from '../tabs-list/TabsListContext';
@@ -27,7 +27,7 @@ const TabIndicator = React.forwardRef(
function TabIndicator(props, forwardedRef) {
const { className, render, renderBeforeHydration = false, ...other } = props;
- const { direction, getTabElementBySelectedValue, orientation, tabActivationDirection, value } =
+ const { getTabElementBySelectedValue, orientation, tabActivationDirection, value } =
useTabsRootContext();
const { tabsListRef } = useTabsListContext();
@@ -46,12 +46,11 @@ const TabIndicator = React.forwardRef(
const state: TabIndicator.State = React.useMemo(
() => ({
- direction,
orientation,
selectedTabPosition,
tabActivationDirection,
}),
- [direction, orientation, selectedTabPosition, tabActivationDirection],
+ [orientation, selectedTabPosition, tabActivationDirection],
);
const { renderElement } = useComponentRenderer({
@@ -94,7 +93,6 @@ namespace TabIndicator {
export interface State extends TabsRoot.State {
selectedTabPosition: ActiveTabPosition | null;
orientation: TabsOrientation;
- direction: TabsDirection;
}
export interface Props extends BaseUIComponentProps<'span', TabIndicator.State> {
diff --git a/packages/react/src/tabs/tab-panel/TabPanel.test.tsx b/packages/react/src/tabs/tab-panel/TabPanel.test.tsx
index 4746039bdb..8aa9546152 100644
--- a/packages/react/src/tabs/tab-panel/TabPanel.test.tsx
+++ b/packages/react/src/tabs/tab-panel/TabPanel.test.tsx
@@ -13,7 +13,6 @@ describe('', () => {
getTabElementBySelectedValue: () => null,
getTabIdByPanelValueOrIndex: () => '',
getTabPanelIdByTabValueOrIndex: () => '',
- direction: 'ltr',
orientation: 'horizontal',
tabActivationDirection: 'none',
};
diff --git a/packages/react/src/tabs/tab-panel/TabPanel.tsx b/packages/react/src/tabs/tab-panel/TabPanel.tsx
index a18de9deef..6c43b34e2a 100644
--- a/packages/react/src/tabs/tab-panel/TabPanel.tsx
+++ b/packages/react/src/tabs/tab-panel/TabPanel.tsx
@@ -28,7 +28,6 @@ const TabPanel = React.forwardRef(function TabPanel(
value: selectedValue,
getTabIdByPanelValueOrIndex,
orientation,
- direction,
tabActivationDirection,
} = useTabsRootContext();
@@ -41,12 +40,11 @@ const TabPanel = React.forwardRef(function TabPanel(
const state: TabPanel.State = React.useMemo(
() => ({
- direction,
hidden,
orientation,
tabActivationDirection,
}),
- [direction, hidden, orientation, tabActivationDirection],
+ [hidden, orientation, tabActivationDirection],
);
const { renderElement } = useComponentRenderer({
diff --git a/packages/react/src/tabs/tab/Tab.test.tsx b/packages/react/src/tabs/tab/Tab.test.tsx
index a0df40aadc..c52060addc 100644
--- a/packages/react/src/tabs/tab/Tab.test.tsx
+++ b/packages/react/src/tabs/tab/Tab.test.tsx
@@ -32,7 +32,6 @@ describe('', () => {
getTabIdByPanelValueOrIndex: () => '',
getTabPanelIdByTabValueOrIndex: () => '',
orientation: 'horizontal',
- direction: 'ltr',
tabActivationDirection: 'none',
};
diff --git a/packages/react/src/tabs/tabs-list/TabsList.test.tsx b/packages/react/src/tabs/tabs-list/TabsList.test.tsx
index 17ce391fec..3ca0a1988e 100644
--- a/packages/react/src/tabs/tabs-list/TabsList.test.tsx
+++ b/packages/react/src/tabs/tabs-list/TabsList.test.tsx
@@ -20,7 +20,6 @@ describe('', () => {
getTabIdByPanelValueOrIndex: () => '',
getTabPanelIdByTabValueOrIndex: () => '',
orientation: 'horizontal',
- direction: 'ltr',
tabActivationDirection: 'none',
}}
>
diff --git a/packages/react/src/tabs/tabs-list/TabsList.tsx b/packages/react/src/tabs/tabs-list/TabsList.tsx
index 28ca823047..4d405cd364 100644
--- a/packages/react/src/tabs/tabs-list/TabsList.tsx
+++ b/packages/react/src/tabs/tabs-list/TabsList.tsx
@@ -28,7 +28,6 @@ const TabsList = React.forwardRef(function TabsList(
const { activateOnFocus = true, className, loop = true, render, ...other } = props;
const {
- direction = 'ltr',
getTabElementBySelectedValue,
onValueChange,
orientation = 'horizontal',
@@ -53,11 +52,10 @@ const TabsList = React.forwardRef(function TabsList(
const state: TabsList.State = React.useMemo(
() => ({
- direction,
orientation,
tabActivationDirection,
}),
- [direction, orientation, tabActivationDirection],
+ [orientation, tabActivationDirection],
);
const { renderElement } = useComponentRenderer({