بنقرة واحدة
inline-widget
Inline HTML widgets: charts, dashboards, data tables rendered directly in the chat via ShowWidget
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
Inline HTML widgets: charts, dashboards, data tables rendered directly in the chat via ShowWidget
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
استنادا إلى تصنيف SOC المهني
Workspace and research management — dispatch analyses, monitor running agents, manage workspaces and threads.
Draw price lines, trendlines, zones, and event markers directly on a stock's price chart — reach for it whenever you'd otherwise describe a level, pattern, or event in prose. Renders live on MarketView and as a clickable preview card in any other chat.
Event tracker: earnings dates, economic releases, conferences, regulatory events
Financial model audit: structural checks, formula validation, integrity testing
Comparable company analysis: operating metrics, valuation multiples, peer benchmarking
DCF valuation: free cash flow projections, WACC, terminal value, sensitivity analysis
| name | inline-widget |
| description | Inline HTML widgets: charts, dashboards, data tables rendered directly in the chat via ShowWidget |
Render interactive HTML/SVG widgets directly inside the chat conversation using ShowWidget. Widgets appear inline between text — no sandbox, no preview URL, no side panel. They run JavaScript, so lean into making them interactive and explorable where it helps — something the user can sort, filter, toggle, and hover over, not just a static picture.
Use interactive-dashboard instead if: User needs a multi-page web app, server-side data, live data refresh, or complex interactivity requiring React/FastAPI.
Read .agents/skills/ui-design/SKILL.md for design quality — its color discipline, chart restraint, and anti-slop principles apply here too. Its font pairings and type scale, though, are for full documents; a widget sits on the chat surface, so use the host-font typography rules below instead.
ShowWidget(html: str, title: str | None = None, data_files: list[str] | None = None)
html: Raw HTML fragment — no <!DOCTYPE>, <html>, <head>, or <body> tagstitle: Optional metadata (not displayed to user)data_files: Optional list of sandbox file paths to make available as window.__WIDGET_DATA__The HTML is rendered in a sandboxed iframe with:
cdnjs.cloudflare.com, cdn.jsdelivr.net, unpkg.com, esm.shsendPrompt('text'): global function to trigger follow-up chat messageswindow.__WIDGET_DATA__: dict of filename→content for files passed via data_filesfetch() / XMLHttpRequest to arbitrary URLs are blocked by CSP — only CDN domains (cdnjs, jsdelivr, unpkg, esm.sh) are allowed. Use data_files for sandbox files, or embed small data directly in HTMLThe widget sits directly on the chat surface inside a transparent iframe. Follow these rules for seamless integration:
The outermost HTML element must have:
background: transparent)<!-- CORRECT: transparent outer shell -->
<div>
<div style="background: var(--color-bg-card); border-radius: 8px; padding: 16px; ...">
...inner card content...
</div>
</div>
<!-- WRONG: styled outer wrapper — will be rejected -->
<div style="background: var(--color-bg-page); border: 1px solid ...; border-radius: 8px; padding: 20px;">
...content...
</div>
Inner cards, sections, and components should use CSS variables for styling:
/* Card */
background: var(--color-bg-card);
border: 0.5px solid var(--color-border-muted);
border-radius: 8px;
padding: 16px;
/* Metric card */
background: var(--color-bg-subtle);
border: 0.5px solid var(--color-border-muted);
border-radius: 8px;
position: fixed — breaks iframe auto-sizing (elements collapse to 0 height)position: relative for chart containersThese CSS variables are automatically injected and resolve correctly in both light and dark mode:
| Variable | Purpose |
|---|---|
--color-bg-page | Page background |
--color-bg-card | Card/panel background |
--color-bg-elevated | Elevated surface |
--color-bg-subtle | Subtle/muted background |
--color-bg-hover | Hover state background |
--color-text-primary | Primary text |
--color-text-secondary | Secondary/muted text |
--color-text-tertiary | Hint/label text |
--color-border-muted | Default border (use with 0.5px) |
--color-accent-primary | Brand/accent color |
--color-profit | Positive/gain (green) |
--color-loss | Negative/loss (red) |
--color-warning | Warning (amber) |
--color-info | Info (blue) |
--color-success | Success (green) |
Never hardcode colors like #333 or rgb(...) for text, backgrounds, or borders — they break in dark mode. Use CSS variables for everything except chart canvas colors (Chart.js canvas cannot read CSS variables — use computed hex values via getComputedStyle).
Load Chart.js from CDN and follow these rules:
<!-- Wrapper div with explicit height — REQUIRED -->
<div style="position: relative; height: 200px;">
<canvas id="myChart"></canvas>
</div>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script>
// Read CSS variables for chart colors (canvas can't use var())
var cs = getComputedStyle(document.documentElement);
var accent = cs.getPropertyValue('--color-accent-primary').trim();
var border = cs.getPropertyValue('--color-border-muted').trim();
new Chart(document.getElementById('myChart'), {
type: 'line',
data: {
labels: [...],
datasets: [{
data: [...],
borderColor: accent,
backgroundColor: accent + '20',
tension: 0.4,
fill: true
}]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: { legend: { display: true } },
scales: {
y: { grid: { color: border } },
x: { grid: { display: false } }
}
}
});
</script>
Key rules:
responsive: true, maintainAspectRatio: falsewindow.Chart global)getComputedStyle for chart colors-apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif)A widget runs JavaScript, so prefer something the user can poke at, not just read. When the data supports it, reach for:
It all runs client-side over the embedded data — never fetch() a non-CDN origin (CSP blocks it; use data_files for anything large). Keep a meaningful default state so the widget reads correctly before any interaction. Use sendPrompt() only when the next step genuinely belongs back in the chat (a new query, a deeper analysis) — handle exploration the widget can do itself in-place.
Call sendPrompt('text') from buttons to trigger a follow-up chat message:
<button onclick="sendPrompt('Show detailed revenue breakdown')"
style="padding: 8px 16px; background: var(--color-accent-primary); color: white;
border: none; border-radius: 6px; cursor: pointer;">
Revenue Details ↗
</button>
Add a ↗ arrow on buttons that call sendPrompt() to signal they trigger a chat action.
setInterval and requestAnimationFrame work normally for animations and live tickers:
setInterval(function() {
// Update prices, rotate data, animate
updateDisplay();
}, 3000);
Use data_files to load data from sandbox files instead of inlining everything in the HTML string. This is especially useful for larger datasets.
ShowWidget via data_fileswindow.__WIDGET_DATA__["filename"]# Step 1: Generate data
import json
data = {"labels": ["Q1", "Q2", "Q3"], "values": [100, 150, 200]}
with open("work/<task_name>/chart_data.json", "w") as f:
json.dump(data, f)
# Step 2: Agent calls ShowWidget with data_files
ShowWidget(
html='<div id="chart">...</div><script>var d = JSON.parse(__WIDGET_DATA__["chart_data.json"]); ...</script>',
data_files=["work/<task_name>/chart_data.json"]
)
// Text files (json, csv, txt, etc.) — returned as strings
var data = JSON.parse(window.__WIDGET_DATA__["chart_data.json"]);
var csvText = window.__WIDGET_DATA__["results.csv"];
// Binary files (png, jpg, etc.) — returned as data URLs
document.getElementById("img").src = window.__WIDGET_DATA__["chart.png"];
.json, .csv, .txt, .html, .xml, .svg, .md, .yaml, .yml, .tsv, .geojson, .topojson.png, .jpg, .jpeg, .gif, .webp, .icoTotal inline data is capped at 500KB across all files. Keep datasets concise — aggregate or sample large files before passing them.
The following will cause ShowWidget to reject your HTML with an error. Fix and retry:
| Pattern | Why blocked |
|---|---|
new ResizeObserver(...) | Host handles iframe sizing — your observer creates infinite resize loops |
parent.postMessage(...) | Use sendPrompt() instead — direct postMessage bypasses the bridge |
window.top.* / window.parent.* | Sandboxed iframe — parent access is blocked |
position: fixed | Breaks iframe auto-sizing |
| Background/border on outermost element | Breaks seamless integration with chat surface |
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 12px; margin-bottom: 16px;">
<div style="background: var(--color-bg-subtle); padding: 14px 16px; border-radius: 8px; border: 0.5px solid var(--color-border-muted);">
<div style="font-size: 11px; color: var(--color-text-tertiary); text-transform: uppercase; letter-spacing: 0.06em; margin-bottom: 6px;">Revenue</div>
<div style="font-size: 24px; font-weight: 500;">$2.4M</div>
<div style="font-size: 12px; color: var(--color-profit);">+12.5%</div>
</div>
<!-- more cards... -->
</div>
<table style="width: 100%; border-collapse: collapse; font-size: 14px;">
<thead>
<tr style="border-bottom: 0.5px solid var(--color-border-muted);">
<th style="text-align: left; padding: 8px; color: var(--color-text-secondary); font-weight: 500; font-size: 12px;">Symbol</th>
<th style="text-align: right; padding: 8px; color: var(--color-text-secondary); font-weight: 500; font-size: 12px;">Price</th>
</tr>
</thead>
<tbody>
<tr style="border-bottom: 0.5px solid var(--color-border-muted);">
<td style="padding: 8px; font-weight: 500;">AAPL</td>
<td style="text-align: right; padding: 8px;">$213.18</td>
</tr>
</tbody>
</table>
<div style="background: var(--color-bg-card); border-radius: 8px; border: 0.5px solid var(--color-border-muted); padding: 16px; margin-bottom: 16px;">
<div style="font-size: 16px; font-weight: 500; margin-bottom: 12px;">Performance</div>
<div style="position: relative; height: 200px;">
<canvas id="perfChart"></canvas>
</div>
</div>