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

[List] Making list meet Material Guidelines #6316

Closed
wants to merge 20 commits into from

Conversation

kybarg
Copy link
Contributor

@kybarg kybarg commented Mar 9, 2017

Trying to make list component more functional following Material Design Guidelines

(Cheking if functionality is implemented and demo is ready)

  • Single-line list
    • Text only
    • Icon with text
    • Avatar with text
    • Avatar with text and icon
  • Two-line list
    • Text only
    • Icon with text
    • Avatar with text
    • Avatar with text and icon
  • Three-line list
    • Text only
    • Icon with text
    • Avatar with text
    • Avatar with text and icon

Fancy demo:
image

@kybarg kybarg changed the title [List] Making list meet Mterial Guidelines [List] Making list meet Material Guidelines Mar 9, 2017
@muibot muibot added PR: needs revision The pull request can't be merged. More details is available on the code review or fails in the CI and removed PR: Needs Review labels Mar 9, 2017
Copy link
Member

@oliviertassinari oliviertassinari left a comment

Choose a reason for hiding this comment

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

Some early feedback. That's looks really good 😍 .
My main concern for now would be with the performance implication of iterating throw the children.
Once that's sorted, we would definitely needs to add some visual regression tests.
Thanks for working in that 👍

src/List/List.js Outdated
[classes.padding]: padding,
[classes.subheader]: subheader,
}, classNameProp);

return (
<ComponentProp ref={rootRef} className={className} {...other}>
{subheader}
{children}
{React.Children.map(children, (child) =>
React.cloneElement(child, { dense }),
Copy link
Member

Choose a reason for hiding this comment

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

I would rather be using the context. I think that it would perform much better.
Eventually, we would need a perf benchmark.

},
dense: {
paddingTop: 8,
paddingBottom: 8,
},
avatarDense: {
height: '32px !important',
Copy link
Member

Choose a reason for hiding this comment

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

!important sounds definitely like a hack.

return (
<div className={className} {...other}>
{primary && (
typeof primary === 'string' ? (
<Text type="subheading">
<Text type="subheading" className={classNameText}>
Copy link
Member

Choose a reason for hiding this comment

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

What about relying on CSS inheritance instead?

@@ -20,12 +20,16 @@ export const styleSheet = createStyleSheet('MuiListItemText', () => {
paddingLeft: 56,
},
},
dense: {
fontSize: '13px',
Copy link
Member

Choose a reason for hiding this comment

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

fontSize: 13,


// let hasIcon;
let hasAvatar;
React.Children.map(children, (child) => {
Copy link
Member

Choose a reason for hiding this comment

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

use forEach on the children instead, you are paying the Children method cost twice.

Copy link
Member

Choose a reason for hiding this comment

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

Or even better use some.

Copy link
Member

Choose a reason for hiding this comment

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

That perform better

@@ -54,6 +59,14 @@ export const styleSheet = createStyleSheet('MuiListItem', (theme) => {
};
});

const mapListIemChildren = (children, classes, dense) => React.Children.map(children, (child) => {
Copy link
Member

Choose a reason for hiding this comment

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

If we have to perform such expensive operation/brittle logic, I think that relying on the context would be better.
(We would need a ListItemAvar component if we follow that direction)

Copy link
Contributor Author

@kybarg kybarg Mar 9, 2017

Choose a reason for hiding this comment

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

@oliviertassinari Definitely context will rock here ☺️ my lack of experience is making me find hard ways in first place 😂

@oliviertassinari oliviertassinari added component: list This is the name of the generic UI component, not the React module! next and removed PR: Needs Review labels Mar 9, 2017
import SvgIcon from 'material-ui/SvgIcon';
import Text from 'material-ui/Text';

const SqureIcon = (props) => (
Copy link
Member

Choose a reason for hiding this comment

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

@mbrookes This one is for you 💃

backgroundSize: '20px 20px',
backgroundPosition: '10px -10px',
bottom: 0,
content: '""',
Copy link
Member

@oliviertassinari oliviertassinari Mar 9, 2017

Choose a reason for hiding this comment

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

Good, doing the other way around crash on IE11 "''" cssinjs/jss#242

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@oliviertassinari So content: '""' or content: "''" is the right way? 😄

Copy link
Member

@oliviertassinari oliviertassinari left a comment

Choose a reason for hiding this comment

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

12 problems (3 errors, 9 warnings)

You have the following eslint issues.

What's your plan going forward? I would avoid doing something too ambitious. We would definitely needs adding visual regressions tests for the new use cases.

height: 10,
position: 'absolute',
width: '100%',
zIndex: 99,
Copy link
Member

Choose a reason for hiding this comment

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

Why using that value?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@oliviertassinari You mean z-index? Basically to be over all elements in demo but not overlap toolbar when scrolling.

Copy link
Member

@oliviertassinari oliviertassinari Mar 9, 2017

Choose a reason for hiding this comment

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

In that case, you could be using the zIndex key of the theme. That would add constraints to the value. (Less likely to break in the future).

@@ -104,14 +105,21 @@ export default class ListItem extends Component {
gutters,
...other
} = this.props;

const isDense = dense || this.context.dense;
Copy link
Member

Choose a reason for hiding this comment

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

const isDense = dense || this.context.dense || false;

To be safe?

const children = React.Children.toArray(childrenProp);

let hasAvatar;
Object.entries(children).some((value) => {
Copy link
Member

Choose a reason for hiding this comment

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

That looks suspicious. What about

const hasAvatar = children.some((child) => {

className: classNameProp,
...other
} = this.props;
const { dense } = this.context;
Copy link
Member

Choose a reason for hiding this comment

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

Looks overkill to destructure.

const { dense } = this.context;
const classes = this.context.styleManager.render(styleSheet);
const className = classNames(classes.root, {
[classes.dense]: dense,
Copy link
Member

Choose a reason for hiding this comment

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

What about?

[classes.dense]: this.context.dense || false,

@@ -20,6 +20,11 @@ export const styleSheet = createStyleSheet('MuiListItemText', () => {
paddingLeft: 56,
},
},
dense: {
'& > *': {
Copy link
Member

@oliviertassinari oliviertassinari Mar 9, 2017

Choose a reason for hiding this comment

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

I was thinking about a simple CSS inheritance. Do we need to target the children elements?
I think that it would be better that the fontSize naturally inherent. Maybe we can't. I haven't looked in detail. That's always better than before 👍 .

Copy link
Contributor Author

@kybarg kybarg Mar 9, 2017

Choose a reason for hiding this comment

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

<Text /> component is a child and it has fontSize style already. SO just using fontSize on parent has no effect.

Copy link
Member

Choose a reason for hiding this comment

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

We have a colorInherit property on the Text component. We could imagine a fontSizeInherit property.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@octavioamu would be nice

Copy link
Member

Choose a reason for hiding this comment

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

So, what do you think about @mbrookes's idea.

  1. We set the font size to the parent element
  2. We add a class on the Text to get the inheritance.

The win is a flatten CSS selector, that's always better for composition.

@oliviertassinari oliviertassinari removed the PR: needs revision The pull request can't be merged. More details is available on the code review or fails in the CI label Mar 11, 2017
@oliviertassinari
Copy link
Member

@kybarg I have lost track of the state of this PR. Do you need any feedback?

@mbrookes
Copy link
Member

Yay for reincarnation of the MobileTearSheet! 🎉 ❤️

I have a small hack for continuing the border along the zig-zig that I'll post tomorrow (not on the right machine at the mo).

Also, I appreciate you were trying to recreate the MDM guidelines, but a real icon might be preferable to the placeholder square for 'Icon with text".

@kybarg
Copy link
Contributor Author

kybarg commented Mar 14, 2017

@oliviertassinari Yes, if everything is fine with my current fixes, I can continue with two and three line variations. Also we haven't agreed on how to change text size for dense list.

@mbrookes Tried to add border to jugged edge but it looks ugly in Firefox and IE 😄 They render it differently and it looks like 2px border. I hope you can do it better then me ☺️

@mbrookes
Copy link
Member

@kybarg Grrr, no, you're right! 😞 I get the same 2px in Safari. I had only tried in Chrome. We could use an SVG instead. :)

Otherwise, still to do:

  • Replace the Square icon and comment icon with an SvgIcon, (Or, if we're going the other way around, and showing specification not examples, replace the Avatar with a circle / empty Avatar, and comment icon with a square, and change the color to dark gray, not black.)
  • Agree styling approach for text size (@oliviertassinari?)

Copy link
Member

@oliviertassinari oliviertassinari left a comment

Choose a reason for hiding this comment

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

I have made minor comments, it's 80% ready to be merged 😄 . You rock 🚀
Also, we gonna need some visual regression tests for that new dense property.

},
},
title: {
margin: '32px 0 16px',
Copy link
Member

Choose a reason for hiding this comment

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

I would rathe be using the unit to show it's existing and that spacing should be consitent.

margin: `${theme.spacing.unit * 4}px 0 ${theme.spacing.unit * 2}px`,

@@ -20,6 +20,11 @@ export const styleSheet = createStyleSheet('MuiListItemText', () => {
paddingLeft: 56,
},
},
dense: {
'& > *': {
Copy link
Member

Choose a reason for hiding this comment

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

So, what do you think about @mbrookes's idea.

  1. We set the font size to the parent element
  2. We add a class on the Text to get the inheritance.

The win is a flatten CSS selector, that's always better for composition.

@oliviertassinari oliviertassinari added PR: needs revision The pull request can't be merged. More details is available on the code review or fails in the CI and removed PR: Needs Review labels Mar 14, 2017
1. Using spacing unit for margins
2. Fixed icon in example
3.  Simplified `ListItemAvatar` logic
4. Proper `Text` font size inheritance
5. Removed tests for `ListItemAvatar` (need to agree on final
implementation)
import { LabelCheckbox } from 'material-ui/Checkbox';
import Layout from 'material-ui/Layout';
import Text from 'material-ui/Text';
import TriangleImageLight from 'docs/site/assets/images/bg-triangle-light.svg';
Copy link
Member

Choose a reason for hiding this comment

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

Oh noooo, the demo is no longer working in isolation. It's going to be a pain for user starting from the demos.
@mbrookes What do you suggest?

Copy link
Member

Choose a reason for hiding this comment

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

@oliviertassinari Either the <svg> could be defined inline rather than being imported, or the file be treated as an img, so will fail gracefully if the example code is copied without the svg file.

@kybarg Could the CSS fill & stroke attributes perhaps be used so as to not need two separate svgs?

Copy link
Member

@oliviertassinari oliviertassinari Mar 15, 2017

Choose a reason for hiding this comment

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

You see me coming but simplicity might be just as good: removing that fancy effect.
I hope we will find a better solution.

Copy link
Member

Choose a reason for hiding this comment

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

Nooooo!! 🤣 🤣 🤣

};
});

export default class ListItemAvatar extends Component {
Copy link
Member

@oliviertassinari oliviertassinari Mar 15, 2017

Choose a reason for hiding this comment

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

No need for a Component here.

@oliviertassinari
Copy link
Member

@kybarg The build fails because of the regressions tests. The changes look fine to me. I can take care of writing new one for the dense property and updating the base screenshots if needed.

@oliviertassinari oliviertassinari added PR: Review Accepted and removed PR: Needs Review PR: needs revision The pull request can't be merged. More details is available on the code review or fails in the CI labels Mar 15, 2017
@kybarg
Copy link
Contributor Author

kybarg commented Mar 15, 2017

@oliviertassinari would be great! 👍

@muibot muibot added PR: Needs Review PR: needs revision The pull request can't be merged. More details is available on the code review or fails in the CI and removed PR: Needs Review labels Mar 17, 2017
@oliviertassinari
Copy link
Member

@kybarg Hold on. I'm continuing the PR to add the missing tests 😄 .

@oliviertassinari
Copy link
Member

oliviertassinari commented Mar 17, 2017

Here is it #6367. Thanks for pushing it forward!

@kybarg kybarg deleted the next-list-guidelines branch April 10, 2017 03:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
component: list This is the name of the generic UI component, not the React module! PR: needs revision The pull request can't be merged. More details is available on the code review or fails in the CI
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants