Skip to content

Commit 4907e80

Browse files
committed
docs: add architecture docs
1 parent c34dff9 commit 4907e80

1 file changed

Lines changed: 98 additions & 0 deletions

File tree

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
# Architecture
2+
3+
This package mirrors components from `@primer/react` but optionally provides
4+
support for `sx` and `styled-system` props to a component. Only components
5+
that have downstream `sx` usage across GitHub are included in this package.
6+
7+
There are several ways a component is added to this package:
8+
9+
- A functional component
10+
- A functional component with `forwardRef`
11+
- A polymorphic functional component with `forwardRef`
12+
13+
The way we author the wrappers for these components will differ depending on
14+
what type the component is originally.
15+
16+
**A functional component**
17+
18+
```tsx
19+
import {
20+
ExampleComponent as PrimerExampleComponent,
21+
type ExampleComponentProps as PrimerExampleComponentProps,
22+
} from '@primer/react'
23+
24+
type ExampleComponentProps = PrimerExampleComponentProps & SxProp
25+
26+
function ExampleComponent(props: ExampleComponentProps) {
27+
return <Box as={PrimerExampleComponent} {...props} />
28+
}
29+
30+
export {ExampleComponent}
31+
```
32+
33+
**A functional component with `forwardRef`**
34+
35+
```tsx
36+
import {
37+
ExampleComponent as PrimerExampleComponent,
38+
type ExampleComponentProps as PrimerExampleComponentProps,
39+
} from '@primer/react'
40+
import {forwardRef} from 'react'
41+
42+
type ExampleComponentProps = PrimerExampleComponentProps & SxProp
43+
44+
const ExampleComponent = forwardRef<HTMLElement, ExampleComponentProps(function ExampleComponent(props, ref) {
45+
return <Box ref={ref} as={PrimerExampleComponent} {...props} />
46+
});
47+
48+
export {ExampleComponent}
49+
```
50+
51+
It's important that this signature matches the original component exactly,
52+
including both the type of the `ref` and props.
53+
54+
**A polymorphic functional component with `forwardRef`**
55+
56+
```tsx
57+
import {
58+
ExampleComponent as PrimerExampleComponent,
59+
type ExampleComponentProps as PrimerExampleComponentProps,
60+
} from '@primer/react'
61+
import {forwardRef} from 'react'
62+
import {PolymorphicForwardRef as ForwardRefComponent} from '../polymorphic'
63+
64+
type ExampleComponentProps = PrimerExampleComponentProps & SxProp
65+
66+
const ExampleComponent = forwardRef(function ExampleComponent(props, ref) {
67+
// @ts-expect-error the polymorphic component type is not inferred
68+
// correctly
69+
return <Box ref={ref} as={PrimerExampleComponent} {...props} />
70+
}) as ForwardRefComponent<'div', ExampleComponentProps>
71+
72+
export {ExampleComponent}
73+
```
74+
75+
## Sub-components
76+
77+
Some components will include sub-components as a part of their properties. For
78+
example, `SubNav` also includes `SubNav.Link`. When wrapping these components,
79+
it's important to also wrap the sub-components so that these accessors
80+
continue to work as expected.
81+
82+
```tsx
83+
type SubNavProps = PrimerSubNavProps & SxProp
84+
85+
const SubNavImpl = forwardRef<HTMLElement, SubNavProps>(function SubNav(props, ref) {
86+
return <Box as={PrimerSubNav} ref={ref} {...props} />
87+
})
88+
89+
type SubNavLinkProps = PrimerSubNavLinkProps & SxProp
90+
91+
const SubNavLink = forwardRef<HTMLAnchorElement, SubNavLinkProps>(function SubNavLink(props, ref) {
92+
return <Box as={PrimerSubNav.Link} ref={ref} {...props} />
93+
})
94+
95+
const SubNav = Object.assign(SubNavImpl, {
96+
Link: SubNavLink,
97+
})
98+
```

0 commit comments

Comments
 (0)