Safari
A macOS browser window drawn in CSS around a picture, a video or live UI. The chrome follows the theme, stays sharp at any size and gives way gracefully when the window gets narrow.
Examples
Picture
Live UI
A block rendered inside the window, in the simple chrome. With a fixed aspectRatio, the page scrolls inside the window like a real one.
Changing pages
When the picture changes, the new page fades in over the old one, so the window never flashes empty.
Dark chrome
The chrome reads the theme tokens. Wrap the window in an element with the dark class to show the dark chrome on a light page.
Hero arrangement
The browser, the iPhone and the Android phone composed for a landing page.
Installation
npx shadcn@latest add https://ui.ndekocode.dev/r/motion-safari.jsonComponent API
Safari
| Prop | Type | Default | Description |
|---|---|---|---|
| url | string | 'example.com' | The address in the field. The protocol and a trailing slash are left out, as Safari shows them. |
| imageSrc | string | A picture for the page, covering the content area from the top. | |
| videoSrc | string | A muted looping video for the page. It wins over imageSrc. | |
| alt | string | '' | The text alternative of the picture or the video. Leave it empty when label already says what the window shows. |
| mode | 'simple' | 'full' | 'full' | full draws the sidebar, back, forward, share, new tab and tab overview buttons; simple keeps the address only. |
| aspectRatio | number | 16 / 10 | Width over height of the content area. Without it, live UI sets the height of the window. |
| label | string | 'Browser window at ...' | The accessible name of the figure. |
| children | ReactNode | Live UI for the page, drawn above the picture or the video when both are given. | |
| className | string | Optional CSS class for the window. Its width sets the size. |
The window is a figure named by label; the chrome is decorative and hidden from assistive technologies. The traffic lights, the toolbar glyphs and the address are drawn at their real size, so a window narrower than 36rem hides the sidebar and share buttons, and one narrower than 28rem keeps only back and the address.
When imageSrc or videoSrc changes, the new page fades in over the old one in 240ms. Under reduced motion the fade stays, the video does not play by itself and shows its controls instead.
Credits
Inspired by the device mockups of Magic UI, drawn again on our tokens.