Design
llms.txt digitalcrew.tech

Motion

JoyfulTaskCheckbox

A task checkbox with a small, restrained completion moment: one soft bloom, two sparks, then stillness.

MaxMotionDigitalCrew.JoyfulTaskCheckbox
JoyfulTaskCheckbox · liveOpen

Guidelines#

Tasks and Pipeline both use it.

Use it for completing a task, a one-way action. It checks at once and asks you to confirm the write.

What you provide

  • checked and label, which is the accessible name.
  • onComplete(), which returns Promise<boolean>. Resolve false if the write was refused and the control settles back to idle.
  • Optional: disabled (default false), disabledReason (shown as a title and an aria-description) and className.

Anatomy

  • A size-6 box with a rounded-[6px], border-2 border-foreground/65 edge on bg-background. Hover gives border-foreground bg-muted/60.
  • Checked: border-emerald-500 bg-emerald-500 text-white.
  • Disabled: border-foreground/45 bg-muted/30 at full opacity.
  • The hit area extends 10px beyond the box (after:-inset-2.5), and focus shows a 2px ring with a 2px offset.

Motion (CSS, while the write is pending)

  • task-complete-pop: scale 0.82 to 1.18 to 1 over 360ms, cubic-bezier(0.22, 1, 0.36, 1).
  • A halo in border-emerald-400/70 grows from 0.75 to 2.35 and fades out over 520ms ease-out.
  • Two 4px sparks: emerald-400 flies up-left (480ms) and amber-300 up-right (520ms, 35ms delay).
  • The check mark turns in from scale 0.55 and −8° over 240ms.
  • prefers-reduced-motion turns all of it off. It is still a real, labelled checkbox to assistive technology.

Don't use it for settings or anything that can be unchecked (a checked box is disabled), and don't add confetti on top.

Facts#

GroupMotion
ProductMax
Globalwindow.DigitalCrew.JoyfulTaskCheckbox
Sourcemax-agent: src/features/tasks/ui/joyful-task-checkbox.tsx
Import in the appimport { JoyfulTaskCheckbox } from "@/features/tasks/ui/joyful-task-checkbox";

API#

TypeScript declarations emitted from src/features/tasks/ui/joyful-task-checkbox.tsx.

interface JoyfulTaskCheckboxProps {
    checked: boolean;
    disabled?: boolean;
    disabledReason?: string;
    label: string;
    className?: string;
    /**
     * Return false when the write was refused. The control then settles back to
     * its idle state instead of leaving an optimistic check on screen.
     */
    onComplete(): Promise<boolean>;
}
/**
 * A restrained completion moment shared by Tasks and Pipeline.
 *
 * The check fills immediately so the click feels responsive, then the caller
 * confirms whether the canonical task write succeeded. Motion is CSS-only and
 * disappears under prefers-reduced-motion; the control remains a real,
 * labelled checkbox to assistive technology.
 */
export declare function JoyfulTaskCheckbox({ checked, disabled, disabledReason, label, className, onComplete, }: JoyfulTaskCheckboxProps): JSX.Element;

Example#

The code of the preview above: plain React.createElement against window.DigitalCrew, with realistic data.

<div id="root" class="p-6"></div>
<script>
(function () {
  var h = React.createElement, DC = window.DigitalCrew, I = DC.Icons;
  var TASKS = [
    { id: "t1", title: "Send Claire Dubois the Thursday call agenda", meta: "Due today · Northwind Traders" },
    { id: "t2", title: "Log the discovery call with Marcus Reinholt", meta: "Due today · Brightline Logistics" },
    { id: "t3", title: "Follow up on the Brightline pilot proposal", meta: "Due Fri · Tomás Alvarez" }
  ];
  function App() {
    var d = React.useState({}), done = d[0], setDone = d[1];
    var k = React.useState(0), round = k[0], setRound = k[1];
    function completer(id) {
      return function () {
        return new Promise(function (resolve) {
          setTimeout(function () {
            setDone(function (x) { var n = Object.assign({}, x); n[id] = true; return n; });
            resolve(true);
          }, 700);
        });
      };
    }
    React.useEffect(function () {
      // Complete two tasks on their own so the burst plays without a click
      // (the second lands where a still capture at ~1.5s catches it mid-bloom).
      function tick(id) {
        var box = document.querySelector('[data-auto="' + id + '"] button[role="checkbox"]');
        if (box) box.click();
      }
      var a = setTimeout(function () { tick("t2"); }, 600);
      var b = setTimeout(function () { tick("t3"); }, 1350);
      return function () { clearTimeout(a); clearTimeout(b); };
    }, [round]);
    var count = Object.keys(done).length;
    return h("div", { className: "mx-auto max-w-[520px] rounded-2xl border border-border/60 bg-card p-2 shadow-sm" },
      h("div", { className: "flex items-center justify-between px-3 pb-1 pt-2" },
        h("span", { className: "text-sm font-semibold" }, "Today"),
        h("button", { type: "button", className: "text-xs text-muted-foreground hover:text-foreground",
          onClick: function () { setDone({}); setRound(round + 1); } }, count + " of 3 done · reset")),
      TASKS.map(function (t) {
        var checked = !!done[t.id];
        return h("div", { key: t.id + round, "data-auto": t.id, className: "flex items-center gap-3 rounded-xl px-3 py-2.5 hover:bg-muted/40" },
          h(DC.JoyfulTaskCheckbox, { checked: checked, label: "Complete: " + t.title, onComplete: completer(t.id) }),
          h("div", { className: "min-w-0 flex-1" },
            h("div", { className: "truncate text-sm font-medium transition-colors " + (checked ? "text-muted-foreground line-through" : "") }, t.title),
            h("div", { className: "text-xs text-muted-foreground" }, t.meta)));
      }));
  }
  ReactDOM.createRoot(document.getElementById("root")).render(h(DC.TooltipProvider, { delayDuration: 80 }, h(App)));
})();
</script>