Skip to content

Frontend Standards

General

  • No commented out code
  • Avoid magic numbers
  • Avoid inline css
  • Always look to the design system for guidance
  • Mobile first CSS
  • Think accessibly

HTML

  • Prefer semantic tags whenever possible
  • Always use self closing tags where possible
  • New line for each attribute if more than 1
  • 2 spaces per indent
  • Inner contents of a tag should be on a new line

CSS

  • Prefer css variables whenever possible
  • Use postcss for css tools like nesting & browser compatibility
  • Use CSS Modules for scoping, and scope to a $s . CSS modules is preferable to scoped because it doesn’t change the selection strength, and is more robustly scoped.
vue
<div class="$s.my-component">
...
<style module="$s">
  • Always use design system variables instead of hardcoding values for things like color, spacing, etc
  • ❗️Never override the styles of a UI component from the design system. Instead, raise the issue to design or an architect so that it can be addressed in the design system.
  • Use a combination of BEM and Suitcss
css
.card {}
.card__header {}
.card__header-title {}

/* Create new classes for modifiers. These do not override styles,
but rather define them differently */
.button--variant-primary {}
.button--variant-secondary {}
.button--variant-muted {}

/* Create override classes for states */
.button.disabled {}
.button.loading {}
.button.error {}
  • use kebab case in your classes
  • use __ to separate elements
  • use - to separate sub elements
  • use -- to separate modifiers
  • use boolean guidelines for naming states and nest them under the selector they’re affecting
  • prefix modifiers if that modifier has several options
/* Bad */
.my-component--primary {}
.my-component--secondary {}
.my-component--small {}
.my-component--large {}

/* Good */
.my-component--variant-primary {}
.my-component--variant-secondary {}
.my-component--size-small {}
.my-component--size-large {}

Javascript

When used all together, these rules allow you to write very concise code that is self documenting

  • Use clear function names like submitForm() vs handleClick()
  • Use clear variable names like elementHeight vs h
  • If comments feel necessary, look to the function or variable names to see if they can be made more clear first
  • Booleans should be affirmative and singular if possible or begin with is or has
javascript
// Bad
notEnabled
isFullwidth
labelPresent

// Good
disabled
fullwidth // doesn't need an "is-" to make sense
hasLabel
  • Use arrow functions over for loops
  • Include only one return per function
  • Use ternary operators whenever possible, if it does not add complexity (avoid nested ternary operators or complex boolean logic)
javascript
// Bad
if (someBool) {
  resultString = 'foo'
} else {
  resultString = 'bar'
}

// Good
resultString = someBool ? 'foo' : 'bar'
  • Use template literals to do string concatenation
javascript
// Bad
return prefix + 'some string' + suffix

// Good
return `${prefix} some string ${suffix}`

Vue

  • Always use single file components (SFC)
  • Group code in a SFC by concern, with all the data and methods for each functional concern together rather than grouping all data, then all computed then all methods etc
  • Use kebab case for imported components
// Bad
<CiButton />

// Good
<ci-button />
  • Prefer simple props to object props whenever possible
// Bad
<avatar options="{image: '', name: '', profileUrl: ''}" />

// Good
<avatar image="" name="" profile-url="" />
  • Prefer computed props for event propagation
// Bad
let someValue = '' as string
function updateValue() {
  someValue = newValue;
  emits('myEvent', newValue)
}

// Good
let someValueData = '' as string
const someValue = computed({
  get () {
    return someValueData;
  },
  set (val: string) {
    someValueData = val;
    emits('myEvent', val)
  }
})

function updateValue() {
  ...
  someValue.value = newValue;
}
  • Always use component class name that follows the CiComponentName naming scheme
// Bad
export default {
  name: 'Modal'
}

// Good
export default {
  name: 'CiModal'
}

Vuex

  • Only write simple mutations
  • Getters can be provided when digging into arrays/objects is necessary in multiple places
  • Prefer object of objects to array of objects, for easier getting

Components

  • Components should each have a singular concern
  • Components should be broken down into multiple components or shared helpers if they become too complex
  • A component that is universal and not specific to a feature or application should go in the design system