-
Notifications
You must be signed in to change notification settings - Fork 616
[Accepted] ADR: Use Box + sx to author components #2020
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 all commits
2f93670
3514352
913d99f
619f7f2
191315f
72fa0db
b01cf7b
a591c25
67586e8
c40fb77
323d78c
845e32a
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 |
---|---|---|
@@ -0,0 +1,62 @@ | ||
# ADR 005: Use Box as a building block for all other components | ||
|
||
## Status | ||
|
||
Approved | ||
|
||
## Context | ||
|
||
In Primer React and consuming applications, we use many different patterns for creating React components. Two common patterns are: | ||
|
||
1. Creating components with styled-components | ||
|
||
```tsx | ||
const Avatar = styled.img.attrs<StyledAvatarProps>(props => ({ | ||
height: props.size, | ||
width: props.size | ||
}))<StyledAvatarProps>` | ||
display: inline-block; | ||
overflow: hidden; | ||
line-height: ${get('lineHeights.condensedUltra')}; | ||
border-radius: ${props => getBorderRadius(props)}; | ||
${sx} | ||
` | ||
``` | ||
|
||
[Show full code example →](https://github.com/primer/react/pull/2019/files?diff=split&w=0) | ||
|
||
2. Creating components with Box | ||
|
||
```tsx | ||
const Avatar: React.FC<AvatarProps> = ({size = 20, alt = '', square = false, sx = {}, ...props}) => { | ||
const styles:BetterSystemStyleObject = { | ||
display: 'inline-block', | ||
overflow: 'hidden', | ||
lineHeight: 'condensedUltra', | ||
borderRadius: getBorderRadius({size, square}) | ||
} | ||
|
||
return ( | ||
<Box | ||
as="img" | ||
alt={alt} | ||
sx={merge<BetterSystemStyleObject>(styles, sx)} // styles needs to merge with props.sx | ||
{...props} | ||
/> | ||
) | ||
} | ||
``` | ||
|
||
[Show full code example →](https://github.com/primer/react/pull/2019/files?diff=split&w=0) | ||
|
||
| ||
|
||
## Decision | ||
|
||
Prefer using method #2: Creating components with Box for the following reasons: | ||
|
||
- Better authoring experience with Typescript. With Box, we can improve the API and autocomplete for consuming primitives. [See research](https://github.com/github/primer/discussions/755#discussioncomment-2318144) | ||
- The styling library (i.e. styled-components) becomes an implementation detail and can be changed later with minimal breaking changes for consumers. (Avoids leaky abstractions) | ||
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. In what cases what 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 want to say that if you're using primer primitives, then Box + sx is always recommended over styled-components. @colebemis are there any use cases where this wouldn't be true? There is a slight syntax difference between string with styled-components and an object with Box, which can be a tradeoff in developer experience. The planned improvements with Box should make that tradeoff easy to make though. 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 there's anything you can do with styled-components that you can't do with Box + sx. Styled-components has a slightly more convenient API in some cases but it comes with the tradeoffs you listed in this ADR 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. Could the additional runtime overheads to using Box + sx be highlighted in this ADR as a known risk? Particularly as we're recommending authors use the costlier implementation approach at this 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. @siddharthkp @colebemis related to
Should Primer expose a replacement for the styled-components built in version of This might enable applications that are "all in" on using primer primitives for styling, and allow for things like an eslint plugin that bans internal usage of styled-components directly, directing consumers to the primer-based alternatives? 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 like that idea 🤔 Just to make sure, could this result in multiple versions of styled-components on the page because of version mismatch? 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. As long as it's still just a peer of primer I don't think there's any risk of multiple versions for sc. I think that the only limit on styled components be via an eslint rule saying, use box and ..... Instead of using styled components directly, which should provide a nice way to nudge other sc usage towards primer apis |
||
- We have had issues with exporting types, we can increase confidence by keeping the exported types close to what we author. | ||
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 you expand on the issues we've had with exporting types? 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. sorry for my lazy phrasing here 😅 What I'm trying to convey here is that
I feel more confident having more control over what we export + keeping it as flat as possible. Types deserves an ADR of it's own, to be honest. 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 it be useful to amend the ADR to include some of these additional details for context, either now or in a follow-up PR? 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. Going to create a new ADR for types (in new PR), there's more to discuss there because we don't have a standard way right now to propose :) |
||
|
||
See diff for moving Avatar from approach 1 to 2: https://github.com/primer/react/pull/2019/files?diff=split&w=0 |
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.
Ah, this is good to know...I am building new components in dotcom right now, but I suppose if we wanted them upstreamed into Primer React, it would make more sense to follow this guidance!
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'd recommend using the same method in dotcom as well.
We want to improve the way product specific React components can consume primer primitives and those improvements will ship in Box. (more here)
Also, replacing styled-components with a more performant styling framework is on our radar, although not soon.