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

[Layout]: Add new Layout components #5267

Closed
wants to merge 70 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
70 commits
Select commit Hold shift + click to select a range
48700a8
[style]: Add `priority` and `isMatch`
Sep 27, 2016
65c9775
[Layout]: Add a new `Layout` components
Sep 27, 2016
460df18
[mocha]: jsdom stub `window.matchMedia` function
Sep 27, 2016
b4309bf
[Layout]: fix some of the `flex` issues
Oct 3, 2016
2f451e3
[babel] Fix plugin format
oliviertassinari Sep 28, 2016
9f72b65
[test] Improve the solution
oliviertassinari Sep 29, 2016
73e232c
[docs] Import the Related projects section from master
oliviertassinari Oct 1, 2016
93ed119
[docs] Migrate required-knowledge section from master
oliviertassinari Oct 1, 2016
8d85105
Add card component basics
nathanmarks Sep 7, 2016
a5cf000
Rebase and update docs
nathanmarks Oct 2, 2016
377755b
Fix lint error
nathanmarks Oct 2, 2016
1dc8259
Fix flow errors
nathanmarks Oct 2, 2016
4696d17
[eslint] Go deeper in the folder strucutre
oliviertassinari Oct 2, 2016
97a262b
[test] Fix the regression test suite on travis
oliviertassinari Oct 2, 2016
1b2aa01
[test] Fix the regression test suite
oliviertassinari Oct 2, 2016
d590328
[TextField] Add required prop
leMaik Sep 29, 2016
657760d
[TextField] Add a visual regression test
oliviertassinari Oct 3, 2016
2339048
[test] Run eslint on more files
oliviertassinari Oct 3, 2016
c845258
[TextField] Follow the spec more closely
oliviertassinari Oct 3, 2016
fc8d5ac
[test] Run eslint on more files
oliviertassinari Oct 3, 2016
a131435
Update jss-theme-reactor and refactor sheet ordering configuration
nathanmarks Oct 8, 2016
e954567
Quick fix for ordering bug
nathanmarks Oct 9, 2016
b34363c
[npm] Upgrade the dependencies on the next
oliviertassinari Oct 4, 2016
bb94260
[react] Remove the static keyword from getChildContext methods
oliviertassinari Oct 9, 2016
2c420b2
Use circleCI for next branch (#5366)
nathanmarks Oct 10, 2016
1799ef2
Remove unused cache folder from circle config
nathanmarks Oct 10, 2016
c1f2f21
[ListItemText] Unwrap text from object
Oct 16, 2016
31c063a
[ListItemText] Add some test for the primary and secondary fix
oliviertassinari Oct 16, 2016
6c5afff
[npm] Upgrade the dependencies
oliviertassinari Oct 16, 2016
85806b2
[npm] Upgrade the dev dependencies
oliviertassinari Oct 25, 2016
c6703ad
[docs] Add a note regarding other properties
oliviertassinari Oct 31, 2016
fac0c82
[Subheader] Migration of subheader component
pradel Sep 26, 2016
3a48889
[theme] Add ListSubheader to the list
oliviertassinari Nov 5, 2016
19d5525
[Dialog] Fix an issue with the SSR
oliviertassinari Nov 5, 2016
ec09543
Hotfix a few instances of missing rule refs
nathanmarks Nov 6, 2016
21b04a2
Remove component variable file (#5519)
nathanmarks Nov 6, 2016
bd52c19
[LinearProgress] Migration of linear-progress component (#5463)
pradel Nov 8, 2016
85722fc
[LinearProgress] Add visual regression test
oliviertassinari Nov 9, 2016
6d9894e
[npm] Upgrade the dependencies (#5530)
oliviertassinari Nov 10, 2016
16757a9
[eslint] Lint more files
oliviertassinari Nov 12, 2016
d049564
[style] Add a withStyles HoC (#5542)
oliviertassinari Nov 12, 2016
0ab76cf
[Dialog] add a paperClassName property
oliviertassinari Nov 13, 2016
5a3599d
[style] use fontWeightRegular instead of fontWeightNormal as in the spec
oliviertassinari Nov 14, 2016
0955977
[style] Iteration on the typography
oliviertassinari Nov 14, 2016
ba908ba
[npm] Upgrade the dependencies (#5598)
oliviertassinari Nov 19, 2016
4574110
[Radio] label (outer element) should be customizable via labelClassNa…
rosskevin Nov 19, 2016
5f64549
[TextField] Improve the required feature (#5599)
oliviertassinari Nov 19, 2016
4db81d9
[BottomNavigation] Migration of bottom-navigation component (#5600)
oliviertassinari Nov 19, 2016
1d38b3b
[TextField] Fix an issue on IE11
oliviertassinari Nov 19, 2016
7aa3db6
[docs] Makes it run locally on windows box (#5602)
oliviertassinari Nov 19, 2016
076a241
[docs] Improve the readability
oliviertassinari Nov 19, 2016
975671a
[TextField] Use palette.text.primary for the input color
oliviertassinari Nov 19, 2016
b2ab6b6
[Dialog] Add a DialogContentText component (#5605)
oliviertassinari Nov 21, 2016
6e23d39
[Divider] Add inset prop (#5617)
pradel Nov 22, 2016
d9f56c1
[Divider] Add visual regressions tests
pradel Nov 22, 2016
455f739
[Checkbox] Add visual regressions tests
pradel Nov 22, 2016
f77698e
[IconButton] Add visual regressions tests
pradel Nov 22, 2016
701bca9
Fix function name
pradel Nov 22, 2016
32dd850
[Docs] Add more examples to list (#5616)
pradel Nov 22, 2016
acc52de
[Tabs] Initial migration of component
newoga Aug 31, 2016
a1f0bd1
[mocha]: jsdom stub `window.matchMedia` function
Sep 27, 2016
bb414cf
[test] Run eslint on more files
oliviertassinari Oct 3, 2016
658e001
[git]: fix merge conflict
Nov 23, 2016
12c906c
[layout]: better nesting using `jss-nested`
Nov 23, 2016
fe2eb6c
[layout]: `flexNone` should be `0 0 auto`
Nov 24, 2016
7fd0af1
[Layout]: interactive demo
Nov 24, 2016
157cec5
Merge remote-tracking branch 'refs/remotes/upstream/next'
Dec 2, 2016
8c3e8c5
[Layout]: renaming to `LayoutInteractive`
Dec 2, 2016
238b670
[Layout]: fix typo
Dec 2, 2016
dbe2e25
[layout]: fix `offset` referencing `order` prop.
Dec 5, 2016
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
26 changes: 26 additions & 0 deletions docs/site/src/demos/layout/LayoutColumn.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// @flow weak

import React, { PropTypes } from 'react';
import { createStyleSheet } from 'jss-theme-reactor';
import Block from 'material-ui/Layout';
import { darkWhite, teal, deepPurple } from 'material-ui/styles/colors';

const styleSheet = createStyleSheet('LayoutColumn', () => ({
root: { height: 150, width: '50%', backgroundColor: darkWhite },
cell1: { backgroundColor: teal[300] },
cell2: { backgroundColor: deepPurple[300] },
}));

export default function LayoutColumn(props, context) {
const { root, cell1, cell2 } = context.styleManager.render(styleSheet);
return (
<Block className={root} layout="column">
<Block flex className={cell1}>First item</Block>
<Block flex="20" className={cell2}>Second item</Block>
</Block>
);
}

LayoutColumn.contextTypes = {
styleManager: PropTypes.object.isRequired,
};
178 changes: 178 additions & 0 deletions docs/site/src/demos/layout/LayoutInteractive.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
// @flow weak

import React, { Component, PropTypes } from 'react';
import { createStyleSheet } from 'jss-theme-reactor';
import Block from 'material-ui/Layout';
import { Radio, RadioGroup } from 'material-ui/Radio';
import Switch from 'material-ui/Switch';
import Text from 'material-ui/Text';
import Button from 'material-ui/Button';
import IconButton from 'material-ui/IconButton';
import { teal, deepPurple } from 'material-ui/styles/colors';

const styleSheet = createStyleSheet('LayoutInteractive', ({ shadows, palette }) => ({
root: { width: 750, backgroundColor: palette.background.paper, position: 'relative' },
add: { position: 'absolute', top: '42%', right: 0 },
demo: {
height: 300,
boxShadow: shadows[1],
},
zone: {
'& > div': {
'&:nth-child(even)': { backgroundColor: teal[300] },
'&:nth-child(odd)': { backgroundColor: deepPurple[300] },
},
},
}));

export default class Interactive extends Component {
static contextTypes = {
styleManager: PropTypes.object.isRequired,
}
state = {
block: {
direction: 'row',
justification: 'center',
alignment: 'center',
padding: false,
margin: false,
fill: false,
wrap: false,
},
cells: [{ flex: false }, { flex: false }, { flex: false }],
}
handleChange = (key) => (e, val) => {
const { block } = this.state;
this.setState({ block: { ...block, [key]: val } });
}
setCell = (idx) => () => {
const { cells } = this.state;
if (idx === undefined && cells.length < 30) {
this.setState({ cells: [...cells, { flex: false }] });
return;
}
if (cells.length > 1) {
const cellSlice = cells.slice();
cellSlice.splice(idx, 1);
this.setState({ cells: cellSlice });
}
}
render() {
const { root, add, demo, zone } = this.context.styleManager.render(styleSheet);
const {
block: { direction, justification, alignment, padding, margin, fill, wrap },
cells,
} = this.state;

return (
<Block className={root} layout="column" margin>
<Block flex="none" layout="row">
<Block flex layout="column">
<Text type="title">Direction</Text>
<RadioGroup
aria-label="Direction"
selectedValue={direction}
onChange={this.handleChange('direction')}
>
<Radio label="Row" value="row" />
<Radio label="Column" value="column" />
</RadioGroup>
</Block>
<Block flex>
<Block layout="row" align="center">
<Text type="subheading">Padding</Text>
<Switch
checked={padding}
onChange={this.handleChange('padding')}
aria-label="padding"
/>
</Block>
<Block layout="row" align="center">
<Text type="subheading">Margin</Text>
<Switch
checked={margin}
onChange={this.handleChange('margin')}
aria-label="margin"
/>
</Block>
<Block layout="row" align="center">
<Text type="subheading">Fill</Text>
<Switch
checked={fill}
onChange={this.handleChange('fill')}
aria-label="fill"
/>
</Block>
<Block layout="row" align="center">
<Text type="subheading">Wrap</Text>
<Switch
checked={wrap}
onChange={this.handleChange('wrap')}
aria-label="wrap"
/>
</Block>
</Block>
<Block flex>
<Text type="title">Justification</Text>
<RadioGroup
aria-label="Justification"
selectedValue={justification}
onChange={this.handleChange('justification')}
>
<Radio label="Start" value="start" />
<Radio label="Center" value="center" />
<Radio label="End" value="end" />
<Radio label="Space Between" value="space-between" />
<Radio label="Space Around" value="space-around" />
</RadioGroup>
</Block>
<Block flex>
<Text type="title">Alignment</Text>
<RadioGroup
aria-label="Alignment"
selectedValue={alignment}
onChange={this.handleChange('alignment')}
>
<Radio label="Start" value="start" />
<Radio label="Center" value="center" />
<Radio label="End" value="end" />
<Radio label="Stretch" value="stretch" />
</RadioGroup>
</Block>
</Block>
<Button
fab
accent
disabled={cells.length >= 30}
onClick={this.setCell()}
className={add}
>
<span className="material-icons">add</span>
</Button>
<Block flex className={demo} layout="row">
<Block
scroll
className={zone}
flex
layout={direction}
justify={justification}
align={alignment}
padding={padding}
margin={margin}
fill={fill}
wrap={wrap}
>
{
cells.map((cell, i) => (
<Block {...cell} layout="row" align="center">
<IconButton accent onClick={this.setCell(i)}>delete</IconButton>
<Button>{`Cell ${i + 1}`}</Button>
</Block>
))
}
</Block>
</Block>
</Block>
);
}
}
26 changes: 26 additions & 0 deletions docs/site/src/demos/layout/LayoutRow.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
// @flow weak

import React, { PropTypes } from 'react';
import { createStyleSheet } from 'jss-theme-reactor';
import Block from 'material-ui/Layout';
import { darkWhite, teal, deepPurple } from 'material-ui/styles/colors';

const styleSheet = createStyleSheet('LayoutRow', () => ({
root: { height: 150, width: '50%', backgroundColor: darkWhite },
cell1: { backgroundColor: teal[300] },
cell2: { backgroundColor: deepPurple[300] },
}));

export default function LayoutRow(props, context) {
const { root, cell1, cell2 } = context.styleManager.render(styleSheet);
return (
<Block className={root} layout="row">
<Block className={cell1} flex>First item</Block>
<Block className={cell2} flex="20">Second item</Block>
</Block>
);
}

LayoutRow.contextTypes = {
styleManager: PropTypes.object.isRequired,
};
17 changes: 17 additions & 0 deletions docs/site/src/demos/layout/layout.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# Layout

Layout is based on [flexbox](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Flexible_Box_Layout/Using_CSS_flexible_boxes) and inspired by [angular material](https://material.angularjs.org/latest/layout/introduction)


## Row layout

{{demo='demos/layout/LayoutRow.js'}}

## Column layout

{{demo='demos/layout/LayoutColumn.js'}}


## Play

{{demo='demos/layout/LayoutInteractive.js'}}
7 changes: 7 additions & 0 deletions src/Layout/Block.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// @flow weak
import withLayout from './with-layout';

/*
* This is the Base <Block /> Element
*/
export default withLayout('div');
Copy link
Member

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?

126 changes: 126 additions & 0 deletions src/Layout/Block.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
// @flow weak
/* eslint-env mocha */
/* eslint react/prop-types: off */
import React from 'react';
import { assert } from 'chai';
import { createShallowWithContext, createMountWithContext } from 'test/utils';
import Block from './Block';
import { styleSheet } from './with-layout';

describe('<Block /> component', () => {
let shallow;
let mount;
let classes;
before(() => {
shallow = createShallowWithContext();
mount = createMountWithContext();
classes = shallow.context.styleManager.render(styleSheet);
});
it('Renders a div', () => {
const wrapper = shallow(<Block />);
assert.isTrue(wrapper.is('div'), 'should be a div');
});

it('should render with layout classes', () => {
const wrapper = shallow(<Block layout="row" />);
const className = wrapper.prop('className');
assert.isOk(className, 'should have className prop');
const classNames = className.split(' ');
const expected = [
classes.layoutRow,
classes.alignStretch,
classes.justifyStart,
];
assert.sameMembers(classNames, expected, `should have className prop be ${expected.join(' ')}`);
});
it('should create layout algin and justify property', () => {
const wrapper = shallow(
<Block
layout="row"
fill
align="start"
justify="start"
/>,
);
const className = wrapper.prop('className');
assert.isOk(className, 'should have className prop');
const classNames = className.split(' ');
const expected = [
classes.layoutRow,
classes.layoutFill,
classes.justifyStart,
classes.alignStart,
];
assert.sameMembers(classNames, expected, `should have className prop be ${expected.join(' ')}`);
});

it('should render child component.', () => {
const wrapper = shallow(<Block layout="row"><span>Hello</span></Block>);
assert.isTrue(wrapper.childAt(0).is('span'), 'should be a `span`');
});

it('should include the existing className', () => {
const wrapper = shallow(<Block className="someClass" layout="row"><span>Hello</span></Block>);
const className = wrapper.prop('className');
assert.isOk(className, 'should have className prop');
assert.include(className, 'someClass', '`someClass` class name be part of `className` prop');
});

describe('flex props', () => {
let wrapper;
before(() => {
wrapper = mount(
<Block layout="row">
<Block flex>just flex</Block>
<Block flex={33}>flex 33%</Block>
<Block flex={50}>flex 50%</Block>
<Block flex="none">flex none</Block>
<Block flex="grow">flex none</Block>
<Block flex order={3}>flex none</Block>
<Block flex order={-10}>flex none</Block>
<Block flex offset={2}>flex none</Block>
</Block>,
);
});
it('should have .flex class', () => {
const actual = wrapper.childAt(0).find('div').prop('className');
const expected = classes.flex;
assert.strictEqual(actual, expected);
});
it('should have .flex33 class', () => {
const actual = wrapper.childAt(1).find('div').prop('className');
const expected = classes.flex33;
assert.strictEqual(actual, expected);
});
it('should have .flex50 class', () => {
const actual = wrapper.childAt(2).find('div').prop('className');
const expected = classes.flex50;
assert.strictEqual(actual, expected);
});
it('should have .flexNone class', () => {
const actual = wrapper.childAt(3).find('div').prop('className');
const expected = classes.flexNone;
assert.strictEqual(actual, expected);
});
it('should have .flexGrow class', () => {
const actual = wrapper.childAt(4).find('div').prop('className');
const expected = classes.flexGrow;
assert.strictEqual(actual, expected);
});
it('should have .flexOrder3 class', () => {
const actual = wrapper.childAt(5).find('div').prop('className');
const expected = classes.flexOrder3;
assert.include(actual, expected);
});
it('should have .flexOrder-10 class', () => {
const actual = wrapper.childAt(6).find('div').prop('className');
const expected = classes['flexOrder-10'];
assert.include(actual, expected);
});
it('should have .flexOffset2 class', () => {
const actual = wrapper.childAt(7).find('div').prop('className');
const expected = classes.flexOffset2;
assert.include(actual, expected);
});
});
});
5 changes: 5 additions & 0 deletions src/Layout/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
/* eslint-disable flowtype/require-valid-file-annotation */

export default from './Block';
export Block from './Block';
export withLayout from './with-layout';
Loading