Skip to the page
Tactile UI

Start here

Using a framework

The objects are framework-free on purpose: a class that takes an element. Every framework can hand one over. The pattern is always the same: create on mount, update when options change, destroy on unmount.

On this page
  1. React
  2. Vue
  3. Svelte
  4. Astro
  5. Server rendering

The quickest way is the wrapper that ships in every package: wrappers/react.mjs, vue.mjs, svelte.mjs, or element.mjs for a custom element that works in Angular, Astro or a plain page. On any piece's page, pick your framework in the Code tab and it writes the example with your settings. Below is what the wrappers do for you, if you'd rather wire it yourself.

React

import { useEffect, useRef } from 'react';
import { Odometer } from './odometer/odometer.mjs';
import './odometer/odometer.css';

export function Seats({ value }) {
  const host = useRef(null);
  const odo = useRef(null);

  useEffect(() => {
    odo.current = new Odometer(host.current, { value, digits: 3 });
    return () => odo.current.destroy();
  }, []);

  useEffect(() => { odo.current?.setValue(value); }, [value]);

  return <div ref={host} />;
}

In Next.js, put 'use client' at the top of the file: the objects draw in the browser.

Vue

<script setup>
import { onMounted, onBeforeUnmount, ref, watch } from 'vue';
import { Iris } from './iris/iris.mjs';
import './iris/iris.css';

const props = defineProps({ open: Number });
const host = ref(null);
let iris;

onMounted(() => { iris = new Iris(host.value, { driver: 'manual' }); });
watch(() => props.open, (v) => iris?.open(v));
onBeforeUnmount(() => iris?.destroy());
</script>

<template><div ref="host"><img src="/work.jpg" alt="The project"></div></template>

Svelte

<script>
  import { onMount } from 'svelte';
  import { PinScreen } from './pin-screen/pin-screen.mjs';
  import './pin-screen/pin-screen.css';

  export let text = 'HELLO';
  let host, board;

  onMount(() => {
    board = new PinScreen(host, { text });
    return () => board.destroy();
  });
  $: board?.update({ text });
</script>

<div bind:this={host} style="height: 420px"></div>

Astro

<div id="vessel" style="height: 360px"></div>
<link rel="stylesheet" href="/vessel/vessel.css" />
<script>
  import { Vessel } from '../vessel/vessel.mjs';
  new Vessel(document.getElementById('vessel'), { level: 0.62 });
</script>

Server rendering

The objects touch window, document and the canvas, so construct them only in the browser: in an effect, onMount, a client script or behind a dynamic import. Rendering the empty host element on the server is fine; it is what the object fills.