diff --git a/docs/pages/material-ui/api/tab-panel.json b/docs/pages/material-ui/api/tab-panel.json
index 01ec545ad24756..7c80cfabce2bc7 100644
--- a/docs/pages/material-ui/api/tab-panel.json
+++ b/docs/pages/material-ui/api/tab-panel.json
@@ -3,6 +3,7 @@
"value": { "type": { "name": "string" }, "required": true },
"children": { "type": { "name": "node" } },
"classes": { "type": { "name": "object" }, "additionalInfo": { "cssApi": true } },
+ "keepMounted": { "type": { "name": "bool" }, "default": "false" },
"sx": {
"type": {
"name": "union",
@@ -14,6 +15,12 @@
"name": "TabPanel",
"imports": ["import TabPanel from '@mui/lab/TabPanel';", "import { TabPanel } from '@mui/lab';"],
"classes": [
+ {
+ "key": "hidden",
+ "className": "MuiTabPanel-hidden",
+ "description": "State class applied to the root `div` element if `hidden={true}`.",
+ "isGlobal": false
+ },
{
"key": "root",
"className": "MuiTabPanel-root",
diff --git a/docs/translations/api-docs/tab-panel/tab-panel.json b/docs/translations/api-docs/tab-panel/tab-panel.json
index 97fdf34bb33934..9f39bbeca855b1 100644
--- a/docs/translations/api-docs/tab-panel/tab-panel.json
+++ b/docs/translations/api-docs/tab-panel/tab-panel.json
@@ -3,6 +3,7 @@
"propDescriptions": {
"children": { "description": "The content of the component." },
"classes": { "description": "Override or extend the styles applied to the component." },
+ "keepMounted": { "description": "Always keep the children in the DOM." },
"sx": {
"description": "The system prop that allows defining system overrides as well as additional CSS styles."
},
@@ -10,5 +11,12 @@
"description": "The value
of the corresponding Tab
. Must use the index of the Tab
when no value
was passed to Tab
."
}
},
- "classDescriptions": { "root": { "description": "Styles applied to the root element." } }
+ "classDescriptions": {
+ "hidden": {
+ "description": "State class applied to {{nodeName}} if {{conditions}}.",
+ "nodeName": "the root div
element",
+ "conditions": "hidden={true}
"
+ },
+ "root": { "description": "Styles applied to the root element." }
+ }
}
diff --git a/packages/mui-lab/src/TabPanel/TabPanel.d.ts b/packages/mui-lab/src/TabPanel/TabPanel.d.ts
index 235ccbc3d6dc59..378190b80f60e7 100644
--- a/packages/mui-lab/src/TabPanel/TabPanel.d.ts
+++ b/packages/mui-lab/src/TabPanel/TabPanel.d.ts
@@ -22,6 +22,11 @@ export interface TabPanelProps extends StandardProps {
- const { classes } = ownerState;
+ const { classes, hidden } = ownerState;
const slots = {
- root: ['root'],
+ root: ['root', hidden && 'hidden'],
};
return composeClasses(slots, getTabPanelUtilityClass, classes);
@@ -28,7 +28,7 @@ const TabPanelRoot = styled('div', {
const TabPanel = React.forwardRef(function TabPanel(inProps, ref) {
const props = useThemeProps({ props: inProps, name: 'MuiTabPanel' });
- const { children, className, value, ...other } = props;
+ const { children, className, value, keepMounted = false, ...other } = props;
const ownerState = {
...props,
@@ -54,7 +54,7 @@ const TabPanel = React.forwardRef(function TabPanel(inProps, ref) {
ownerState={ownerState}
{...other}
>
- {value === context.value && children}
+ {(keepMounted || value === context.value) && children}
);
});
@@ -76,6 +76,11 @@ TabPanel.propTypes /* remove-proptypes */ = {
* @ignore
*/
className: PropTypes.string,
+ /**
+ * Always keep the children in the DOM.
+ * @default false
+ */
+ keepMounted: PropTypes.bool,
/**
* The system prop that allows defining system overrides as well as additional CSS styles.
*/
diff --git a/packages/mui-lab/src/TabPanel/TabPanel.test.tsx b/packages/mui-lab/src/TabPanel/TabPanel.test.tsx
index ba0487616e45f9..bf6ec9394c9737 100644
--- a/packages/mui-lab/src/TabPanel/TabPanel.test.tsx
+++ b/packages/mui-lab/src/TabPanel/TabPanel.test.tsx
@@ -24,14 +24,17 @@ describe('', () => {
],
}));
- it('renders a [role="tabpanel"]', () => {
- const { getByTestId } = render(
+ it('renders a [role="tabpanel"] and mounts children', () => {
+ const { getByTestId, queryByTestId } = render(
-
+
+
+
,
);
expect(getByTestId('tabpanel')).to.have.attribute('role', 'tabpanel');
+ expect(queryByTestId('child')).to.not.equal(null);
});
it('is [hidden] when TabPanel#value !== TabContext#value and does not mount children', () => {
@@ -47,6 +50,19 @@ describe('', () => {
expect(queryByTestId('child')).to.equal(null);
});
+ it('is [hidden] when TabPanel#value !== TabContext#value but does mount children when keepMounted', () => {
+ const { getByTestId, queryByTestId } = render(
+
+
+
+
+ ,
+ );
+
+ expect(getByTestId('tabpanel')).to.have.property('hidden', true);
+ expect(queryByTestId('child')).to.not.equal(null);
+ });
+
it('is accessible when TabPanel#value === TabContext#value', () => {
const { getByTestId } = render(
diff --git a/packages/mui-lab/src/TabPanel/tabPanelClasses.ts b/packages/mui-lab/src/TabPanel/tabPanelClasses.ts
index 0adc5d0626c42d..cbcff1befa4d5d 100644
--- a/packages/mui-lab/src/TabPanel/tabPanelClasses.ts
+++ b/packages/mui-lab/src/TabPanel/tabPanelClasses.ts
@@ -4,6 +4,8 @@ import generateUtilityClasses from '@mui/utils/generateUtilityClasses';
export interface TabPanelClasses {
/** Styles applied to the root element. */
root: string;
+ /** State class applied to the root `div` element if `hidden={true}`. */
+ hidden: string;
}
export type TabPanelClassKey = keyof TabPanelClasses;
@@ -12,6 +14,6 @@ export function getTabPanelUtilityClass(slot: string): string {
return generateUtilityClass('MuiTabPanel', slot);
}
-const tabPanelClasses: TabPanelClasses = generateUtilityClasses('MuiTabPanel', ['root']);
+const tabPanelClasses: TabPanelClasses = generateUtilityClasses('MuiTabPanel', ['root', 'hidden']);
export default tabPanelClasses;