The NOVA LAB storage has multiple sections - a header with a label, a main cargo chamber, and a control panel at the bottom. Vue allows you to define multiple slots in a single component - these are named slots.
In the child component, you give slots names using the
name attribute:1<!-- StoragePanel.vue -->
2<template>
3 <div class="storage-panel">
4 <header class="panel-header">
5 <slot name="header">
6 <h2>Default Header</h2>
7 </slot>
8 </header>
9
10 <main class="panel-body">
11 <slot>
12 <!-- Slot without name = "default" slot -->
13 <p>No content loaded</p>
14 </slot>
15 </main>
16
17 <footer class="panel-footer">
18 <slot name="footer">
19 <p>Standard footer</p>
20 </slot>
21 </footer>
22 </div>
23</template>The parent uses
<template v-slot:name> to direct content to the appropriate slot:1<template>
2 <StoragePanel>
3 <template v-slot:header>
4 <h2>Cargo Bay Alpha</h2>
5 </template>
6
7 <!-- Content without template goes to the default slot -->
8 <p>Main cargo content here</p>
9
10 <template v-slot:footer>
11 <button>Seal Bay</button>
12 </template>
13 </StoragePanel>
14</template>Instead of
v-slot:header you can write #header:1<template>
2 <StoragePanel>
3 <template #header>
4 <h2>Cargo Bay Alpha</h2>
5 </template>
6
7 <template #default>
8 <p>Main content</p>
9 </template>
10
11 <template #footer>
12 <button>Seal Bay</button>
13 </template>
14 </StoragePanel>
15</template>You can check whether the parent has filled a slot and conditionally render a section:
1<!-- StoragePanel.vue -->
2<script setup>
3import { useSlots } from 'vue'
4const slots = useSlots()
5</script>
6
7<template>
8 <div class="panel">
9 <header v-if="slots.header" class="header">
10 <slot name="header" />
11 </header>
12
13 <main>
14 <slot />
15 </main>
16
17 <footer v-if="slots.footer" class="footer">
18 <slot name="footer" />
19 </footer>
20 </div>
21</template>In the template you can also use
$slots.header without importing.