Adventure Product UI Style Guide


Aug 26, 2022

ACCEPTED

Peter, Ivan

#adventure-product #ui

Technical Story: PT1-117

Context and Problem Statement

As the team grows, inconsistency with how we create and use UI components has begun to sneak in. Whilst there's clearly a tolerable level and we don't want to hamper our agility, allowing a free-for-all (particularly with Peter on the team) will likely create a situation where it's harder to make substantial changes and alter conventions later.

As a result, we'll implement the attached style guide as a reference for working specifically on the adventure product frontend.

Decision Drivers

  • Growing team and need to share context/conventions in writing
  • Lack of clarity not only in which components to use when but also which library (e.g. we have both mui and styled-components)
  • Clearer framework to allow us to bring in less senior engineers

Decision Outcome

Keep a style guide (appended) in our ADRs, which we can update by superseding as necessary. This guide should not hamper innovation or experimentation and it's encouraged to find new patterns that are helpful and propose changes to supersede this document where they should be adopted.

Positive Consequences

  • Clear reference document for frontend conventions
  • Shorter time to merge with fewer changes requested
  • Happy Morgan

Negative Consequences

  • Small risk of reduced agility but should be minimal as this a guide not a rulebook

Styleguide

General

  • Always prefer arrow functions vs regular or anonymous functions
  • Always prefer named exports as opposed to default exports
  • Use the generated types whenever possible

React component skeleton

React components should adhere to the following skeleton:

import React from "react";

interface PropTypes {
  exampleProperty: string;
}

export const ExampleComponent: FC<PropTypes> = (props) => {
  const { exampleProperty } = props;

  // render
};

const SomeStyledComponent = styled.div`
  color: red;
`;

Notes from the snippet above:

  • PropTypes are defined separately in their own interface (not inlined in the component declaration)
  • PropTypes are passed to the component using FC
  • Components are always functional components
  • Any one-off customized styled components go below the component in order to not hurt readability
  • Props are destructured inside the components body (not in the param declaration), it could be useful in some cases to destructure inline but only up to two parameters

Styling

One-off customizations

One-off customizations are really specific to a usecase and they are not meant to be reused. One-off customizations are done using inline css, the sx prop on mui components or styled components

  • Rule of thumb
    • If less than 4 css properties are specified use inline css or the sx prop (less pollution of the jsx)
    • Otherwise use a styled component to override the styling

Reusable customizations

  • Customization of generic material ui components that are used across the app should be done in the theme
  • Custom defined reusable elements should be defined as react component / styled components in the shared module
  • Whenever possible, components defined from mui should be preffered as opposed to defining custom reusable component

    • Use one of the typographies variants from mui as opposed to defining custom labels with custom fonts
      • If the typography variants do not have the specific typography you need, define a custom variant in the theme, this will allow us to have finite set of typographies mapped to the theme

Spacings

  • Defined spacing in the app in the form of margins or paddings should be done using the theme spacing as opposed to custom one-off customized spacings
    • Example: padding: ${(props) => props.theme.mui.spacing(4)}; instead of padding: 30px
    • This will aid the responsiveness process in the future, as well as allowing us to have consistent spacing based on some spacing factor that we define and control