Getting started

Your first field

Eight short steps from npm install to a headline that gains weight and glow as the field pools around it. Every step is runnable on its own — paste, save, watch.

1. Install

Pick the entry point for your stack. The rest of this tutorial uses the web component.

npm i @field-ui/elements

2. Drop the field

One field lives behind your whole page. Register the element and drop a single <field-root> — it mounts a fixed, full-viewport canvas and starts the engine. Nothing reacts yet; there are no bodies.

<script type="module">
  import '@field-ui/elements';
</script>

<!-- one field, behind everything -->
<field-root accent="#4da3ff"></field-root>

3. Add your first body

A body is any element with data-body. Mark your headline an attract body and the field starts pulling matter toward it. Move the element and the force moves with it — the engine re-reads its box every frame.

HTML
<h1 data-body="attract" data-strength="0.9" data-range="320">
  field-ui
</h1>
attract what your headline now does to nearby matter
React note. Components render their bodies after the field mounts, so call field.scan() once from onReady to pick them up.
React
// bodies are plain elements anywhere in your tree
<h1 data-body="attract" data-strength="0.9" data-range="320">
  field-ui
</h1>

// React renders bodies after the field mounts — rescan once they're in:
<FieldField accent="#4da3ff" onReady={(field) => field.scan()} />

4. Make the type react

This is the payoff. Add data-feedback and the field writes the density it gathered back to your element as the --d custom property (∈ [0, 1], low-pass filtered so it eases). Drive weight and glow from it — the word grows where matter collects.

HTML + CSS
<h1 data-body="attract" data-range="320" data-feedback>field-ui</h1>

<style>
  h1 {
    --d: 0;  /* the engine eases this in, density ∈ [0,1] */
    font-variation-settings: 'wght' calc(380 + var(--d) * 420);
    text-shadow: 0 0 calc(var(--d) * 36px) rgba(77, 163, 255, var(--d));
  }
</style>
Words glow, they are never drawn. The text stays real, selectable, and accessible — --d only enhances it; particles never assemble into letterforms.

5. Compose another force

Forces compose, space-separated. Add swirl and your headline now both pulls and spins the matter around it. Each force reads only the attributes it uses — swirl takes data-spin; attract ignores it.

HTML
<h1
  data-body="attract swirl"
  data-strength="0.9"
  data-range="320"
  data-spin="1"
  data-feedback
>field-ui</h1>
swirl the spin you just composed on top of attract

6. Gate it on a condition

A force can act only when a condition holds, via data-when. Mark an element data-hot so hover and keyboard focus set its engaged state, then gate the force on active — it swirls only while the link is engaged.

HTML
<a data-hot data-body="swirl" data-when="active" data-spin="1" data-range="220">
  hover me
</a>

7. Drive it from code

Every entry point hands you a FieldHandle. With the web component it's proxied onto the element, so you can reshape the field and react to events:

JavaScript
const field = document.querySelector('field-root');

// a global bias on every particle
field.setFormation('wells');

// a one-shot shove + heat at the cursor
document.addEventListener('click', (e) => field.burst(e.clientX, e.clientY));

8. Where to go next