zebflow 0.10.10

Reactive web automation platform — pipelines, templates, and real-time collaboration in a single binary.
Documentation
import { cx } from "zeb/react";
import { CodeBlock } from "zeb/ui/code-block";

/**
 * The scaffolding every gallery section is built from. A section is a list
 * of `Entry`s; an entry is a heading, a live demo on a card, and the code
 * that produced it. Nothing here is a primitive — the primitives live in
 * `components/ui/` and this page only shows them.
 */

export function SectionHeading({ title, description }) {
  return (
    <div className="mb-8">
      <h2 className="text-2xl font-bold tracking-tight text-foreground">{title}</h2>
      {description ? <p className="mt-1.5 max-w-2xl text-sm text-muted-foreground">{description}</p> : null}
      <div className="mt-5 h-px bg-border" />
    </div>
  );
}

export function SubHeading({ title }) {
  return (
    <h3 className="mb-4 mt-10 text-[0.68rem] font-bold uppercase tracking-widest text-muted-foreground first:mt-0">
      {title}
    </h3>
  );
}

/** A live demo sits on a card so surface tokens are visible against the page. */
export function Demo({ children, className }) {
  return <div className={cx("rounded-xl border border-border bg-card p-6 text-card-foreground", className)}>{children}</div>;
}

/** The code that produced a demo — zeb/ui's own CodeBlock, so the gallery eats its own cooking. */
export function SampleCode({ code, language = "tsx" }) {
  return <CodeBlock className="mt-3" language={language} code={code} />;
}

/**
 * One component. `file` is the path under `components/ui/` — the guard in
 * tests/rwe reads these to prove every primitive is on the page.
 */
export function Entry({ name, file, description, children, code, demoClassName }) {
  return (
    <div className="mb-12" data-gallery-entry={file}>
      <div className="mb-3 flex items-start gap-4">
        <div className="flex-1">
          <h3 className="text-base font-semibold text-foreground">{name}</h3>
          {description ? <p className="mt-0.5 text-sm text-muted-foreground">{description}</p> : null}
        </div>
        <code className="shrink-0 whitespace-nowrap rounded border border-border bg-muted px-2 py-1 font-mono text-[0.68rem] text-muted-foreground">
          {file.includes("/") ? file : `ui/${file}`}
        </code>
      </div>
      <Demo className={demoClassName}>{children}</Demo>
      {code ? <SampleCode code={code} /> : null}
    </div>
  );
}

/** A variant × size grid: one row per variant, one column per size. */
export function Matrix({ rows, cols, render, rowLabel = "variant", colLabel = "size" }) {
  return (
    <div className="overflow-x-auto">
      <table className="w-full border-collapse text-sm">
        <thead>
          <tr>
            <th className="pb-2 pr-4 text-left font-mono text-[0.65rem] font-normal uppercase tracking-wider text-muted-foreground">
              {rowLabel} \ {colLabel}
            </th>
            {cols.map((c) => (
              <th key={c} className="pb-2 pr-4 text-left font-mono text-[0.65rem] font-normal uppercase tracking-wider text-muted-foreground">
                {c}
              </th>
            ))}
          </tr>
        </thead>
        <tbody>
          {rows.map((r) => (
            <tr key={r} className="border-t border-border">
              <td className="py-2.5 pr-4 font-mono text-xs text-muted-foreground">{r}</td>
              {cols.map((c) => (
                <td key={c} className="py-2.5 pr-4 align-middle">
                  {render(r, c)}
                </td>
              ))}
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
}

/** A theme token as it currently resolves, with its name. */
export function TokenSwatch({ token, foreground }) {
  return (
    <div className="flex items-center gap-3">
      <span
        className="h-9 w-9 shrink-0 rounded-md border border-border"
        style={{ background: `var(--${token})` }}
      >
        {foreground ? (
          <span className="flex h-full w-full items-center justify-center font-mono text-[0.7rem]" style={{ color: `var(--${foreground})` }}>
            Aa
          </span>
        ) : null}
      </span>
      <div className="min-w-0">
        <div className="truncate font-mono text-xs text-foreground">--{token}</div>
        {foreground ? <div className="truncate font-mono text-[0.65rem] text-muted-foreground">--{foreground}</div> : null}
      </div>
    </div>
  );
}