Crux
GuidesPlans & Tasks

Reactive UI

Subscribe to plans and task ledgers from React with canonical hooks.

React exposes canonical hooks for plan and task-ledger reads:

import { usePlan, useTasks } from "@use-crux/react";

function WorkPanel({
  planId,
  taskListId,
}: {
  planId?: string;
  taskListId?: string;
}) {
  const planState = usePlan(planId);
  const tasksState = useTasks(taskListId);

  if (!planId || !taskListId) return null;
  if (planState === undefined || tasksState === undefined)
    return <p>Loading...</p>;
  if (planState === null) return <p>Plan not found.</p>;

  return (
    <section>
      <h2>{planState.title}</h2>
      <ul>
        {tasksState.map((item) => (
          <li key={item.id}>
            <span>{item.label}</span>
            <span>{item.status}</span>
          </li>
        ))}
      </ul>
    </section>
  );
}

Hooks also accept handles:

function WorkPanel({
  roadmap,
  work,
}: {
  roadmap?: PlanHandle;
  work?: TasksHandle;
}) {
  const planState = usePlan(roadmap);
  const tasksState = useTasks(work);
  // ...
}

Passing undefined skips the subscription. This is useful while a creation tool has not created an entity yet.

Status Display

Use the core status vocabulary directly:

const toneByStatus = {
  pending: "muted",
  in_progress: "active",
  completed: "success",
  failed: "danger",
  skipped: "muted",
  cancelled: "warning",
} as const;

Task progress is a message string. Treat numeric progress as a separate UI concern.

Devtools

Crux devtools projects canonical plan and task activity into the Plans views. Task failures, skipped tasks, cancellations, removals, and discarded ledgers keep their own statuses instead of collapsing into pending.

On this page