- Alert
- Avatar
- Badge
- Breadcrumb
- Button
- Button Group
- Calendar
- Card
- Carousel
- Chart
- Checkbox
- Checkbox Group
- ComboBox
- Command
- Data Table
- Date Field
- Date Picker
- Date Range Picker
- Dialog
- Disclosure
- Disclosure Group
- Drawer
- Empty
- Field
- File Trigger
- Form
- Grid List
- Hover Card
- Input
- Input Group
- Input OTP
- Item
- Kbd
- Label
- ListBox
- Menu
- Number Field
- Pagination
- Popover
- Progress Bar
- Radio Group
- Range Calendar
- Resizable
- Search Field
- Select
- Separator
- Sheet
- Sidebar
- Skeleton
- Slider
- Sonner
- Spinner
- Switch
- Table
- Tabs
- Tag Group
- Text Field
- Textarea
- Time Field
- Toast
- Toggle Button
- Toggle Button Group
- Tooltip
- Tree
- Typography
"use client"
import { useState } from "react"
import { ChevronLeftIcon, ChevronRightIcon, RotateCwIcon } from "lucide-react"
import {
WebPreview,
WebPreviewBody,
WebPreviewConsole,
WebPreviewNavigation,
WebPreviewNavigationButton,
WebPreviewUrl,
} from "@/components/ai-elements/web-preview"
export function WebPreviewDemo() {
const [url, setUrl] = useState("https://ai-sdk.dev")
const [logs] = useState([
{
level: "log" as const,
message: "Page loaded successfully",
timestamp: new Date(),
},
{
level: "log" as const,
message: "Ready to display content",
timestamp: new Date(),
},
])
return (
<div className="h-[600px] w-full">
<WebPreview defaultUrl={url} onUrlChange={setUrl}>
<WebPreviewNavigation>
<WebPreviewNavigationButton disabled tooltip="Back">
<ChevronLeftIcon className="size-4" />
</WebPreviewNavigationButton>
<WebPreviewNavigationButton disabled tooltip="Forward">
<ChevronRightIcon className="size-4" />
</WebPreviewNavigationButton>
<WebPreviewNavigationButton tooltip="Refresh">
<RotateCwIcon className="size-4" />
</WebPreviewNavigationButton>
<WebPreviewUrl placeholder="Enter URL..." />
</WebPreviewNavigation>
<WebPreviewBody src={url} />
<WebPreviewConsole logs={logs} />
</WebPreview>
</div>
)
}
Installation
pnpmnpmyarnbunpnpm dlx shadcn@latest add web-previewCopy
Usage
Copy import { WebPreview, WebPreviewNavigation, WebPreviewNavigationButton, WebPreviewUrl, WebPreviewBody, WebPreviewConsole, } from "@/components/ai-elements/web-preview"
Copy const [url, setUrl] = useState("https://example.com") <WebPreview defaultUrl={url} onUrlChange={setUrl}> <WebPreviewNavigation> <WebPreviewNavigationButton tooltip="Back"> <ChevronLeftIcon /> </WebPreviewNavigationButton> <WebPreviewNavigationButton tooltip="Forward"> <ChevronRightIcon /> </WebPreviewNavigationButton> <WebPreviewNavigationButton tooltip="Refresh"> <RotateCwIcon /> </WebPreviewNavigationButton> <WebPreviewUrl placeholder="Enter URL..." /> </WebPreviewNavigation> <WebPreviewBody src={url} /> <WebPreviewConsole logs={[]} /> </WebPreview>
Examples
Default
Console
"use client"
import { useState } from "react"
import { ChevronLeftIcon, ChevronRightIcon, RotateCwIcon } from "lucide-react"
import {
WebPreview,
WebPreviewBody,
WebPreviewConsole,
WebPreviewNavigation,
WebPreviewNavigationButton,
WebPreviewUrl,
} from "@/components/ai-elements/web-preview"
export function WebPreviewDemo() {
const [url, setUrl] = useState("https://ai-sdk.dev")
const [logs] = useState([
{
level: "log" as const,
message: "Page loaded successfully",
timestamp: new Date(),
},
{
level: "log" as const,
message: "Ready to display content",
timestamp: new Date(),
},
])
return (
<div className="h-[600px] w-full">
<WebPreview defaultUrl={url} onUrlChange={setUrl}>
<WebPreviewNavigation>
<WebPreviewNavigationButton disabled tooltip="Back">
<ChevronLeftIcon className="size-4" />
</WebPreviewNavigationButton>
<WebPreviewNavigationButton disabled tooltip="Forward">
<ChevronRightIcon className="size-4" />
</WebPreviewNavigationButton>
<WebPreviewNavigationButton tooltip="Refresh">
<RotateCwIcon className="size-4" />
</WebPreviewNavigationButton>
<WebPreviewUrl placeholder="Enter URL..." />
</WebPreviewNavigation>
<WebPreviewBody src={url} />
<WebPreviewConsole logs={logs} />
</WebPreview>
</div>
)
}
Anatomy
The WebPreview component is composed of several sub-components:
Copy <WebPreview> <WebPreviewNavigation> <WebPreviewNavigationButton /> <WebPreviewUrl /> </WebPreviewNavigation> <WebPreviewBody /> <WebPreviewConsole /> </WebPreview>
Features
- Live Preview: Display web content in an iframe with sandbox protection
- URL Navigation: Input field for entering URLs with Enter key support
- Navigation Controls: Back, forward, and refresh buttons with tooltip support
- Integrated Console: Collapsible console panel for logging and debugging
- Context Management: Shared state between components via React Context
- Responsive Design: Adapts to different screen sizes and layouts
- Keyboard Support: Press Enter in URL input to navigate
- Sandbox Security: iframe includes security restrictions for safe preview
API Reference
WebPreview
Main container that provides context for all child components.
| Prop | Type | Default | Description |
|---|---|---|---|
defaultUrl | string | "" | Initial URL to load |
onUrlChange | (url: string) => void | - | Callback when URL changes |
className | string | - | Custom CSS classes |
WebPreviewNavigation
Navigation bar that contains controls and URL input.
| Prop | Type | Default | Description |
|---|---|---|---|
className | string | - | Custom CSS classes |
children | ReactNode | - | Navigation controls |
WebPreviewNavigationButton
Button for navigation actions (back, forward, refresh, etc.).
| Prop | Type | Default | Description |
|---|---|---|---|
tooltip | string | - | Tooltip text on hover |
disabled | boolean | false | Disable the button |
onClick | () => void | - | Click handler |
children | ReactNode | - | Button content (usually an icon) |
WebPreviewUrl
URL input field with automatic syncing to preview context.
| Prop | Type | Default | Description |
|---|---|---|---|
placeholder | string | "Enter URL..." | Placeholder text |
value | string | - | Controlled value (optional) |
onChange | (e: ChangeEvent) => void | - | Change handler (optional) |
onKeyDown | (e: KeyboardEvent) => void | - | Key down handler (optional) |
The URL input automatically syncs with the preview context. Press Enter to navigate to the entered URL.
WebPreviewBody
iframe container for displaying web content.
| Prop | Type | Default | Description |
|---|---|---|---|
src | string | - | URL to display (overrides context URL) |
loading | ReactNode | - | Loading indicator overlay |
className | string | - | Custom CSS classes |
The iframe includes sandbox restrictions: allow-scripts allow-same-origin allow-forms allow-popups allow-presentation
WebPreviewConsole
Collapsible console panel for displaying logs.
| Prop | Type | Default | Description |
|---|---|---|---|
logs | Array<ConsoleLog> | [] | Array of console log entries |
className | string | - | Custom CSS classes |
children | ReactNode | - | Additional console content |
ConsoleLog Type:
Copy { level: "log" | "warn" | "error" message: string timestamp: Date }
The console displays with color coding:
log: Default foreground colorwarn: Yellowerror: Destructive color
Advanced Usage
With Loading State
Copy <WebPreview defaultUrl={url}> <WebPreviewNavigation> <WebPreviewUrl /> </WebPreviewNavigation> <WebPreviewBody src={url} loading={ isLoading && ( <div className="absolute inset-0 flex items-center justify-center bg-background/80"> <Loader /> </div> ) } /> </WebPreview>
With Console Logging
Copy const [logs, setLogs] = useState<Array<ConsoleLog>>([]) // Add logs from your app const addLog = (level: "log" | "warn" | "error", message: string) => { setLogs(prev => [...prev, { level, message, timestamp: new Date() }]) } <WebPreview defaultUrl={url}> <WebPreviewNavigation> <WebPreviewUrl /> </WebPreviewNavigation> <WebPreviewBody src={url} /> <WebPreviewConsole logs={logs} /> </WebPreview>
Custom Navigation Controls
Copy <WebPreview defaultUrl={url}> <WebPreviewNavigation> <WebPreviewNavigationButton onClick={() => console.log('Back')} tooltip="Go back" > <ChevronLeftIcon className="size-4" /> </WebPreviewNavigationButton> <WebPreviewNavigationButton onClick={() => console.log('Forward')} tooltip="Go forward" > <ChevronRightIcon className="size-4" /> </WebPreviewNavigationButton> <WebPreviewNavigationButton onClick={() => window.location.reload()} tooltip="Refresh" > <RotateCwIcon className="size-4" /> </WebPreviewNavigationButton> <WebPreviewUrl /> </WebPreviewNavigation> <WebPreviewBody src={url} /> </WebPreview>
Hooks
useWebPreview
Access the preview context from within child components (not exported by default).
Copy const { url, setUrl, consoleOpen, setConsoleOpen } = useWebPreview()
This hook is used internally by the sub-components and is not typically needed in user code.