Skip to content
Reece Adamson edited this page Mar 4, 2020 · 10 revisions

Table of Contents

Linting and Formatting

This project uses ESLint and Prettier to define, inspect and automatically correct (when possible) the style and format of source code in the repository.

Before submitting a pull request the linter should be ran and issues fixed.

The linter can be executed with: yarn lint. Some errors can be automatically corrected with yarn lint-fix

Some aspects of the style guide may not be automatically processed by these tools.

Programming Languages

All source files should use TypeScript. JavaScript files will not be accepted into the repository.

That being said, outside contributions using JavaScript are still desired and we will help convert any functionality to TypeScript!

Styling

This project uses Sass. All style sheets should use the .scss file extension and the SCSS syntax.

Style Naming

Local class names should use camelCase.

This allows styles to be accessed with dot notation cleanly and consistently.

e.g.

// Goodstyles.className// Badstyles['class-name']

See the CSS Modules README

Importing styles

CSS Module styles should be imported as styles

e.g. from Create React App docs

importReact,{Component}from'react';importstylesfrom'./Button.module.css';// Import css modules stylesheet as stylesimport'./another-stylesheet.css';// Import regular stylesheetclassButtonextendsComponent{render(){return<buttonclassName={styles.error}>ErrorButton</button>;}}

Spacing

Default spacing is 2 spaces.

Semicolons

Use semicolons to terminate statements.

Console.logs

console.error and console.warn are ok.

Debugging console.logs are not ok.

Module imports

Use a relative import if the module is located in the current or a child directory. Tests should use a relative import for the module they are testing when located in the __tests__ directory in the module. Otherwise use an absolute import.

e.g.

// GoodimportPatientfrom'./Patient'// BadimportPatientfrom'components/Patient'
// GoodimportPractitionerfrom'./doctors/Practitioner'// BadimportPractitionerfrom'components/hospital/doctors/Practitioner'
// GoodimportCombustionfrom'engine/Combustion'// BadimportEnginefrom'../engine/Combustion'
// __tests__/App.tsx// GoodimportAppfrom'../App'// BadimportAppfrom'components/App'

Strings

Template Literals are preferred.

e.g. use

constname='John'console.log(`Hi ${name}`)

not

constname='John'console.log('Hi '+name)

Prefer single quotes to double quotes.

Do not break long strings over multiple lines

// Badconstsentence=`A very long string that should not\be broken up over multiple lines`;// Goodconstsentence='A very long string that should not be broken up over multiple lines';

Default Exports

If a file exports only a single class or function, that export should be marked as default.

React Components

Individual React Components should live in their own directory.

For example a Header component:

src/
|-- components
|-- Header
|-- Header.module.scss
|-- Header.tsx
|-- index.ts
|-- __tests__
|-- Header.test.tsx
  • Header.tsx provides the React component.
  • index.ts default exports the component so that other components may include it with import components/Header
  • Header.module.scss provides the React component SASS styling

Tests for the component should be included in a __tests__ directory.

Components shall be styled using SASS.

Props

A single file may have multiple React components which need styling. Type and interface declaration names should be prefixed with the name of the ReactComponent they are associated with.

e.g.

interfaceHeaderProps{title: string;logo: string;}

index.ts

Do not define functions or classes in any index.ts files. The index.ts files are should solely be used to pull together and export functions and classes defined in other files. Example see some of the React components in this project or this example of an index.js from Material-UI

Functions vs Classes

Prefer functions over classes if the instances of the class would be ephemeral.

Always use React function components, not class components.

Types Alias vs Interface

For consistency prefer type aliases over interfaces.

Arrays

Prefer [] over `Array

// Goodletlist: number[]=[1,2,3];// Badletlist: Array<number>=[1,2,3];

Naming

Function Naming

Function names should use lower camelCase (camelCase). e.g.

functionfooBar(){}

Class Naming

Class names should use PascalCase (PascalCase). e.g.

classFoo{bar: number;bazQux(){}}

Variable Naming

Variables should use lower camelCase (camelCase). e.g.

constfooBar='baz';

Interface Naming

Use PascalCase for the name. Use camelCase for the members. e.g.

interfaceFoo{barBaz: string;}

Type Naming

Use PascalCase for the name. Use camelCase for the members. e.g.

typeFoo={barBaz: string;}

Namespace Naming

Use PascalCase for the name. e.g.

namespaceFoo{}

Yarn or NPM scripts

Use kebab-case. (e.g. lint-fix)

File Naming

A file which exports a single class should have the same name as the class it exports.

A file which exports a single function should have the same name as the function it exports.

A file which exports multiple functions, objects or primitive values shall have an all lowercase name that may include dashes (-). e.g. react-dom

JSX

Logical && vs Conditional Operator

Prefer logical && when else is not needed

e.g.

/** Good **/<div>{showTitle&&<h1>Good!<h2/>}</div>/** Good **/<div>{showTitle ? <h1>Good!<h2/> : <strong>Nice Job!<strong/>}</div>
/** Bad **/
<div>{showTitle ? <h1>Bad!<h2/> : null }</div>

Git Workflow

Before submitting a pull request to merge a feature branch into master, it should first be rebased with master. This ensures that there are no conflicts when the feature gets merged and this approach also keeps the commits linear so that it is easier to follow when reading the log.

Here's the workflow:

  1. Checkout master and pull the latest:
git checkout master git pull
  1. Checkout feature branch and rebase with master:
git checkout feature-branch
git rebase master
  1. Push changes
git push -f

Using Icons

This project uses Font Awesome Icons.

Icons should be explicitly imported.

// Goodimport{faCheck}from'@fortawesome/free-solid-svg-icons'constelement=<FontAwesomeIconicon={faCheck}/>// Badconstelement=<FontAwesomeIconicon="check"/>