Development

Introduction

Watson provides three libraries:

  • Tokens - a collection of styles that contain the necessary to use Watson Design System in your project. This package contains a /dist folder with:
    • index.css: contains CSS custom properties including our three tiers of design tokens: components, semantic and core.
    • /components, /semantic, /core: contains CSS custom properties and JS variables separately.
  • Components - a set of Vue components ready to use to help developers with their work building high-quality components based on Watson foundations. This package contains a /dist folder with:
    • watson.css: contains compiled CSS styles including foundations and components classes.
    • watson.es.js: contains compiled JS.
  • Web Components - a set of web components that can be used in non-Vue projects. These are converted from Vue components and verified to work as close as possible to the Vue components.

Do we have utility classes?

Watson does not include CSS utility classes as we don't want to break component encapsulation or facilitate their misuse. We aim to create a UI language for you to use and not another vast CSS framework, so instead, we provide components like Grid, Stack, and Spacer to help with distributing items on the screen. Additionally, you can always use the semantic Tokens mentioned above in case you need to build your own solutions.

Note

If you want to know more about tokens tiers structure, please read Design Tokens section

Vue

Installation

All modules are available in DocPlanner private package registry as separate npm packages. In order to use them in your project you need to add .npmrc file to it and configure it as follows:

always-auth=true
registry=https://npm-proxy.docplanner.io
//npm-proxy.docplanner.io/:_authToken="YOUR_TOKEN_GOES_HERE"

Please note that both @dp-watson-web/components and @dp-watson-web/web-components are a standalone packages including CSS and compiled JS. You don't need to include @dp-watson-web/tokens as dependency in your Vue project as it is already integrated as part of the package.

Tokens should be used in case you plan to add custom components that are not available in the @dp-watson-web/components package or if you are working into a non Vue ecosystem and you want to include the foundations of Watson Design System.

Components

Import CSS file

import "@dp-watson-web/components/dist/watson.css";

Import JS file

You can import @dp-watson-web/components Watson Components in two ways:

  1. As a plugin

This option makes all Vue componentes available into your project and you don't need to import them all the time you need them, just use them directly in your Vue templates. Don't pick this option if you want to be ** tree-shakeable**.

import WatsonComponents from "@dp-watson-web/components";
import { createApp } from "vue";

const app = createApp(App);
app.use(WatsonComponents);
  1. Importing components manually in your views.
import { WGrid, WGridItem, WCard, WText } from "@dp-watson-web/components";

Design Tokens

Design tokens are a set of CSS properties used to build Watson Design System. They store foundational styles on spacing, color, typography, shadows, and border radius.

Do not use the core tokens - Core tokens is a strict set of variables carefully picked by the design team. By themselves they do not have any context, and they should not be used in any other way than by referencing them in other tokens. Use semantic tokens instead.

They are divided into three tiers:

Core tokens

Content-agnostic values. Used only internally as a reference for semantic, and component tokens.

Example: --w-color-red-200

Semantic tokens

Their name describes the intended use of the token — this tier references core tokens.

Example: --w-font-size-page-heading

Component tokens

Tokens are tied to a specific component value — this tier references semantic tokens.

Example: --w-button-background-secondary

Tokens are delivered as CSS and JS variables in @dp-watson-web/tokens package, each tier available as a separate file inside /dist folder. Additionally, there is a JSON object with all tokens in it. This format may come in handy in cases when the developer needs access to the style dictionary that was used to build design tokens. Except for the name and value JSON file contains additional fields used to generate this documentation like description, tokenRefercence or comment.

Examples

Live Preview

Watson Design System provides a set of web components that can be used in non-Vue projects. Using web components offers several benefits like:

  • Reusability: Web components are self-contained and can be reused across different projects.
  • Encapsulation: Web components are encapsulated, meaning their styles and logic are scoped to the component.
  • Interoperability: Web components can be used in any framework or library.
  • Browser support: Web components are supported by all modern browsers.
  • Future-proof: Web components are part of the web standards and are here to stay.
  • Ease of use: Web components can be used like any other HTML element.

The core concept of web components remains the same across all frameworks, but each framework has different mechanisms for handling component communication, rendering, and reactivity. You'll need to bridge some of these differences when integrating web components into your specific framework.

Web components

Installation

Import CSS file

import '@dp-watson-web/web-components/dist/watson.css'

Import components

import '@dp-watson-web/web-components/dist/components/WAvatar/WAvatar.js';

Importing components in this way will define the custom element in the global scope, so you can use it in your HTML.

If you want to manually define the component, you can do it like this:

import WAvatar from '@dp-watson-web/web-components/dist/components/WAvatar/WAvatar.component.js';

WAvatar.define();

It may be useful in some scenarios when you do not have all required properties available at the time of the component is defined.

Working with web components

General rules

  • Use camelCase for properties and dash-case for attributes: HTML has only two types of values: strings and booleans. Any property that stores other type of value cannot be represented as an attribute. There are multiple ways of approaching booleans. If treated as an attribute boolean is true when the attribute is present and false when it is not.
    <!--Vue -->
    <!--attribute set to true-->
    <w-checkbox model-value />
    <!--attribute set to false-->
    <w-checkbox />
    <!--property set to false-->
    <w-checkbox :modelValue="true" />
    <!--property set to false-->
    <w-checkbox :modelValue="false" />
    
  • All our components emit custom DOM events Use detail property of CustomEvent to obtain payload data from the event. The detail property is an array that contains the data passed to the event.
    ...
    document.querySelector('w-checkbox').addEventListener('update:modelValue', onUpdateCheckbox);
    
    function onUpdateCheckbox(event) {
    checkboxValue = event.detail[0];
    ...
    };
    
  • Slots: Some of our components utilize slots to obtain content. Those with a single slot use the 'default' slot which does not need additional configuration. Those with multiple slots utilize named slots. In order to pass content to the named slot you need to use slot attribute and pass slot's name into it. Please note that Vue slot syntax won't work with web components.
    <!--Vue-->
    <w-collapse
      :indent="false"
      padding="none"
    >
      <div slot="header">
        <w-text type="subSectionHeading">Default slot content</w-text>
      </div>
      <div slot="panel">
        Named slot content
      </div>
    </w-collapse>
    
  • Defining web components: We offer two versions of each component in our library:
    • One that auto registers itself when imported (Files withouth the .component suffix). After importing the component it registers itself as custom element in the browser and is ready to use.
    import '@dp-watson-web/web-components/dist/components/WText/WText.js';
    
    • One that needs to be registered manually (Files with the .component suffix). It imports the component, but does not register it as custom element. You need to call the define method on the component to register it. This option gives you more flexibility and control over the registration process.
    import WText from '@dp-watson-web/web-components/dist/components/WText/WText.component.js';
    
    WText.define();
    
  • Component dependencies: Some of our components depend on other components. We take care of importing those dependencies for you so you don't have to worry about importing them separately. We also make sure that the component won't be registered twice so if you import the same component in multiple views you're covered.

Vanilla JS

  • Direct Interaction: Without a framework, you can directly manipulate web components using their API. You have full control over attributes, properties, and events using standard JavaScript methods.
  • Manual DOM Updates: Without the help of a framework, you’ll need to manually handle state changes and DOM updates, which might require more boilerplate code compared to using a framework.

<w-text id="checkbox-text">Lorem ipsum</w-text>
<w-checkbox label="Checkbox label"></w-checkbox>
let checkboxValue = false;
document.querySelector('w-checkbox').modelValue = checkboxValue;
document.querySelector('w-checkbox').addEventListener('update:modelValue', onUpdateCheckbox);

function onUpdateCheckbox(event) {
  checkboxValue = event.detail[0];
  document.querySelector('w-checkbox').modelValue = checkboxValue;
  document.querySelector('#checkbox-text').innerHTML = `The checkbox value is: ${checkboxValue}`;
};

Vue

Vue works very well with web components. If you stick to the general rules listed above you should be able to use web components without any issue.

Angular

When using web components in Angular, you need to remember to add the CUSTOM_ELEMENTS_SCHEMA to the schemas array in the component decorator. This tells Angular to ignore unknown elements and attributes, which is necessary when using web components.


<w-button
  label="Push me!"
  [fullWidth]="isFullWidth"
  (click)="onClick()"
/>
import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';

import '@dp-watson-web/web-components/dist/components/WButton/WButton.js';

@Component({
  schemas: [CUSTOM_ELEMENTS_SCHEMA]
})

export class ButtonComponent {
  isFullWidth = false;

  onClick() {
  ...
  }
}

React

React is currently not supported by our web components.