Get Started
Introduction
Components
Accordion
Badge
Button
Card
Checkbox
Command
Dialog
Dropdown Menu
Input
Select
Switch
Table
Tabs
Toast
Tooltip
Forms
Introduction
Validation
Field Arrays

State Machine Playground

Interactive state machine explorer with preset workflows, per-state multi-conditional classes that flip together on transition, a reactive transitions loop source, and a history memo chain that filters and groups derived views.

#Preview

A classic three-state loop with a maintenance detour.
Current: Red
Current
Red
Visited
1 / 4
Possible now
2
Events fired
0

States

4 total

Transitions

History

0 events

No transitions yet. Click a transition to fire it.

1"use client"23import { createSignal, createMemo } from '@barefootjs/client'45// Each state node evaluates three independent conditional classes6// (isCurrent / isReachable / isVisited). Firing a single transition7// flips all three across multiple list items at once — the compiler8// must wire reactive className bindings inside the states loop so9// every affected node updates on the next microtask.1011function StateMachinePlayground() {12  const [machineId, setMachineId] = createSignal('traffic-light')13  const [currentState, setCurrentState] = createSignal(machine().initial)14  const [history, setHistory] = createSignal<HistoryEntry[]>([])15  const [onlyPossible, setOnlyPossible] = createSignal(false)16  const [historySearch, setHistorySearch] = createSignal('')17  const [groupBy, setGroupBy] = createSignal<'none' | 'event' | 'target'>('none')1819  const machine = createMemo(() => MACHINES.find(m => m.id === machineId())!)2021  // Drives the "reachable" highlight on state nodes.22  const possibleTransitions = createMemo(() =>23    machine().transitions.filter(t => t.from === currentState())24  )2526  // The transitions loop source itself is reactive.27  const visibleTransitions = createMemo(() =>28    onlyPossible() ? possibleTransitions() : machine().transitions29  )3031  // 3-level history memo chain: raw → filtered → grouped.32  const historyFiltered = createMemo(() => /* filter by search */)33  const historyGroups = createMemo(() => /* group by mode */)3435  return (36    <div>37      {/* Every state node has three conditional classes that flip together. */}38      {machine().states.map(s => (39        <button key={s.id}40          className={`state-node${s.id === currentState() ? ' state-current' : ''}${possibleTargetIds()[s.id] ? ' state-reachable' : ''}${visitedSet()[s.id] ? ' state-visited' : ''}`}41          onClick={() => setCurrentState(s.id)}42        >43          {s.label}44        </button>45      ))}4647      {/* Loop source may be the full list OR the filtered one. */}48      {visibleTransitions().map(t => (49        <button key={t.id}50          disabled={t.from !== currentState()}51          onClick={() => fireTransition(t)}52        >53          {t.event}: {t.from} → {t.to}54        </button>55      ))}5657      {/* Loop-of-loops over the grouped history. */}58      {historyGroups().map(g => (59        <div key={g.key}>60          <h4>{g.key}</h4>61          {g.entries.map(e => (62            <div key={String(e.id)}>{e.event}: {e.from} → {e.to}</div>63          ))}64        </div>65      ))}66    </div>67  )68}

#Features

Many Conditionals Switching Simultaneously

Every state node evaluates three independent conditional classes —isCurrent,isReachableFromCurrent, andisVisited — inside the same.map() body. Firing one transition flips all three conditions for multiple list items at once, exercising reactive className binding wiring across every loop item on a single signal update.

Dynamic Transition List

The "Only possible" toggle switches the transitions loop source between the full machine transition array and thepossibleTransitions() filter. Toggling it shrinks or grows the rendered list entirely — the compiler must re-run the loop with a different source signal without stale list items left behind.

Machine Switching Reshapes Loop Structure

Selecting a different preset replaces the states, transitions, and initial state all at once via selectMachine(). Every loop on the page (states, transitions, history) re-renders against completely new source data, stressing the compiler's key-based reconciliation.

History Filter/Group Memo Chain

History rendering uses a three-level memo chain:historyhistoryFiltered (search text) →historyGroups (mode: none / event / target). The outer grouped loop and each group's inner entries loop both react to signal changes upstream in the chain. Group keys change as the grouping mode changes, so every list item's key identity shifts.