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

[Breadcrumbs] Migrate to emotion #24522

Merged
merged 36 commits into from
Jan 25, 2021
Merged
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
449a845
[Breadcrumbs] Migrate to emotion
queengooborg Jan 20, 2021
48dac4f
Breadcrumbs doesn't need to test theme variants
queengooborg Jan 21, 2021
ecfc45c
Resolve TS issues with sx prop
queengooborg Jan 21, 2021
12ef735
Recompile docs + prototypes
queengooborg Jan 21, 2021
644497e
sx is optional
queengooborg Jan 21, 2021
4188f3a
Simplify styles for root slot
queengooborg Jan 21, 2021
4c13038
Remove redundant LI slot
queengooborg Jan 21, 2021
dcf69ce
Fix styleProps
queengooborg Jan 21, 2021
3e926b5
Update tests
queengooborg Jan 21, 2021
67070d0
Update styleProps
queengooborg Jan 21, 2021
59c6ca4
Remove redundant LI slot
queengooborg Jan 21, 2021
4721344
Apply suggestions from code review
queengooborg Jan 21, 2021
4234049
Merge branch 'next' into migrate/Breadcrumbs
queengooborg Jan 21, 2021
1d17c05
Convert BreadcrumbCollapsed to emotion
queengooborg Jan 21, 2021
b53826c
Merge branch 'next' into migrate/Breadcrumbs
queengooborg Jan 21, 2021
8ee9c98
"classes" is no longer required for BreadcrumbCollapsed
queengooborg Jan 21, 2021
ff7d0c6
Apply suggestions from code review
queengooborg Jan 21, 2021
2f6d270
Update packages/material-ui/src/Breadcrumbs/BreadcrumbCollapsed.js
queengooborg Jan 21, 2021
e57b6f1
Fix closing tag
queengooborg Jan 21, 2021
dd1caa7
Re-add useUtilityClasses()
queengooborg Jan 21, 2021
54224fa
Remove unused imports
queengooborg Jan 21, 2021
f120e8e
Improve dark theme support
queengooborg Jan 21, 2021
91ce0a8
Apply suggestions from code review
queengooborg Jan 21, 2021
9c143e9
Apply suggestions from code review
queengooborg Jan 21, 2021
6329cad
Remove unused variable
queengooborg Jan 21, 2021
e46f357
Update packages/material-ui/src/Breadcrumbs/BreadcrumbCollapsed.js
queengooborg Jan 22, 2021
ae1aef7
Include "expanded" in styleProps
queengooborg Jan 22, 2021
be6f967
Merge branch 'next' into migrate/Breadcrumbs
queengooborg Jan 23, 2021
57cb867
no need to rename the prop
oliviertassinari Jan 23, 2021
6cc5083
no need to clone the props
oliviertassinari Jan 23, 2021
c7e5d3d
no use case for forward ref
oliviertassinari Jan 23, 2021
4003189
rerun ci
oliviertassinari Jan 24, 2021
e7c7832
rerun ci
oliviertassinari Jan 24, 2021
972829e
Update packages/material-ui/src/Breadcrumbs/Breadcrumbs.js
mnajdova Jan 25, 2021
6635d86
Update packages/material-ui/src/Breadcrumbs/Breadcrumbs.js
mnajdova Jan 25, 2021
153fc5c
Update packages/material-ui/src/Breadcrumbs/Breadcrumbs.js
mnajdova Jan 25, 2021
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
5 changes: 3 additions & 2 deletions docs/pages/api-docs/breadcrumbs.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
"itemsAfterCollapse": { "type": { "name": "number" }, "default": "1" },
"itemsBeforeCollapse": { "type": { "name": "number" }, "default": "1" },
"maxItems": { "type": { "name": "number" }, "default": "8" },
"separator": { "type": { "name": "node" }, "default": "'/'" }
"separator": { "type": { "name": "node" }, "default": "'/'" },
"sx": { "type": { "name": "object" } }
},
"name": "Breadcrumbs",
"styles": {
Expand All @@ -20,6 +21,6 @@
"filename": "/packages/material-ui/src/Breadcrumbs/Breadcrumbs.js",
"inheritance": null,
"demos": "<ul><li><a href=\"/components/breadcrumbs/\">Breadcrumbs</a></li></ul>",
"styledComponent": false,
"styledComponent": true,
"cssComponent": false
}
3 changes: 2 additions & 1 deletion docs/translations/api-docs/breadcrumbs/breadcrumbs.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
"itemsAfterCollapse": "If max items is exceeded, the number of items to show after the ellipsis.",
"itemsBeforeCollapse": "If max items is exceeded, the number of items to show before the ellipsis.",
"maxItems": "Specifies the maximum number of breadcrumbs to display. When there are more than the maximum number, only the first <code>itemsBeforeCollapse</code> and last <code>itemsAfterCollapse</code> will be shown, with an ellipsis in between.",
"separator": "Custom separator node."
"separator": "Custom separator node.",
"sx": "The system prop that allows defining system overrides as well as additional CSS styles. See the <a href=\"/system/basics/#the-sx-prop\">`sx` page</a> for more details."
},
"classDescriptions": {
"root": { "description": "Styles applied to the root element." },
Expand Down
96 changes: 68 additions & 28 deletions packages/material-ui/src/Breadcrumbs/BreadcrumbCollapsed.js
Original file line number Diff line number Diff line change
@@ -1,52 +1,92 @@
import * as React from 'react';
import PropTypes from 'prop-types';
import withStyles from '../styles/withStyles';
import { unstable_composeClasses as composeClasses } from '@material-ui/unstyled';
import experimentalStyled from '../styles/experimentalStyled';
import { emphasize } from '../styles/colorManipulator';
import MoreHorizIcon from '../internal/svg-icons/MoreHoriz';
import ButtonBase from '../ButtonBase';
import { getBreadcrumbCollapsedUtilityClass } from './breadcrumbCollapsedClasses';

const styles = (theme) => ({
button: {
display: 'flex',
marginLeft: theme.spacing(0.5),
marginRight: theme.spacing(0.5),
backgroundColor: theme.palette.grey[100],
color: theme.palette.grey[700],
borderRadius: 2,
'&:hover, &:focus': {
backgroundColor: theme.palette.grey[200],
},
'&:active': {
boxShadow: theme.shadows[0],
backgroundColor: emphasize(theme.palette.grey[200], 0.12),
},
const useUtilityClasses = (styleProps) => {
const { classes } = styleProps;

const slots = {
button: ['button'],
icon: ['icon'],
};

return composeClasses(slots, getBreadcrumbCollapsedUtilityClass, classes);
};

const BreadcrumbCollapsedButton = experimentalStyled(
ButtonBase,
{},
{
name: 'PrivateBreadcrumbCollapsed',
slot: 'Button',
},
)(({ theme }) => ({
display: 'flex',
marginLeft: theme.spacing(0.5),
marginRight: theme.spacing(0.5),
...(theme.palette.type === 'light'
queengooborg marked this conversation as resolved.
Show resolved Hide resolved
? { backgroundColor: theme.palette.grey[100], color: theme.palette.grey[700] }
: { backgroundColor: theme.palette.grey[700], color: theme.palette.grey[100] }),
borderRadius: 2,
'&:hover, &:focus': {
...(theme.palette.mode === 'light'
? { backgroundColor: theme.palette.grey[200] }
: { backgroundColor: theme.palette.grey[600] }),
},
icon: {
width: 24,
height: 16,
'&:active': {
boxShadow: theme.shadows[0],
...(theme.palette.mode === 'light'
? { backgroundColor: emphasize(theme.palette.grey[200], 0.12) }
: { backgroundColor: emphasize(theme.palette.grey[600], 0.12) }),
},
}));

const BreadcrumbCollapsedIcon = experimentalStyled(
MoreHorizIcon,
{},
{
name: 'PrivateBreadcrumbCollapsed',
slot: 'Icon',
},
)({
width: 24,
height: 16,
});

/**
* @ignore - internal component.
*/
function BreadcrumbCollapsed(props) {
const { classes, ...other } = props;
const BreadcrumbCollapsed = React.forwardRef(function BreadcrumbCollapsed(props, ref) {
const { ...other } = props;

const styleProps = props;

const classes = useUtilityClasses(styleProps);

return (
<li>
<ButtonBase className={classes.button} focusRipple {...other}>
<MoreHorizIcon className={classes.icon} />
</ButtonBase>
<BreadcrumbCollapsedButton
className={classes.button}
focusRipple
{...other}
styleProps={styleProps}
>
<BreadcrumbCollapsedIcon className={classes.icon} styleProps={styleProps} />
</BreadcrumbCollapsedButton>
</li>
);
}
});

BreadcrumbCollapsed.propTypes = {
/**
* @ignore
* The system prop that allows defining system overrides as well as additional CSS styles.
*/
classes: PropTypes.object.isRequired,
sx: PropTypes.object,
};

export default withStyles(styles, { name: 'PrivateBreadcrumbCollapsed' })(BreadcrumbCollapsed);
export default BreadcrumbCollapsed;
Original file line number Diff line number Diff line change
@@ -1,17 +1,13 @@
import * as React from 'react';
import { expect } from 'chai';
import { spy } from 'sinon';
import { getClasses, fireEvent, createClientRender } from 'test/utils';
import { fireEvent, createClientRender } from 'test/utils';
import BreadcrumbCollapsed from './BreadcrumbCollapsed';
import classes from './breadcrumbCollapsedClasses';

describe('<BreadcrumbCollapsed />', () => {
let classes;
const render = createClientRender();

before(() => {
classes = getClasses(<BreadcrumbCollapsed />);
});

it('should render an icon', () => {
const { container, getByRole } = render(<BreadcrumbCollapsed />);

Expand Down
6 changes: 6 additions & 0 deletions packages/material-ui/src/Breadcrumbs/Breadcrumbs.d.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
import * as React from 'react';
import { SxProps } from '@material-ui/system';
import { Theme } from '@material-ui/core/styles';
import { OverridableComponent, OverrideProps } from '../OverridableComponent';

export interface BreadcrumbsTypeMap<P = {}, D extends React.ElementType = 'nav'> {
Expand Down Expand Up @@ -49,6 +51,10 @@ export interface BreadcrumbsTypeMap<P = {}, D extends React.ElementType = 'nav'>
* @default '/'
*/
separator?: React.ReactNode;
/**
* The system prop that allows defining system overrides as well as additional CSS styles.
*/
sx?: SxProps<Theme>;
};
defaultComponent: D;
}
Expand Down
125 changes: 94 additions & 31 deletions packages/material-ui/src/Breadcrumbs/Breadcrumbs.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,41 +2,86 @@ import * as React from 'react';
import { isFragment } from 'react-is';
import PropTypes from 'prop-types';
import clsx from 'clsx';
import withStyles from '../styles/withStyles';
import { deepmerge } from '@material-ui/utils';
import { unstable_composeClasses as composeClasses } from '@material-ui/unstyled';
import experimentalStyled from '../styles/experimentalStyled';
import useThemeProps from '../styles/useThemeProps';
import Typography from '../Typography';
import BreadcrumbCollapsed from './BreadcrumbCollapsed';
queengooborg marked this conversation as resolved.
Show resolved Hide resolved
import breadcrumbsClasses, { getBreadcrumbsUtilityClass } from './breadcrumbsClasses';

export const styles = {
/* Styles applied to the root element. */
root: {},
/* Styles applied to the ol element. */
ol: {
display: 'flex',
flexWrap: 'wrap',
alignItems: 'center',
padding: 0,
margin: 0,
listStyle: 'none',
const overridesResolver = (props, styles) => {
return deepmerge(styles.root || {}, {
[`& .${breadcrumbsClasses.ol}`]: styles.ol,
mnajdova marked this conversation as resolved.
Show resolved Hide resolved
[`& .${breadcrumbsClasses.separator}`]: styles.separator,
});
};

const useUtilityClasses = (styleProps) => {
const { classes } = styleProps;

const slots = {
root: ['root'],
mnajdova marked this conversation as resolved.
Show resolved Hide resolved
ol: ['ol'],
separator: ['separator'],
};

return composeClasses(slots, getBreadcrumbsUtilityClass, classes);
};

const BreadcrumbsRoot = experimentalStyled(
Typography,
{},
{
name: 'MuiBreadcrumbs',
slot: 'Root',
overridesResolver,
},
/* Styles applied to the li element. */
li: {},
/* Styles applied to the separator element. */
separator: {
display: 'flex',
userSelect: 'none',
marginLeft: 8,
marginRight: 8,
)({});

const BreadcrumbsOl = experimentalStyled(
'ol',
{},
{
name: 'MuiBreadcrumbs',
slot: 'Ol',
},
};
)({
display: 'flex',
flexWrap: 'wrap',
alignItems: 'center',
padding: 0,
margin: 0,
listStyle: 'none',
});

function insertSeparators(items, className, separator) {
const BreadcrumbsSeparator = experimentalStyled(
'li',
{},
{
name: 'MuiBreadcrumbs',
slot: 'Separator',
},
)({
display: 'flex',
userSelect: 'none',
marginLeft: 8,
marginRight: 8,
});

function insertSeparators(items, className, separator, styleProps) {
return items.reduce((acc, current, index) => {
if (index < items.length - 1) {
acc = acc.concat(
current,
<li aria-hidden key={`separator-${index}`} className={className}>
<BreadcrumbsSeparator
aria-hidden
key={`separator-${index}`}
className={className}
styleProps={styleProps}
>
{separator}
</li>,
</BreadcrumbsSeparator>,
);
} else {
acc.push(current);
Expand All @@ -46,10 +91,10 @@ function insertSeparators(items, className, separator) {
}, []);
}

const Breadcrumbs = React.forwardRef(function Breadcrumbs(props, ref) {
const Breadcrumbs = React.forwardRef(function Breadcrumbs(inProps, ref) {
const props = useThemeProps({ props: inProps, name: 'MuiBreadcrumbs' });
const {
children,
classes,
className,
component: Component = 'nav',
expandText = 'Show path',
Expand All @@ -60,6 +105,18 @@ const Breadcrumbs = React.forwardRef(function Breadcrumbs(props, ref) {
...other
} = props;

const styleProps = {
queengooborg marked this conversation as resolved.
Show resolved Hide resolved
...props,
component: Component,
expandText,
itemsAfterCollapse,
itemsBeforeCollapse,
maxItems,
separator,
};

const classes = useUtilityClasses(styleProps);

const [expanded, setExpanded] = React.useState(false);

const listRef = React.useRef(null);
Expand Down Expand Up @@ -120,23 +177,25 @@ const Breadcrumbs = React.forwardRef(function Breadcrumbs(props, ref) {
));

return (
<Typography
<BreadcrumbsRoot
ref={ref}
component={Component}
color="textSecondary"
className={clsx(classes.root, className)}
styleProps={styleProps}
{...other}
>
<ol className={classes.ol} ref={listRef}>
<BreadcrumbsOl className={classes.ol} ref={listRef} styleProps={styleProps}>
{insertSeparators(
expanded || (maxItems && allItems.length <= maxItems)
? allItems
: renderItemsBeforeAndAfter(allItems),
classes.separator,
separator,
styleProps,
)}
</ol>
</Typography>
</BreadcrumbsOl>
</BreadcrumbsRoot>
);
});

Expand Down Expand Up @@ -191,6 +250,10 @@ Breadcrumbs.propTypes = {
* @default '/'
*/
separator: PropTypes.node,
/**
* The system prop that allows defining system overrides as well as additional CSS styles.
*/
sx: PropTypes.object,
};

export default withStyles(styles, { name: 'MuiBreadcrumbs' })(Breadcrumbs);
export default Breadcrumbs;
Loading