Documentation menu

code

Shiki-highlighted code windows: tabbed snippets with crossfade, and an annotated walkthrough with bidirectional linked highlighting.

codeshikisyntax-highlightingtabswalkthrough

Preview

greet.js
function greet(name) {
  return "Hello, " + name + "!";
}
counter.ts
let count = 0;
export const inc = () => ++count;
export const get = () => count;

Installation

Ask Claude (MCP)

With the MCP server configured, just ask:

Claude
add the moco code component

shadcn CLI

Terminal
npx shadcn@latest add https://mocoui.site/r/code.json

Manual

Copy each file from the Source section into its target path:

registry/code/code.tsx  →  components/moco/code.tsx
registry/code/code-client.tsx  →  components/moco/code-client.tsx
registry/code/code.css  →  components/moco/code.css

npm dependencies: shiki. Needs moco items: tokens

Usage

usage.tsx
import { CodeTabs, Walkthrough } from "./code";

const BEFORE = `function greet(name) {
  return "Hello, " + name + "!";
}
`;

const AFTER = `function greet(name: string): string {
  return \`Hello, \${name}!\`;
}
`;

export default function Demo() {
  return (
    <div style={{ display: "grid", gap: "2rem" }}>
      <CodeTabs
        tabs={[
          { label: "before", filename: "greet.js", lang: "js", code: BEFORE, highlight: [2], highlightTone: "warn" },
          { label: "after", filename: "greet.ts", lang: "ts", code: AFTER, highlight: [2] },
        ]}
      />

      <Walkthrough
        filename="counter.ts"
        lang="ts"
        regions={[
          {
            id: "state",
            label: "State",
            note: "A single mutable count, closed over by the returned functions.",
            code: `let count = 0;\n`,
          },
          {
            id: "api",
            label: "API",
            note: "Increment and read — the only two ways in.",
            code: `export const inc = () => ++count;\nexport const get = () => count;\n`,
          },
        ]}
        blocks={[
          { id: "state", label: "count", sub: "module state" },
          { id: "api", label: "inc / get", sub: "public api" },
        ]}
      />
    </div>
  );
}

Source

components/moco/code.tsx
import * as React from "react";
import { codeToHtml } from "shiki";
import { CodeTabsClient, WalkthroughClient, type Region } from "./code-client";
import "./code.css";

/** A light TextMate theme keyed to the moco palette. Keywords take the one accent. */
const LIGHT = {
  name: "moco-plate",
  type: "light",
  colors: {
    "editor.background": "#fcfbf9",
    "editor.foreground": "#242424",
  },
  settings: [
    { settings: { foreground: "#242424", background: "#fcfbf9" } },
    {
      scope: ["comment", "punctuation.definition.comment"],
      settings: { foreground: "#8a8477", fontStyle: "italic" },
    },
    {
      scope: ["string", "string.quoted", "constant.other.symbol", "meta.embedded.line"],
      settings: { foreground: "#3f6d33" },
    },
    {
      scope: ["keyword", "storage", "storage.type", "keyword.control", "keyword.operator.new"],
      settings: { foreground: "#5b770c" },
    },
    { scope: ["constant.numeric", "constant.language"], settings: { foreground: "#7a4b9c" } },
    {
      scope: ["entity.name.function", "support.function", "meta.function-call.generic"],
      settings: { foreground: "#1a1a1a" },
    },
    {
      scope: ["variable", "meta.definition.variable", "support.type"],
      settings: { foreground: "#242424" },
    },
    { scope: ["punctuation", "meta.brace"], settings: { foreground: "#8a8477" } },
  ],
} as const;

/** Dark twin: warm near-black ground (the dark token palette), lime takes keyword duty. */
const DARK = {
  name: "moco-plate-dark",
  type: "dark",
  colors: {
    "editor.background": "#121110",
    "editor.foreground": "#dedcd7",
  },
  settings: [
    { settings: { foreground: "#dedcd7", background: "#121110" } },
    {
      scope: ["comment", "punctuation.definition.comment"],
      settings: { foreground: "#8a8477", fontStyle: "italic" },
    },
    {
      scope: ["string", "string.quoted", "constant.other.symbol", "meta.embedded.line"],
      settings: { foreground: "#a9c98a" },
    },
    {
      scope: ["keyword", "storage", "storage.type", "keyword.control", "keyword.operator.new"],
      settings: { foreground: "#c6f24e" },
    },
    { scope: ["constant.numeric", "constant.language"], settings: { foreground: "#c9a1ec" } },
    {
      scope: ["entity.name.function", "support.function", "meta.function-call.generic"],
      settings: { foreground: "#f2f0ec" },
    },
    {
      scope: ["variable", "meta.definition.variable", "support.type"],
      settings: { foreground: "#dedcd7" },
    },
    { scope: ["punctuation", "meta.brace"], settings: { foreground: "#8a8477" } },
  ],
} as const;

export type { Region };

export interface Snippet {
  label: string;
  filename: string;
  lang: string;
  code: string;
  /** 1-indexed lines to band. Use "warn" to band them in --moco-warn instead. */
  highlight?: number[];
  highlightTone?: "true" | "warn";
  /** Where line numbering starts, for excerpted regions. */
  startLine?: number;
}

async function render(s: Snippet): Promise<string> {
  const hl = new Set(s.highlight ?? []);
  const tone = s.highlightTone ?? "true";
  return codeToHtml(s.code.replace(/\n$/, ""), {
    lang: s.lang,
    // Dual themes: tokens carry --shiki-light/--shiki-dark vars (defaultColor:
    // false); code.css switches between them with the color scheme.
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    themes: { light: LIGHT as any, dark: DARK as any },
    defaultColor: false,
    transformers: [
      {
        line(node, line) {
          if (hl.has(line)) node.properties["data-hl"] = tone;
        },
      },
    ],
  });
}

/** Window chrome, line numbers, line highlights, tabs bottom-right. */
export async function CodeTabs({ tabs }: { tabs: Snippet[] }) {
  const html = await Promise.all(tabs.map(render));
  return (
    <CodeTabsClient
      labels={tabs.map((t) => t.label)}
      filenames={tabs.map((t) => t.filename)}
      panes={html.map((h, i) => (
        <div key={i} dangerouslySetInnerHTML={{ __html: h }} />
      ))}
    />
  );
}

/** Two-column code walkthrough with bidirectional linked highlighting. */
export async function Walkthrough({
  filename,
  lang,
  regions,
  blocks,
}: {
  filename: string;
  lang: string;
  regions: (Region & { code: string })[];
  blocks: { id: string; label: string; sub?: string }[];
}) {
  const html = await Promise.all(
    regions.map((r) => render({ label: r.id, filename, lang, code: r.code })),
  );
  return (
    <WalkthroughClient
      filename={filename}
      regions={regions.map(({ id, label, note }) => ({ id, label, note }))}
      panes={html.map((h, i) => (
        <div key={i} dangerouslySetInnerHTML={{ __html: h }} />
      ))}
      blocks={blocks}
    />
  );
}
components/moco/code-client.tsx
"use client";

import * as React from "react";

/** Tabs sit bottom-right and crossfade between versions of the same snippet. */
export function CodeTabsClient({
  labels,
  filenames,
  panes,
}: {
  labels: string[];
  filenames: string[];
  panes: React.ReactNode[];
}) {
  const [i, setI] = React.useState(0);
  return (
    <div className="moco-win">
      <div className="moco-win-bar">
        <span>{filenames[i]}</span>
      </div>
      <div className="moco-win-body" key={i}>
        <div className="moco-win-fade">{panes[i]}</div>
      </div>
      {labels.length > 1 ? (
        <div className="moco-win-tabs" role="tablist" aria-label="Snippet versions">
          {labels.map((l, j) => (
            <button
              key={l}
              type="button"
              role="tab"
              className="moco-pill"
              aria-selected={i === j}
              aria-pressed={i === j}
              onClick={() => setI(j)}
            >
              {l}
            </button>
          ))}
        </div>
      ) : null}
    </div>
  );
}

/* ───────────────── annotated walkthrough with linked highlighting ──────────────── */

export interface Region {
  id: string;
  label: string;
  note: React.ReactNode;
}

export function WalkthroughClient({
  filename,
  regions,
  panes,
  blocks,
}: {
  filename: string;
  regions: Region[];
  /** Highlighted markup for each region, same order as `regions`. */
  panes: React.ReactNode[];
  /** The adjacent diagram, keyed by the same region ids. */
  blocks: { id: string; label: string; sub?: string }[];
}) {
  const [hover, setHover] = React.useState<string | null>(null);
  const [pinned, setPinned] = React.useState<string | null>(null);
  const active = pinned ?? hover;

  const dim = (id: string) => (active != null && active !== id ? "true" : undefined);

  return (
    <div className="moco-walk">
      <div className="moco-win">
        <div className="moco-win-bar">
          <span>{filename}</span>
          {pinned ? (
            <button type="button" className="moco-btn-sm" onClick={() => setPinned(null)}>
              unpin
            </button>
          ) : null}
        </div>
        <div className="moco-win-body">
          {regions.map((r, i) => (
            <div
              key={r.id}
              className="moco-walk-region"
              data-on={active === r.id}
              data-dim={dim(r.id)}
              tabIndex={0}
              role="button"
              aria-pressed={pinned === r.id}
              aria-label={`${r.label} — ${pinned === r.id ? "pinned" : "click to pin"}`}
              onMouseEnter={() => setHover(r.id)}
              onMouseLeave={() => setHover(null)}
              onFocus={() => setHover(r.id)}
              onBlur={() => setHover(null)}
              onClick={() => setPinned((p) => (p === r.id ? null : r.id))}
              onKeyDown={(e) => {
                if (e.key === "Enter" || e.key === " ") {
                  e.preventDefault();
                  setPinned((p) => (p === r.id ? null : r.id));
                }
              }}
            >
              {panes[i]}
            </div>
          ))}
        </div>
      </div>

      <div>
        <div className="moco-dgm" style={{ minWidth: 0, marginBottom: "1.25rem" }}>
          <div className="moco-dgm-track" style={{ flexWrap: "wrap" }}>
            {blocks.map((b) => (
              <button
                key={b.id}
                type="button"
                className="moco-dgm-block"
                data-variant={active === b.id ? "active" : "default"}
                data-dim={dim(b.id)}
                style={{ flexBasis: "45%" }}
                onMouseEnter={() => setHover(b.id)}
                onMouseLeave={() => setHover(null)}
                onFocus={() => setHover(b.id)}
                onBlur={() => setHover(null)}
                onClick={() => setPinned((p) => (p === b.id ? null : b.id))}
              >
                <span className="moco-b-label">{b.label}</span>
                {b.sub ? <span className="moco-b-sub">{b.sub}</span> : null}
              </button>
            ))}
          </div>
        </div>

        {regions.map((r) => (
          <button
            key={r.id}
            type="button"
            className="moco-walk-note"
            data-on={active === r.id}
            data-dim={dim(r.id)}
            onMouseEnter={() => setHover(r.id)}
            onMouseLeave={() => setHover(null)}
            onFocus={() => setHover(r.id)}
            onBlur={() => setHover(null)}
            onClick={() => setPinned((p) => (p === r.id ? null : r.id))}
          >
            <b>{r.label}</b>
            {r.note}
          </button>
        ))}
      </div>
    </div>
  );
}
components/moco/code.css
/* moco/code — window chrome, line numbers, tabs, annotated walkthrough. */

.moco-win {
  border: 1px solid var(--moco-line);
  border-radius: 3px;
  background: var(--moco-bg);
  overflow: hidden;
}

.moco-win-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding: 0.4rem 0.75rem;
  border-bottom: 1px solid var(--moco-line);
  font-size: 12px;
  color: var(--moco-faint);
}

/* The counter lives here, not on `code`, so line numbers stay continuous
   across the separately-highlighted regions of a walkthrough. */
.moco-win-body {
  position: relative;
  overflow-x: auto;
  counter-reset: ln;
}

.moco-win-body pre {
  margin: 0;
  padding: 0.9rem 0;
  font-size: 12.5px;
  line-height: 22px;
  background: transparent !important;
}

@media (min-width: 560px) {
  .moco-win-body pre {
    font-size: 13px;
  }
}

.moco-win-body code {
  display: block;
}

.moco-win-body .line {
  display: block;
  padding: 0 1rem 0 0;
  min-height: 22px;
}

.moco-win-body .line::before {
  counter-increment: ln;
  content: counter(ln);
  display: inline-block;
  width: 2.4rem;
  padding-right: 0.85rem;
  text-align: right;
  color: var(--moco-faint);
  opacity: 0.7;
  user-select: none;
}

/* Shiki dual themes (defaultColor: false): every token carries
   --shiki-light/--shiki-dark vars; pick one per scheme, mirroring how
   tokens.css does its dark switching. */
.moco-win-body .line span {
  color: var(--shiki-light);
  font-style: var(--shiki-light-font-style, inherit);
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .moco-win-body .line span {
    color: var(--shiki-dark);
    font-style: var(--shiki-dark-font-style, inherit);
  }
}

[data-theme="dark"] .moco-win-body .line span {
  color: var(--shiki-dark);
  font-style: var(--shiki-dark-font-style, inherit);
}

/* Line bands use the wash tokens, which already flip with the scheme. */
.moco-win-body .line[data-hl="true"] {
  background: var(--moco-accent-wash);
  box-shadow: inset 2px 0 0 var(--moco-accent-dk);
}

.moco-win-body .line[data-hl="warn"] {
  background: var(--moco-warn-wash);
  box-shadow: inset 2px 0 0 var(--moco-warn);
}

.moco-win-tabs {
  display: flex;
  justify-content: flex-end;
  gap: 0.35rem;
  padding: 0.4rem 0.6rem;
  border-top: 1px solid var(--moco-line);
}

.moco-win-fade {
  animation: moco-fadein 220ms var(--moco-ease);
}

@keyframes moco-fadein {
  from {
    opacity: 0;
  }
  to {
    opacity: 1;
  }
}

.moco-pill {
  border: 1px solid var(--moco-line);
  border-radius: 999px;
  padding: 0.2rem 0.75rem;
  font-size: 12px;
  color: var(--moco-muted);
  background: var(--moco-bg);
  transition:
    color 150ms var(--moco-ease),
    border-color 150ms var(--moco-ease),
    background 150ms var(--moco-ease);
}

.moco-pill:hover {
  color: var(--moco-ink);
  border-color: var(--moco-faint);
}

.moco-pill[aria-pressed="true"],
.moco-pill[aria-selected="true"] {
  background: var(--moco-accent);
  border-color: var(--moco-accent);
  color: var(--moco-on-accent);
}

.moco-btn-sm {
  border: 1px solid var(--moco-line);
  border-radius: 2px;
  padding: 0.2rem 0.6rem;
  font-size: 12px;
  color: var(--moco-muted);
  background: var(--moco-bg);
  transition:
    color 150ms var(--moco-ease),
    border-color 150ms var(--moco-ease);
}

.moco-btn-sm:hover {
  color: var(--moco-accent-dk);
  border-color: var(--moco-accent-dk);
}

/* Annotated walkthrough */
.moco-walk {
  display: grid;
  grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr);
  gap: 1.5rem;
  align-items: start;
}

@media (max-width: 860px) {
  .moco-walk {
    grid-template-columns: 1fr;
  }
}

.moco-walk-note {
  border-left: 1px solid var(--moco-line);
  padding: 0.35rem 0 0.35rem 0.9rem;
  font-size: 13px;
  line-height: 1.55;
  color: var(--moco-muted);
  text-align: left;
  width: 100%;
  transition: opacity 200ms var(--moco-ease);
}

.moco-walk-note b {
  color: var(--moco-ink);
  font-weight: 400;
  display: block;
}

.moco-walk [data-dim="true"] {
  opacity: 0.4;
}

/* Each region is its own <pre>, so the default block padding stacks up into a
   blank line between every region. Trim it; the window keeps its own padding. */
.moco-walk-region pre {
  padding: 0;
}

.moco-walk-region:first-child pre {
  padding-top: 0.9rem;
}

.moco-walk-region:last-child pre {
  padding-bottom: 0.9rem;
}

.moco-walk-region[data-on="true"] {
  background: var(--moco-accent-wash);
  box-shadow: inset 2px 0 0 var(--moco-accent-dk);
}

.moco-walk-note[data-on="true"] {
  border-left-color: var(--moco-accent-dk);
  color: var(--moco-body);
}

/* Diagram kit (subset the walkthrough renders) */
.moco-dgm {
  display: grid;
  gap: 1.1rem;
  min-width: 460px;
  font-size: 13px;
  line-height: 1.4;
}

.moco-dgm-track {
  display: flex;
  align-items: stretch;
  gap: 6px;
  flex-wrap: nowrap;
}

.moco-dgm-block {
  position: relative;
  flex: 1 1 0;
  min-width: 0;
  border: 1px solid var(--moco-line);
  border-radius: 2px;
  padding: 0.5rem 0.6rem;
  background: var(--moco-bg);
  color: var(--moco-body);
  text-align: left;
  transition:
    opacity 200ms var(--moco-ease),
    border-color 200ms var(--moco-ease),
    background 200ms var(--moco-ease),
    color 200ms var(--moco-ease);
}

.moco-dgm-block .moco-b-label {
  display: block;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.moco-dgm-block .moco-b-sub {
  display: block;
  color: var(--moco-faint);
  font-size: 11.5px;
  margin-top: 2px;
}

.moco-dgm-block[data-variant="active"] {
  background: var(--moco-accent);
  border-color: var(--moco-accent);
  color: var(--moco-on-accent);
}
.moco-dgm-block[data-variant="active"] .moco-b-sub {
  color: rgba(20, 24, 10, 0.72);
}

/* Hover: dim siblings. */
.moco-dgm-track:has(.moco-dgm-block:hover) .moco-dgm-block:not(:hover),
.moco-dgm-track:has(.moco-dgm-block:focus-visible) .moco-dgm-block:not(:focus-visible) {
  opacity: 0.4;
}