Modal
Modal
The modal suite covers four distinct use cases. XMarkModal is the low-level base component. XMarkModalVideo wraps it for media playback. XMarkModalImage provides a keyboard-navigable lightbox. XMarkModalChat is a floating chat prompt overlay. XMarkModalFeature presents an immersive full-screen feature story.
Components
<XMarkModal />
The base modal. Place your trigger in the default slot (a button or any element); the modal opens on click. Use the content slot for the modal body and the footer slot for a bottom bar. Exposes open and close events and a close function via the content slot.
<XMarkModal
title="Custom Modal"
description="Subtitle shown in the footer bar"
size="2xl"
:dark="true"
>
<!-- Trigger -->
<UButton label="Open Modal" />
<!-- Content -->
<template #content="{ close }">
<div class="p-8">
<p>Your modal content here.</p>
<UButton @click="close">Close</UButton>
</div>
</template>
</XMarkModal>
Props
| Prop | Type | Default | Description |
|---|---|---|---|
title | String | '' | Title shown in the modal footer bar |
description | String | '' | Description shown in the modal footer bar |
size | String | '4xl' | Modal width: 'sm' through '7xl', 'full' |
fullscreen | Boolean | false | Use fullscreen modal |
dark | Boolean | true | Dark mode for the modal chrome (affects close button) |
padding | String | 'p-0' | Body padding class |
Slots
| Slot | Description |
|---|---|
default | Trigger element |
content | Modal body — receives { close } |
footer | Override the footer bar |
Events
| Event | Description |
|---|---|
open | Modal opened |
close | Modal closed |
<XMarkModalVideo />
Opens a video in a modal. Supports YouTube, Vimeo, and direct video URLs — the embed type is detected automatically. Supply a thumbnail prop to show an image with a play button as the trigger, or place a custom trigger in the default slot.
<!-- YouTube with thumbnail trigger -->
<XMarkModalVideo
src="https://www.youtube.com/watch?v=dQw4w9WgXcQ"
thumbnail="/images/video-thumb.jpg"
title="Product Demo"
description="See how it works in 3 minutes"
:autoplay="true"
size="5xl"
/>
<!-- Button trigger -->
<XMarkModalVideo src="https://vimeo.com/123456789">
<UButton label="Watch Demo" leading-icon="i-lucide-play" />
</XMarkModalVideo>
Props
| Prop | Type | Default | Description |
|---|---|---|---|
src | String | YouTube example | Video URL (YouTube, Vimeo, or direct .mp4) |
thumbnail | String | '' | Thumbnail image URL — renders as play-button trigger |
poster | String | '' | Poster image for direct video files |
title | String | '' | Title shown in modal footer |
description | String | '' | Description shown in modal footer |
size | String | '4xl' | Modal size |
autoplay | Boolean | true | Autoplay video when modal opens |
button | Object | {} | Default trigger button config { label, color?, variant?, icon?, size? } |
<XMarkModalImage />
A full-screen image lightbox (rendered via Teleport to body). Navigate a gallery with arrow buttons or keyboard. Shows an image counter and optional thumbnail navigation strip.
<template>
<button @click="lightboxOpen = true">
<img src="/gallery/photo-1.jpg" class="cursor-zoom-in" />
</button>
<XMarkModalImage
v-model="lightboxOpen"
:images="[
{ src: '/gallery/photo-1.jpg', alt: 'Interior view', caption: 'Open-plan living area' },
{ src: '/gallery/photo-2.jpg', alt: 'Kitchen', caption: 'Modern kitchen' },
{ src: '/gallery/photo-3.jpg', alt: 'Bedroom' },
]"
:start-index="0"
:has-counter="true"
:has-thumbnails="true"
/>
</template>
Props
| Prop | Type | Default | Description |
|---|---|---|---|
modelValue | Boolean | false | Lightbox open state (v-model) |
images | Array | [] | Image list [{ src, alt, caption? }] |
startIndex | Number | 0 | Index of the first image to show |
hasCounter | Boolean | true | Show "1 / N" counter |
hasThumbnails | Boolean | false | Show thumbnail strip at bottom |
<XMarkModalChat />
A floating chat-prompt widget fixed to the bottom-right of the screen. Appears after delay milliseconds and auto-dismisses after autoDismiss ms (0 = never). Toggle visibility with v-model. Emits action when the CTA button is clicked.
<XMarkModalChat
v-model="chatOpen"
name="Alex from Support"
message="Hi there! 👋 Have questions about our pricing? I'm here to help."
avatar="/avatars/alex.jpg"
:online="true"
action-text="Start a conversation"
:delay="4000"
:auto-dismiss="0"
@action="openIntercom"
@dismiss="chatOpen = false"
/>
Props
| Prop | Type | Default | Description |
|---|---|---|---|
modelValue | Boolean | false | Visibility (v-model) |
avatar | String | '' | Avatar image URL |
name | String | 'Support' | Agent or bot name |
message | String | Default greeting | Chat message text |
online | Boolean | true | Show green online indicator |
actionText | String | '' | CTA button label (hidden when empty) |
autoDismiss | Number | 0 | Auto-dismiss after N ms (0 = never) |
delay | Number | 3000 | Delay before showing (ms) |
Events
| Event | Description |
|---|---|
update:modelValue | v-model sync |
action | CTA button clicked |
dismiss | Widget dismissed |
<XMarkModalFeature />
A full-screen immersive modal for long-form feature storytelling. Accepts a hero section, an array of scrollable blocks (type image, text, or split), and a closing cta section. Triggered by a slot element or a default button.
<XMarkModalFeature
:hero="{
image: '/features/hero.jpg',
title: 'Introducing Spaces',
subtitle: 'A new way to organize your work',
}"
:blocks="[
{ type: 'text', title: 'Focus on what matters', body: 'Spaces help teams...' },
{ type: 'split', image: '/features/split.jpg', title: 'Side by side', body: 'Work together...', features: ['Real-time sync', 'Version history'] },
{ type: 'image', image: '/features/full.jpg', alt: 'Full product view' },
]"
:cta="{
title: 'Ready to try Spaces?',
subtitle: 'Available on all plans.',
button: { label: 'Get Started', color: 'primary' },
}"
:button="{ label: 'Learn More', icon: 'i-lucide-arrow-right' }"
/>
Props
| Prop | Type | Default | Description |
|---|---|---|---|
hero | Object | null | Hero config { image, title, subtitle? } |
blocks | Array | [] | Content blocks [{ type: 'image'|'text'|'split', ... }] |
cta | Object | null | Closing CTA { title, subtitle?, button?: { label, color? } } |
button | Object | {} | Default trigger button config |
AI Context
category: Modal
package: "@xenterprises/nuxt-x-marketing"
components:
- XMarkModal
- XMarkModalVideo
- XMarkModalImage
- XMarkModalChat
- XMarkModalFeature
use-when: >
Presenting media or content without navigating away from the current page.
Use Video for demo/explainer videos, Image for galleries, Chat for
support prompts, Feature for detailed product storytelling, and the base
Modal for any custom dialog.
typical-page-section: >
Video/Feature: triggered from hero or features section.
Image: triggered from gallery or media sections.
Chat: persistent overlay on key conversion pages.
Modal: anywhere a dialog is needed.
Directory
Directory listing components for building product, tool, or resource directories — listing cards, a filterable grid, a detail page layout, a dark category hero, and a submit CTA.
Affiliate
Affiliate marketing components for product showcases — individual product cards in multiple layouts, a ranked product grid, a spec comparison table, a detailed product review page, and a compliance disclosure component.
