Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions packages/react-aria-components/src/Tabs.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -627,11 +627,17 @@ function TabPanelInner(
let domProps = isSelected
? mergeProps(DOMProps, tabPanelProps, focusProps, renderProps)
: mergeProps(DOMProps, renderProps);
let style = {
'--tab-panel-width': 'auto',
'--tab-panel-height': 'auto',

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
'--tab-panel-width': 'auto',
'--tab-panel-height': 'auto',
'--tab-panel-width': 'unset',
'--tab-panel-height': 'unset',

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See reasoning here: #10292 (comment)

...renderProps.style
} as React.CSSProperties;

return (
<dom.div
{...domProps}
ref={ref}
style={style}
data-focused={isFocused || undefined}
data-focus-visible={isFocusVisible || undefined}
// @ts-ignore
Expand Down
102 changes: 102 additions & 0 deletions packages/react-aria-components/test/Tabs.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -695,6 +695,52 @@ describe('Tabs', () => {
expect(innerTabs[1]).toHaveTextContent('Two');
});

it('resets tab panel transition variables for nested tabpanels', async () => {
let {getByTestId} = render(
<Tabs>
<TabList aria-label="Outer tabs">
<Tab id="foo">Foo</Tab>
<Tab id="bar">Bar</Tab>
</TabList>
<TabPanels
data-testid="outer-tabpanels"
style={{
'--tab-panel-width': '320px',
'--tab-panel-height': '240px'
}}>
<TabPanel id="foo" data-testid="outer-tabpanel">
<Tabs>
<TabList aria-label="Inner tabs">
<Tab id="one">One</Tab>
<Tab id="two">Two</Tab>
</TabList>
<TabPanels data-testid="inner-tabpanels">
<TabPanel id="one">One</TabPanel>
<TabPanel id="two">Two</TabPanel>
</TabPanels>
</Tabs>
</TabPanel>
<TabPanel id="bar">Bar</TabPanel>
</TabPanels>
</Tabs>
);

// Wait a tick for MutationObserver in useHasTabbableChild to fire.
// This avoids React's "update not wrapped in act" warning.
await waitFor(() => Promise.resolve());

let outerTabPanels = getByTestId('outer-tabpanels');
let outerTabPanel = getByTestId('outer-tabpanel');
let innerTabPanels = getByTestId('inner-tabpanels');

expect(outerTabPanels.style.getPropertyValue('--tab-panel-width')).toBe('320px');
expect(outerTabPanels.style.getPropertyValue('--tab-panel-height')).toBe('240px');
expect(outerTabPanel.style.getPropertyValue('--tab-panel-width')).toBe('auto');
expect(outerTabPanel.style.getPropertyValue('--tab-panel-height')).toBe('auto');
expect(innerTabPanels.style.getPropertyValue('--tab-panel-width')).toBe('');
expect(innerTabPanels.style.getPropertyValue('--tab-panel-height')).toBe('');
});

it('can add tabs and keep the current selected key', async () => {
let onSelectionChange = jest.fn();
function Example(props) {
Expand Down Expand Up @@ -829,6 +875,62 @@ describe('Tabs', () => {
expect(tabPanels).toHaveStyle({width: '100px'});
});

it('should allow tab panel styles to override transition variable resets', () => {
let {getByTestId} = render(
<Tabs>
<TabList aria-label="test">
<Tab id="a">A</Tab>
<Tab id="b">B</Tab>
</TabList>
<TabPanels>
<TabPanel
id="a"
data-testid="tabpanel"
style={{
'--tab-panel-width': '50px',
'--tab-panel-height': '75px'
}}>
A
</TabPanel>
<TabPanel id="b">B</TabPanel>
</TabPanels>
</Tabs>
);

let tabPanel = getByTestId('tabpanel');
expect(tabPanel.style.getPropertyValue('--tab-panel-width')).toBe('50px');
expect(tabPanel.style.getPropertyValue('--tab-panel-height')).toBe('75px');
});

it('should merge tab panel transition variable resets with style render props', () => {
let {getByTestId} = render(
<Tabs>
<TabList aria-label="test">
<Tab id="a">A</Tab>
<Tab id="b">B</Tab>
</TabList>
<TabPanels>
<TabPanel
id="a"
className={() => 'selected'}
data-testid="tabpanel"
style={() => ({
opacity: 1
})}>
A
</TabPanel>
<TabPanel id="b">B</TabPanel>
</TabPanels>
</Tabs>
);

let tabPanel = getByTestId('tabpanel');
expect(tabPanel).toHaveAttribute('class', 'selected');
expect(tabPanel.style.getPropertyValue('--tab-panel-width')).toBe('auto');
expect(tabPanel.style.getPropertyValue('--tab-panel-height')).toBe('auto');
expect(tabPanel).toHaveStyle({opacity: '1'});
});

it('should detect block-size in transition for TabPanels', async () => {
let originalGetComputedStyle = window.getComputedStyle;
window.getComputedStyle = el => ({
Expand Down