Skip to content

DEG UI Code Standards, Design Patterns, Frameworks & Tooling

Notifications You must be signed in to change notification settings

degdigital/UIEcosystem

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

71 Commits
 
 
 
 
 
 

Repository files navigation

UI Ecosystem

DEG UI Code Standards, Design Patterns, Frameworks & Tooling

Table of Contents

  1. Code Style Guide - HTML - CSS - Javascript
  2. Design Patterns & Considerations - Atomic Design - Browser Support - Accessibility - Performance - Detailed Design Patterns & Anti-Patterns
  3. Frameworks - Skeletor - Pattern Lab
  4. Libraries - DEGJS - jQuery
  5. Tooling - IDEs/Editors - CSS - Javascript - Task Runners - Visual Editors - Virtual Machines - ALM/Version Control - Continuous Integration - Testing - Reviews and Pull Requests

Code Style Guide

HTML

Formatting & Syntax

  • Use tabs (4 spaces) for indentation.

  • Nested elements should be indented once.

  • Don’t omit optional closing tags (e.g. </li> or </body>).

  • Typically there is no need to specify a type when including CSS and JavaScript files as text/css and text/javascript are their respective defaults.

  • JavaScript files should be included at the bottom of a document whenever possible.

    Bad Formatting

    <header class="header header--primary">
                <nav class="nav nav--primary">
            // ...
        </nav></header>

    Good Formatting

    <header class="header header--primary">
        <nav class="nav nav--primary">
            // ...
        </nav>
    </header>

HTML5 doctype

  • HTML5 (HTML syntax) is preferred for all HTML documents.
  • Enforce standards mode and more consistent rendering in every browser possible with this simple doctype at the beginning of every HTML page: <!DOCTYPE html>.

Semantics

  • Use semantic elements when possible. For example, use <header> elements for headers, <p> elements for paragraphs, <button> elements for buttons, etc.

  • Using HTML according to its purpose is important for accessibility, SEO, reuse, and code efficiency.

    Bad Semantics

    <div class="header header--primary">
        <div class="nav nav--primary">
            // ...
        </div>
    </div>

    Good Semantics

    <header class="header header--primary">
        <nav class="nav nav--primary">
            // ...
        </nav>
    </header>

CSS

PostCSS

  • DEG utilizes PostCSS to process CSS files and aims to write modern and future-proof CSS based on W3C specifications while avoiding the proprietary syntax of preproccesors whenever possible.
  • Skeletor comes preconfigured with our preferred out-of-the-box PostCSS plugins, but developers are encouraged to add new plugins as the need arises on a per-project basis, while keeping the overall goals of future-proof CSS in mind.

Organization

  • CSS should be organized into partials and follow DEG's modified Atomic CSS structure of Basics, Components, Templates, & Utilities. These partials will be processed using PostCSS and the available configuration options in Skeletor.

    css
    |-- basics/
    |   |-- buttons.css
    |   |-- headings.css
    |   |-- ...
    |-- components/
    |-- templates/
    |-- utilities/
    

Formatting

  • Use tabs (4 spaces) for indentation

  • Use ID selectors sparingly, if at all

  • Use classes over generic element tags when possible

  • When using multiple selectors in a rule declaration, give each selector its own line

  • Properties should be organized in the most logical order

  • When defining multiple properties, give each property its own line

    Bad Formatting

    .selector{
            property:value; property:value; }
        .selector, .selector, .selector {
            // ...
        }
        #id {
          // ...
        }

    Good Formatting

    .selector {
        property: value;
        property: value;
    }
    
    .selector,
    .selector,
    .selector {
        // ...
    }

Pseudo BEM

  • BEM is a CSS methodology and syntax, that helps achieve reusable components. BEM stands for Block Element Modifier and consists of:
    • Block: Standalone entity that is meaningful on its own.
    • Element: Parts of a block and have no standalone meaning. They are semantically tied to its block.
    • Modifier: Flags on blocks or elements. Use them to change appearance or behavior.
  • DEG's approach is to follow the general guidelines of BEM and it's syntax, though it is not strictly enforced, which is why it's referred to as Pseudo BEM here and throughout this document. For full documentation on the BEM methodology, reference the BEM website.

Variables

  • Use CSS variables for consistancy and maintainablity of styles.

  • It is recommended that you use variables for color palettes, font properties, & animation properties. Additional variables may be created on an as needed basis.

  • Namespace all variables with --property-group. Examples: --font-weight-bold and font-weight-regular.

  • Append a logical and easy to reference modifier to all variations: -modifier.

  • If a logical scale can be applied, -point-scale can be used as the modifier. If no logical scale can be applied, use logical modifiers i.e. -light.

  • Add a line break between different property group types.

  • There are no standardized guidelines for mapping variables to other variables, but it is strongly encouraged that mappings are kept consistant and easy to reference.

    Bad

    --blue: #005da8;
    --blue2: #00a0dd;
    --blue3: #acd5f8;
    --timing: .25s;
    --othertiming: 1s;

    Good: Logicial Modifiers

    --color-blue: #005da8;
    --color-blue-light: #00a0dd;
    --color-blue-dark: #acd5f8;
    
    --timing-fast: .25s;
    --timing-slow: .1s;

    Good: Point Scale

    --color-blue-10: #00a0dd;
    --color-blue-20: #005da8;
    --color-blue-30: #acd5f8;

Nested Selectors

  • Following BEM or pseudo BEM should allow you to avoid unnecessary nesting. This creates CSS that is easier to maintain, less fragile, and smaller in size. When nesting does become needed, it should be kept as shallow as possible. A good rule of thumb is to nest selectors no more than three levels deep.

    When selectors become more deeply nested than three levels, you're likely writing CSS that is:

    • Strongly coupled to the HTML & fragile
    • Overly specific
    • Not reusable
  • When nesting is required, nesting order should be based on specificity.

    1. Properties applied to selector: property: value;
    2. Element modifiers: :before, :hover, &--modifier
    3. Elements: li, span
    4. Classes: .nested-class

    Bad Nesting Order

    .selector {
        element {
            // ...
        }
        property: value;
        property: value;
        .class {
            // ...
        }
        &:before {
            // ...
        }
    }

    Good Nesting Order

    .selector {
        property: value;
        property: value;
        &:before {
            // ...
        }
        element {
            // ...
        }
        .class {
            // ...
        }
    }

Breakpoints & Media Queries

  • Write Mobile First CSS. Authoring mobile-first styles results in smaller, simpler, more maintainable code and is in line with DEG's stance on progressive enhancement.

  • Don’t use device dimensions to determine breakpoints. The device landscape is always changing, so today’s values might be moot even just a year down the road. The Web is inherently fluid, so it’s our job to create interfaces that look and function beautifully on any screen instead of in just a few arbitrary buckets.

  • Use em's to define dimensions for media queries. Avoid px and rem based units as em's are the only units that perform reliably across browsers.

    Bad

    .column {
        float: left;
        width: 50%;
    }
    @media all and (max-width: 800px) {
        .column {
            float: none;
            width: auto;
        }
    }

    Good

    @media all and (min-width: 50em) {
        .column {
            float: left;
            width: 50%;
        }
    }

Vendor Prefixes

  • Avoid using vendor prefixes within your authored CSS. Autoprefixer is available within Skeletor and should be configured to apply vendor prefixes based on a projects browser support through the build process.

Javascript Hooks & State Classes

  • Avoid binding to the same class in both your CSS and JavaScript.

  • Depending on your specific needs, we recommend creating Javascript hooks & state classes in 1 of 3 ways:

    js- prefix for hooks

    <button class="button js-button">Action Button</button>

    is- prefix for temporary state classes

    <button class="button is-active">Active Action Button State</button>

    --is- modifier for temporary state classes that are element dependant

    <button class="button button--is-active">Active Action Button State</button>

Box Sizing

  • Skeletor's default CSS reset resets box-sizing to border-box on the html selector and every other element inherits this value.

    html {
        box-sizing: border-box;
    }
    
    *, *:before, *:after {
        box-sizing: inherit;
    }

Javascript

While DEG doesn't maintain a specific code style guide in relation to Javascript, we do utilize es6 features and syntax and tend to follow the guidelines set out by airbnb in their Javascript style guide.

Package Management

  • Deg utilizes NPM for package management.

Modules

  • DEG utilizes Javascript modules to create a maintainable, reusable, and performant codebase rather than a sprawling and interdependent one.
  • Small, self-contained modules with distinct functionality are preferred over large, all inclusive modules. This allows for modules that can be shuffled, removed, or added as necessary, without disrupting the system as a whole.

Module Bundling

  • DEG utilizes Rollup.js for ES6 module bundling and code splitting. For legacy browsers that do not support ES6 modules, Rollup.js can be configured to output bundles in a SystemJS format.

Compiling

  • DEG utilizes Babel to compile and convert modern and next-gen JavaScript into a backwards-compatible version that will run in all necessary browsers.

Polyfilling

  • In addition to core-js polyfills delivered via Babel, DEG utilizes Polyfill.io to polyfill JavaScript and DOM API features as necessary. To reduce the payload size of the polyfill file, it is recommended that only features being used by the codebase be polyfilled.

Tools

Skeletor

Skeletor is a Node-powered, Pattern Lab-centric, highly-customizable web project boilerplate and build tool created by the DEG UI team. Skeletor uses PostCSS for CSS processing and Rollup.js for Javascript module bundling. Full Skeletor documentation is available here.

Pattern Lab

Pattern Lab is a collection of tools to help you create atomic design systems. DEG uses Pattern Lab as a design & development tool, a prototyping & demo tool, and as an interactive style guide deliverable for clients. Although Pattern Lab comes with an out of the box pattern starter kit, we have modified this kit to more closely resemble the types of projects we work on and practices we follow. Our modified version of Pattern Lab can be found within Skeletor. Pattern Lab specific documentation can be found on the Pattern Lab website.

Libraries

DEGJS

DEGJS is a curated list of ES6-formatted JavaScript modules, encompassing front-end functionality and utilities, developed by the DEG UI team. All modules are hosted under our DEGJS GitHub account, and are formatted to work with Babel, the JSPM package manager and its accompanying JavaScript loader, System.js.

jQuery

* Magento & Legacy Only * The ubiquitous javascript library. Many legacy projects as well as anything on the Magento platform will include the jQuery library. The DEG UI team recommends against using jQuery when possible.

Design Patterns & Considerations

Atomic Design

The DEG UI team encourages the use of the Atomic Design methodology for creating design systems. The basic gist of atomic design is to break interfaces down into fundamental building blocks and work up from there. Traditional atomic design consists of 5 distinct levels:

  • Atoms: Basic building blocks. HTML tags, such as a form label, an input or a button.
  • Molecules: Groups of atoms bonded together. Form label, input & button combined together.
  • Organisms: Groups of molecules joined together to form a distinct section of an interface.
  • Templates: Groups of organisms stitched together to form pages.
  • Pages: Specific instances of templates.

DEG uses a modified version of these levels to simplify development, tie in better with design processes & deliverables, and to use terminology that is easier for clients to understand. Our version of atomic design consists of 4 dinstinct levels:

  • Basics: Basic building blocks. Typography, colors, & basic HTML tags.
  • Components: Groups of basics or other components combined together. Components should be nested into parent & child relationships when applicable.
  • Templates: Groups of components combined together to create pages.
  • Pages: Specific instances of templates.

Browser Support

DEG uses the concept of Graded Browser Support, which defines the set of browsers that should receive a verified, usable experience. However, trying to deliver the same "A-grade" experience across all tested browsers is neither cost-effective nor common. We support a tiered approach to user experience design, development, and testing, and encourage each project to define their own tiers that serve their users and stakeholders best. For a more detailed explanation and a guide to help determine what browsers to support, view our Browser Support Guide on Google Docs.

Accessibility

DEG Standards of Quality stipulate a minimum of WCAG 2.0 Level A accessibility conformance. However, some projects may have more strict accessibility needs. For WCAG 2.0 Level A development requirements, reference the WCAG 2.0 Checklist.

Performance

Because speed and performance is a vital part of any website, DEG encourages the use of performance budgets to help guide design and development decisions.

A performance budget is like any other project budget: it defines a clear goal that the project can be evaluated against to determine success. More specifically, a performance budget sets limits for individual pages of a website that should not be exceeded. These limits can be expressed in the form of several metrics, such as how long it takes for a page to load and how many kilobytes a page weighs. A performance budget helps you choose how to display content or define functionality. It does not dictate what content should be displayed. Removing something important to decrease page weight is not a good performance strategy. The overall benefit of a performance budget is a fast, lightweight website.

For more details on how and when DEG sets performance budgets, view our Performance Budget Guide on Google Docs.

Detailed Design Patterns & Anti-Patterns

Although projects do often present unique challenges, there are certain challenges we see repeated across many projects. Because of this, the DEG UI team maintains a set of client facing documentation on the best practices for using and implementing common design patterns & anti-patterns including:

Tooling

IDEs/Editors

  • VS Code
  • Sublime Text
  • PHPStorm
  • Visual Studio

CSS

  • PostCSS
  • Legacy Projects: Sass/Compass

Javascript

  • Node - Package Management
  • Rollup.js - Module Bundling
  • Babel - Compiling

Task Runners

  • Node scripts
  • Skeletor 2.0

Visual Editors

  • Photoshop
  • Illustrator
  • Sketch
  • IcoMoon

Virtual Machines

  • VirtualBox
  • Vagrant

ALM / Version Control

  • JIRA
  • Bitbucket
  • Git

Continuous Integration

  • Jenkins

Testing

  • BrowserStack

Pull Requests

Pull Requests are both a great way to maintain high quality code and an opportunity to learn from each other. Here are a few best practices to get you started:

Submitting a Pull Request

  • It's much better to submit small pull requests often. Shoot to submit at least one Pull Request (PR) per day. If your ticket is bigger than that. Try to break it into smaller chunks. It's much easier for a reviewer to read through a four file change than it is to read through a massive refactor.

  • Link the Pull Request to a ticket if there is one. You can link in most source control by just noting the ticket number---#542. In other situations, drop a URL. This gives the reviewer some feedback.

  • If there is no issue to link to, leave a brief explanation on why you are submitting the PR. This help the reviewer, but it also helps it later if someone is trying to figure out why a piece of code was changed.

Reviewing a Pull Request

  • Who can review? Simple, everyone should review code. If you are new to a project, you'll get a feeling for the structure other projects. If you are experienced, you'll be able to offer more insights.

  • Each project will need to decide who is able to officially approve a request. If you are principle reviewer, try to finish a review within 24 hours. When you approve a PR, leave a comment saying it looks good or a simple đź‘Ť. Some systems have official approval buttons.

  • Merging a pull request is the responsibility of the person who opened the PR. Why? There may be additional tasks such as deploying or updating a tag.

  • When reviewing, open the code in a browser if possible. It can be hard to grasp a change until you see it live.

  • Remember to be polite. As one guideline says "Accept that many programming decisions are opinions. Discuss tradeoffs, which you prefer, and reach a resolution quickly."

  • We are all learning. As long as the code does not violate agreed standards, the author has a right to use whatever solution they want.

  • If possible, don't just leave a comment about a potential issue, recommend a fix. Sketch the solution if possible.

  • If you think there is a better solution, but are not sure, you can say that. Just note that it is a gut feeling and the code may be fine.

  • A comment is the start of a conversation, you may need to clarify and expand on your suggestions.

  • For more guidelines on review code, see the thoughtbot guide and the guide by github.

What To Look for When Reviewing Code

  • There are some things that must be completed before code can be accepted. These include following linting rules and testing requirements if applicable.

  • Syntax suggestions:

const settings = Object.assign({}, defaults, options);

A review might say:

Consider using object spread:

const settings = {
  ...defaults,
  ...options
}
  • Code Reuse
function getNames(people) {
  return people.map(person => person.name);
}

function getAges(people) {
  return people.map(person => person.age);
}

Reviewer:

You should consider a reusable function

function extractField(group, field) {
  return group.map(item => item[field]);
}

getNames(people) {
 return extractField(people, 'names')
}
  • Readability
function createSidebar(data) {
 let small = true;
 let sidebar;
 if(data.length > 20) {
   small = false;
 }
 // 50 more lines of data manipulation

Reviewer:

I get a little lost on this function. Could you split it up?

  • Incorporating libraries
// File someproject/bankingForm.js
function checkPassword(element, rules) {
// check password for strength
}

Reviewer:

We have a library called Password Strength you might check to see if that would work in this situation.

  • Catching potential bugs
function getTotalMileage(reports) {
  reports.reduce((total, report) => {
    return total + report.miles
   }, 0)
 }

Reviewer:

Looks like you forgot to return the total after running the reduce function. That'll return undefined everytime.

  • Updating documentation and tests

Reviewer:

Looks good, but you should probably add a note to the README.

  • And more

There are many more things you may notice. It's ok to ask just remember to be polite.

Receiving Feedback

  • Assume everyone is acting in good faith. It's hard to communicate tone on the web. So assume that everyone is giving suggestions in a compassionate manner. It's almost certainly true.

  • You have the right to say no. As long as you are not violating an agreed upon set of standards, it's your code. But if you disagree just note that you read the comment, but prefer to keep it how it is. It's helpful if you can give a justification---"I think a for loop communicates a little more clearly than a reduce function"---but it's not mandatory.

  • If you like a suggestion, but do not have time, create an issue or leave a TODO statement in the code.

Reviewer:

You should consider a reusable function

You:

I think that's a good idea, but this code fixes a bug on production and needs to go out. I'm leaving a TODO note in the code so I can catch it next time.

Updating A Pull Request

  • Submit any changes on the same branch as the original PR. It will update the PR code and maintain the conversation. It will also alert reviewers that you made a change.

Finalizing

  • After the reviewer has approved. Close the PR and make any finalizations such as updating a tag or publishing to npm.

About

DEG UI Code Standards, Design Patterns, Frameworks & Tooling

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published