@arc-web/components
TypeScript icon, indicating that this package has built-in type declarations

3.0.1 • Public • Published

ARC

Arup Reusable Components

Storybook | Documentation | Playgrounds | Issues | Discussions | Contributing | Code Of Conduct | Security | License |Sharepoint (Arup Internal) | Jira (Arup Internal)

Thanks to the popularity of frameworks such as Angular, Vue, and React, component-driven development has become a part of our everyday lives. Components help us encapsulate styles and behaviours into reusable building blocks. They make a lot of sense in terms of design, development, and testing.

Unfortunately, framework-specific components fail us in a number of ways:

  • You can only use them in the framework they're designed for
  • Their lifespan is limited to that of the framework's
  • New frameworks/versions can lead to breaking changes, requiring substantial effort to update components

ARC is built with Web Components. These are sharable and standalone pieces of code (HTML/JS/CSS) that offer visual style and interactivity out of the box. They're supported by all modern browsers, they're framework-agnostic, and they're part of the standard, so we know they'll be supported for many years to come.

What problem does this solve?

ARC provides a collection of professionally designed UI components built on a framework-agnostic technology. Why spend hundreds of hours (or more) building a design system from scratch? Why make a component library that only works with one framework?

With ARC, you can:

  • Start building things faster (no need to roll your own buttons)
  • Build multiple apps with different frameworks that all share the same UI components
  • Fully customize components to match your existing designs
  • Incrementally adopt components as needed (no need to ditch your framework)
  • Upgrade or switch frameworks without rebuilding foundational components

Documentation

Getting Started

1: Installation

Install the latest version of the @arc-web/components package from npm:

npm install @arc-web/components@latest

2: Setup Stylesheets

ARC components depend upon the stylesheet in the themes directory @arc-web/components/themes to be loaded at runtime. Ensure that the stylesheet is loaded by your application:

Build Script

Add a step to your build script that copies the contents of the @arc-web/components/themes directory into a directory that serves static assets by your applications web server:

+ cp -r node_modules/@arc-web/components/themes <public directory>

Load the stylesheet in your application:

  <html>
    <head>
    ...
+   <link rel="stylesheet" href="<public directory>/themes/index.css" />
    ...
    </head>
  </html>
Angular CLI

Add the stylesheet directly to the styles array in your angular.json configuration file:

  {
    ...
    "styles": [
+     "node_modules/@arc-web/components/themes/index.css",
      ...
    ]
    ...
  }
CSS Imports

Bundlers that support CSS imports allow you to import CSS files directly into your application's entry point. This is the recommended approach as it allows the bundler to optimize the CSS and remove any unused styles:

+ import '@arc-web/components/themes/index.css';
...

3: Import and Use Components

Import the @arc-web/components package:

import '@arc-web/components';

Components are now be available to use in your application:

<arc-button>Click Me</arc-button>
Cherry Pick Components

Import only required components individually over importing the entire @arc-web/components package to reduce the bundle size of your application:

import `@arc-web/components/src/components/button/arc-button`;

See the Storybook for a full list of available components and their documentation.

[!IMPORTANT] Icons are not imported by default and must be cherry picked.

Typescript

ARC components are written in Typescript and come with their own type definitions. This means you can use them in a Typescript project without any additional setup. Import an ARC component and its type definition:

import type { ArcButton } from '@arc-web/components';
import '@arc-web/components;
Cherry Pick Components
import type { ArcButtton } from '@arc-web/components/src/components/button/arc-button';
import '@arc-web/components/src/components/button/arc-button';

React

React can render web components, however, makes assumptions about HTML elements that don't always hold for custom elements, while also treating lower-case tag names differently from upper-cased. This makes working with web components harder than necessary to use. React is working on fixes to these issues, but in the meantime, the @arc-web/react provides a wrapper that takes care of setting properties and listening to events for you. Read more about why we need this wrapper here

Install both the @arc-web/components and @arc-web/react packages from npm:

npm install @arc-web/components@latest @arc-web/react@latest

Setup the @arc-web/components package as described above, however, import components from the @arc-web/react package instead:

import { ArcButton } from '@arc-web/react';

export const App = () => {
  return <ArcButton>Click Me</ArcButton>;
};

Customization

ARC components can be customized at a high level through design tokens. This gives you control over theme colours and general styling. For more advanced customizations, web-components can expose something called CSS parts. To ensure that each application looks and feels the same, these parts are not being exposed from the ARC components.

Design Tokens

ARC makes use of several design tokens to provide a consistent appearance across components. You can customize them and use them in your own application with pure CSS. Design tokens offer a high-level approach to customizing your components, with minimal effort. There are no component-specific variables, however, as design tokens are intended to be generic and highly reusable.

Design tokens are accessed through CSS custom properties that are defined within the theme. Because design tokens live at the page level, they're prefixed with --arc- to avoid collisions with other libraries.

To customize a design token, simply override it in your stylesheet using a :root block. If you are including the ARC-provided theme stylesheets, be sure to import your own after the ARC stylesheets so that your styles override the ARC-provided ones where relevant.

Here's an example that changes the primary color of the light theme. Note that you should use the ARC color palette, but if you must provide a different color you should provide only the comma separated numbers to go inside an rgba block (e.g. 255,255,255,1, not rgba(255,255,255,1) and not #FFFFFF)

:root {
  --arc-light-color-primary: var(--arc-green-050);
}

Custom Properties

For convenience, some components expose CSS custom properties you can override. These are not design tokens, nor do they have the same --arc- prefix since they're scoped to a component.

You can set custom properties on a component in your stylesheet.

arc-button {
  --btn-color: green;
}

This will also work if you need to target a subset of components with a specific class.

arc-button.green {
  --btn-color: rgb(var(--arc-green-050));
}

arc-button.blue {
  --btn-color: rgb(var(--arc-blue-050));
}

Alternatively, you can set them inline directly on the component.

<arc-button style="--btn-color=rgb(var(--arc-green-050))">My Button</arc-button>

Not all components expose CSS custom properties. For those that do, they can be found in the component's API documentation. In the properties table, these can be found under the CSS CUSTOM PROPERTIES row.

Icons

ARC used the Phosphor Icons icon set and provides a web component for each icon. To use an icon, import the icon component and use it in your application as you would any other component cherry picked as follows:

import '@arc-web/components/src/components/ph-{icon-name}/ph-icon-{icon-name}.js';
<ph-icon-{icon-name}></ph-icon-{icon-name}>

Forms

Every ARC component makes use of a shadow DOM to encapsulate markup, styles and behaviour. One caveat of this approach is that native form elements do not recognize form controls located inside a shadow root.

ARC solves this problem by using the formData event, which is available in all modern browsers. This means, when a form is submitted, ARC form controls (i.e. arc-radio) will automatically append their values to the FormData object that is used to submit the form. In most cases, things will 'just work.' However, if you are using a form serialization library, it might need to be adapted to recognize ARC form controls.

Form Serialization

When you are relying on standard form submissions, e.g. <form action="...">, you can probably skip this section. However, most modern apps use the Fetch API or a library such as axios to submit forms using JavaScript.

The FormData interface offers a standard way to serialize forms in the browser. You can create a FormData object from any <form> element like this.

const form = document.querySelector('form');
const data = new FormData(form);

// All form control data is available in a FormData object

However, if you find FormData tricky to work with, or need to pass a JSON payload to the server, ARC offers a serialization utility that gathers form data and returns a simple JavaScript object instead.

import { serialize } from '@arc-web/components/utilities/form-utils.js';

const form = document.querySelector('form');
const data = serialize(form);

// All form control data is available in a plain object

This results in an object with name/value pairs that map to each form control. If more than one form control shares the same name, the values will be passed as an array, e.g. { name: ['value1', 'value2'] }.

Form Control Validation

Client-side validation can be enabled through the browser's Constraint Validation API for ARC form controls. You can activate it using attributes such as required, minlength and maxlength. ARC implements many of the same attributes as native form controls, but checks each form control's documentation for a list of all supported properties.

<form>
  <arc-switch name="arc_is_great" value="true" required>Do you love arc?</arc-switch>
  <arc-button submit>Submit</arc-button>
</form>
<script type="module">
  const form = document.querySelector('form');
  form.addEventListener('submit', (e) => {
    e.preventDefault();
    console.log(form.checkValidity());
  });
</script>

When the switch does NOT have the checked state, it will be invalid, as the required property is defined on the component. You can log the validity of the form by calling checkValidity(). You can also report the validity of the input element, by calling reportValidity(). Calling the reportValidity() method on the component itself will return true or false. If the component is invalid, the browser will show the user a relevant error message.

<form>
  <arc-switch name="arc_is_great" value="true" required>Do you love arc?</arc-switch>
  <arc-button submit>Submit</arc-button>
</form>

<script type="module">
  const arcSwitch = document.querySelector('arc-switch');
  arcSwitch.reportValidity();
</script>

As the user interacts with a form control, its invalid attribute will reflect its validity based on its current value and the constraints that have been defined. When a form control is invalid, the containing form will not be submitted. Instead, the browser will show the user a relevant error message.

All form controls support validation, but not all validation props are available for every component. Refer to a component's documentation to see which validation props it supports.

Custom validation

To create a custom validation error, pass a non-empty string to the setCustomValidity() method. This will override any existing validation constraints. The form will not be submitted when a custom validity is set and the browser will show a validation error when the containing form is submitted. To make the input valid again, call setCustomValidity() again with an empty string.

<form>
  <arc-switch name="arc_is_great" value="true">Do you love arc?</arc-switch>
  <arc-button submit>Submit</arc-button>
</form>

<script type="module">
  const arcSwitch = document.querySelector('arc-switch');
  arcSwitch.setCustomValidity('This will never submit the form!');

  const form = document.querySelector('form');
  form.addEventListener('submit', (e) => {
    e.preventDefault();
    console.log(form.checkValidity());
  });
</script>

Flash of unstyled content (FOUC)

A flash of unstyled content (FOUC, also flash of unstyled text) is an instance where a web page appears briefly with the browser's default styles prior to loading an external CSS stylesheet, due to the web browser engine rendering the page before all information is retrieved. The page corrects itself as soon as the style rules are loaded and applied; however, the shift may be distracting or even seem unprofessional. These problems can be resolved by using the built-in noFOUC() utility function as shown below. This will only display the content once the document.readyState is equal to 'complete'.

<body>
  <arc-container></arc-container>
  <script>
    import '@arc-web/components;
  </script>
</body>
import { noFOUC } from '@arc-web/components/utilities/style-utils.js';

noFOUC();

Server Side Rendering (SSR)

Server-side rendering (SSR) is a technique for generating and serving the HTML of your components, including shadow DOM and styles, before their JavaScript implementations have loaded and executed.

You can use SSR for a variety of reasons:

  • Performance. Some sites can render faster if they render static HTML first without waiting for JavaScript to load, then (optionally) load the page's JavaScript and hydrate the components.
  • SEO and web crawlers. While the major search-engine web crawlers render pages with full JavaScript-enabled browsers, not all web crawlers support JavaScript.
  • Robustness. Static HTML renders even if the JavaScript fails to load or the user has JavaScript disabled.

For a deeper dive into server-side rendering concepts and techniques generally, see Rendering on the Web on web.dev.

Playgrounds

Prebuild playgrounds provide examples of how to use ARC components in various frameworks and environments:

  • Angular An Angular application build with the Angular CLI.
  • LIT A LIT application build and bundled with Vite.
  • React A React application build and bundled with Vite.
  • Vue A Vue application build and bundled with Vite.
  • Vanilla JS A Vanilla JS application build and bundled with Vite.
  • Node SSR A Node application that uses The Koa framework to server side render and hydrate ARC components.
  • Node Prerender A Node application that prerenders a static index.html file that included *ARC components.
Running Playgrounds Locally

To run a playground locally, clone the repository and run the following commands:

nix develop
npm ci
npx nx run <playground-name>:serve

Readme

Keywords

none

Package Sidebar

Install

npm i @arc-web/components

Weekly Downloads

498

Version

3.0.1

License

none

Unpacked Size

7.96 MB

Total Files

4043

Last publish

Collaborators

  • tom-m-arup
  • dominicegginton
  • cerimorse
  • jasperwieringa