@framer-framer/vue
v3.4.0
Published
Vue 3 embed component for framer-framer
Downloads
301
Maintainers
Readme
@framer-framer/vue
Vue 3 embed component for framer-framer. Resolve any URL to embed HTML with a simple component or composable.
Installation
npm install @framer-framer/vue framer-framer vueUsage
<Embed> Component
<script setup>
import { Embed } from '@framer-framer/vue';
</script>
<template>
<Embed
url="https://www.youtube.com/watch?v=dQw4w9WgXcQ"
:max-width="640"
@load="(result) => console.log('Loaded:', result.provider)"
@error="(err) => console.error(err)"
/>
</template>Custom Slots
<template>
<Embed url="https://www.youtube.com/watch?v=dQw4w9WgXcQ">
<!-- Custom loading skeleton -->
<template #loading>
<div class="skeleton" />
</template>
<!-- Custom error display -->
<template #error="{ error }">
<div class="error">Failed: {{ error.message }}</div>
</template>
<!-- Custom embed rendering -->
<template #default="{ result }">
<div v-html="result.html" />
<p>{{ result.title }} — {{ result.provider }}</p>
</template>
</Embed>
</template>useEmbed() Composable
<script setup>
import { useEmbed } from '@framer-framer/vue';
const { result, loading, error } = useEmbed(
'https://www.youtube.com/watch?v=dQw4w9WgXcQ',
{ maxWidth: 640 }
);
</script>
<template>
<div v-if="loading">Loading...</div>
<div v-else-if="error">Error: {{ error.message }}</div>
<div v-else-if="result" v-html="result.html" />
</template>The composable also accepts a reactive ref or getter as the URL:
<script setup>
import { ref } from 'vue';
import { useEmbed } from '@framer-framer/vue';
const url = ref('https://www.youtube.com/watch?v=dQw4w9WgXcQ');
const { result, loading, error } = useEmbed(url);
</script>Props
| Prop | Type | Required | Description |
|------|------|----------|-------------|
| url | string | Yes | URL to resolve |
| maxWidth | number | No | Max embed width |
| maxHeight | number | No | Max embed height |
| options | EmbedOptions | No | Options passed to framer-framer's embed() |
| theme | "light" \| "dark" \| "auto" | No | Theme mode (default: "auto") |
Events
| Event | Payload | Description |
|-------|---------|-------------|
| @load | EmbedResult | Emitted when the embed is resolved |
| @error | Error | Emitted when resolution fails |
Slots
| Slot | Props | Description |
|------|-------|-------------|
| default | { result: EmbedResult } | Custom embed rendering |
| loading | — | Custom loading skeleton |
| error | { error: Error } | Custom error display |
Nuxt Integration
SSR with useNuxtEmbed() (Recommended)
The useNuxtEmbed() composable resolves embeds on the server and hydrates the result on the client — no loading flash, instant rendering.
<script setup>
import { useNuxtEmbed } from '@framer-framer/vue/nuxt';
const { data, status, error, refresh } = useNuxtEmbed(
'https://www.youtube.com/watch?v=dQw4w9WgXcQ',
{ maxWidth: 640 }
);
</script>
<template>
<div v-if="status === 'pending'">Loading...</div>
<div v-else-if="error">Error: {{ error.message }}</div>
<div v-else-if="data" v-html="data.html" />
</template>Reactive URL
<script setup>
import { ref } from 'vue';
import { useNuxtEmbed } from '@framer-framer/vue/nuxt';
const url = ref('https://www.youtube.com/watch?v=dQw4w9WgXcQ');
const { data, status } = useNuxtEmbed(url);
</script>Lazy Loading
Use lazy: true to skip server-side resolution and resolve client-side only:
<script setup>
import { useNuxtEmbed } from '@framer-framer/vue/nuxt';
const { data, status } = useNuxtEmbed(
'https://www.youtube.com/watch?v=dQw4w9WgXcQ',
{ lazy: true }
);
</script>Client-Only Mode
For the <Embed> component, use <ClientOnly> to avoid SSR issues:
<template>
<ClientOnly>
<Embed url="https://www.youtube.com/watch?v=dQw4w9WgXcQ" />
<template #fallback>
<div>Loading embed...</div>
</template>
</ClientOnly>
</template>License
MIT
