Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
37 changes: 18 additions & 19 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@
"fs-extra": "7.0.0",
"globby": "8.0.1",
"jest": "23.5.0",
"jest-emotion": "9.2.7",
"jest-styled-components": "6.3.1",
"jscodeshift": "0.5.1",
"mdx-live": "2.0.0-alpha.2",
"next": "7.0.2",
Expand Down
27 changes: 16 additions & 11 deletions src/BorderBox.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,23 @@
import {withSystemProps} from './system-props'
import styled from 'styled-components'
import Box from './Box'
import theme from './theme'
import {BORDER} from './constants'

const BorderBox = withSystemProps(
{
is: Box,
border: 1,
borderColor: 'gray.2',
borderRadius: 1
},
['boxShadow']
)
const BorderBox = styled(Box)`
${BORDER};
`

BorderBox.defaultProps = {
theme,
border: '1px solid',
borderColor: 'gray.2',
borderRadius: 1
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These default props won't update if the consumer is using a custom theme, right? Is that a problem?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not as written, no. I think we still have to figure out what the "right" way is to do a default theme prop, if that's even a thing. 🙁

Copy link
Author

@emplums emplums Nov 20, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@shawnbot this is setting the default theme here only if the user doesn't provide one, or are you talking about something else?

@colebemis - yeah, these values won't use the provided theme value it always defaults to our theme values... though I'm not sure if that's a huge problem or not? IMO the default values should be set to values from the Primer theme, and can always be overridden if you'd like to provide your own theme by providing a value for that prop. cc @broccolini

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@emplums I think the problem with this approach is that themeGet() doesn't work with it — but I could be wrong, and maybe it will magically work the way I expect it to with styled-components? IIRC, this wasn't working last I checked:

const Blue = styled.div`
  background-color: ${themeGet('colors.blue.4')}
`

Blue.defaultProps = {theme}

// <Blue /> → no background-color

Last I remember looking at this, I suspected it was an issue with the theme not being available in context as opposed to props, but I might be totally off base. 🤔

Copy link
Author

@emplums emplums Nov 20, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah right we'd have to do it like this if we want to use themeGet since props aren't available outside the context of the component: 7e1c2c1

Doesn't feel too bad though?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fwiw this isn't working currently in primer/components anyways 😂

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I discovered something interesting... the reason this isn't working in primer/components (more accurately... the docs for primer/components) is because the theme prop for every component rendered in the docs is being overridden by the theme provided to Layout from mdx-docs... so the default is never set in any component because there is already a theme prop provided 🤦‍♀️

Two take-aways from this:

  1. We should really have some sort of clean-ish dev environment so we aren't deciphering between primer/components issues and issues due to clashes with our docs stack 😂

  2. I'd be keen to pair with you @shawnbot tomorrow to pull mdx-docs out and use your system for primer.style/design so that we're on the same page between repos and don't need to worry about theme clashes with Layout.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yay, nice detective work! I think this is a simple fix: we can just use an <MDXProvider> in place of the Layout. Let me know if that works, and we can pair if need be!

Copy link

@mannybecerra mannybecerra Nov 24, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah right we'd have to do it like this if we want to use themeGet since props aren't available outside the context of the component: 7e1c2c1

Doesn't feel too bad though?

@emplums and team, I read through this RFC PR, dig it. I apologize if you arrived at a conclusion or answer already regarding the themeGet utility, however, in the off chance that you're still exploring approaches, I have found that you can still leverage themeGet successfully in your custom Primer component when the theme provider is not defined, but the default theme prop is, as follows (ala styled-components)

...
  themeGet
} from 'styled-system'
import theme from './theme'
...
border: ${props => themeGet('borders.1'), theme.borders[1])(props)};
...
Box.defaultProps = {
  theme
}
...

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@mannybecerra ah yes! We found a bug that was preventing the defaultProps from kicking in, which is why we were having issues with themeGet. We've resolved that and now it should work swimmingly! 🙌


// spread prop types here
BorderBox.propTypes = {
...Box.propTypes
...Box.propTypes,
...BORDER.propTypes
}

export default BorderBox
17 changes: 15 additions & 2 deletions src/Box.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
import {withSystemProps, LAYOUT, COMMON} from './system-props'
import {LAYOUT, COMMON} from './constants'
import styled from 'styled-components'
import theme from './theme'

const Box = withSystemProps('div', [...LAYOUT, ...COMMON])
const Box = styled.div`
${LAYOUT} ${COMMON};
`

Box.defaultProps = {
theme
}

Box.propTypes = {
...LAYOUT.propTypes,
...COMMON.propTypes
}

export default Box
16 changes: 12 additions & 4 deletions src/Button.js
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import React from 'react'
import classnames from 'classnames'
import PropTypes from 'prop-types'
import styled from 'styled-components'
import {width} from 'styled-system'
import sass from 'sass.macro'
import {injectGlobal} from 'emotion'
import {withSystemProps, COMMON} from './system-props'
import {COMMON} from './constants'

injectGlobal(sass`
@import "primer-buttons/index.scss";
`)

function Button({is: Tag, children, size, grouped, scheme, onClick, disabled, className, ...rest}) {
function ButtonProto({is: Tag, children, size, grouped, scheme, onClick, disabled, className, ...rest}) {
const classes = classnames(
className,
'btn',
Expand All @@ -28,6 +30,10 @@ function Button({is: Tag, children, size, grouped, scheme, onClick, disabled, cl
)
}

const Button = styled(ButtonProto)`
${COMMON} ${width};
`

Button.defaultProps = {
is: 'button'
}
Expand All @@ -39,7 +45,9 @@ Button.propTypes = {
is: PropTypes.oneOfType([PropTypes.oneOf(['button', 'a', 'summary', 'input']), PropTypes.func]),
onClick: PropTypes.func,
scheme: PropTypes.string,
size: PropTypes.oneOf(['sm', 'large'])
size: PropTypes.oneOf(['sm', 'large']),
...COMMON.propTypes,
...width.propTypes
}

export default withSystemProps(Button, [...COMMON, 'width'])
export default Button
27 changes: 18 additions & 9 deletions src/Flex.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,22 @@
import {withSystemProps, FLEX_CONTAINER, COMMON, FLEX_ITEM} from './system-props'
import styled from 'styled-components'
import {display} from 'styled-system'
import theme from './theme'
import {FLEX_CONTAINER, FLEX_ITEM, COMMON} from './constants'

const Flex = withSystemProps(
{
is: 'div',
display: 'flex'
},
[...FLEX_CONTAINER, ...COMMON]
)
const Flex = styled.div`
${FLEX_CONTAINER}
${COMMON}
${display}
`
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason we use template literal syntax instead of passing the system prop functions as arguments?

const Flex = styled.div`
  ${FLEX_CONTAINER}
  ${COMMON}
  ${display}
`

// vs

const Flex = styled.div(FLEX_CONTAINER, COMMON, display)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll be honest, I prefer the latter form for components that only use system props. However, I think there's a lot of value in consistency, and if folks need to add additional styles, it should be obvious how to do that. So leaving all of the components using tagged template literals might be good for that.

OTOH: in theory, there's a performance penalty for using template literals when we don't need them. Maybe we could compile those away with a babel plugin or something? 🤔

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@colebemis @shawnbot hmm yeah honestly the only reason I left the syntax like that was because I'd previously had some CSS in there 😂 I like having consistent syntax but if there's a performance penalty then I don't think doing const Flex = styled.div(FLEX_CONTAINER, COMMON, display) is too confusing of a departure from the tagged template literal syntax

Copy link
Contributor

@mxstbr mxstbr Nov 28, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Chiming in here 👋 since I know a little bit about styled-components 🙈: our Babel plugin automatically optimizes tagged template literals under the hood for perf. For example, by default babel-preset-env (or whatever the relevant Babel plugin is that's used under the hood) would turn this component:

const Simple = styled.div`
  width: 100%;
`

into this JS:

var _templateObject = _taggedTemplateLiteral(['width: 100%;'], ['width: 100%;'])
function _taggedTemplateLiteral(strings, raw) {
  return Object.freeze(Object.defineProperties(strings, { raw: { value: Object.freeze(raw) } }))
}
var Simple = _styledComponents2.default.div(_templateObject)

which is done to be 100% spec-compliant, most of which is 100% irrelevant for writing styled components.

Our Babel plugin pre-empts that transformation and instead turns it into this much faster and smaller version ✨:

var Simple = _styledComponents2.default.div(['width: 100%;'])

You can read more about that transformation in the docs, but TL;DR: if you use the Babel plugin it's not a problem since the two forms are basically identical perf-wise, if not then... use the Babel plugin! 😉


Flex.Item = withSystemProps('div', [...FLEX_ITEM, ...COMMON])
Flex.defaultProps = {
display: 'flex',
theme
}

const FlexItem = styled.div`
${FLEX_ITEM} ${COMMON};
`
Flex.Item = FlexItem

export default Flex
4 changes: 0 additions & 4 deletions src/__tests__/BorderBox.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,6 @@ import {render} from '../utils/testing'
import {LAYOUT} from '../system-props'

describe('BorderBox', () => {
it('is a system component', () => {
expect(BorderBox.systemComponent).toEqual(true)
})

it('implements layout system props', () => {
expect(BorderBox).toImplementSystemProps(LAYOUT)
})
Expand Down
9 changes: 0 additions & 9 deletions src/__tests__/Box.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,6 @@ import {render} from '../utils/testing'
import {LAYOUT} from '../system-props'

describe('Box', () => {
it('is a system component', () => {
expect(Box.systemComponent).toEqual(true)
})

it('implements layout system props', () => {
expect(Box).toImplementSystemProps(LAYOUT)
})
Expand All @@ -35,9 +31,4 @@ describe('Box', () => {
expect(render(<Box display="none" />)).toMatchSnapshot()
expect(render(<Box display={['none', 'none', 'block']} theme={theme} />)).toMatchSnapshot()
})

it('respects position', () => {
expect(render(<Box position="absolute" />)).toMatchSnapshot()
expect(render(<Box position="relative" />)).toMatchSnapshot()
})
})
10 changes: 1 addition & 9 deletions src/__tests__/__snapshots__/Avatar.js.snap
Original file line number Diff line number Diff line change
@@ -1,14 +1,6 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP

exports[`Avatar renders default props 1`] = `
.emotion-0 {
display: inline-block;
overflow: hidden;
line-height: 1;
vertical-align: middle;
border-radius: 2px;
}

<img
alt=""
blacklist={
Expand All @@ -30,7 +22,7 @@ exports[`Avatar renders default props 1`] = `
"py",
]
}
className="emotion-0"
className="css-6rzz8m"
height={20}
width={20}
/>
Expand Down
Loading