Skip to content

Development Guidelines

Jenna Badanowski edited this page Mar 22, 2019 · 8 revisions

Authoring a new component

The workflow to implement a new component or modify an existing component.

Developer

  • Create a new branch feature/ISSUE_NUMBER
  • Develop component template and SASS as a standalone component
  • Follow development guidelines around BEM structure and SASS
  • Test in multiple browsers with no CSS dependencies and with common libs like Bootstrap
  • Create PR to branch master
  • Assign for code review

Code Reviewer

  • Review code against guidelines
  • Perfunctory visual review of branch feature/ISSUE_NUMBER

If approved continue ⤵︎, else send back to Developer ⤴︎

  • Assign for design review

Design Reviewer

  • Thorough visual review in branch feature/ISSUE_NUMBER. See test/README to get started.

If approved continue ⤵︎, else send back to Developer ⤴︎

Developer or Scrum Master

  • Merge PR to master and delete the feature branch
  • Close the issue

Component data structures

When developing a component, we must always consider that the data determines everything about what you see on the screen. There are flavors of data which can be characterized as 1) presentation, 2) content, and 3) interactivity or state.

To maintain consistency across all components, each has a constructor that accepts a standard data object separated by concerns.

A basic example ...

modifier: {
  block: []
},
properties: {},
state: {},
aria: {}

Let's look at each in more detail.

modifier

To separate presentation from content, the modifier object holds all the variants needed for a single component.

  • Use modifier.block to apply modifiers to the block/root, e.g., block: ["vertical"] would output the class tn-card--vertical for a card.
  • Use additional keys to apply modifiers to component elements, e.g., image: ["circle"] would output tn-card__image--circle.

The component templates can accept either a string or an array.

properties

This object is only about content data such as titles, descriptions, urls, etc. The properties of each component will be customized but the names should match element names in the HTML and CSS as closely as possible. For example, properties.title: "Card Title" should have a corresponding HTML representation such as <h1 class="tn-card__title">Card Title</h1>.

Always try to use a common vocabulary across components. Be descriptive of usage not visual representation, i.e., favor header, body, footer over top, middle, bottom.

state

This is the interactivity part of the component. Options like disabled, readonly, status will be common. States are most often output as is- classes that can be toggled by page scripts based on certain behaviors, i.e., disabled: true results in <button class="tn-button is-disabled"></button> where the CSS selector .tn-button.is-disabled tightly binds the styles.

NOTE: These state classes are the primary contract between UI and back-end. Angular developers should not need to worry about modifier classes, they should learn to toggle is- classes and [aria-] attributes. Keeps things simple and clean.

aria

Very similar to state these indicate interactivity. In most cases, these mirror state classes, however, ARIA is preferred for accessibility advantages. Additionally, roles can be set for some components, e.g., role="button" when using a non-button element like a div.

ARIA and states classes are both included for convenience. In the CSS, these are usually together such as .tn-button.is-disabled, .tn-button[aria-disabled=true] ensuring they do the same thing.

classes

Passing additional classes should also be considered when building a new component. Helper classes are a good example when a "one-off" presentation override is needed but not worth creating a new modifier, like adding a background color to an identifier. <div class="fd-identifier fd-has-background-color-accent-1">.

Clone this wiki locally