-
Notifications
You must be signed in to change notification settings - Fork 654
Open
Labels
enhancementNew feature or requestNew feature or request
Description
Goal
Introduce a new iframe() component that allows developers to embed external web applications, tools, dashboards, or content directly within a Preswald app layout using an <iframe>.
📌 Motivation
Many teams use Preswald alongside other tools—BI dashboards, model explainers, internal portals, notebooks, etc. Being able to embed these external apps directly inside a Preswald app via iframe unlocks:
- Seamless multi-tool integration
- Side-by-side app views
- Embedding internal web apps or dashboards (Grafana, Metabase, MLflow, etc.)
- Embedded documentation, YouTube tutorials, or interactive notebooks
This makes Preswald a composable dashboard shell.
✅ Acceptance Criteria
- Add a new
iframe()component topreswald.interfaces.components - Accept props:
url: str— required external sourceheight: Union[int, str]— default:"500px"width: Union[int, str]— default:"100%"title: Optional[str]— optional accessible title
- Render as a
<Card>with an embedded<iframe>in the frontend - Handle sandboxing / security via attribute defaults
- Display error if URL is invalid or blocked (e.g.
X-Frame-Options: deny)
🛠 Implementation Plan
1. Python API: iframe() in components.py
def iframe(url: str, height: str = "500px", width: str = "100%", title: str = ""):
service = PreswaldService.get_instance()
component = {
"type": "iframe",
"id": f"iframe-{hashlib.md5(url.encode()).hexdigest()[:6]}",
"url": url,
"height": height,
"width": width,
"title": title,
}
service.append_component(component)2. Frontend Widget: IframeWidget.jsx
import React from 'react';
import { Card } from '@/components/ui/card';
const IframeWidget = ({ url, height, width, title }) => {
return (
<Card className="mb-4 p-2 overflow-hidden">
<iframe
src={url}
title={title || "Embedded Frame"}
style={{ width: width || "100%", height: height || "500px", border: "none" }}
loading="lazy"
allowFullScreen
sandbox="allow-scripts allow-same-origin"
/>
</Card>
);
};
export default IframeWidget;3. Register in DynamicComponents.jsx
import IframeWidget from '@/components/widgets/IframeWidget';
case 'iframe':
return (
<IframeWidget
url={component.url}
height={component.height}
width={component.width}
title={component.title}
/>
);🧪 Testing Plan
- Embed:
- YouTube video
- Hugging Face demo
- Internal dashboard URL
- Test with:
iframe("https://huggingface.co/spaces/yuntian-deng/ChatGPT", height="600px")
- Validate:
- Renders correctly
- Respects sizing
- Does not crash if blocked (show fallback message)
📚 Docs To Add
-
docs/sdk/iframe.mdx - Add security note: some websites block embedding via
X-Frame-Options - Show how to embed Grafana, JupyterLite, etc.
🧩 Files Affected
preswald/interfaces/components.pyfrontend/src/components/widgets/IframeWidget.jsxDynamicComponents.jsxdocs/sdk/iframe.mdx
Metadata
Metadata
Assignees
Labels
enhancementNew feature or requestNew feature or request