Vitral 0.2
Media

Galleria

Images with thumbnails, indicators, rotation and a full-screen mode.

Import

main.ts
import { Galleria } from '@vitral/vue';

Thumbnails

1 of 8
Photograph 1
Photograph 1
<script setup lang="ts">import { Galleria } from '@vitral/vue';import { ref } from 'vue'; const photos = [1011, 1012, 1013, 1014, 1015, 1016, 1018, 1019].map((id, i) => ({ id, alt: `Photograph ${i + 1}` }));const index = ref(0);</script> <template>    <Galleria v-model:active-index="index" :value="photos" :num-visible="5" show-item-navigators aria-label="Photographs" style="max-width: 40rem">        <template #item="{ item }">            <img width="800" height="450" :src="`https://picsum.photos/id/${(item as { id: number }).id}/800/450`" :alt="(item as { alt: string }).alt" style="display: block; width: 100%; height: auto" />        </template>        <template #thumbnail="{ item }">            <img width="120" height="80" :src="`https://picsum.photos/id/${(item as { id: number }).id}/120/80`" alt="" style="display: block; width: 100%; height: auto" />        </template>        <template #caption="{ item }">{{ (item as { alt: string }).alt }}</template>    </Galleria></template>

Transitions

How one picture gives way to the next, by name. The presets are defined once and shared with Carousel, and every one of them stops under prefers-reduced-motion.

1 of 8
Photograph 1
<script setup lang="ts">import { Galleria, SelectButton, StackPanel, transitionPresets, type TransitionPreset } from '@vitral/vue';import { ref } from 'vue'; const photos = [1011, 1012, 1013, 1014, 1015, 1016, 1018, 1019].map((id, i) => ({ id, alt: `Photograph ${i + 1}` }));const shown = ref(0);const preset = ref<TransitionPreset>('fade');const presetOptions = transitionPresets.map((value) => ({ label: value[0]!.toUpperCase() + value.slice(1), value }));</script> <template>    <StackPanel spacing="0.75rem" style="flex: 1 1 100%; min-width: 0">        <SelectButton v-model="preset" :options="presetOptions" option-label="label" option-value="value" size="small" :allow-empty="false" aria-label="Transition" />        <Galleria            v-model:active-index="shown"            :value="photos"            :transition="preset"            :num-visible="5"            show-item-navigators            aria-label="Photographs, with a transition"            style="max-width: 40rem"        >            <template #item="{ item }">                <img :src="`https://picsum.photos/id/${(item as { id: number }).id}/800/450`" :alt="(item as { alt: string }).alt" width="800" height="450" style="display: block; width: 100%; height: auto" />            </template>            <template #thumbnail="{ item }">                <img :src="`https://picsum.photos/id/${(item as { id: number }).id}/120/80`" alt="" width="120" height="80" style="display: block; width: 100%; height: auto" />            </template>        </Galleria>    </StackPanel></template>

Indicators and rotation

1 of 8
Photograph 1
<script setup lang="ts">import { Galleria } from '@vitral/vue'; const photos = [1011, 1012, 1013, 1014, 1015, 1016, 1018, 1019].map((id, i) => ({ id, alt: `Photograph ${i + 1}` }));</script> <template>    <Galleria :value="photos" :show-thumbnails="false" show-indicators auto-play :transition-interval="3000" aria-label="Photographs, rotating" style="max-width: 32rem">        <template #item="{ item }">            <img width="640" height="360" :src="`https://picsum.photos/id/${(item as { id: number }).id}/640/360`" :alt="(item as { alt: string }).alt" style="display: block; width: 100%; height: auto" />        </template>    </Galleria></template>

Full screen

<script setup lang="ts">import { Button, Galleria } from '@vitral/vue';import { ref } from 'vue'; const photos = [1011, 1012, 1013, 1014, 1015, 1016, 1018, 1019].map((id, i) => ({ id, alt: `Photograph ${i + 1}` }));const visible = ref(false);const index = ref(0);</script> <template>    <Button label="Open gallery" icon="image" @click="visible = true" />    <Galleria v-model:visible="visible" v-model:active-index="index" :value="photos" full-screen show-item-navigators circular aria-label="Photographs, full screen">        <template #item="{ item }">            <img width="1200" height="675" :src="`https://picsum.photos/id/${(item as { id: number }).id}/1200/675`" :alt="(item as { alt: string }).alt" style="display: block; width: 100%; height: auto" />        </template>        <template #thumbnail="{ item }">            <img width="120" height="80" :src="`https://picsum.photos/id/${(item as { id: number }).id}/120/80`" alt="" style="display: block; width: 100%; height: auto" />        </template>    </Galleria></template>

API

Read from packages/vue/src/components/Galleria/types.ts, so it says what the component actually accepts.

Props

NameTypeDescription
valueany[]—
numVisiblenumberThumbnails shown at once. Defaults to 3.
fullScreenbooleanShow in a modal over the page, opened with `v-model:visible`.
showThumbnailsbooleanDefaults to true.
thumbnailsPosition'bottom' | 'top' | 'left' | 'right'—
showItemNavigatorsbooleanPrevious and next buttons on the item.
showThumbnailNavigatorsbooleanPrevious and next buttons beside the thumbnails. Defaults to true.
showIndicatorsbooleanDots under the item.
circularbooleanWrap round: the last item is followed by the first. On by default — a gallery that stops dead at the end sends the reader back through everything they have just seen to reach the other end of it.
autoPlaybooleanRotate through the items; a pause button comes with it.
transitionIntervalnumberMilliseconds between items when playing. Defaults to 4000.
transitionTransitionPresetHow one item gives way to the next: `'fade'`, `'slide'`, `'push'`, `'cover'`, `'zoom'`, `'flip'`, or `'none'`, which is the default — a gallery being browsed quickly is better off swapping at once.
ariaLabelstringNames the gallery.

Plus pt, dt and unstyled from BaseProps, see pass-through and unstyled mode.

Emits

EventPayloadDescription
update:activeIndexindex: number—
update:visiblevisible: boolean—

Slots

NameSlot propsDescription
item(props: { item: unknown; index: number })—
thumbnail(props: { item: unknown; index: number })—
caption(props: { item: unknown; index: number })—
indicator(props: { index: number; active: boolean })—
header——
footer——