OutputArea
Wrapper component for rendering multiple Jupyter outputs with collapsible state and scroll behavior
Processing data...
Loading model...
OutputArea handles rendering multiple Jupyter outputs with:
- Output type routing - Automatically routes to the right renderer for each output type
- Secure isolation - HTML, Markdown, SVG, and widgets render in sandboxed iframes
- Collapsible state - Toggle output visibility with a collapse button
- Scroll behavior - Set
maxHeightto enable scrolling for large outputs - Empty state - Renders nothing when there are no outputs
Installation
npx shadcn@latest add @nteract/output-areaNew to @nteract? pnpm dlx shadcn@latest registry add @nteract
Copy from nteract/elements.
Usage
import { OutputArea } from "@/components/cell/OutputArea"
export function CellWithOutputs({ cell }) {
const [collapsed, setCollapsed] = useState(false)
return (
<OutputArea
outputs={cell.outputs}
collapsed={collapsed}
onToggleCollapse={() => setCollapsed(!collapsed)}
maxHeight={400}
/>
)
}Examples
Simple Output
42<OutputArea outputs={[{
output_type: "execute_result",
data: { "text/plain": "42" },
execution_count: 1,
}]} />Stream and Result
Processing data...
Loading model...
<OutputArea outputs={[
{
output_type: "stream",
name: "stdout",
text: "Processing data...\nLoading model...\n",
},
{
output_type: "execute_result",
data: { "text/plain": "{'accuracy': 0.95}" },
execution_count: 2,
},
]} />Error Output
ValueError: invalid literal for int() with base 10: 'hello'---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
Cell In[1], line 1
----> 1 int('hello')
ValueError: invalid literal for int() with base 10: 'hello'<OutputArea outputs={[{
output_type: "error",
ename: "ValueError",
evalue: "invalid literal for int()",
traceback: ["..."],
}]} />Collapsible
Processing data...
Loading model...
const [collapsed, setCollapsed] = useState(false)
<OutputArea
outputs={outputs}
collapsed={collapsed}
onToggleCollapse={() => setCollapsed(!collapsed)}
/>With Max Height
Processing data...
Loading model...
Processing data...
Loading model...
Processing data...
Loading model...
<OutputArea
outputs={largeOutputs}
maxHeight={150}
/>Output Types
OutputArea handles all Jupyter output types:
| Type | Description | Renderer |
|---|---|---|
execute_result | Cell execution result | MediaRouter |
display_data | Rich display output | MediaRouter |
stream | stdout/stderr text | AnsiStreamOutput |
error | Exception traceback | AnsiErrorOutput |
Isolated Rendering
HTML outputs render inside a sandboxed iframe for security:
Certain output types can contain executable JavaScript and must be rendered in a secure iframe:
| MIME Type | Why Isolation |
|---|---|
text/html | Can contain <script> tags |
text/markdown | Rendered HTML may include scripts |
image/svg+xml | SVG can contain embedded scripts |
application/vnd.jupyter.widget-view+json | Widgets run JavaScript |
application/vnd.plotly.v1+json | Plotly runs JavaScript |
application/vnd.vegalite.* | Vega-Lite runs JavaScript |
By default (isolated="auto"), OutputArea automatically detects when isolation is needed and renders those outputs in an IsolatedFrame.
Widget Output in Iframe
Widgets are rendered inside the isolated iframe. The widget state syncs between parent and iframe via the CommBridge:
OutputWidget (ipywidgets.Output) in Iframe
The OutputWidget captures outputs like ipywidgets.Output(). When it contains HTML content, the whole widget renders in an iframe:
Force Isolation Mode
// Always use iframe (most secure)
<OutputArea outputs={outputs} isolated={true} />
// Auto-detect (default) - uses iframe only when needed
<OutputArea outputs={outputs} isolated="auto" />
// Never use iframe (fastest, but less secure)
<OutputArea outputs={outputs} isolated={false} />Preload Iframe
For instant output rendering, preload the iframe before outputs arrive:
<OutputArea
outputs={[]}
preloadIframe={true} // Bootstrap iframe ahead of time
/>Link Handling
Links clicked inside isolated outputs fire the onLinkClick callback:
<OutputArea
outputs={htmlOutputs}
onLinkClick={(url, newTab) => {
// Handle link click (e.g., open in browser)
window.open(url, newTab ? "_blank" : "_self")
}}
/>Props
| Prop | Type | Default | Description |
|---|---|---|---|
outputs | JupyterOutput[] | — | Array of Jupyter outputs to render |
collapsed | boolean | false | Whether outputs are collapsed |
onToggleCollapse | () => void | — | Callback when collapse is toggled |
maxHeight | number | — | Maximum height in pixels before scrolling |
className | string | — | Additional CSS classes |
renderers | Record<string, CustomRenderer> | — | Custom renderers for MediaRouter |
priority | readonly string[] | — | MIME type priority for MediaRouter |
isolated | boolean | "auto" | "auto" | Force isolation mode (true), auto-detect ("auto"), or disable (false) |
preloadIframe | boolean | false | Pre-create iframe for instant rendering |
onLinkClick | (url: string, newTab: boolean) => void | — | Callback when link is clicked in isolated output |
onWidgetUpdate | (commId: string, state: object) => void | — | Widget state update callback (deprecated) |
JupyterOutput Type
type JupyterOutput =
| {
output_type: "execute_result" | "display_data";
data: Record<string, unknown>;
metadata?: Record<string, unknown>;
execution_count?: number | null;
}
| {
output_type: "stream";
name: "stdout" | "stderr";
text: string | string[];
}
| {
output_type: "error";
ename: string;
evalue: string;
traceback: string[];
};