shadcn.io is not affiliated with official shadcn/ui
Embed Video Dialog Block for Ark UI
A site-builder page with its embed dialog shown open: a pasted YouTube or Vimeo link detected by pattern, options for autoplay, controls, loop and start time, a drawn poster that reflects them, and the embed code to copy or insert.
Installation
Overview
Turn a pasted link into an embed you can check before it goes on the page, with this embed dialog for React with Ark UI. It opens from the Launch notes page in the Pagecraft editor, a site builder: the header holds an outline Embed Button, and the editor page, a toolbar, a title bar, paragraph bars and an empty dashed video slot, is drawn under a soft scrim inside a hairline frame with a plus mark on each corner. The Dialog has a link Input with three sample links to press, and a line under it that names what it found with a two-letter tile: YouTube, Vimeo, or not a video link. Four options sit under it, each in a bordered cell: Autoplay, which plays muted because browsers require it, Show controls and Loop as Switches, and a Start at field in minutes and seconds. At the end a 16:9 poster is drawn from those options, with its control bar, loop mark and start time, and the iframe code under it builds the right player address with the right query parameters and has a Copy Button. Insert into page, the only Shine Button, drops a video block captioned with the link into the page behind. Nothing loads: the poster is drawn. For preview the dialog is drawn open in place when the page loads; the header button opens the real Dialog.
FAQ
Why is the dialog already open, and what do I keep?
So you can see it without a click. On load the dialog is a copy drawn in place over the page: a native dialog element that isn't modal, so nothing is trapped, hidden or focused, and the page around the preview keeps working. The Embed button opens the real Dialog, modal, with its focus trap, Escape and focus return, and the copy stays closed until a reload. Both show the same EmbedFields component and share the block's state, so a link pasted in the copy is there in the real one. In your app keep the Dialog and drop the copy: the "in-place" state, the scrim and the dialog element inside the frame.
How does it recognise a link?
By pattern, with no request. YOUTUBE accepts watch, embed, shorts and youtu.be addresses with an eleven-character id, VIMEO accepts vimeo.com addresses with a numeric id, and anything else is "Not a video link". The detected line is a polite live region in one reserved slot, so it is read out when the kind changes without moving the options. To support another service, add its pattern, its mark and its player address to kindOf and srcOf.
What do the options change?
The player address and the poster. Autoplay sets autoplay and mute together, since browsers only autoplay muted video. Show controls sets the controls parameter, Loop sets loop and, for YouTube, the playlist parameter it needs, and Start at turns minutes and seconds into a start time in seconds. A start time that isn't written as 1:05 shows its problem under the link and keeps the dialog open when you try to insert.
What stays local in the demo, and how do I wire it up?
Nothing loads: no iframe is created, no request is made, and the sample ids are placeholders. Insert into page puts a drawn video block with the link as its caption into the drawn page and says in a polite message that nothing was loaded. Copy writes the real clipboard. In your app store the link and options in your page model in insert, render the iframe with the same srcOf address, and consider a privacy-friendly player address and a consent step before any player loads.
Is it accessible from the keyboard?
Yes. Focus starts in the link field, the samples, switches and fields are real controls with names, and the code box is a focusable region you can scroll with the arrow keys. A problem is read out where it appears and puts focus back in the field. The trigger is the Embed button wrapped in DialogTrigger with asChild, and the dialog is controlled with open and onOpenChange. Focus returns to Embed when the dialog closes.
How does it look on a phone?
The copy shown on load docks to the foot of the page as a bottom sheet, its actions pinned at the bottom with Insert into page on top. The poster comes first, then the link and the options in two columns, and the code box last; all of it scrolls above the actions. The real dialog keeps the Dialog's own phone layout: a sheet stuck to the bottom of the screen.