Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Joy] Miscellaneous fixes #34193

Merged
merged 16 commits into from Sep 7, 2022
8 changes: 4 additions & 4 deletions docs/data/joy/components/list/ExampleCollapsibleList.js
Expand Up @@ -85,7 +85,7 @@ export default function ExampleCollapsibleList() {
</IconButton>
}
>
<ListItemButton>
<ListItem>
<Typography
level="inherit"
sx={{
Expand All @@ -98,7 +98,7 @@ export default function ExampleCollapsibleList() {
<Typography component="span" level="body3" sx={{ ml: 1 }}>
9
</Typography>
</ListItemButton>
</ListItem>
{open && (
<List sx={{ '--List-item-paddingY': '8px' }}>
<ListItem>
Expand Down Expand Up @@ -136,7 +136,7 @@ export default function ExampleCollapsibleList() {
</IconButton>
}
>
<ListItemButton>
<ListItem>
<Typography
level="inherit"
sx={{
Expand All @@ -149,7 +149,7 @@ export default function ExampleCollapsibleList() {
<Typography component="span" level="body3" sx={{ ml: 1 }}>
39
</Typography>
</ListItemButton>
</ListItem>
{open2 && (
<List sx={{ '--List-item-paddingY': '8px' }}>
<ListItem>
Expand Down
Expand Up @@ -8,7 +8,7 @@ import Home from '@mui/icons-material/Home';
import KeyboardArrowRight from '@mui/icons-material/KeyboardArrowRight';
import JoyUsageDemo from 'docs/src/modules/components/JoyUsageDemo';

export default function VariantsColorsList() {
export default function ListUsage() {
return (
<JoyUsageDemo
componentName="ListItemButton"
Expand Down
2 changes: 1 addition & 1 deletion docs/data/joy/components/list/list.md
Expand Up @@ -19,7 +19,7 @@ Joy UI provides four list-related components:
- [`ListItemContent`](#ellipsis-content): A container inside a list item, used to display text content.
- [`ListDivider`](#divider): A separator between list items.

{{"demo": "VariantsColorsList.js", "hideToolbar": true}}
{{"demo": "ListUsage.js", "hideToolbar": true}}

## Component

Expand Down
3 changes: 2 additions & 1 deletion docs/data/joy/components/menu/MenuListGroup.js
Expand Up @@ -8,6 +8,7 @@ import Typography from '@mui/joy/Typography';
export default function MenuListGroup() {
return (
<MenuList
component="div"
variant="outlined"
size="sm"
sx={{
Expand All @@ -19,7 +20,7 @@ export default function MenuListGroup() {
}}
>
{[...Array(5)].map((_, categoryIndex) => (
<List role="group" key={categoryIndex}>
<List key={categoryIndex}>
<ListItem sticky>
<Typography
id={`sticky-list-demo-${categoryIndex}`}
Expand Down
4 changes: 2 additions & 2 deletions docs/data/joy/components/tabs/TabsPageExample.js
Expand Up @@ -9,7 +9,7 @@ import Typography from '@mui/joy/Typography';
import Input from '@mui/joy/Input';
import SearchRounded from '@mui/icons-material/SearchRounded';

export default function TabsBasic() {
export default function TabsPageExample() {
const [index, setIndex] = React.useState(0);
return (
<Box
Expand Down Expand Up @@ -125,9 +125,9 @@ export default function TabsBasic() {
</TabPanel>
<TabPanel value={2}>
<Input
autoFocus
placeholder="type a library..."
startDecorator={<SearchRounded />}
sx={{ bgcolor: 'background.body', mb: 0.75 }}
/>
</TabPanel>
</Box>
Expand Down
4 changes: 2 additions & 2 deletions docs/data/joy/components/tabs/TabsPageExample.tsx
Expand Up @@ -9,7 +9,7 @@ import Typography from '@mui/joy/Typography';
import Input from '@mui/joy/Input';
import SearchRounded from '@mui/icons-material/SearchRounded';

export default function TabsBasic() {
export default function TabsPageExample() {
const [index, setIndex] = React.useState(0);
return (
<Box
Expand Down Expand Up @@ -125,9 +125,9 @@ export default function TabsBasic() {
</TabPanel>
<TabPanel value={2}>
<Input
autoFocus
placeholder="type a library..."
startDecorator={<SearchRounded />}
sx={{ bgcolor: 'background.body', mb: 0.75 }}
/>
</TabPanel>
</Box>
Expand Down
2 changes: 1 addition & 1 deletion packages/mui-joy/src/Checkbox/Checkbox.tsx
Expand Up @@ -25,7 +25,7 @@ const useUtilityClasses = (ownerState: CheckboxOwnerState) => {
color && `color${capitalize(color)}`,
size && `size${capitalize(size)}`,
],
checkbox: ['checkbox', disabled && 'disabled'], // disabled class is necessary for displaying global variant
checkbox: ['checkbox', checked && 'checked', disabled && 'disabled'], // disabled class is necessary for displaying global variant
action: [
'action',
checked && 'checked',
Expand Down
2 changes: 1 addition & 1 deletion packages/mui-joy/src/Input/Input.tsx
Expand Up @@ -151,6 +151,7 @@ const InputInput = styled('input', {
fontStyle: 'inherit',
fontWeight: 'inherit',
lineHeight: 'inherit',
textOverflow: 'ellipsis',
'&:-webkit-autofill': {
WebkitBackgroundClip: 'text', // remove autofill background
WebkitTextFillColor: theme.vars.palette[ownerState.color!]?.overrideTextPrimary,
Expand All @@ -169,7 +170,6 @@ const InputStartDecorator = styled('span', {
'--Button-margin': '0 0 0 calc(var(--Input-decorator-childOffset) * -1)',
'--IconButton-margin': '0 0 0 calc(var(--Input-decorator-childOffset) * -1)',
'--Icon-margin': '0 0 0 calc(var(--Input-paddingInline) / -4)',
pointerEvents: 'none', // to make the input focused when click on the element because start element usually is an icon
display: 'inherit',
alignItems: 'center',
marginInlineEnd: 'var(--Input-gap)',
Expand Down
5 changes: 5 additions & 0 deletions packages/mui-joy/src/List/List.test.js
Expand Up @@ -44,6 +44,11 @@ describe('Joy <List />', () => {
expect(container.firstChild).to.have.class(classes.sizeLg);
});

it('should have default size="md" classes', () => {
const { container } = render(<List size={undefined} />);
expect(container.firstChild).to.have.class(classes.sizeMd);
});

it('should have nesting classes', () => {
const { getByRole } = render(
<ListItem nested>
Expand Down
6 changes: 3 additions & 3 deletions packages/mui-joy/src/List/List.tsx
Expand Up @@ -109,7 +109,7 @@ export const ListRoot = styled('ul', {
? {
...(ownerState.wrap
? {
padding: 'var(--List-padding)',
padding: 'var(--List-padding)', // Fallback is not needed for row-wrap List
marginInlineStart: 'calc(-1 * var(--List-gap))',
marginBlockStart: 'calc(-1 * var(--List-gap))',
}
Expand Down Expand Up @@ -151,7 +151,7 @@ const List = React.forwardRef(function List(inProps, ref) {
component,
className,
children,
size = 'md',
size = inProps.size ?? 'md',
row = false,
wrap = false,
variant = 'plain',
Expand All @@ -163,6 +163,7 @@ const List = React.forwardRef(function List(inProps, ref) {
const role = roleProp ?? (menuContext || selectContext ? 'group' : undefined);

const ownerState = {
...props,
instanceSize: inProps.size,
size,
nesting,
Expand All @@ -171,7 +172,6 @@ const List = React.forwardRef(function List(inProps, ref) {
variant,
color,
role,
...props,
};

const classes = useUtilityClasses(ownerState);
Expand Down
2 changes: 1 addition & 1 deletion packages/mui-joy/src/List/ListProps.ts
Expand Up @@ -63,7 +63,7 @@ export interface ListOwnerState extends ListProps {
* @internal
* The explicit size specified on the element instance.
*/
instanceSize: ListProps['size'];
instanceSize?: ListProps['size'];
/**
* @internal
* If `true`, the element is rendered in a nested list item.
Expand Down
14 changes: 13 additions & 1 deletion packages/mui-joy/src/ListItem/ListItem.test.js
Expand Up @@ -18,7 +18,7 @@ describe('Joy <ListItem />', () => {
refInstanceof: window.HTMLLIElement,
testVariantProps: { variant: 'solid' },
testCustomVariant: true,
skip: ['componentsProp', 'classesRoot', 'themeVariants'],
skip: ['componentsProp', 'classesRoot'],
}));

it('should have root className', () => {
Expand Down Expand Up @@ -78,6 +78,18 @@ describe('Joy <ListItem />', () => {

expect(screen.getByText('Foo')).to.have.attribute('role', 'none');
});

it('should have role presentation for grouped options', () => {
render(
<MenuList>
<List>
<ListItem>Foo</ListItem>
</List>
</MenuList>,
);

expect(screen.getByRole('group').firstChild).to.have.attribute('role', 'presentation');
});
});

describe('Semantics - List', () => {
Expand Down
33 changes: 20 additions & 13 deletions packages/mui-joy/src/ListItem/ListItem.tsx
Expand Up @@ -72,6 +72,7 @@ const ListItemRoot = styled('li', {
boxSizing: 'border-box',
borderRadius: 'var(--List-item-radius)',
display: 'flex',
flex: 'none',
position: 'relative',
paddingBlockStart: ownerState.nested ? 0 : 'var(--List-item-paddingY)',
paddingBlockEnd: ownerState.nested ? 0 : 'var(--List-item-paddingY)',
Expand Down Expand Up @@ -159,13 +160,17 @@ const ListItem = React.forwardRef(function ListItem(inProps, ref) {
const [listElement, listRole] = listComponent?.split(':') || ['', ''];
const component =
componentProp || (listElement && !listElement.match(/^(ul|ol|menu)$/) ? 'div' : undefined);
const role =
roleProp ??
(menuContext
? // ListItem can be used inside Menu to create nested menus, so it should have role="none"
// https://www.w3.org/WAI/ARIA/apg/example-index/menubar/menubar-navigation.html
'none'
: { menu: 'none', menubar: 'none', group: 'presentation' }[listRole]);

let role = menuContext ? 'none' : undefined;

if (listComponent) {
// ListItem can be used inside Menu to create nested menus, so it should have role="none"
// https://www.w3.org/WAI/ARIA/apg/example-index/menubar/menubar-navigation.html
role = { menu: 'none', menubar: 'none', group: 'presentation' }[listRole];
}
if (roleProp) {
role = roleProp;
}

const ownerState = {
sticky,
Expand Down Expand Up @@ -231,10 +236,6 @@ ListItem.propTypes /* remove-proptypes */ = {
* The content of the component.
*/
children: PropTypes.node,
/**
* Override or extend the styles applied to the component.
*/
classes: PropTypes.object,
/**
* @ignore
*/
Expand All @@ -243,7 +244,10 @@ ListItem.propTypes /* remove-proptypes */ = {
* The color of the component. It supports those theme colors that make sense for this component.
* @default 'neutral'
*/
color: PropTypes.oneOf(['danger', 'info', 'neutral', 'primary', 'success', 'warning']),
color: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([
PropTypes.oneOf(['danger', 'info', 'neutral', 'primary', 'success', 'warning']),
PropTypes.string,
]),
/**
* The component used for the root node.
* Either a string to use a HTML element or a component.
Expand Down Expand Up @@ -283,7 +287,10 @@ ListItem.propTypes /* remove-proptypes */ = {
* The variant to use.
* @default 'plain'
*/
variant: PropTypes.oneOf(['outlined', 'plain', 'soft', 'solid']),
variant: PropTypes /* @typescript-to-proptypes-ignore */.oneOfType([
PropTypes.oneOf(['outlined', 'plain', 'soft', 'solid']),
PropTypes.string,
]),
} as any;

// @ts-ignore internal logic to prevent <li> in <li>
Expand Down
5 changes: 0 additions & 5 deletions packages/mui-joy/src/ListItem/ListItemProps.ts
@@ -1,7 +1,6 @@
import * as React from 'react';
import { OverridableStringUnion, OverrideProps } from '@mui/types';
import { ColorPaletteProp, VariantProp, SxProps } from '../styles/types';
import { ListItemClasses } from './listItemClasses';

export type ListItemSlot = 'root' | 'startAction' | 'endAction';

Expand All @@ -20,10 +19,6 @@ export interface ListItemTypeMap<P = {}, D extends React.ElementType = 'li'> {
* The content of the component.
*/
children?: React.ReactNode;
/**
* Override or extend the styles applied to the component.
*/
classes?: Partial<ListItemClasses>;
/**
* The element to display at the start of ListItem.
*/
Expand Down
30 changes: 30 additions & 0 deletions packages/mui-joy/src/ListItem/listItemClasses.ts
Expand Up @@ -13,6 +13,26 @@ export interface ListItemClasses {
nesting: string;
/** Styles applied to the root element, if sticky={true}. */
sticky: string;
/** Styles applied to the root element if `color="primary"`. */
colorPrimary: string;
/** Styles applied to the root element if `color="neutral"`. */
colorNeutral: string;
/** Styles applied to the root element if `color="danger"`. */
colorDanger: string;
/** Styles applied to the root element if `color="info"`. */
colorInfo: string;
/** Styles applied to the root element if `color="success"`. */
colorSuccess: string;
/** Styles applied to the root element if `color="warning"`. */
colorWarning: string;
/** State class applied to the root element if `variant="plain"`. */
variantPlain: string;
/** State class applied to the root element if `variant="soft"`. */
variantSoft: string;
/** State class applied to the root element if `variant="outlined"`. */
variantOutlined: string;
/** State class applied to the root element if `variant="solid"`. */
variantSolid: string;
}

export type ListItemClassKey = keyof ListItemClasses;
Expand All @@ -28,6 +48,16 @@ const listItemClasses: ListItemClasses = generateUtilityClasses('JoyListItem', [
'nested',
'nesting',
'sticky',
'colorPrimary',
'colorNeutral',
'colorDanger',
'colorInfo',
'colorSuccess',
'colorWarning',
'variantPlain',
'variantSoft',
'variantOutlined',
'variantSolid',
]);

export default listItemClasses;
4 changes: 3 additions & 1 deletion packages/mui-joy/src/ListItemButton/ListItemButton.tsx
Expand Up @@ -72,7 +72,9 @@ export const ListItemButtonRoot = styled('div', {
minBlockSize: 'var(--List-item-minHeight)',
border: 'none',
borderRadius: 'var(--List-item-radius)',
flex: ownerState.row ? 'none' : 1,
flexGrow: ownerState.row ? 0 : 1,
flexBasis: ownerState.row ? 'auto' : '0%', // for long text (in vertical), displays in multiple lines.
flexShrink: 0,
minInlineSize: 0,
// TODO: discuss the transition approach in a separate PR. This value is copied from mui-material Button.
transition:
Expand Down
1 change: 0 additions & 1 deletion packages/mui-joy/src/MenuList/MenuList.tsx
Expand Up @@ -90,7 +90,6 @@ const MenuList = React.forwardRef(function MenuList(inProps, ref) {
variant,
color,
size,
instanceSize: size,
nesting: false,
row: false,
};
Expand Down
2 changes: 1 addition & 1 deletion packages/mui-joy/src/Radio/Radio.tsx
Expand Up @@ -24,7 +24,7 @@ const useUtilityClasses = (ownerState: RadioOwnerState) => {
color && `color${capitalize(color)}`,
size && `size${capitalize(size)}`,
],
radio: ['radio', disabled && 'disabled'], // disabled class is necessary for displaying global variant
radio: ['radio', checked && 'checked', disabled && 'disabled'], // disabled class is necessary for displaying global variant
icon: ['icon'],
action: [
'action',
Expand Down