Facade Components
A facade renders lightweight placeholder UI until its third-party script and component are ready.
What are facade components?
A video embed, payment modal, or chat widget may fetch several resources during startup. Deferring that work helps the initial page, but inserting the real UI later can cause Cumulative Layout Shift (CLS). A facade reserves the space and can show a loading state while the vendor code loads.
Trade-offs
Facade components can introduce user-experience trade-offs:
- Flash of mismatched content: The placeholder may not look like the final UI. You may need to adjust the default styling to match your app's design.
- Unavailable interactivity: The real element requires the script to load. Keep an alternative available if loading fails.
- Accessibility concerns: Announce loading and failure states clearly.
Available facades
Script-backed facade components wrap the relevant useScript<Provider>() composable and expose props, slots, and events for controlling their placeholders. Some components provide a minimally styled default placeholder. Check each component's registry page for its exact API.
Usage guidance
Provide an error fallback
Tell the user what failed and offer another way to reach the content.
<ScriptYouTubePlayer>
<template #error>
<UAlert color="red" title="YouTube player failed to load" description="Please refresh the page to try again." />
</template>
</ScriptYouTubePlayer>
Provide a loading state with accessible feedback
ScriptLoadingIndicator provides a visible loading state and an accessible status label.
<ScriptYouTubePlayer>
<template #loading>
<ScriptLoadingIndicator />
</template>
</ScriptYouTubePlayer>
Choose the triggering event
Facade components have default triggers, which you can override for the surrounding UI.
Prefer triggers that require explicit user interaction, such as a click. Loading on hover can cause subsequent events, such as clicks, to be lost while the component is replaced.
Facade Components API
The script-backed facade components share a similar API, although the exact props, slots, events, and event payloads vary by component.
Props
trigger: For supported facades, the event that triggers the script to load. See Element Event Triggers for more information. The PayPal facades currently expose this prop but do not use it for loading or facade state. Configure PayPal's registrytriggerinstead.
Slots
ScriptYouTubePlayer, used in the examples below, provides minimal default UI and several slots for customization. Other facade components may expose different slots.
default: Content to always display with the component.
<template>
<ScriptYouTubePlayer>
<div class="bg-blue-500 text-white p-5">
Youtube!
</div>
</ScriptYouTubePlayer>
</template>
loading: The content to display only while the script is loading.
<template>
<ScriptYouTubePlayer>
<template #loading>
<ScriptLoadingIndicator />
</template>
</ScriptYouTubePlayer>
</template>
awaitingLoad: The content to display only while the script is waiting to load.
<template>
<ScriptYouTubePlayer>
<template #awaitingLoad>
<div class="bg-blue-500 text-white p-5">
Click to play!
</div>
</template>
</ScriptYouTubePlayer>
</template>
error: The content to display if the script fails to load.
<template>
<ScriptYouTubePlayer>
<template #error>
<UAlert color="red" title="YouTube player failed to load" description="Please refresh the page to try again." />
</template>
</ScriptYouTubePlayer>
</template>
The Crisp and Intercom components currently check their loading branch before their error branch. Their error events still fire, but their named #error slots cannot render until that ordering is fixed. Handle @error outside those two components for now.
Events
ready: Emitted when the script or component is ready. The payload depends on the component.error: Emitted when the script or component fails to load. The payload depends on the component.