Skip to main content
U.S. flag

An official website of the United States government

Dot gov

The .gov means it’s official.
Federal government websites often end in .gov or .mil. Before sharing sensitive information, make sure you’re on a federal government site.

Https

The site is secure.
The https:// ensures that you are connecting to the official website and that any information you provide is encrypted and transmitted securely.

Documentation

Documentation for developers

How to install and use VA Design System styles and components with your project.

Parts of the Design System

Using the Design System

If you are working in the vets-website repository, you can skip straight to the developer documentation. Otherwise, proceed below.

How you implement VADS styles into your project depends on how your project is structured and your preferences. The easiest way to get started is by using npm. For a prototype where you need the formation styles, you can add a <link> tag with the href set to https://unpkg.com/@department-of-veterans-affairs/formation/dist/formation.min.css.

Install Formation into your project

We recommend using npm to install the formation package into your project.

$ npm install --save @department-of-veterans-affairs/formation

This line installs Formation as a dependency. You can use the compiled files found in the node_modules/@department-of-veterans-affairs/formation/dist directory.

If you would like to use the un-compiled Sass files instead, you can find those in the node_modules/@department-of-veterans-affairs/formation/sass directory.

If you prefer to change the location of the fonts/ and img/ directories relative to formation.min.css, set the following variables in your project:

$formation-asset-path: '../assets';
$formation-image-path: "#{$formation-asset-path}/img";
$formation-font-path: "#{$formation-asset-path}/fonts";

The example above is what is used on VA.gov, but you can customize this for your project.

Sass functions, variables, and interactive components

If you would like to use the Sass functions, such as for spacing, and variables in your project, you can import the files from your project scss. This documentation site imports Formation’s Sass files in its application.scss.

Load the Web Component library

The Design System team is working on developing a library of reusable Web Components that can be used on any HTML page or React application.

This is already handled for the vets-website repository. To get our Web Component library set up in a new project, here is what we recommend:

  1. Add the component-library dependency to your node/yarn project using yarn add @department-of-veterans-affairs/component-library.
  2. Import the global CSS file which contains important CSS variables:
    import "@department-of-veterans-affairs/component-library/dist/main.css";
    
  3. Import the defineCustomElements JS function (applyPolyfills is only necessary if you wish to support older browsers such as IE11):
    import {
      applyPolyfills,
      defineCustomElements,
    } from "@department-of-veterans-affairs/component-library";
    
  4. In the same JS file, call the defineCustomElements function, optionally chained after a call to applyPolyfills:
    applyPolyfills().then(() => {
      defineCustomElements();
    });
    
  5. Make sure this script gets loaded on the HTML page - preferably near the top of the document in the <head> tag.

Using Web Components

Vanilla JavaScript Applications

If the Design System web components will be used in a vanilla JavaScript application, you are ready to use them (identified by tags prefixed with <va-*>).

We make our best efforts to avoid creating web components with object or array properties in order to make them easier to use in static HTML pages.

React Applications

If the Design System web components will be used in a React application, you are ready to use them unless:

  • You must pass in a function, object or array to a web component’s properties
  • You must listen to custom events

If your use case is listed above, you will have to use our web component bindings for React. If you are not sure if you need to use a custom event, please refer to the web component’s Storybook documentation to see its events and properties.

Bindings are component wrappers that allow our web components to work as first-class React components, allowing us to handle custom events and to pass in more than strings and numbers to a web component’s properties. You will have to import each web component’s bindings like you would with a React component.

import { VaExampleComponent } from "@department-of-veterans-affairs/web-components/react-bindings";

const exampleFunction = () => console.log("Hello, World!");

<VaExampleComponent exampleProp={exampleFunction} />

Implementing design work

When a designer hands off work, it is vital to work through potential implications that design may have on Formation. Are there any new variations on components? Are there any new components not present on this site? For more on that process, read about how to contribute.

In general, some rules for implementing design work include:

  • Use spacing units instead of hard-coding pixel values for margins and padding
  • Use Sass variables for colors instead of hex codes
  • Discuss reusability of new design components and where is the most appropriate home for CSS and JS
  • Use the Formation naming convention
  • Do not use ID selectors

Use design system utilities

Sometimes you will need to modify certain default properties of a component depending on how it scaffolds with nearby elements. Use utilites instead of writing new CSS.

Do

Use utility classes to override default properties. This allows components to maintain a well-defined baseline of properties.

HTML
<div class="a-container">
  <div class="a-component vads-u-margin-top--3"></div>
</div>

Don’t

Don’t change CSS properties based on a container or other context. This makes baseline properties for components unclear.

HTML
<div class="a-container">
  <div class="a-component"></div>
</div>
CSS
.a-container .a-component {
  margin-top: 24px;
}

Contributing to the Design System

The two main ways for developers to contribute to the Design System are by writing new components or by modifying existing components. Regardless of which type of contribution you are making, each PR should:

  • have at least 90% test coverage
  • have appropriate comments/documentation for functions, classes, etc.
  • have Storybook stories for new features
  • minimize complexity
  • include only the smallest changeset required for the feature or fix

New components

If you want to contribute something to the Design System, see the Contributing to the Design System page.

Modifying existing code

PRs which make a change to the Design System should be manageable in size (less than ~500 lines of code). This is to meant to:

  • Save your time as the developer
  • Keep PRs tightly focused
  • Keep the review process short.

Writing CSS for the design system

When naming components, be sure to use Formation’s naming conventions.

Searchable selectors

Many of the features in Sass make it easy to use shorthand to reduce repetitive typing and write cleaner .scss files. However, this makes using search features in GitHub or text editors much more difficult because it is not always clear how the shorthand was written; finding the right query requires guesswork.

Do

Write out the full name of each selector.

.alert {
}

.alert--warning {
}

.alert--error {
}

Don’t

Don’t use Sass shorthand features, such as nesting with ampersands often used with BEM syntax.

.alert {
  &--warning {
  }
  &--error {
  }
}

Contributing experimental design code

This document explains the process for contributing code for experimental designs and the reasoning behind that process.

If you haven’t read it already, refer to the experimental design page for more information about the full process.

Writing experimental design code

Each experimental design should:

  • Be absent of business logic and domain knowledge
  • Not import application code
  • Not introduce breaking changes

Developing the experiment as if it were a standalone library will make the code more reusable and graduating the component or pattern into the official design system smoother.

Each experimental design should include a README and be owned by a team.

Sharing experimental design code

Sharing code between applications is necessarily more involved than writing code for a single application. To avoid the overhead that sharing code introduces (reporting development status, managing breaking changes, deprecating the code etc.), it’s recommended to develop experimental designs in the application directory and not import it from another application.

If the time comes that another application needs to use the experiment, the rest of this section describes the process for how to share this code.

Code location

Each experimental design is located in its own directory in vets-website at src/experimental/ unless otherwise noted in its documentation on this site.

Example:
If your team needs an experimental button that’s larger than the standard button, you would create src/experimental/large-button/index.jsx as the entry file for your “library.”

README

Each experimental design should have a README that contains the following information:

  • Development status: stable, unstable, or deprecated
    • The unstable status means the code is under active development and the public API may change without notice
    • The stable status means the public API is finalized, but the code may still receive backward-compatible updates such as accessibility improvements and bug fixes
    • The deprecated status means the code should no longer be used in applications
      • This may be because of a breaking change (see Breaking changes below), official adoption into the design system, or research which indicates the experiment was unsuccessful
      • See Ending the experiment below for instructions on what to do when deprecating code
  • API documentation (optional but encouraged)

Breaking changes

“Breaking changes” is defined here In semver terms as a backwards incompatible change to the public API of your component or pattern. (See the Semantic Versioning Specification for more details.)

Once the code for an experimental design is stable, breaking changes should not be introduced. Other applications may depend on this code, but are unable to pin the version because it’s not a “proper” library.

If you need to introduce breaking changes, do not modify the existing code. Instead, copy the contents of the directory to a sibling directory post-fixed with a version number.

Example:
The LargeButton you created accepted children, but because of reasons, you need to limit the content of the button to only text. You’ve decided to remove the children prop and add a label prop instead which accepts only strings. To introduce this change, you would:

  1. Copy the contents of src/experimental/large-button/ to src/experimental/large-button-2
  2. Update the status in src/experimental/large-button/README to deprecated and indicate why (because there’s a new version)
  3. Make the breaking changes to src/experimental/large-button-2
  4. Change the import statements 'experimental/large-button-2' in your application
  5. Update the CODEOWNERS file to add the new directory
  6. Make an announcement for anybody who may be using the deprecated code

CODEOWNERS

Add your team’s GitHub team name to the CODEOWNERS file to take ownership of the experiment’s code. This will mean your team will be required reviewers on all changes to this code.

Test coverage

As with all code, test coverage is critical. This is especially true with shared code. Aim for at least 90% unit test coverage before declaring an experiment to be stable.

Using shared experimental designs

Before using an experimental design, first check the src/experimental/ directory in vets-website to see if it’s been shared yet. If not, work with the authoring team to move the code into src/experimental/. See Sharing experimental design code above for more information.

The babel module resolver plugin has the root set to "./src", so you can import your experimental design with the following:

import LargeButton from '~/experimental/large-button';

Ending the experiment

Experimental designs are meant to be short-lived. The experimental design code may no longer be needed because:

  • The design was approved for adoption into the design system
  • The design was rejected for adoption into the design system
  • A breaking change was introduced and a new version was created

When code is deprecated for any of these reasons, the goal is to delete the code. If there are no applications using the deprecated code, simply delete the directory.

If there are applications using the deprecated code:

  1. In the README: Mark the code as deprecated
  2. In the REAMDE: Clearly outline what engineers should do to stop using the experiment
    • This may be something like “upgrade to ~/experimental/large-button-2,” “use @department-of-veterans-affairs/component-library/LargeButton,” or “discontinue use; the experiment has been rejected”
  3. In Slack: Notify teams that the code has been deprecated, either via an announcement or reaching out directly to the teams using the experiment
  4. Check in weekly to see if there are still applications using the experiment; delete the directory when no applications are dependent on it

It’s the responsibility of the code owners to delete deprecated code when it’s no longer in use.

Edit this page in GitHub (Permissions required)
Last updated: Jan 12, 2022