-
-
Notifications
You must be signed in to change notification settings - Fork 32.3k
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
[Layout]: Add new Layout
components
#5267
Conversation
Add `priority` and `isMatch` properties to `createBreakpoints`. priority is large to small.
This is an initial take on layout feature heavily influenced by [angular material](https://material.angularjs.org/latest/layout/introduction). There are 2 components exposed here. - `<Block />` Component. Works very similar to the `layout` attributes in **angular material** - `withLayout` HOC. which wraps any component with layout properties which gets rended as `className` property. Also included is the option to set layout properties for media query breakpoints. Example use of `<Block />` component ```jsx import { List, ListItem, Toolbar, ToolbarGroup } from 'material-ui'; import { Block } from 'material-ui/Layout'; import { Link } from 'react-router'; import SvgIconHome from 'material-ui/svg-icons/action/home'; const ToolbarBlock = withLayout(Toolbar); const BlockLink = withLayout(Link); export default (props) => ( <Block flex layout="column"> <Block flex="none"> <ToolbarBlock layout="row"> <ToolbarGroup> <Block layout="row" align="center" justify="start"> <Block hide={['xs', 'sm']}>Hello</Block> <IconButton><SvgIconHome /></IconButton> </Block> </ToolbarGroup> </ToolbarBlock> </Block> <Block flex layout="column" scroll> <List> <ListItem primaryText="Inbox" /> <ListItem primaryText="Starred" /> <ListItem primaryText="Sent mail" /> <ListItem primaryText="Drafts" /> <ListItem primaryText="Inbox" /> </List> </Block> </Block> ); ```
Layout
componentsLayout
components
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wow, that seems like a quite evolved solution.
I'm still wondering about the problem solved.
How is the problem solved related to the Material Design Specification?
Well, I start to find some answer to this question under the Layout section. Feels like it's going in the right direction
- It's based on a 12 column grid system
- They focus on consistent margins and gutters
- A persistent drawer pushs the responsive grid
- A temporary drawer does not affect the grid
return { keys, values, up, down, only, getWidth }; | ||
let matched = priority | ||
.reduce((a, k) => { | ||
const media = window.matchMedia(breakpoints[k]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How does matchMedia
behave when doing server-side rendering?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the feedback. Well I haven't fully thought about it. But one way is to add some listeners on componentWillMount
and setState
. Currently I've been using redux to monitor media query changes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My biggest concern is regarding having a correct layout during the first paint. And not waiting for the js to load in order to get the correct one. As far as I know, we can't use the matchMedia
API with this constrainte.
What are we using it for? Why not using the CSS media queries?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well on the flip side, If we do use media queries for all, the number of classes will go up significantly. I am not sure the performance consequence of JSS rendering so many classes in the style
tag. If the performance is negligible This can be done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, from my point of view, taking the server-side rendering into account, we don't have much choice.
The other option is not to render the layout on the server to prevent a flash of content.
Hopefully, JSS is quite performant and that shouldn't be a real issue.
- Some of the flex styles weren't applied as expected. - add some tests for flex
Closes mui#5276.
I have just came across http://stackoverflow.com/questions/33671469/material-ui-and-grid-system. That's just to add some context on how much people are looking for an answer here. |
Is there any progress? |
@timothyklim see this for an alternative: #3614 (comment) |
- fixed `align` PropTypes values - use camelCase for all classnames - make it easy to read
Demo to show whats possible with this component and how flexible (no pun intended) and easy it is to work with.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The new docs demo is quite cool 👍 .
The Angular Layout approach is really interesting.
It's quite powerful. I hope we can move this PR forward into next
.
Notice that the component would be a good candidate to write test regression against.
return { keys, values, up, down, only, getWidth }; | ||
let matched = priority | ||
.reduce((a, k) => { | ||
const media = window.matchMedia(breakpoints[k]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Well, from my point of view, taking the server-side rendering into account, we don't have much choice.
The other option is not to render the layout on the server to prevent a flash of content.
Hopefully, JSS is quite performant and that shouldn't be a real issue.
/* | ||
* This is the Base <Block /> Element | ||
*/ | ||
export default withLayout('div'); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm curious about this API decision. What's the benefit of having a Higer order Component over a component that accepts a component
property?
order = 0, | ||
offset = 0, | ||
align = 'stretch', // Cross Axis | ||
justify = 'start', // Main Axis |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that it would be better to use the defaultProps
of React over a default argument value.
That would allow us to automatically generate the documentation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would the defaultProps
have impact on the this component being pure?
md, | ||
lg, | ||
xl, | ||
...others |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
other
to be coherent with the code base.
import { createMountWithContext } from 'test/utils'; | ||
import withLayout, { styleSheet } from './with-layout'; | ||
|
||
describe('withFlex HOC', () => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
withLayout
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
naming. I am not 100% set on choosing withLayout
over withFlex
for the HOC. Care to suggest a name?
import IconButton from 'material-ui/IconButton'; | ||
import { teal, deepPurple } from 'material-ui/styles/colors'; | ||
|
||
const styleSheet = createStyleSheet('Interactive', ({ shadows, palette }) => ({ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Interactive
is in a global namespace. It would be better to scope it.
|
||
const flexOrder = () => ({ | ||
flexOrder: { order: 0 }, | ||
...generateProps((i) => ({ [`flexOrder${i}`]: { order: i } }), -20, 20), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[-20,20]
is quite a big range. Would using inline-style for this be a good approach? Or using a smaller window? I know that angular/material is using this value.
}); | ||
|
||
const boxSizing = 'border-box'; | ||
const generateFlexProps = partialRight(generateProps, [0, 20]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Again, I'm wondering about this 20
granularity, having a smaller set of possibilities could enforce having a more consistent UI.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think 12 should do it. as it is used in other grid layouts or make it configurable using theme?
cells.map((cell, i) => ( | ||
<Block {...cell} layout="row" align="center"> | ||
<IconButton accent onClick={this.setCell(i)}>delete</IconButton> | ||
<Button>{`Cell ${i + 1}`}</Button> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure we need a button here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added the button to make it a menu to set flex value to that block. I don't know if I am overdoing the demo.
{ | ||
cells.map((cell, i) => ( | ||
<Block {...cell} layout="row" align="center"> | ||
<IconButton accent onClick={this.setCell(i)}>delete</IconButton> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the sake of simplicity, I would keep a fixed number of children.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had it at 3. Then just for fun I made it dynamic.
Do we know what's going on with the commits here? |
Conflicts: src/styles/breakpoints.js
from `Interactive` on the demo also make variables coherent
@nathanmarks I think I rebased instead of merging. If it is a problem I can close this PR and resubmit |
@VanthiyaThevan You should be able to clean up on a new branch by cherry picking the relevant commits. I see you're developing directly on |
also generate property name based on type. add test for offset and order
@VanthiyaThevan Hey, I have been implementing a We have a tradeoff to make between how much things can be customized depending on the screen size and the overall CSS we inject. |
@mbrookes Thanks for the advice. I've already stated doing that. @oliviertassinari That sounds cool. I would love to see your take on this. As for the server side rendering and media query, we could incorporate |
I have a dilemma with regards to the documentation. Right now the document doesn't get generaged because the proptypes are defined inside the HOC. The solutions I came up to get around are
May be another option is make document generator to look for HOC components as well. Any suggestion is appreciated. |
@VanthiyaThevan Hey, I have started working on that |
@VanthiyaThevan Thanks a lot for your effort here 💯 . I wouldn't have been able to get #5808 out without your PR! A preview is available here. |
@oliviertassinari Can you share the source of that preview? It has the source only for specific sections. I am looking for the code to make the AppBar with menu responsive. |
@emaillenin Everything is public, it's from that PR: #5808. |
Thanks. Glad to have been able to help. This is cool. Lot simpler and a lot less classes. |
This is an initial take on layout feature heavily influenced by angular material. There are 2 components exposed here.
<Block />
Component. Works very similar to thelayout
attributes in angular materialwithLayout
HOC. which wraps any component with layout properties which gets rendered asclassName
property.Also included is the option to set layout properties for media query breakpoints.
Example use of
<Block />
component