Language for UI's

A native DSL for accessible interface decisions.

Language for UI's

Valence is the Web Component design system behind Portfoliable.js. Built in Storybook, it uses native custom elements instead of tying the system to a single framework. A component can be consumed by Portfoliable today and remain available to another JavaScript application tomorrow.[1][2]

Screenshot of a Valence component in Storybook

The components encapsulate behavior and styles through Shadow DOM. Application styles do not accidentally rewrite a button, and a component can evolve without requiring every consumer to copy its CSS. This also keeps the design system close to the browser’s native model—attributes, slots, events, and semantic HTML.

import '@portfoliablejs/valence';

const button = document.createElement('ds-button');
button.setAttribute('label', 'Open case');
button.setAttribute('variant', 'primary');
document.querySelector('#actions').append(button);

A structure that scales with the interface

The library follows an Atomic Design vocabulary, but uses it as an engineering map rather than a taxonomy for its own sake:

Layer What it contains Why it matters
Sub-atoms Tokens, accessibility modes, motion and typography rules Establishes the visual language
Atoms Button, Icon, Toggle, Pill, Tab, Loader Makes primitive behavior reusable
Molecules Summary, Tooltip, Navigation Menu, Video Controls Encodes recurring interaction patterns
Organisms Header, Article, Gallery, Video Player Solves complete interface responsibilities
Templates Case View, Home View, Player View Composes product-level experiences

This separation makes changes easier to reason about. A spacing adjustment belongs to a token; a keyboard interaction belongs to the component that owns it; a reading-flow decision belongs to the consuming template.

flowchart TD subgraph Entry ["DOM Mountpoint (main.js)"] AppShell["<app-shell> (AppShell Class)"] end subgraph Shell ["App Shell Shadow DOM Boundary"] Header["<ds-header id='app-header'>"] Main["<main> Viewport Container"] Toast["<ds-toast id='app-toast'>"] ModalContainer["#modal-container"] VideoPlayer["<ds-video-player id='video-player'>"] end subgraph Views ["Dynamic View Containers"] HomeView["#view-home (<ds-home-view>)"] CaseView["#view-case (<ds-case-view>)"] end subgraph Components ["Valence Component Instances"] GalleryItem["<ds-gallery-item>"] Article["<ds-article>"] Modals["<ds-modal> / <ds-item-row>"] end AppShell --> Header AppShell --> Main AppShell --> Toast AppShell --> ModalContainer AppShell --> VideoPlayer Main --> HomeView Main --> CaseView HomeView --> GalleryItem CaseView --> Article ModalContainer --> Modals

Storybook as a development surface

Storybook is more than a catalog here. It is the place where a component’s API, edge cases, visual states, and accessibility behavior become inspectable. The Canvas gives immediate feedback; the Docs tab explains the contract; controls let a developer test real prop combinations without first wiring a full application.

export const Reflow = {
  args: {
    label: 'reflow',
    count: 3,
    background: '#7ED321'
  }
};

That workflow changes the feedback loop. Instead of asking whether a component works only inside a page, the team can ask better questions earlier: Does a long label reflow? Is the focus state visible? What happens when the count changes? Can the same API represent loading and disabled states?

Controls for a Valence component in Storybook

Accessibility is a global capability

Valence treats accessibility as a system-level concern. The consuming application can toggle modes from the document root and let the component library respond consistently:

<html class="a11y-dark-mode a11y-focus-mode">
  <body>
    <ds-header></ds-header>
  </body>
</html>

In Storybook, these modes appear as global controls, allowing accessibility to be evaluated as part of normal development rather than only as a final audit. With Portfoliable, the runtime can handle user preferences and state, while Valence handles the visual response.

Integration without losing boundaries

Portfoliable consumes Valence through ordinary Web Platform contracts. Simple state travels through attributes; rich content enters through slots; user actions return as namespaced custom events:

<ds-case-view
  title-text="Designing a clearer onboarding flow"
  show-language-menu="true">
  <article slot="content">
    <h2>Outcome</h2>
    <p>The case narrative remains owned by the application.</p>
  </article>
</ds-case-view>

This division keeps responsibilities clear. Valence provides the interaction surface and visual language; Portfoliable provides case data, routes, localization, and product context.

The result

Valence is the layer that allows Portfoliable to be coherent without making every case look the same. It turns interface craft into shared infrastructure while keeping it close to the open web.

What I would do differently

If I started Valence again, I would make some choices more explicit from the beginning:

These changes would not alter the project’s direction, but they would make its decisions more sustainable. The goal would be to preserve Web Component portability and accessibility as a global capability while reducing the system’s weight, complexity, and cost of evolution.

Explore the Valence repository or see how it supports the Portfoliable runtime.


  1. Solo project: Lio Schimanko worked as the UX Designer and Developer. ↩︎

  2. Valence evolved from a pre-release version to version 1.1.2, its latest release. ↩︎