|
| 1 | +# ADR 005: Use Box as a building block for all other components |
| 2 | + |
| 3 | +## Status |
| 4 | + |
| 5 | +Approved |
| 6 | + |
| 7 | +## Context |
| 8 | + |
| 9 | +In Primer React and consuming applications, we use many different patterns for creating React components. Two common patterns are: |
| 10 | + |
| 11 | +1. Creating components with styled-components |
| 12 | + |
| 13 | + ```tsx |
| 14 | + const Avatar = styled.img.attrs<StyledAvatarProps>(props => ({ |
| 15 | + height: props.size, |
| 16 | + width: props.size |
| 17 | + }))<StyledAvatarProps>` |
| 18 | + display: inline-block; |
| 19 | + overflow: hidden; |
| 20 | + line-height: ${get('lineHeights.condensedUltra')}; |
| 21 | + border-radius: ${props => getBorderRadius(props)}; |
| 22 | + ${sx} |
| 23 | + ` |
| 24 | + ``` |
| 25 | + |
| 26 | + [Show full code example →](https://github.com/primer/react/pull/2019/files?diff=split&w=0) |
| 27 | + |
| 28 | +2. Creating components with Box |
| 29 | + |
| 30 | + ```tsx |
| 31 | + const Avatar: React.FC<AvatarProps> = ({size = 20, alt = '', square = false, sx = {}, ...props}) => { |
| 32 | + const styles:BetterSystemStyleObject = { |
| 33 | + display: 'inline-block', |
| 34 | + overflow: 'hidden', |
| 35 | + lineHeight: 'condensedUltra', |
| 36 | + borderRadius: getBorderRadius({size, square}) |
| 37 | + } |
| 38 | +
|
| 39 | + return ( |
| 40 | + <Box |
| 41 | + as="img" |
| 42 | + alt={alt} |
| 43 | + sx={merge<BetterSystemStyleObject>(styles, sx)} // styles needs to merge with props.sx |
| 44 | + {...props} |
| 45 | + /> |
| 46 | + ) |
| 47 | + } |
| 48 | + ``` |
| 49 | + |
| 50 | + [Show full code example →](https://github.com/primer/react/pull/2019/files?diff=split&w=0) |
| 51 | + |
| 52 | + |
| 53 | + |
| 54 | +## Decision |
| 55 | + |
| 56 | +Prefer using method #2: Creating components with Box for the following reasons: |
| 57 | + |
| 58 | +- 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) |
| 59 | +- 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) |
| 60 | +- We have had issues with exporting types, we can increase confidence by keeping the exported types close to what we author. |
| 61 | + |
| 62 | +See diff for moving Avatar from approach 1 to 2: https://github.com/primer/react/pull/2019/files?diff=split&w=0 |
0 commit comments