inline-cards - interactive shtml code blocks in chat messages

SYNOPSIS

Use ```shtml fenced code blocks in chat messages to render interactive cards inline. The HTML content is hydrated into a sandboxed iframe after your response completes. Cards are ephemeral — they have a minimal bridge (lick-only) and no persistent state.

RENDERING

Inline cards render AFTER your response completes — not during streaming. The message renderer preserves ```shtml blocks as raw HTML, then hydrateInlineSprinkles() finds all code.language-shtml elements and replaces each with a sandboxed iframe.

Auto-height is handled via ResizeObserver. The iframe automatically resizes to fit its content — no manual height setting needed.

In CLI mode the content renders as a direct srcdoc iframe. In extension mode it routes through sprinkle-sandbox.html (a CSP-exempt manifest sandbox) which creates a nested srcdoc iframe inside it.

BRIDGE API

Inline cards have a minimal bridge. Only slicc.lick() is available. There is NO readFile, NO setState/getState, NO on('update'). This is unlike panel sprinkles which have the full bridge API.

// Send a lick event with action string only
slicc.lick('approve')

// Send a lick event with action + data
slicc.lick({action: 'deploy', data: {env: 'production', version: '2.1'}})

The data-action attribute is also supported. Any element with data-action automatically calls slicc.lick() on click:

<button data-action="approve">Approve</button>
<button data-action="reject" data-action-data='{"reason":"stale"}'>Reject</button>

LICK EVENT ROUTING

Lick events from inline cards arrive as messages in the agent's conversation. They are routed to the cone as sprinkle lick events with sprinkleName: "inline". The message content is formatted as:

[Sprinkle Event: inline]
```json
{"action": "deploy", "data": {"env": "production"}}
```

These are fire-and-forget — the agent does NOT block waiting for the user to click. The lick arrives as an asynchronous message in the cone's conversation.

WHEN TO USE INLINE CARDS

WHEN TO USE ALTERNATIVES

CSS COMPONENTS

Theme CSS and sprinkle component styles are auto-injected into the iframe. Use the built-in classes — do not write custom CSS.

EXAMPLE

Action card with deploy/cancel buttons:

```shtml
<div class="sprinkle-action-card">
  <div class="sprinkle-action-card__header">
    Deploy to Production
    <span class="sprinkle-badge sprinkle-badge--notice">pending</span>
  </div>
  <div class="sprinkle-action-card__body">
    Version 2.1.0 is ready. 14 files changed, all tests passing.
  </div>
  <div class="sprinkle-action-card__actions">
    <button class="sprinkle-btn sprinkle-btn--secondary"
            onclick="slicc.lick('cancel')">Cancel</button>
    <button class="sprinkle-btn sprinkle-btn--primary"
            onclick="slicc.lick({action:'deploy',data:{env:'prod'}})">Deploy</button>
  </div>
</div>
```

SEE ALSO

shtml(1), sprinkle(1), lick(1)