BrowserFrame
LayoutA presentation browser frame with address text and editable child content.
Responsive viewport — resize the window to explore. Direction and density apply only to this preview. Theme applies to the docs too.
"use client";
import { BrowserFrame } from "@/components/ui/browser-frame";
export default function BrowserFrameExample() {
return (
<div className="w-full max-w-2xl space-y-6">
<BrowserFrame
label="Workspace product preview"
address="studio.apex.example/projects"
>
<div className="space-y-5 p-6">
<div className="flex items-center justify-between">
<span className="text-sm font-semibold">Good morning, Alex.</span>
<span className="rounded-full bg-primary/10 px-2 py-1 text-[10px] text-primary">
Studio
</span>
</div>
<div className="grid grid-cols-2 gap-3">
<div className="rounded-lg border p-4">
<p className="text-xs text-muted-foreground">Active projects</p>
<p className="mt-2 text-2xl font-semibold">24</p>
</div>
<div className="rounded-lg border p-4">
<p className="text-xs text-muted-foreground">
Completed this week
</p>
<p className="mt-2 text-2xl font-semibold">12</p>
</div>
</div>
<p className="text-xs text-muted-foreground">
A presentation frame for screenshots, product tours, and case
studies.
</p>
</div>
</BrowserFrame>
<BrowserFrame
label="Dark browser chrome"
address="apex.example/launch"
chrome="dark"
>
<div className="bg-primary/5 p-6">
<h3 className="font-semibold">Make it yours.</h3>
<p className="mt-2 text-sm text-muted-foreground">
Dark chrome around your own content.
</p>
</div>
</BrowserFrame>
</div>
);
}Usage
Wrap product screenshots, dashboards, or case-study content in a browser-style frame. The address is display text rather than a real location field; the decorative chrome never navigates or requests that address. Children remain ordinary React content, with no iframe or isolation boundary. Use neutral or dark chrome to match the presentation while keeping the child content in its own theme.
import { BrowserFrame } from "@/components/ui/browser-frame";Shipped as editable source in src/components/ui/browser-frame.tsx in both apps. Copy the implementation below when moving it to another project. Copy the complete example from Source code for all imports and state. Add "use client" when using hooks or event handlers. See installation and theming for project setup.
Component source
The complete implementation is included in both apps. It uses the React, Radix, Lucide, and shared-core dependencies already installed in Apex. Keep your project’s semantic theme tokens when reusing it.
src/components/ui/browser-frame.tsx
import type { ReactNode } from "react";
import { LockKeyhole } from "lucide-react";
import { cn } from "@dashboardpack/core/lib/utils";
export interface BrowserFrameProps {
label: string;
address?: string;
children: ReactNode;
chrome?: "neutral" | "dark";
className?: string;
}
export function BrowserFrame({
label,
address = "app.example.com",
children,
chrome = "neutral",
className,
}: BrowserFrameProps) {
return (
<figure
className={cn(
"min-w-0 overflow-hidden rounded-xl border bg-card shadow-sm",
className,
)}
>
<div
className={cn(
"flex items-center gap-3 border-b px-3 py-3",
chrome === "dark" ? "bg-zinc-900 text-white" : "bg-muted/50",
)}
>
<span aria-hidden className="flex shrink-0 gap-1.5">
<span className="size-2 rounded-full bg-rose-400" />
<span className="size-2 rounded-full bg-amber-400" />
<span className="size-2 rounded-full bg-emerald-400" />
</span>
<span
className={cn(
"flex min-w-0 flex-1 items-center justify-center gap-1.5 rounded-md px-2 py-1 text-[10px]",
chrome === "dark"
? "bg-white/10"
: "bg-background text-muted-foreground",
)}
>
<LockKeyhole aria-hidden className="size-3 shrink-0" />
<span className="truncate" dir="ltr">
{address}
</span>
</span>
</div>
<figcaption className="sr-only">
{label}. Presentation frame, address is display text.
</figcaption>
<div className="min-w-0">{children}</div>
</figure>
);
}API reference
Common props and defaults. Slot-specific props are named below; native elements also accept their standard HTML attributes. The component TypeScript definitions are the complete type reference.
| Prop | Type / Default | Description |
|---|---|---|
| label | stringDefault: required | Accessible presentation caption. |
| address | stringDefault: app.example.com | Display-only address text. |
| children | ReactNodeDefault: required | Content inside the frame. |
| chrome | neutral | darkDefault: neutral | Chrome appearance, independent of child content. |
| className | stringDefault: — | Extend the container with semantic theme utilities. |