Using the components

Attributes, properties, events and framework integration.

The components are standard custom elements. Everything below is plain DOM and needs no framework, followed by the details each framework adds.

Attributes and properties

Each parameter can be set either as an HTML attribute or as a JavaScript property. The name differs between the two:

  • Attribute written in HTML, always lowercase: iconright
  • Property set from JavaScript, in camelCase: iconRight
<!-- attribute -->
<tuix-input iconright="search"></tuix-input>
<tuix-input descriptiontype="error" description="Required"></tuix-input>
// property
input.iconRight = 'search'
input.descriptionType = 'error'

Every component page lists both names side by side. Most attributes are the property name in lowercase; two are written with a hyphen:

PropertyAttributeElement
borderRadiusborder-radiustuix-paper
visibilityDurationvisibility-durationtuix-toast

Objects and arrays

Attribute values are always text. The parameters that take an object or an array are therefore set as properties:

ElementParameters
tuix-dropdownoptions, value
tuix-radio-buttonoptions
tuix-tabledata, headers, pageSizeOptions, loader
const table = document.querySelector('tuix-table')
table.headers = [{ name: 'Name', dataKey: 'name', width: 30 }]
table.data = [{ id: 1, name: 'Alice' }]

In a plain HTML page there is no JavaScript to do that, so the value goes into the attribute as JSON instead:

<tuix-dropdown options='["Draft", "Sent", "Paid"]'></tuix-dropdown>

JSON cannot carry functions, so a header that uses cellColor has to be set as a property.

The next section shows how each framework sets a property.

Passing a parameter

Every parameter falls into one of five kinds, and each framework has one way of passing each. The tabs show the same dropdown written three times: a string, an enum, an object list, the shared dark boolean and an event.

example.component.html
<tuix-dropdown
    title="Country"
    description="Pick a country"
    [type]="DropdownType.SEARCH"
    [descriptionType]="DescriptionType.ERROR"
    [options]="countries"
    [dark]="isDark"
    (select)="onSelect($event)"
></tuix-dropdown>
example.component.ts
import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'
import { DescriptionType, DropdownType } from 'tuix-webcomponents'

@Component({
    selector: 'app-example',
    standalone: true,
    schemas: [CUSTOM_ELEMENTS_SCHEMA],
    templateUrl: './example.component.html',
})
export class ExampleComponent {
    readonly DescriptionType = DescriptionType
    readonly DropdownType = DropdownType

    readonly countries = [
        { name: 'Switzerland', value: 'CH' },
        { name: 'Germany', value: 'DE' },
    ]

    isDark = false

    onSelect(event: Event) {
        const { value } = (event as CustomEvent<{ value: string | number | boolean }>).detail
        console.log(value)
    }
}
KindPlain HTMLAngularVueReact
Stringtitle="Country"samesametitle="Country"
Enumtype="search"[type]:typetype={...}
Boolean, dark includeddark[dark]:darkdark={...}
Object or arrayJSON[options]:optionsoptions={...}
EventaddEventListener(select)@selectonSelect={...}

Dark mode

Every element except tuix-table takes a dark boolean. Nothing reads a global theme: the application passes dark per element, from whatever it uses to track the theme.

<tuix-button variant="primary" dark>Save</tuix-button>

dark reaches what a component renders itself (the modal hands it to its card and its close icon, the toast and the checkbox to the label they draw) and never what is slotted into it. Content of your own therefore carries its own dark:

<tuix-modal dark visible>
    <tuix-text slot="title" dark>Delete this template?</tuix-text>
    <tuix-button slot="actions" variant="primary" dark>Delete</tuix-button>
</tuix-modal>

That one exception is worth planning for: the table's own tuix-text and tuix-icon stay on the light palette whatever the page does, so a dark design gives the table a light surface rather than switching it.

Events

The components communicate through CustomEvents that bubble. The payload, when there is one, is in event.detail, which for most events means event.detail.value:

document.querySelector('tuix-input').addEventListener('on-change', (event) => {
    console.log(event.detail.value)
})

tuix-table's three pagination events are the exception: they carry event.detail.page and event.detail.pageSize and no value at all. A checkbox and a toggle put event.detail.label next to the value.

Note the names are not the native ones: a button fires customClick, an input fires on-change. The full list is in Events.

Only tuix-table's pagination events cross the shadow boundary (composed: true). The rest bubble inside the tree they were fired in, which is what a normal listener on the element or one of its ancestors sees.

In a framework

Each framework needs a little setup: a wrapper library for React, a compiler flag for Vue, a schema for Angular. One guide each, and once that is done every example on the component pages can be read in the framework picked in the tabs above it:

Plain HTML

Load the bundle with the two tags from Installation. Their URLs carry the release, so they are generated there rather than written out here. The elements are then plain tags:

<tuix-paper elevation="2" border-radius="10px">
    <tuix-text size="l" color="section">Invoice</tuix-text>
    <tuix-button variant="primary" iconleft="download">Download</tuix-button>
</tuix-paper>
 
<script>
    document.querySelector('tuix-button').addEventListener('customClick', () => {
        window.print()
    })
</script>

Slots and layout

Text content goes into the default slot of the element, and the components that have more than one region name their slots (tuix-modal: title, body, actions; tuix-table: one slot per cell). Because the content stays in the light DOM, the page's own styles still apply to it; only the component's chrome is isolated.

On this page