-
Notifications
You must be signed in to change notification settings - Fork 23
Add JSS example #23
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,8 @@ | ||
{ | ||
"extends": "airbnb", | ||
|
||
"rules": { | ||
"react/prop-types": 0 | ||
}, | ||
"env": { | ||
"browser": true, | ||
"mocha": true | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
{ | ||
"name": "jss-example", | ||
"version": "1.0.0", | ||
"description": "", | ||
"main": "src/index.js", | ||
"scripts": { | ||
"start": "../node_modules/.bin/webpack-dev-server --config ../webpack.base.babel.js --content-base build" | ||
}, | ||
"author": "Max Stoiber", | ||
"license": "MIT", | ||
"devDependencies": { | ||
"css-loader": "0.25.0", | ||
"jss": "5.5.4", | ||
"jss-preset-default": "0.4.0", | ||
"react-jss": "3.0.1", | ||
"style-loader": "0.13.1" | ||
}, | ||
"dependencies": {} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import React from 'react'; | ||
import useSheet from 'react-jss'; | ||
|
||
import Tweet from '../tweet'; | ||
import data from '../../../../shared/data/755481795206971392.json'; | ||
|
||
import 'normalize.css'; | ||
|
||
const styles = { | ||
// Local styles | ||
container: { | ||
margin: '0 auto', | ||
width: '100%', | ||
'@media screen and (min-width: 360px)': { | ||
maxWidth: '400px', | ||
}, | ||
'@media screen and (min-width: 600px)': { | ||
maxWidth: '600px', | ||
}, | ||
}, | ||
}; | ||
|
||
const App = (props) => ( | ||
<div className={props.sheet.classes.container}> | ||
<Tweet data={data} /> | ||
</div> | ||
); | ||
|
||
export default useSheet(App, styles); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export { default } from './app'; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import React, { PropTypes } from 'react'; | ||
import useSheet from 'react-jss'; | ||
|
||
const styles = { | ||
text: { | ||
fontSize: '1.25rem', | ||
fontWeight: '300', | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you can use a number here |
||
lineHeight: '1.5em', | ||
margin: '0', | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you can use a number here |
||
padding: '.65625rem 0 .98438rem', | ||
}, | ||
media: { | ||
borderRadius: '.35rem', | ||
border: '1px solid #e1e8ed', | ||
color: '#1da1f2', | ||
display: 'block', | ||
margin: '.65625rem 0 1.3125rem', | ||
}, | ||
image: { | ||
display: 'block', | ||
maxWidth: '100%', | ||
}, | ||
}; | ||
|
||
const Content = ({ text, media, sheet }) => ( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. same here, looks like much less repition to me if you spread the sheet and just pick classes ... you rarely need the sheet ref:
|
||
<div> | ||
<p className={sheet.classes.text} dangerouslySetInnerHTML={{ __html: text }} /> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. not sure if I need to comment on this, because not related to jss, but looks like something can be done differently ... |
||
<a className={sheet.classes.media} href={media.expanded_url}> | ||
<img className={sheet.classes.image} src={media.media_url_https} alt="" /> | ||
</a> | ||
</div> | ||
); | ||
|
||
Content.propTypes = { | ||
media: PropTypes.object, | ||
text: PropTypes.string, | ||
}; | ||
|
||
export default useSheet(Content, styles); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export { default } from './content'; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,136 @@ | ||
import React, { Component, PropTypes } from 'react'; | ||
import useSheet from 'react-jss'; | ||
|
||
import ReplyIcon from '../../../../shared/assets/reply.svg'; | ||
import RetweetIcon from '../../../../shared/assets/retweet.svg'; | ||
import LikeIcon from '../../../../shared/assets/like.svg'; | ||
import MoreIcon from '../../../../shared/assets/more.svg'; | ||
|
||
const styles = { | ||
'@keyframes liked': { | ||
'50%': { | ||
transform: 'scale(1.2)', | ||
}, | ||
'100%': { | ||
tranform: 'scale(1)', | ||
}, | ||
}, | ||
date: { | ||
paddingBottom: '.98438rem', | ||
color: '#8899a6', | ||
}, | ||
counters: { | ||
borderTop: '1px solid #e1e8ed', | ||
padding: '.98438rem 0', | ||
textTransform: 'uppercase', | ||
}, | ||
value: { | ||
fontWeight: '700', | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can be a number |
||
}, | ||
label: { | ||
color: '#8899a6', | ||
fontSize: '.85rem', | ||
}, | ||
favorite: { | ||
display: 'inline-block', | ||
marginLeft: '1.96875rem', | ||
}, | ||
actions: { | ||
alignItems: 'center', | ||
borderBottom: '1px solid #e1e8ed', | ||
borderTop: '1px solid #e1e8ed', | ||
color: '#8899a6', | ||
display: 'flex', | ||
fontSize: '1.5rem', | ||
height: '3.28125rem', | ||
width: '100%', | ||
}, | ||
icon: { | ||
display: 'flex', | ||
flexGrow: '1', | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can be a number |
||
justifyContent: 'center', | ||
textAlign: 'center', | ||
}, | ||
button: { | ||
display: 'flex', | ||
flexGrow: '1', | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can be a number |
||
justifyContent: 'center', | ||
textAlign: 'center', | ||
background: 'none', | ||
border: 'none', | ||
color: 'inherit', | ||
cursor: 'pointer', | ||
fontSize: 'inherit', | ||
outline: 'none', | ||
}, | ||
liked: { | ||
animationName: 'liked', | ||
animationDuration: '.25s', | ||
color: '#e81c4f', | ||
}, | ||
}; | ||
|
||
class Footer extends Component { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why not to use decorator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not a fan of decorators since they aren't standardized yet and rely on a legacy babel transform. 😁 See this dicussion: facebook/create-react-app#107 Specifically this part:
|
||
|
||
constructor(props) { | ||
super(props); | ||
|
||
this.state = { | ||
liked: false, | ||
}; | ||
|
||
this.handleClick = this.handleClick.bind(this); | ||
} | ||
|
||
handleClick() { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why not to use this syntax so you don't need to bind:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good idea, but need to update all examples. Will add to #24! |
||
this.setState({ | ||
liked: !this.state.liked, | ||
}); | ||
} | ||
|
||
render() { | ||
const { createdAt, favoriteCount, retweetCount, sheet } = this.props; | ||
const { liked } = this.state; | ||
|
||
return ( | ||
<div> | ||
<div className={sheet.classes.date}>{createdAt}</div> | ||
<div className={sheet.classes.counters}> | ||
<span> | ||
<span className={sheet.classes.value}>{retweetCount}</span> | ||
<span className={sheet.classes.label}> Retweets</span> | ||
</span> | ||
<span className={sheet.classes.favorite}> | ||
<span className={sheet.classes.value}> | ||
{liked ? favoriteCount + 1 : favoriteCount} | ||
</span> | ||
<span className={sheet.classes.label}> Likes</span> | ||
</span> | ||
</div> | ||
<div className={sheet.classes.actions}> | ||
<div className={sheet.classes.icon}> | ||
<ReplyIcon /> | ||
</div> | ||
<div className={sheet.classes.icon}> | ||
<RetweetIcon /> | ||
</div> | ||
<button className={sheet.classes.button} onClick={this.handleClick}> | ||
<LikeIcon className={liked && sheet.classes.liked} /> | ||
</button> | ||
<div className={sheet.classes.icon}> | ||
<MoreIcon /> | ||
</div> | ||
</div> | ||
</div> | ||
); | ||
} | ||
|
||
} | ||
|
||
Footer.propTypes = { | ||
createdAt: PropTypes.string, | ||
favoriteCount: PropTypes.number, | ||
retweetCount: PropTypes.number, | ||
}; | ||
|
||
export default useSheet(Footer, styles); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export { default } from './footer'; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
import React, { PropTypes } from 'react'; | ||
import useSheet from 'react-jss'; | ||
|
||
const styles = { | ||
header: { | ||
display: 'flex', | ||
padding: '1rem 0 .65625rem', | ||
}, | ||
profile: { | ||
flex: '1 0 0', | ||
margin: '0 .3rem', | ||
}, | ||
image: { | ||
borderRadius: '.35rem', | ||
display: 'block', | ||
width: '100%', | ||
}, | ||
user: { | ||
flex: '7 0 0', | ||
margin: '0 .3rem', | ||
}, | ||
url: { | ||
display: 'inline-block', | ||
marginTop: '-.15rem', | ||
}, | ||
name: { | ||
color: '#292f33', | ||
fontWeight: '700', | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can be a number |
||
'&:hover': { | ||
textDecoration: 'underline', | ||
}, | ||
}, | ||
screenName: { | ||
color: '#8899a6', | ||
'&:before': { | ||
content: '"\\a"', | ||
whiteSpace: 'pre', | ||
}, | ||
}, | ||
}; | ||
|
||
const Header = ({ name, profileImageUrl, screenName, url, sheet }) => ( | ||
<div className={sheet.classes.header}> | ||
<div className={sheet.classes.profile}> | ||
<a href={url}> | ||
<img className={sheet.classes.image} src={profileImageUrl} alt={name} /> | ||
</a> | ||
</div> | ||
<div className={sheet.classes.user}> | ||
<a className={sheet.classes.url} href={url}> | ||
<span className={sheet.classes.name}>{name}</span> | ||
<span className={sheet.classes.screenName}>@{screenName}</span> | ||
</a> | ||
</div> | ||
</div> | ||
); | ||
|
||
Header.propTypes = { | ||
name: PropTypes.string, | ||
profileImageUrl: PropTypes.string, | ||
screenName: PropTypes.string, | ||
url: PropTypes.string, | ||
}; | ||
|
||
export default useSheet(Header, styles); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export { default } from './header'; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
export { default } from './tweet'; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
import React, { PropTypes } from 'react'; | ||
import useSheet from 'react-jss'; | ||
|
||
import Header from '../header'; | ||
import Content from '../content'; | ||
import Footer from '../footer'; | ||
import { transform } from '../../../../shared/utils/text'; | ||
|
||
const styles = { | ||
container: { | ||
padding: '0 .6rem', | ||
}, | ||
}; | ||
|
||
const Tweet = ({ data, sheet }) => ( | ||
<div className={sheet.classes.container}> | ||
<Header | ||
name={data.user.name} | ||
profileImageUrl={data.user.profile_image_url_https} | ||
screenName={data.user.screen_name} | ||
url={data.user.url} | ||
/> | ||
<Content | ||
media={data.entities.media[0]} | ||
text={transform(data)} | ||
/> | ||
<Footer | ||
createdAt={data.created_at} | ||
favoriteCount={data.favorite_count} | ||
retweetCount={data.retweet_count} | ||
/> | ||
</div> | ||
); | ||
|
||
Tweet.propTypes = { | ||
data: PropTypes.object, | ||
}; | ||
|
||
export default useSheet(Tweet, styles); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
import React from 'react'; | ||
import { render } from 'react-dom'; | ||
import jss from 'jss'; | ||
import preset from 'jss-preset-default'; | ||
|
||
jss.setup(preset()); | ||
|
||
const globalStyles = { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. would probably put this global styles and its rendering into a separate module. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. so that this file has a focus on app setup/initialization. |
||
// Global styles | ||
html: { | ||
color: '#292f33', | ||
fontFamily: '"Helvetica Neue", Helvetica, Arial, sans-serif', | ||
fontSize: '14px', | ||
lineHeight: '1.3125', | ||
}, | ||
a: { | ||
textDecoration: 'none', | ||
color: '#1da1f2', | ||
}, | ||
svg: { | ||
fill: 'currentColor', | ||
height: '1.25em', | ||
}, | ||
'@media screen and (min-width: 360px)': { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. to show the beauty of js, you could put all media queries into a separate file and then use them like this:
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Again, would need to update for all CSS-in-JS examples – will add to #24! |
||
html: { | ||
fontSize: '15px', | ||
}, | ||
}, | ||
'@media screen and (min-width: 600px)': { | ||
html: { | ||
fontSize: '16px', | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. jss-default-unit allows us to have numeric values here as well, px is added automatically. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. there are 2 more cases of this in this sheet. |
||
}, | ||
}, | ||
}; | ||
|
||
// Attach global styles | ||
jss.createStyleSheet(globalStyles, { named: false }).attach(); | ||
|
||
import App from './components/app'; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. imports should be on top, because they are hoisted anyways ... this may lead to a wrong understanding of execution order. |
||
|
||
render(<App />, document.getElementById('example-root')); |
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.
a bit nicer notation (but really stylistic preference)