-
Notifications
You must be signed in to change notification settings - Fork 622
Refactor StateLabel 🚀 #311
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
Changes from 24 commits
6f97674
7c463cf
0e68ae2
5141166
372a2d1
2d8cd2b
97a3f23
13006a2
71db707
3b3b7cd
0b46f6f
eb3964b
639fae9
b9d8010
b10cdaa
efa0421
a489821
035f725
8944d90
ca89f3d
6dd5c26
cebe780
49d60c7
16597f5
e400c6e
aac775e
721c420
bc20ec8
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,38 +1,50 @@ | ||
import React from 'react' | ||
import PropTypes from 'prop-types' | ||
import classnames from 'classnames' | ||
import sass from 'sass.macro' | ||
import {injectGlobal} from 'emotion' | ||
import {color} from 'styled-system' | ||
import styled from 'react-emotion' | ||
import {withSystemProps} from './system-props' | ||
import theme, {colors} from './theme' | ||
|
||
injectGlobal(sass` | ||
@import "primer-support/index.scss"; | ||
@import "primer-labels/lib/labels.scss"; | ||
`) | ||
const sizeMap = { | ||
small: `padding 0.125em ${theme.space[1]}px; font-size: ${theme.fontSizes[0]}px;`, | ||
medium: `padding: 3px ${theme.space[1]}px; font-size: ${theme.fontSizes[0]}px;`, | ||
large: `padding: 4px ${theme.space[2]}px; ${theme.fontSizes[1]}px;`, | ||
xl: `padding: ${theme.space[1]}px; ${theme.space[2]}px; ${theme.fontSizes[2]}px;` | ||
} | ||
|
||
const outlineStyles = ` | ||
margin-top: -1px; // offsets the 1px border | ||
margin-bottom: -1px; // offsets the 1px border | ||
font-weight: 400; | ||
color: ${colors.gray[6]}; | ||
background-color: transparent; | ||
border: ${theme.borders[1]} ${colors.blackfade15}; | ||
box-shadow: none; | ||
` | ||
|
||
const colorScheme = (scheme, outline) => { | ||
if (outline) { | ||
return { | ||
'Label--outline-green': scheme === 'green' | ||
} | ||
} else { | ||
return { | ||
'Label--gray': scheme == null || scheme === 'gray', | ||
'Label--gray-darker': scheme === 'gray-darker', | ||
'Label--orange': scheme === 'orange', | ||
'bg-green': scheme === 'green' | ||
} | ||
const styledLabel = styled('span')` | ||
display: inline-block; | ||
font-weight: 600; | ||
line-height: ${theme.lineHeights.condensedUltra}; | ||
color: ${colors.white}; | ||
border-radius: 2px; | ||
&:hover { | ||
text-decoration: none; | ||
} | ||
} | ||
${color} //eslint-disable-line | ||
${props => (props.dropshadow ? 'box-shadow: inset 0 -1px 0 rgba(27, 31, 35, 0.12)' : '')}; | ||
${props => sizeMap[props.size]}; | ||
${props => (props.outline ? outlineStyles : '')}; // must be last to override other values | ||
` | ||
|
||
function Label({className, outline, scheme, ...rest}) { | ||
const classes = classnames(className, 'Label', outline && 'Label--outline', colorScheme(scheme, outline)) | ||
return <span className={classes} {...rest} /> | ||
styledLabel.defaultProps = { | ||
theme, | ||
bg: 'gray.5', | ||
size: 'medium' | ||
} | ||
|
||
Label.propTypes = { | ||
outline: PropTypes.bool, | ||
scheme: PropTypes.oneOf(['gray', 'gray-darker', 'green', 'orange']) | ||
styledLabel.propTypes = { | ||
dropshadow: PropTypes.bool, | ||
outline: PropTypes.bool | ||
} | ||
|
||
export default withSystemProps(Label, ['space']) | ||
export default withSystemProps(styledLabel, ['space']) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,83 +1,56 @@ | ||
import React from 'react' | ||
import PropTypes from 'prop-types' | ||
import Octicon, {GitMerge, IssueClosed, IssueOpened, IssueReopened} from '@githubprimer/octicons-react' | ||
import classnames from 'classnames' | ||
import sass from 'sass.macro' | ||
import {injectGlobal} from 'emotion' | ||
import {colors} from './theme' | ||
import styled from 'react-emotion' | ||
import {GitMerge, GitPullRequest, IssueClosed, IssueOpened} from '@githubprimer/octicons-react' | ||
import theme, {colors} from './theme' | ||
import {withSystemProps, COMMON} from './system-props' | ||
|
||
injectGlobal(sass` | ||
@import "primer-support/index.scss"; | ||
@import "primer-labels/lib/states.scss"; | ||
`) | ||
|
||
const stateColorMap = { | ||
open: 'green', | ||
opened: 'green', | ||
reopened: 'green', | ||
closed: 'red', | ||
merged: 'purple' | ||
import Octicon from './Octicon' | ||
|
||
const schemeMap = { | ||
issueClosed: colors.red[6], | ||
pullClosed: colors.red[6], | ||
pullMerged: colors.purple[5], | ||
issueOpened: '#2cbe4e', // This was generated by a sass function in Primer, so using a hex here | ||
pullOpened: '#2cbe4e', // This was generated by a sass function in Primer, so using a hex here | ||
gray: colors.gray[5] | ||
} | ||
|
||
const stateOcticonMap = { | ||
open: IssueOpened, | ||
opened: IssueOpened, | ||
reopened: IssueReopened, | ||
closed: IssueClosed, | ||
merged: GitMerge | ||
const octiconMap = { | ||
issueOpened: IssueOpened, | ||
pullOpened: GitPullRequest, | ||
issueClosed: IssueClosed, | ||
pullClosed: GitPullRequest, | ||
pullMerged: GitMerge | ||
} | ||
|
||
function getOcticon(state) { | ||
if (!state) { | ||
return null | ||
} | ||
return <Octicon icon={stateOcticonMap[state]} /> | ||
} | ||
|
||
function getIconComponent(icon, children) { | ||
if (icon && children) { | ||
return <span className="mr-1">{icon}</span> | ||
} else if (icon) { | ||
return <span className="d-flex m-1">{icon}</span> | ||
} | ||
return null | ||
} | ||
|
||
function StateLabel({state, className, scheme, icon, small, children}) { | ||
if (icon !== false) { | ||
icon = icon || getOcticon(state) | ||
} | ||
|
||
const color = scheme || stateColorMap[state] | ||
const styleProps = {} | ||
if (color === 'yellow') { | ||
styleProps.style = {backgroundColor: colors.yellow[7]} | ||
} | ||
const iconComponent = getIconComponent(icon, children) | ||
const classes = classnames( | ||
className, | ||
'State', | ||
{ | ||
'State--small': small | ||
}, | ||
color && color !== 'yellow' ? `State--${color}` : null | ||
) | ||
const getOcticon = (scheme, small) => | ||
small ? <Octicon mr={1} width="1em" icon={octiconMap[scheme]} /> : <Octicon mr={1} icon={octiconMap[scheme]} /> | ||
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. This smells funky to me since all it's actually varying is the <Octicon icon={octiconMap[scheme]} mr={1} width={small ? '1em' : null} /> 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. No, because setting the 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. Oof. Maybe something like this? 😬 const octiconProps = small ? {width: '1em'} : {}
// ...
<Octicon mr={1} icon={octiconMap[scheme]} {...octiconProps} /> |
||
|
||
function StateLabel({className, scheme, small = false, children}) { | ||
return ( | ||
<span className={classes} {...styleProps}> | ||
{iconComponent} | ||
<span className={className}> | ||
{scheme && getOcticon(scheme, small)} | ||
{children} | ||
</span> | ||
) | ||
} | ||
|
||
const styledLabel = styled(StateLabel)` | ||
display: inline-flex; | ||
align-items: center; | ||
padding: ${props => (props.small ? `0.125em ${theme.space[1]}px` : `${theme.space[1]}px ${theme.space[2]}px`)}; | ||
font-weight: 600; | ||
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. If we have 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. We could, but it's not defined yet - I can add it in, what font weights should we use? 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. Agreed: we should add 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. I don't think we want fontWeight to be a prop on this component, but yeah I agree we should add font weight to our theme! We can do that as a follow up, and replace any other instances at that time. 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. Ah, so maybe: |
||
line-height: 20px; | ||
color: ${colors.white}; | ||
font-size: ${props => (props.small ? `${theme.fontSizes[0]}px` : `${theme.fontSizes[1]}px`)}; | ||
text-align: center; | ||
background-color: ${props => (props.scheme ? schemeMap[props.scheme] : schemeMap.gray)}; | ||
border-radius: ${theme.radii[1]}px; | ||
` | ||
|
||
StateLabel.propTypes = { | ||
children: PropTypes.node, | ||
icon: PropTypes.oneOfType([PropTypes.node, PropTypes.bool]), | ||
scheme: PropTypes.string, | ||
small: PropTypes.bool, | ||
state: PropTypes.oneOf(Object.keys(stateOcticonMap)) | ||
scheme: PropTypes.oneOf(['issueOpened', 'pullOpened', 'issueClosed', 'pullClosed', 'pullMerged']), | ||
small: PropTypes.bool | ||
} | ||
|
||
export default withSystemProps(StateLabel, COMMON) | ||
export default withSystemProps(styledLabel, COMMON) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
// Jest Snapshot v1, https://goo.gl/fbAQLP | ||
|
||
exports[`Label respects the "outline" prop 1`] = ` | ||
.emotion-0 { | ||
display: inline-block; | ||
font-weight: 600; | ||
line-height: 1; | ||
color: #fff; | ||
border-radius: 2px; | ||
background-color: #6a737d; | ||
margin-top: -1px; | ||
margin-bottom: -1px; | ||
font-weight: 400; | ||
color: #586069; | ||
background-color: transparent; | ||
border: 1px solid rgba(27,31,35,0.15); | ||
box-shadow: none; | ||
padding: 3px 4px; | ||
font-size: 12px; | ||
} | ||
|
||
.emotion-0:hover { | ||
-webkit-text-decoration: none; | ||
text-decoration: none; | ||
} | ||
|
||
<span | ||
className="emotion-0" | ||
size="medium" | ||
/> | ||
`; |
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 to put this here in order to get eslint to shut up about this being on it's own line 😭
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.
That's crazy. What if you put a semicolon at the end?