Unified UX relies on a host of popular technologies. Here we signpost you to some self-learning resources to get you up to speed quickly. As a starting point, it is assumed that developers are familiar with HTML and JavaScript.

  1. Web Components Crash Course
  2. Building Web Components with lit-html
  3. An introduction to writing raw web components. Get hands on experience by downloading the zip containing example code for creating web component- webcomponent-code.zip
  1. TypeScript Tutorial - TypeScript for React - Learn TypeScript -2020
  2. In-Depth TypeScript Tutorials for 2021
  3. TypeScript Cheatsheet
  1. Lit Tutorial
  2. Web Components Integration using LitElement and TypeScript
  3. LitElement app tutorial part 1: Getting started
  4. Lit playground/sandpit site
  5. Plugin for VS Code

Lit TypeScript starter project

Download the ts starter kit lit-element-starter-ts-main.zip. Unzip, explore to the folder and use ‘cmd’…

npm i
npm audit fix &:: tidy any deprecated packages
npm run build &:: to compile the ts from the /src folder into js
npm run serve &:: to run the web server

browse to http://localhost:8000/ (port may vary!!!) put your ts in the src folder

Lit-VSCode-Extension This VS Code extension is really helpfullit-vcode extension. In a new folder…

npm init @vitejs/app --template lit-element-ts &:: We want a lit ts install
cd lit-element-ts
npm install
npm run dev

That runs a web server on port 3000 using the files in the (current) folder C:\D\UUX\lit-element-ts.

Simple Example TS:

import {html, css, LitElement} from 'lit';
import {customElement, property} from 'lit/decorators.js';
export class SimpleGreeting extends LitElement {
static styles = css`p { color: blue }`;
name = 'Somebody';
render() {
return html`<p>Hello, ${this.name}!</p>`;


import {html, css, LitElement} from 'lit';
export class SimpleGreeting extends LitElement {
static styles = css`p { color: blue }`;
static properties = {
name: {type: String},
constructor() {
this.name = 'Somebody';
render() {
return html`<p>Hello, ${this.name}!</p>`;
customElements.define('simple-greeting', SimpleGreeting);


<simple-greeting name="World"></simple-greeting>

More detailed example with buttons

import {LitElement, html, css} from 'lit';
import {customElement, property} from 'lit/decorators.js';
export class MyElement extends LitElement {
// Styles are scoped to this element: they won't conflict with styles
// on the main page or in other components. Styling API can be exposed
// via CSS custom properties.
static styles = css`
:host {
display: inline-block;
padding: 10px;
background: lightgray;
.planet {
color: var(--planet-color, blue);
// Define reactive properties--updating a reactive property causes
// the component to update.
@property() greeting = "Hello";
@property() planet = "World";
// The render() method is called any time reactive properties change.
// Return HTML in a string template literal tagged with the `html`
// tag function to describe the component's internal DOM.
// Expressions can set attribute values, property values, event handlers,
// and child nodes/text.
render() {
return html`
<span @click=${this.togglePlanet}
<span class="planet">${this.planet}</span>
// Event handlers can update the state of @properties on the element
// instance, causing it to re-render
togglePlanet() {
this.planet = this.planet === "World" ? "Mars" : "World";


<!DOCTYPE html>
<script type="module" src="./my-element.js"></script>
.mars {
--planet-color: red;
<hr />
<my-element class="mars" planet="Mars"></my-element>

Vanilla Router supports simple navigation between so-called “pages” in a single page web application. The route/page name is seen after a # in the url shown by the browser. e.g. http://ip:port/mypage.html#main

When routing (“navigateTo”) occurs, a function is run that can re-render some, or all, of the page.

To install

npm install vanilla-router

To include in your html page

<script defer src="./node_modules/vanilla-router/index.js"></script>

Setup script

function beforeRoute(){
// optional hook function to execute before any navigation
function afterRoute(){
// optional hook function to execute after any navigation
var router = new Router({
    mode: 'hash',
    root: '/CSA.html',
    hooks: {
        before: function (newPage) {
            if (logging) {console.info('Before page loads hook', newPage);}
            beforeRoute();         },
        after: function (newPage) {
            if (logging) {console.info('After page loads hook', newPage);}
    page404: function (path) {
        console.log('"/' + path + '" Page not found');
router.add('main', function () {
    if (logging) {console.log('router main');}
router.add('txndet', function () {
    if (logging) {console.log('router txndet');}
// activate and make available globally
window.router = router;

Function to navigate to main (the main page layout)…

// function to route “main” to re-render so page returns to “normal”
// i.e the “content” div is shown and everything else is hidden or empty
function loadMain(){
    const emptyHtml = html``;
    // Ensure rendered popup, card and iframe are blank
    render(emptyHtml, document.body.querySelector('.popuphost'));
    // Show standard content only, not any alternate content

Function to navigate to txndet (a page layout that includes a popup showing transaction details)…

// function to route “txndet” to render the transaction details popup in div .popuphost
function loadTxnDet(){
    if (logging) {console.log('loading TxnDet');}
// this is the actual html to be rendered
    const popupHtml = html`
        <transaction-details class="ea transactiondetails popupESC" instance="0" transactiondata="${sessionStorage.getItem('txndet_transactiondata')}" accountid="${sessionStorage.getItem('txndet_accountid')}"></transaction-details>
// render it into a div called popuphost
    render(popupHtml, document.body.querySelector('.popuphost'));
//post-rendering actions (could be anything you need)...
    setTimeout( function(){
        var txnpopup = document.getElementsByClassName("transactiondetails");

Using vanilla-router to navigate…

// use this to “goto” the main page layout
// or use this to goto/show the txndet popup
    sessionStorage.setItem('txndet_accountid', myAccountId);
    sessionStorage.setItem('txndet_transactiondata', myTransactionData);

In order to access APIs in varying locations, it is necessary to run a cors proxy on your machine. If you do not, the browser will issue a cross-origin error.

Extract the cors-cache-proxy.zip from the resources folder and run the command below to run a proxy on port 8080.

npm start

Any API calls must use the prefix http://localhost:8080/ e.g. http://localhost:8080/

Whilst this looks strange, the proxy accepts the request and forwards it on to the specified URL.

More reading on CORS: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS

  1. UUX grid example
  2. Grid system explainer
  3. UUX grid component usage
  1. Dynamic Module Imports in JavaScript

New user agents will use the Temenos Explorer. However, you can wrap a web component for use in Visualizer by following this video: