Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
A simple thought experiment demonstrating concepts I'm thinking about for styling react components in javascript
import React, { Component, PropTypes } from 'react';
import { Link } from 'react-router';
import useSheet from 'react-jss';
import CloudinaryImage from './CloudinaryImage';
const Author = ({image, name}, {theme}) => {
const classes = useSheet(stylesheet, theme);
const { authorKey, bio, id, image, name, summary, urlPath } = this.props;
return (
<Link to={urlPath} className={classes.author}>
{this.renderImage()}
<div className={classes.content}>
<h2 className={classes.name}>{name}</h2>
{summary && <p className={classes.bio}>{summary}</p>}
</div>
</Link>
);
};
///
const myStylesheet = Author.stylesheet();
myStylesheet.imageWrapper.border = '1px solid pink';
<Author stylesheet={myStyleSheet} author={theAuthor} />
///
class Author extends Component {
componentWillMount () {
this.sheet = this.props.stylesheet ? retainSheet(this.props.stylesheet) : retainSheet(Author.stylesheet, this.context.theme);
this.sheet = retainSheet(this.props.stylesheet, Author.stylesheet, this.context.theme);
}
componentWillUpdate () {
this.sheet.release();
this.sheet = retainSheet(this.props.stylesheet || Author.stylesheet, this.context.theme);
}
componentWillUnmount () {
this.sheet.release();
}
getClasses () {
return this.sheet.classes;
}
renderImage () {
const classes = this.getClasses();
const { image, name } = this.props;
return (
<div className={classes.imageWrapper}>
<CloudinaryImage image={image} alt={name} options={{ width: 300, height: 300, crop: 'fill', gravity: 'face' }} className={classes.imageSource} />
</div>
);
}
render () {
const classes = this.getClasses();
const { authorKey, bio, id, image, name, summary, urlPath } = this.props;
return (
<Link to={urlPath} className={classes.author}>
{this.renderImage()}
<div className={classes.content}>
<h2 className={classes.name}>{name}</h2>
{summary && <p className={classes.bio}>{summary}</p>}
</div>
</Link>
);
}
};
Author.contextTypes = {
theme: PropTypes.object,
};
Author.propTypes = {
authorKey: PropTypes.string,
bio: PropTypes.string,
id: PropTypes.string,
image: PropTypes.object.isRequired,
name: PropTypes.string.isRequired,
urlPath: PropTypes.string.isRequired,
};
Author.stylesheet = (theme) => ({
author: {
color: 'black',
display: 'block',
padding: theme.spacing.default / 2,
'&:hover, &:focus': {
'text-decoration': 'none',
},
'&:active': {
background: 'rgba(0,0,0,0.05)',
},
},
// image
imageWrapper: {
backgroundColor: 'rgba(0,0,0,0.05)',
overflow: 'hidden',
},
imageSource: {
height: 'auto',
maxWidth: '100%',
},
// content
name: {
fontSize: theme.font.size.default,
fontWeight: 500,
margin: 0,
'&:hover, &:focus': {
'text-decoration': 'underline',
},
},
bio: {
fontSize: theme.font.size.small,
marginTop: '1em',
opacity: 0.6,
},
// Responsive
// ------------------------------
// mobile and below
[`@media (max-width: ${theme.breakpoint.mobileMax})`]: {
author: {
borderBottom: `1px solid ${theme.color.gray10}`,
borderTop: `1px solid ${theme.color.gray10}`,
display: 'inline-flex',
marginTop: -1,
},
imageWrapper: {
marginRight: theme.spacing.small,
width: 60,
},
content: {
flex: '1 0 auto',
},
},
// portrait tablet and above
[`@media (min-width: ${theme.breakpoint.tabletPortraitMin})`]: {
bio: {
overflow: 'hidden',
textOverflow: 'ellipsis',
whiteSpace: 'nowrap',
},
imageWrapper: {
height: 0,
marginBottom: theme.spacing.small,
paddingBottom: '100%',
},
},
// portrait tablet and above
[`@media (min-width: ${theme.breakpoint.tabletLandscapeMin})`]: {},
});
module.exports = useSheet(Author, styles);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.