Skip to content

Instantly share code, notes, and snippets.

@pdf
Last active December 9, 2017 02:06
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pdf/a61e989d14dd3d4e57882cbb34fb0efe to your computer and use it in GitHub Desktop.
Save pdf/a61e989d14dd3d4e57882cbb34fb0efe to your computer and use it in GitHub Desktop.
Trivial implementation of a responsive grid system using Flexbox and redux-responsive
import { Flex, Box } from './flexbox.jsx';
// A basic example. Note that the number of grid columns is not fixed,
// instead you simply specify sizes as fractions (or decimals between
// 0.0 and 1.0), and the items will be sized appropriately. For example,
// the outer <Flex/> is full size at the `xs` breakpoint, 2/3 of full size
// at the `md` breakpoint, and 1/2 at `lg` or higher.
export const Basic (props) => (
<Flex xs={1} md={2 / 3} lg={1 / 2} auto >
<Box auto />
<Box xs={1} sm={1 / 3} />
</Flex>
);
import React from 'react';
import { connect } from 'react-redux';
const styles = {
flex: {
display: 'flex',
flexDirection: 'row',
flexWrap: 'wrap',
overflow: 'hidden',
},
box: {
overflow: 'hidden',
},
};
const defaultPropTypes = {
xs: React.PropTypes.number,
sm: React.PropTypes.number,
md: React.PropTypes.number,
lg: React.PropTypes.number,
xl: React.PropTypes.number,
alignContent: React.PropTypes.string,
alignItems: React.PropTypes.string,
alignSelf: React.PropTypes.string,
auto: React.PropTypes.bool,
browser: React.PropTypes.object.isRequired,
children: React.PropTypes.node,
column: React.PropTypes.bool,
justifyContent: React.PropTypes.string,
overflow: React.PropTypes.string,
noWrap: React.PropTypes.bool,
row: React.PropTypes.bool,
style: React.PropTypes.object,
};
const applyWidth = (style, width) => {
const size = `${width * 100}%`;
return Object.assign({}, style, {
flexBasis: size,
maxWidth: size,
});
};
const applyStyle = (base, props) => {
let style = Object.assign({}, base);
if (props.xs !== undefined && props.browser.lessThan.small) {
style = applyWidth(style, props.xs);
} else if (props.browser.lessThan.medium) {
if (props.sm !== undefined) {
style = applyWidth(style, props.sm);
} else if (props.xs !== undefined) {
style = applyWidth(style, props.xs);
}
} else if (props.browser.lessThan.large) {
if (props.md !== undefined) {
style = applyWidth(style, props.md);
} else if (props.sm !== undefined) {
style = applyWidth(style, props.sm);
} else if (props.xs !== undefined) {
style = applyWidth(style, props.xs);
}
} else if (props.browser.lessThan.extraLarge) {
if (props.lg !== undefined) {
style = applyWidth(style, props.lg);
} else if (props.md !== undefined) {
style = applyWidth(style, props.md);
} else if (props.sm !== undefined) {
style = applyWidth(style, props.sm);
} else if (props.xs !== undefined) {
style = applyWidth(style, props.xs);
}
} else {
if (props.xl !== undefined) {
style = applyWidth(style, props.xl);
} else if (props.lg !== undefined) {
style = applyWidth(style, props.lg);
} else if (props.md !== undefined) {
style = applyWidth(style, props.md);
} else if (props.sm !== undefined) {
style = applyWidth(style, props.sm);
} else if (props.xs !== undefined) {
style = applyWidth(style, props.xs);
}
}
if (props.auto) {
style = Object.assign({}, style, {
flex: '1 1 auto',
maxWidth: style.maxWidth ? style.maxWidth : '100%',
});
}
if (props.alignContent) {
style = Object.assign({}, style, { alignContent: props.alignContent });
}
if (props.alignItems) {
style = Object.assign({}, style, { alignItems: props.alignItems });
}
if (props.alignSelf) {
style = Object.assign({}, style, { alignSelf: props.alignSelf });
}
if (props.column) {
style = Object.assign({}, style, { flexDirection: 'column' });
}
if (props.justifyContent) {
style = Object.assign({}, style, { justifyContent: props.justifyContent });
}
if (props.noWrap) {
style = Object.assign({}, style, { flexWrap: 'nowrap' });
}
if (props.row) {
style = Object.assign({}, style, { flexDirection: 'row' });
}
if (props.overflow) {
style = Object.assign({}, style, { overflow: props.overflow });
}
return Object.assign({}, style, props.style);
};
const FlexComponent = (props) => (
<div style={applyStyle(styles.flex, props)}>{props.children}</div>
);
const BoxComponent = (props) => (
<div style={applyStyle(styles.box, props)}>{props.children}</div>
);
FlexComponent.propTypes = defaultPropTypes;
BoxComponent.propTypes = defaultPropTypes;
const mapStateToProps = (state) => ({
browser: state.get('browser'),
});
// Flex component has `display: flex`, Box component does not, otherwise they're interchangeable.
export const Flex = connect(mapStateToProps)(FlexComponent);
export const Box = connect(mapStateToProps)(BoxComponent);
import { createResponsiveStateReducer } from 'redux-responsive';
export default createResponsiveStateReducer({
extraSmall: 600,
small: 1024,
medium: 1440,
large: 1920,
extraLarge: null,
performanceMode: true,
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment