diff --git a/src/Tabs/TabPanel.tsx b/src/Tabs/TabPanel.tsx
index 47517d54..34fec346 100644
--- a/src/Tabs/TabPanel.tsx
+++ b/src/Tabs/TabPanel.tsx
@@ -10,13 +10,14 @@ export function TabPanel(props: TabPanelProps) {
context.registerTab({
id: props.id,
title: props.title,
+ order: props.order,
});
return () => {
context.unregisterTab(props.id);
};
// eslint-disable-next-line react-hooks/exhaustive-deps
- }, [props.id, props.title]);
+ }, [props.id, props.title, props.order]);
return (
`
`}
`;
+function sortedByOrder(tabs: Array): Array {
+ return [...tabs].sort((tab, other) => (tab.order ?? 0) - (other.order ?? 0));
+}
+
export function TabsHeader() {
const context = useContext(TabsContext);
return (
- {context.tabs.map((tab: TabPanelProps) => {
+ {sortedByOrder(context.tabs).map((tab: TabPanelProps) => {
const isActiveTab = context.activeTabID === tab.id;
return (
diff --git a/src/Tabs/index.test.tsx b/src/Tabs/index.test.tsx
index 1bf744f5..5952dfbf 100644
--- a/src/Tabs/index.test.tsx
+++ b/src/Tabs/index.test.tsx
@@ -50,6 +50,27 @@ describe('Tabs', () => {
expect(tabContent2).toBeVisible();
});
+ it('shows tabs in ascending order, no matter when they mount', () => {
+ const { rerender } = render(
+
+
+
+ ,
+ );
+
+ rerender(
+
+
+
+
+ ,
+ );
+
+ expect(
+ screen.getAllByRole('listitem').map((title) => title.textContent),
+ ).toEqual(['first', 'second', 'third']);
+ });
+
it('set active tab to last tabID', () => {
const title1 = 'My tab title1';
const content1 = 'My tab content1';
diff --git a/src/Tabs/types.ts b/src/Tabs/types.ts
index 8947ccdf..54b28d7f 100644
--- a/src/Tabs/types.ts
+++ b/src/Tabs/types.ts
@@ -11,5 +11,9 @@ export type TabsProps = {
export type TabPanelProps = {
id: TTabID;
title: ReactNode;
+
+ /** Ascending, panels sharing an order keep the order they mounted in. */
+ order?: number;
+
children?: ReactNode;
};