@acorns/web-components v3.6.0
Web Components
Web components is a library of React components that were originally used to build Acorn's A3 web app. The components were split out into a standalone repo to enable different teams and apps to consume the same components for ease of development and retention of the original A3 look and feel.
Quick Start
yarn install
yarn storybook
Help
Ask someone in the #web Slack channel!
Authoring a New Component
In web-components
, every component should be 100% strongly typed and any
's should not be used unless there is a definitive need for them.
We're also adopting the philosophy of only typing out your code when necessary. A lot of the time, TypeScript can implicitly
determine the shape of your data, and in those cases, we'll avoid explicitly providing types to keep our code from being overly verbose.
In addition, since this is a library that will be consumed by multiple clients, it has to be rock solid so each component should be thorougly covered by tests. Specifically:
- A
jest
unit test for any logic that exists within the component.- Oftentimes, the test will just ensure that a handler gets called
- A Storybook story
- This will, in turn, autogenerate a text snapshot and an image screenshot
- It is the developer's responsibility to go through the diffs if these snapshots and screenshots cause a test to fail. DO NOT JUST UPDATE THEM WITHOUT KNOWING WHY THE TESTS FAIL.
Create a New Folder and File For Your Component
In this example, we'll create an Example
component, so start with create the Example
folder inside of src
where all components live. Create an index.tsx
file within the Example
folder
web-components/
├── src/
│ ├── Button
│ ├── Example // Our new folder
│ │ └── index.tsx
│ ├── FadeIn
│ └── ...
├── stories/
│ ├── __image_snapshots__
│ ├── __snapshots__
│ ├── Button.stories.tsx
│ └── ...
└──
Define Props
By convention, Props
should be at the top of your component's file, after all the imports
. These props should be exported for consumers of the library to use. Due to some technical limitations, they'll have to be exported in the following way.
import React from 'react'
...
export type ExampleProps = Props
type Props = {
someData: string
}
By convention, your components props should be named Props
and when exported, they should be named <ComponentName>Props
. Props
represent all the data your component will accept externally and also what data is needed to get it to get it working. If using recompose
, Props
will serve as your OuterProps
.
Next, style your component accordingly using styled-components
. For colors, breakpoints, etc refer to our theme
file. Avoid creating your own colors and try to use predefined theme colors whenever possible. Also, be sure to import styled
from our utils
folder as it's setup to be strongly typed in accordance with our theme file.
import styled from 'utils/styling/styled-components'
const Container = styled.div`
background-color: ${props => props.theme.colors.green};
`
If your component's styles require knowledge of props, you will need to pass in props as a generic like so:
const Container = styled.div<Partial<Props>>`
background-color: ${props => props.theme.colors.green};
opacity: ${props => props.someData ? 1 : 0};
`
Adding Logic Through Recompose
This step is optional and most of the time, it won't be necessary, however if you find yourself needing to use recompose
follow these guidelines for typing.
As mentioned before Props
is already defined and should be used to define your component's outer props. For all data that your component needs to function but shouldn't be exposed to the consumer, store them in InnerProps
. For typing handlers, you should create a HandlerProp
type and have that be a subset of InnerProp
. When all put together, it should look something like this:
type Props = {
someData: string
}
type InnerProps = {
secretData: number
} & HandlerProps
type HandlerProps = {
handleChange: (e: React.ChangeEvent<HTMLInputElement>) => void
}
const enhance = compose<InnerProps, Props>(
defaultProps<Partial<InnerProps>>({
secretData: 42,
})
withHandlers<InnerProps, HandlerProps>({
handleChange: () => e => console.log(e.currentTarget.value)
})
)
Write JSX, Export, and Done!
If your component doesn't leverage recompose
, you'll have to type it as a React.SFC<Props>
. For ex:
const Example: React.SFC<Props> = props => <Container value={props.someData} />
If your component does leverage recompose
, you won't need to specify types since you've already typed the enhance
function.
// When destructuring variables, make sure they're alphabetized.
const Example = enhance(({ handleChange, secretData, someData }) => (
<Container onChange={onChange} placeholder={secreteData} value={someData} />
))
Lastly, just export it and you're good to go! (Avoid default exports)
export { Example }
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago
5 years ago