Skip to content
Merged
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import TableBody from '@mui/material/TableBody';
import TableRow from '@mui/material/TableRow';
import TableCell from '@mui/material/TableCell';
import TableSortLabel from '@mui/material/TableSortLabel';
import TablePagination from '@mui/material/TablePagination';
import Slider from '@mui/material/Slider';
import Link from '@mui/material/Link';
import Breadcrumbs from '@mui/material/Breadcrumbs';
Expand Down Expand Up @@ -429,6 +430,18 @@ export default function FullFocusVisibleDemo() {
)}
/>
</Row>
<Row label="TablePagination">
<TablePagination
component="div"
count={24}
page={0}
onPageChange={noop}
rowsPerPage={5}
rowsPerPageOptions={[5, 10]}
onRowsPerPageChange={noop}
labelRowsPerPage="Rows:"
/>
</Row>
</Bucket>
</Stack>
</ThemeProvider>
Expand Down
25 changes: 19 additions & 6 deletions packages/mui-material/src/TablePagination/TablePagination.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ import composeClasses from '@mui/utils/composeClasses';
import { styled } from '../zero-styled';
import memoTheme from '../utils/memoTheme';
import { useDefaultProps } from '../DefaultPropsProvider';
import { applyInsetFocusVisible } from '../styles/focusVisible';
import { buttonBaseClasses } from '../ButtonBase';
import InputBase from '../InputBase';
import MenuItem from '../MenuItem';
import Select from '../Select';
Expand Down Expand Up @@ -57,6 +59,9 @@ const TablePaginationToolbar = styled(Toolbar, {
[`& .${tablePaginationClasses.actions}`]: {
flexShrink: 0,
marginLeft: 20,
...(theme.focusVisible && {
[`& .${buttonBaseClasses.root}`]: applyInsetFocusVisible(1),
}),
},
})),
);
Expand Down Expand Up @@ -104,11 +109,17 @@ const TablePaginationSelect = styled(Select, {
});

const TablePaginationInputBase = styled(InputBase)(
memoTheme(({ theme }) => ({
[`& .${tablePaginationClasses.select}:focus`]: {
backgroundColor: (theme.vars || theme).palette.action.focus,
},
})),
memoTheme(({ theme }) =>
theme.focusVisible
? {
[`& .${tablePaginationClasses.select}:focus-visible`]: theme.focusVisible,
}
: {
[`& .${tablePaginationClasses.select}:focus`]: {
backgroundColor: (theme.vars || theme).palette.action.focus,
},
},
),
);

const TablePaginationMenuItem = styled(MenuItem, {
Expand Down Expand Up @@ -276,7 +287,9 @@ const TablePagination = React.forwardRef(function TablePagination(inProps, ref)
{rowsPerPageOptions.length > 1 && (
<SelectSlot
variant="standard"
{...(!selectProps.variant && { input: <TablePaginationInputBase /> })}
{...(!selectProps.variant && {
input: <TablePaginationInputBase internalDisabledThemeFocusVisible />,
Comment thread
siriwatknp marked this conversation as resolved.
Resolved
})}
value={rowsPerPage}
onChange={onRowsPerPageChange}
id={selectId}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,15 @@ import { describe, it, expect, beforeEach } from 'vitest';
import * as React from 'react';
import { spy } from 'sinon';
import PropTypes from 'prop-types';
import { fireEvent, createRenderer, isJsdom, screen } from '@mui/internal-test-utils';
import {
act,
fireEvent,
createRenderer,
focusVisible,
isJsdom,
screen,
simulatePointerDevice,
} from '@mui/internal-test-utils';
import TableFooter from '@mui/material/TableFooter';
import TableCell from '@mui/material/TableCell';
import TableRow from '@mui/material/TableRow';
Expand All @@ -11,6 +19,7 @@ import { inputClasses } from '@mui/material/Input';
import { outlinedInputClasses } from '@mui/material/OutlinedInput';
import { filledInputClasses } from '@mui/material/FilledInput';
import { createTheme, ThemeProvider } from '@mui/material/styles';
import { inputBaseClasses } from '@mui/material/InputBase';
import IconButton, { iconButtonClasses } from '@mui/material/IconButton';
import { svgIconClasses } from '@mui/material/SvgIcon';
import { createSvgIcon } from '@mui/material/utils';
Expand Down Expand Up @@ -566,6 +575,88 @@ describe('<TablePagination />', () => {
});
});

describe('theme: focusVisible', () => {
function setup(theme) {
render(
<ThemeProvider theme={theme}>
<table>
<TableFooter>
<TableRow>
<TablePagination
count={1}
page={0}
onPageChange={noop}
onRowsPerPageChange={noop}
rowsPerPage={10}
/>
</TableRow>
</TableFooter>
</table>
</ThemeProvider>,
);

return screen.getByRole('combobox');
}

it.skipIf(isJsdom())('keeps the focus tint on the select without the theme ring', () => {
const combobox = setup(createTheme());

act(() => combobox.focus());

expect(combobox).toHaveComputedStyle({ backgroundColor: 'rgba(0, 0, 0, 0.12)' });
});

it.skipIf(isJsdom())('drops the focus tint on the select with the theme ring', () => {
const combobox = setup(createTheme({ focusVisible: true }));

act(() => combobox.focus());

expect(combobox).toHaveComputedStyle({ backgroundColor: 'rgba(0, 0, 0, 0)' });
});

it.skipIf(isJsdom())('rings the select on keyboard focus instead of the InputBase root', () => {
const combobox = setup(createTheme({ focusVisible: true }));

focusVisible(combobox);

expect(combobox).toHaveComputedStyle({ outlineStyle: 'solid', outlineWidth: '2px' });
expect(combobox.closest(`.${inputBaseClasses.root}`)).toHaveComputedStyle({
outlineStyle: 'none',
});
});

it.skipIf(isJsdom())('insets the action button ring so the root cannot clip it', () => {
render(
<ThemeProvider
theme={createTheme({
focusVisible: true,
components: { MuiButtonBase: { defaultProps: { disableRipple: true } } },
})}
>
<table>
<TableFooter>
<TableRow>
<TablePagination
count={30}
page={0}
onPageChange={noop}
onRowsPerPageChange={noop}
rowsPerPage={10}
/>
</TableRow>
</TableFooter>
</table>
</ThemeProvider>,
);
const nextButton = screen.getByRole('button', { name: 'Go to next page' });

simulatePointerDevice();
focusVisible(nextButton);

expect(nextButton).toHaveComputedStyle({ outlineStyle: 'solid', outlineOffset: '-2px' });
});
});

describe('prop: rowsPerPage', () => {
it('should display max number of rows text when prop is -1', () => {
const { container } = render(
Expand Down
Loading