Slide over
A slide over is a modal-like interface that slides in from the side of the view to display additional content or options. It typically allows users to easily access important information without disrupting their current workflow. Slide overs are mostly used to reveal opions for an entity.
Props
is-closeable?: boolean
If the slide-over can be closed with the escape key.
view-key?: string
A unique key to identify the current view within the slide over. Used for view-based transitions.
Emits
close: []
Triggered when the slide over is closed.
Slots
default
The content of the slide over.
Examples
Basic
A basic slide over.
<template>
<FluxSecondaryButton
icon-leading="arrow-left-to-line"
label="Open"
@click="isSlideOverOpened = true"/>
<FluxSlideOver>
<FluxPane v-if="isSlideOverOpened">
<FluxPaneHeader title="Slide over">
<FluxSecondaryButton
icon-before="xmark"
@click="isSlideOverOpened = false"/>
</FluxPaneHeader>
<FluxPaneBody>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ab beatae dolore et ex facere itaque iusto labore minima, neque repellat sint vitae. Adipisci aliquid deserunt ea itaque laudantium quaerat sequi!</p>
<p>Atque beatae delectus dolor ducimus eius officiis reprehenderit! Accusamus accusantium ex laudantium libero magnam minus numquam odio pariatur, perferendis quisquam veritatis voluptates. Aperiam, autem temporibus! Dolore harum nesciunt odit rem.</p>
<p>Assumenda error illum, necessitatibus nihil provident ratione repellat repudiandae vero. Eius eveniet ex hic id incidunt molestiae perspiciatis quaerat quidem sed ullam. Aut cumque delectus laborum minima sunt voluptas voluptatibus?</p>
</FluxPaneBody>
<FluxPaneFooter>
<FluxSecondaryButton
label="Close"
@click="isSlideOverOpened = false"/>
<FluxSpacer/>
<FluxPrimaryButton
icon-before="circle-check"
label="Save"
@click="isSlideOverOpened = false"/>
</FluxPaneFooter>
</FluxPane>
</FluxSlideOver>
</template>
<script
setup
lang="ts">
import { FluxPane, FluxPaneBody, FluxPaneFooter, FluxPaneHeader, FluxPrimaryButton, FluxSecondaryButton, FluxSlideOver, FluxSpacer } from '@flux-ui/components';
import { ref } from 'vue';
const isSlideOverOpened = ref(false);
</script>Tabs
A slide over with tabs.
<template>
<FluxSecondaryButton
icon-leading="arrow-left-to-line"
label="Open"
@click="isSlideOverOpened = true"/>
<FluxSlideOver>
<FluxPane v-if="isSlideOverOpened">
<FluxPaneHeader title="Slide over">
<FluxSecondaryButton
icon-before="xmark"
@click="isSlideOverOpened = false"/>
</FluxPaneHeader>
<FluxTabs>
<template #tabs="{ modelValue, tabs, activate }">
<FluxTabBar>
<template
v-for="(tab, index) in tabs"
:key="index">
<FluxTabBarItem
:icon="tab.icon"
:is-active="modelValue === index"
:label="tab.label"
@click="activate(index)"/>
</template>
</FluxTabBar>
</template>
<FluxTab label="Common">
<FluxPaneBody>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Aliquam aliquid aperiam earum facilis fugiat in, itaque laboriosam, libero molestias nulla, pariatur qui quod sequi sint totam? Fuga ipsum placeat unde.
</FluxPaneBody>
</FluxTab>
<FluxTab label="Advanced">
<FluxPaneBody>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Animi consequatur dolorem dolorum ducimus enim, fuga, hic illo labore libero, magnam minima odio pariatur porro quasi quidem quis repellat reprehenderit vero?
</FluxPaneBody>
</FluxTab>
</FluxTabs>
<FluxPaneFooter>
<FluxSecondaryButton
label="Close"
@click="isSlideOverOpened = false"/>
<FluxSpacer/>
<FluxPrimaryButton
icon-before="circle-check"
label="Save"
@click="isSlideOverOpened = false"/>
</FluxPaneFooter>
</FluxPane>
</FluxSlideOver>
</template>
<script
setup
lang="ts">
import { FluxPane, FluxPaneBody, FluxPaneFooter, FluxPaneHeader, FluxPrimaryButton, FluxSecondaryButton, FluxSlideOver, FluxSpacer, FluxTab, FluxTabBar, FluxTabBarItem, FluxTabs } from '@flux-ui/components';
import { ref } from 'vue';
const isSlideOverOpened = ref(false);
</script>Router-driven
Pair the slide over with Vue Router to open detail views through navigation. Define an over named view on every route that should appear inside the slide over, and render a single <RouterView name="over"/> from your top-level layout.
The layout watches route.matched for the first record that exposes the over view. When such a record is matched the <RouterView> renders inside the slide over; otherwise the slide over stays empty and the transition closes it. The matched route's fullPath is forwarded to the view-key prop so transitions are scoped to the active resource.
<template>
<RouterView/>
<FluxSlideOver :view-key="slideOverRoute?.fullPath">
<RouterView
v-if="slideOverRoute"
name="over"
:route="slideOverRoute"/>
</FluxSlideOver>
</template>
<script
lang="ts"
setup>
import { FluxSlideOver } from '@flux-ui/components';
import { computed } from 'vue';
import { useRoute } from 'vue-router';
const route = useRoute();
const slideOverRoute = computed(() => {
const match = route.matched.find(record => 'over' in (record.components ?? {}));
if (!match) {
return null;
}
return route;
});
</script>import { createRouter, createWebHistory, type RouteRecordRaw } from 'vue-router';
const routes: RouteRecordRaw[] = [
{
path: '/orders',
component: () => import('./views/Orders.vue'),
children: [
{
name: 'order',
path: ':id',
components: {
over: () => import('./views/Order.vue')
},
children: [
{
name: 'order-buyer',
path: 'buyer',
component: () => import('./views/OrderBuyer.vue')
},
{
name: 'order-payment',
path: 'payment',
component: () => import('./views/OrderPayment.vue')
}
]
}
]
}
];
export const router = createRouter({
history: createWebHistory(),
routes
});TIP
Push to one of the named routes (e.g. router.push({name: 'order', params: {id: 42}})) to open the slide over, and call router.back() from inside it to close. The slide over also supports nested children (such as tabs), each with their own URL.