Overlay
Overlays can be used to reveal larger contents or options that are hidden behind a button or a similar component. The content is animated on top of the document and the rest of the interface is blocked.
Props
is-closeable?: boolean
If the overlay is closeable with the escape key.
size?: FluxSize
The size of the overlay.
Default: small
Emits
close: []
Emitted when the overlay is closed.
Slots
default
The contents of the overlay. For the best result, use a with a v-if to control its visibility.
Examples
Basic
A basic overlay.
<template>
<FluxSecondaryButton
icon-leading="copy"
label="Open overlay"
@click="isOpen = true"/>
<FluxOverlay size="medium">
<FluxPane v-if="isOpen">
<FluxPaneHeader title="Overlay"/>
<FluxPaneBody>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aliquam aspernatur, consequuntur debitis eligendi eum magnam necessitatibus nulla perferendis sequi voluptate. Aut consequatur ducimus, quaerat quos ratione sequi veniam? Quis, rem.</p>
<p>Alias dolorum laboriosam pariatur qui ut. Debitis distinctio expedita impedit ipsam voluptatem? Asperiores assumenda dolorem ducimus earum nam placeat ut velit. Ab debitis dicta in itaque quos ut veritatis voluptatum.</p>
<p>Ducimus nemo officiis, quas saepe sequi tempora unde! Debitis dolores eos exercitationem itaque laboriosam magni nam, neque officiis, pariatur quis ratione recusandae reiciendis repudiandae tempore temporibus veritatis vero, voluptates? Earum?</p>
</FluxPaneBody>
<FluxPaneFooter>
<FluxSecondaryButton
label="Close"
@click="isOpen = false"/>
</FluxPaneFooter>
</FluxPane>
</FluxOverlay>
</template>
<script
setup
lang="ts">
import { FluxOverlay, FluxPane, FluxPaneBody, FluxPaneFooter, FluxPaneHeader, FluxSecondaryButton } from '@flux-ui/components';
import { ref } from 'vue';
const isOpen = ref(false);
</script>Re-authenticatie
A re-authentication overlay.
<template>
<FluxDestructiveButton
icon-leading="lock"
label="Re-authenticate"
@click="isOpen = true"/>
<FluxOverlay size="small">
<FluxPane v-if="isOpen">
<FluxForm>
<FluxPaneBody>
<h2>You've been signed out.</h2>
</FluxPaneBody>
<FluxPaneBody>
<p>To continue using your account, please sign in again using your password.</p>
</FluxPaneBody>
<FluxPaneBody>
<FluxFormColumn>
<FluxFormField label="Username">
<FluxFormInput type="email" model-value="bas@flux-ui.dev" disabled is-readonly/>
</FluxFormField>
<FluxFormField label="Password">
<FluxFormInput type="password" model-value="12345678"/>
</FluxFormField>
</FluxFormColumn>
</FluxPaneBody>
<FluxPaneFooter>
<FluxButtonStack
is-fill
direction="vertical">
<FluxPrimaryButton
icon-trailing="user-key"
label="Sign in"/>
<FluxSecondaryButton
label="Cancel"
@click="isOpen = false"/>
</FluxButtonStack>
</FluxPaneFooter>
</FluxForm>
</FluxPane>
</FluxOverlay>
</template>
<script
setup
lang="ts">
import { FluxButtonStack, FluxDestructiveButton, FluxForm, FluxFormColumn, FluxFormField, FluxFormInput, FluxOverlay, FluxPane, FluxPaneBody, FluxPaneFooter, FluxPrimaryButton, FluxSecondaryButton } from '@flux-ui/components';
import { ref } from 'vue';
const isOpen = ref(false);
</script>Router-driven
Pair the overlay with Vue Router to open it through navigation. Define an overlay named view on every route that should appear inside the overlay, and render a single <RouterView name="overlay"/> from your top-level layout.
The layout watches route.matched for the first record that exposes the overlay view. When such a record is matched the <RouterView> renders inside the overlay; otherwise the overlay stays empty and the transition closes it.
<template>
<RouterView/>
<FluxOverlay
:key="overlayRoute?.fullPath"
size="medium">
<RouterView
v-if="overlayRoute"
name="overlay"
:route="overlayRoute"/>
</FluxOverlay>
</template>
<script
lang="ts"
setup>
import { FluxOverlay } from '@flux-ui/components';
import { computed } from 'vue';
import { useRoute } from 'vue-router';
const route = useRoute();
const overlayRoute = computed(() => {
const match = route.matched.find(record => 'overlay' in (record.components ?? {}));
if (!match) {
return null;
}
return route;
});
</script>import { createRouter, createWebHistory, type RouteRecordRaw } from 'vue-router';
const routes: RouteRecordRaw[] = [
{
path: '/projects',
component: () => import('./views/Projects.vue'),
children: [
{
name: 'projects-create',
path: 'create',
components: {
overlay: () => import('./views/ProjectsCreate.vue')
}
},
{
name: 'projects-edit',
path: 'edit/:id',
components: {
overlay: () => import('./views/ProjectsEdit.vue')
}
}
]
}
];
export const router = createRouter({
history: createWebHistory(),
routes
});TIP
Push to one of the named routes (e.g. router.push({name: 'projects-create'})) to open the overlay, and call router.back() from inside the overlay to close it. This keeps the URL in sync with what's on screen and makes the overlay deep-linkable.