N
Nuxt4w ago
FoxCode

Nuxt Content 3 and docus elements

I would like to replace List.vue to make it work with NuxtContent 3. unwrap() no longer exists, and ContentSlot is also gone. How can I update this code to work with NuxtContent 3?
<script lang="ts">
const iconTypeMap = {
primary: 'heroicons-outline:check',
info: 'heroicons-outline:information-circle',
success: 'heroicons-outline:check-circle',
warning: 'heroicons-outline:exclamation',
danger: 'heroicons-outline:exclamation-circle'
}

export default defineComponent({
props: {
/**
* Used to override the default <code>type</code> icon, check out the
* <a href="https://github.com/nuxt/content/tree/dev/packages/theme-docs/src/components/global/icons">icons available</a>
*/
icon: {
type: String,
default: null
},
/**
* Type of list
*/
type: {
type: String,
default: 'primary',
validator: (value: string) => ['primary', 'info', 'success', 'warning', 'danger'].includes(value)
}
},
setup (props) {
const slots = useSlots()

const { flatUnwrap, unwrap } = useUnwrap()

const iconName = computed(() => props.icon || (iconTypeMap as any)[props.type])

// Usage of render function is mandatory to access default slot
// Otherwise Vue warns that slot "default" was invoked outside of the render function
return () => {
const items = flatUnwrap((slots.default && slots.default()) ?? [], ['ul']).map(li => unwrap(li, ['li']))

return h(
'ul',
items.map(item =>
h('li', [
h('span', { class: `list-icon ${props.type}` }, h(resolveComponent('icon'), { name: iconName.value, class: 'icon' })),
h('span', h(resolveComponent('ContentSlot'), { use: () => item }))
])
)
)
}
}
})
</script>
<script lang="ts">
const iconTypeMap = {
primary: 'heroicons-outline:check',
info: 'heroicons-outline:information-circle',
success: 'heroicons-outline:check-circle',
warning: 'heroicons-outline:exclamation',
danger: 'heroicons-outline:exclamation-circle'
}

export default defineComponent({
props: {
/**
* Used to override the default <code>type</code> icon, check out the
* <a href="https://github.com/nuxt/content/tree/dev/packages/theme-docs/src/components/global/icons">icons available</a>
*/
icon: {
type: String,
default: null
},
/**
* Type of list
*/
type: {
type: String,
default: 'primary',
validator: (value: string) => ['primary', 'info', 'success', 'warning', 'danger'].includes(value)
}
},
setup (props) {
const slots = useSlots()

const { flatUnwrap, unwrap } = useUnwrap()

const iconName = computed(() => props.icon || (iconTypeMap as any)[props.type])

// Usage of render function is mandatory to access default slot
// Otherwise Vue warns that slot "default" was invoked outside of the render function
return () => {
const items = flatUnwrap((slots.default && slots.default()) ?? [], ['ul']).map(li => unwrap(li, ['li']))

return h(
'ul',
items.map(item =>
h('li', [
h('span', { class: `list-icon ${props.type}` }, h(resolveComponent('icon'), { name: iconName.value, class: 'icon' })),
h('span', h(resolveComponent('ContentSlot'), { use: () => item }))
])
)
)
}
}
})
</script>
2 Replies
kapa.ai
kapa.ai4w ago
Hi @FoxCode. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- To update this code to work with Nuxt Content 3, you'll need to make several changes. The unwrap() function and ContentSlot component are no longer available in Nuxt Content 3. Here's how you can modify the code: 1. Replace unwrap() with the new mdc-unwrap attribute on the <slot> component. 2. Use Vue's native <slot> component instead of ContentSlot. 3. Update the way you handle the default slot content. Here's an updated version of the code that should work with Nuxt Content 3:
<script setup lang="ts">
import { computed, h } from 'vue'

const iconTypeMap = {
primary: 'heroicons-outline:check',
info: 'heroicons-outline:information-circle',
success: 'heroicons-outline:check-circle',
warning: 'heroicons-outline:exclamation',
danger: 'heroicons-outline:exclamation-circle'
}

const props = defineProps({
icon: {
type: String,
default: null
},
type: {
type: String,
default: 'primary',
validator: (value: string) => ['primary', 'info', 'success', 'warning', 'danger'].includes(value)
}
})

const iconName = computed(() => props.icon || iconTypeMap[props.type as keyof typeof iconTypeMap])

const renderList = () => {
return h('ul', {}, [
h('li', [
h('span', { class: `list-icon ${props.type}` }, [
h('UIcon', { name: iconName.value, class: 'icon' })
]),
h('span', [
h('slot', { 'mdc-unwrap': 'p' })
])
])
])
}
</script>

<template>
<component :is="renderList" />
</template>
<script setup lang="ts">
import { computed, h } from 'vue'

const iconTypeMap = {
primary: 'heroicons-outline:check',
info: 'heroicons-outline:information-circle',
success: 'heroicons-outline:check-circle',
warning: 'heroicons-outline:exclamation',
danger: 'heroicons-outline:exclamation-circle'
}

const props = defineProps({
icon: {
type: String,
default: null
},
type: {
type: String,
default: 'primary',
validator: (value: string) => ['primary', 'info', 'success', 'warning', 'danger'].includes(value)
}
})

const iconName = computed(() => props.icon || iconTypeMap[props.type as keyof typeof iconTypeMap])

const renderList = () => {
return h('ul', {}, [
h('li', [
h('span', { class: `list-icon ${props.type}` }, [
h('UIcon', { name: iconName.value, class: 'icon' })
]),
h('span', [
h('slot', { 'mdc-unwrap': 'p' })
])
])
])
}
</script>

<template>
<component :is="renderList" />
</template>
Key changes: 1. We've switched to the <script setup> syntax for better TypeScript support and simpler code. 2. The unwrap() function is replaced by using the mdc-unwrap attribute on the <slot> component. This attribute tells Nuxt Content to remove the wrapping paragraph tags from the slot content. 3. We're using Vue's native <slot> component instead of ContentSlot. 4. The rendering logic is simplified and now uses the <component :is="renderList"> syntax in the template to render the dynamic content. Note that this code assumes you're using Nuxt UI for the UIcon component. If you're not, you may need to adjust the icon rendering part. Remember to update your nuxt.config.ts file to use Nuxt Content 3:
export default defineNuxtConfig({
modules: ['@nuxt/content']
})
export default defineNuxtConfig({
modules: ['@nuxt/content']
})
For more information on the changes in Nuxt Content 3, you can refer to the Nuxt Content v3 announcement and the migration guide. ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai4w ago
<@363971301947342848> Kapa.ai is still learning and improving, please let me know how I did by reacting below.

Did you find this page helpful?