3.6.0 • Published 4 years ago

@acorns/web-components v3.6.0

Weekly downloads
-
License
UNLICENSED
Repository
github
Last release
4 years ago

Web Components

Slack CircleCI Maintainability Test Coverage

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

  1. yarn install
  2. 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 }
3.6.1

4 years ago

3.6.0

4 years ago

3.5.1-0

4 years ago

3.5.0

4 years ago

3.4.0

4 years ago

3.3.0

4 years ago

3.2.0

4 years ago

1.1.0

4 years ago

3.0.0

4 years ago

1.0.0

4 years ago

2.0.0

4 years ago

0.1.40

4 years ago

0.1.39

4 years ago

0.1.38

4 years ago

0.1.37

4 years ago

0.1.36

4 years ago

0.1.35

4 years ago

0.1.34

4 years ago

0.1.33

4 years ago

0.1.32

4 years ago

0.1.31

4 years ago

0.1.28

4 years ago

0.1.27

4 years ago

0.1.26

4 years ago

0.1.25

4 years ago

0.1.24

4 years ago

0.1.23

4 years ago

0.1.22

4 years ago

0.1.21

4 years ago

0.1.20

4 years ago

0.1.19

4 years ago

0.1.18

4 years ago

0.1.17

4 years ago

0.1.16

4 years ago

0.1.15

4 years ago

0.1.14

4 years ago

0.1.13

4 years ago

0.1.12

4 years ago

0.1.11

4 years ago

0.1.10

4 years ago

0.1.9

4 years ago

0.1.8

4 years ago

0.1.7

4 years ago

0.1.6

4 years ago

0.1.5

4 years ago

0.1.4

4 years ago

0.1.3

4 years ago

0.1.2

5 years ago

0.1.1

5 years ago

0.0.59

5 years ago

0.0.58

5 years ago

0.0.57

5 years ago

0.0.56

5 years ago

0.0.55

5 years ago

0.0.54

5 years ago

0.0.53

5 years ago

0.0.52

5 years ago

0.0.51

5 years ago

0.0.50

5 years ago

0.0.49

5 years ago

0.0.48

5 years ago

0.0.47

5 years ago

0.0.46

5 years ago

0.0.45

5 years ago

0.0.44

5 years ago

0.0.43

5 years ago

0.0.42

5 years ago

0.0.41

5 years ago

0.0.40

5 years ago

0.0.39

5 years ago

0.0.38

5 years ago

0.0.37

5 years ago

0.0.36

5 years ago

0.0.35

5 years ago

0.0.34

5 years ago

0.0.33

5 years ago

0.0.32

5 years ago

0.0.31

5 years ago

0.0.30

5 years ago

0.0.29

5 years ago

0.0.28

5 years ago

0.0.27

5 years ago

0.0.26

5 years ago

0.0.25

5 years ago

0.0.24

5 years ago

0.0.23

5 years ago

0.0.22

5 years ago

0.0.21

5 years ago

0.0.20

5 years ago

0.0.19

5 years ago

0.0.18

5 years ago

0.0.17

5 years ago

0.0.16

5 years ago

0.0.15

5 years ago

0.0.14

5 years ago

0.0.13

5 years ago

0.0.12

5 years ago

0.0.11

5 years ago

0.0.10

5 years ago

0.0.9

5 years ago

0.0.8

5 years ago

0.0.7

5 years ago

0.0.6

5 years ago

0.0.5

5 years ago

0.0.4

5 years ago

0.0.3

5 years ago

0.1.0

5 years ago

0.0.2

5 years ago

0.0.1

5 years ago