Elements

Code

Syntax-highlighted code elements using standard HTML, with numerous configurable options.


Setup

Code block styles ship as a separate stylesheet (independent of manifest.css) and reference theme variables.

Code block functionality is included in manifest.js with all core plugins, or it can be loaded selectively.

<!-- Code block styles -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/mnfst@latest/lib/manifest.code.min.css" />

<!-- Manifest JS -->
<script src="https://cdn.jsdelivr.net/npm/mnfst@latest/lib/manifest.min.js"></script>

The plugin loads highlight.js on demand the first time an element with an x-code attribute scrolls into view. The code snippet's language may be auto-detected, or can be explicitly set with a value like x-code="html" or x-code="javascript".


Inline Code

Add an x-code attribute to <code>, <span>, or other inline elements for syntax highlighting. They can also be given click-to-copy functionality.

<p>If at first you don’t succeed, just <code x-code="html" copy><del></del></code> and pretend it never happened.</p>

The copy attribute on an inline element makes inline code click-copyable, triggered with Tab + Enter for keyboard users.

If the tooltip plugin is loaded and the element has no x-tooltip of its own, a confirmation tooltip automatically appears on copy.

If writing the inline code in markdown (using backticks), a trailing brace can be used to specify the snippet's language, whether it's copyable, and to add any CSS classes, e.g. `npx mnfst-run`{copy} or `<button>Click Me</button>`{html copy .btn-red}.

Supported tokens inside the braces:

Token Effect
copy Adds [copy] for click-to-copy with tooltip confirmation
<language> Bareword like bash, js, html becomes the language hint for highlighting
.class Appended to the element's class list
key="value" Any arbitrary attribute

Code Blocks

Add x-code to any block text element to apply syntax highlighting.

Use a <pre x-code> element to visualize the same line breaks and indents as the written snippet. In markdown files, fenced code blocks (```) are automatically compiled to <pre x-code>, with every character of the body landing in the rendered output unchanged. See the markdown plugin for the fence info-string syntax.

<pre x-code="javascript" name="Demo" lines copy>
function hello() {
  console.log('Hello, World!');
  return true;
}
</pre>

The above snippets each create this code block:

Demo
function hello() { console.log('Hello, World!'); return true; }

Every block-level feature is a plain HTML attribute on:

Attribute Purpose
x-code="language" Language for syntax highlighting (e.g. javascript, css, html, bash). Omit the value to auto-detect.
name="…" Adds a title bar above the code. Also used as the tab label when inside a group.
lines Renders a line-numbers gutter on the left.
copy Adds a copy-to-clipboard button at the top-end.
collapse / collapse="N" Caps the block to N visible lines (default 20) with a +N / toggle below.
edit Mounts a CodeJar editor on the block. Fully editable with live re-highlighting on each keystroke.
from="#id" Pulls the source from another element's innerHTML. Useful for showing a live demo and its source from a single authored element.

Collapse

Long blocks can be capped to a preview length with a toggle below. Use collapse without a value for a default 20 lines, or collapse="#" to set the threshold. Blocks shorter than the threshold render normally with no toggle.

<pre x-code="javascript" collapse="5">
// …
</pre>

Edit

Add edit to make the block text-editable. The editor uses CodeJar (~4 KB gzipped, loaded lazily), with highlight.js re-highlighting on every keystroke.

<pre x-code="javascript" edit>
function hello() {
  console.log('Hello, World!');
  return true;
}
</pre>
Try editing me
function hello() { console.log('Hello, World!'); return true; }

The CodeJar instance is exposed on the element as pre._codeJar, and a code:editor-ready event fires once it's mounted. This lets you integrate the editor with Alpine state, custom commands, or external save logic.

<pre x-code="javascript" edit x-ref="editor"></pre>
<script>
  document.querySelector('[x-ref=editor]').addEventListener('code:editor-ready', (e) => {
    e.detail.editor.onUpdate(code => console.log('user typed:', code));
  });
</script>

HTML Source

When rendered HTML on the page is a snippet's source of truth, link a code block to it with from="#id". The block reads the referenced element's innerHTML as its source, so you only write the example once.

<!-- Code block -->
<pre x-code="html" from="#counter-demo"></pre>

<!-- Reference HTML -->
<div id="counter-demo" class="frame">
  <button x-data="{ n: 0 }" @click="n++">
    Clicked <span x-text="n">0</span> times
  </button>
</div>

In markdown, to render a demo and show its source in one go, add the demo modifier to the frame fence. The plugin emits both the live frame contents and a sibling <pre x-code="html" copy> showing the same source.

::: frame demo
<button class="primary">Click me</button>
:::

Tab Groups

Group multiple panels into a tabbed interface with x-code-group on any wrapper element (<pre>, <div>, <section>, etc.). The plugin normalizes the wrapper to a <pre> at process time so the same CSS targets both standalone and grouped blocks. This tab group block is a rendered example of its own snippets:

<pre x-code-group copy>
  <pre x-code="html" name="HTML"></pre>
  <pre x-code="markdown" name="Markdown"></pre>
</pre>

Direct children with a name attribute become tab panels. Children without name are always-visible ambient content.

The lines, copy, edit, and collapse attributes can be set on the wrapper for panels that don't set them themselves. This avoids repeating the same feature across every tab:

<pre x-code-group lines>
  <pre x-code="html" name="HTML"></pre>            <!-- inherits lines -->
  <pre x-code="css" name="CSS" collapse="5"></pre> <!-- inherits lines, has its own collapse -->
  <pre x-code="js" name="JS" edit></pre>           <!-- inherits lines, has its own edit -->
</pre>

Visual Tabs

Similar to HTML Source above, content can be visualized within a code block using <aside class="frame"> as unique panels.

<div x-code-group>

  <!-- Code tabs -->
  <pre x-code="html" name="HTML">...</pre>
  <pre x-code="css" name="CSS">...</pre>

  <!-- Frame paired with HTML tab due to matching name -->
  <aside class="frame" name="HTML">...</aside>

  <!-- Frame is a standalone tab due to unique name -->
  <aside class="frame" name="Demo">...</aside>

  <!-- Frame is always visible due to no name -->
  <aside class="frame">...</aside>

</div>

Accessibility

The plugin applies ARIA attributes automatically when authors don't supply them:

Element Applied
<pre x-code> (standalone) role="region", aria-label="…" (from name)
<pre x-code> inside <pre x-code-group> role="tabpanel", aria-labelledby (the tab's button id)
Tab strip <div role="tablist" aria-label="Code examples"> inside <header>
Tab buttons role="tab", aria-selected, full keyboard navigation (Arrow / Home / End)
Copy button aria-label="Copy code to clipboard"
Inline [copy] role="button", tabindex="0", aria-label="Click to copy"
Line numbers gutter aria-hidden="true"
Collapse toggle aria-expanded, aria-label ("Show N more lines" / "Show less")

Any of these can be overridden by setting the attribute yourself before the plugin processes the element.


Styles

Theme

Default code blocks use these theme variables:

Variable Purpose
--color-page Code block background
--color-content-neutral Default code text color
--color-content-stark Inline code text color, editor caret
--color-content-subtle Line numbers, expand toggle text
--color-brand-content Active tab indicator
--color-field-surface Header (title or tab strip) background
--color-line Block border
--spacing-field-height Header and expand-toggle height
--radius Border radius

Plus the syntax-color set (--color-code-keyword, --color-code-string, --color-code-comment, etc.) defined in manifest.code.css. Override any of them in your project's theme stylesheet.

:root {
  --color-code-keyword: #ff6b6b;
  --color-code-string: #4ecdc4;
  --color-code-comment: #95a5a6;
}

Icons

CSS variables hold the encoded SVGs used by the copy button:

Variable Used for
--icon-code-copy Idle copy button state
--icon-code-copied Briefly after a successful copy, plus the inline-copy tooltip flash

To override:

  1. Pick an icon from Iconify or another SVG source.
  2. Copy the encoded SVG string (Iconify's CSS tab provides the --svg value), or use an SVG encoder.
  3. Override the variable in your CSS.
Default icons
:root { --icon-code-copy: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cg fill='none' stroke='%23000' stroke-linecap='round' stroke-linejoin='round' stroke-width='2'%3E%3Crect width='14' height='14' x='8' y='8' rx='2' ry='2'/%3E%3Cpath d='M4 16c-1.1 0-2-.9-2-2V4c0-1.1.9-2 2-2h10c1.1 0 2 .9 2 2'/%3E%3C/g%3E%3C/svg%3E"); --icon-code-copied: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='none' stroke='%23000' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='M20 6L9 17l-5-5'/%3E%3C/svg%3E"); }

Customization

Style blocks directly with CSS, using <pre>, [x-code], [x-code-group], or a combination to target desired elements.

pre[x-code], pre[x-code-group] {
  background: var(--color-surface-1);
  border: 1px solid var(--color-line);
  border-radius: 0;

  /* Header (title bar or tab strip wrapper) */
  & > header {
    font-family: var(--font-mono);
    font-weight: bold;

    & > [role="tablist"] {
      & > button[role="tab"][aria-selected="true"] {
        background: var(--color-accent-content);

        &::after {
          background: var(--color-accent-content);
        }
      }
    }
  }

  /* Line numbers gutter */
  & .lines {
    background: var(--color-surface-2);
    border-radius: 0;
  }

  /* Code area */
  & > code {
    background: var(--color-surface-3);
  }

  /* Copy button (absolute over the top-end of the wrapper) */
  & > button.copy {
    background: transparent;
    border-radius: 0;
  }

  /* Expand and collapse toggle (full-width, bottom row) */
  & > button.expand {
    background: var(--color-surface-2);
  }
}