vue-stacked-ui
provides "Stacked UI" at the top of vue-router(v4).
It is possible to realize a UI that allows users to drill down through data, sometimes seen in dashboards.
Following features,
- Allows infinite number of pages to be stacked.
- URL-first design. (URL representing stack state)
- Browser history support.
- Route params passed to page by vue-router.
- Provides callback to block when "pop" Stack.
- Vue 3
- vue-router 4
npm install vue-stacked-ui
import router from './router'
import { stackedUI } from 'vue-stacked-ui'
import 'vue-stacked-ui/dist/vue-stacked-ui.css'
// Then use it as Vue plugin.
app.use(stackedUI, {router: router});
<StackRootView />
<!-- Reserve Drawer Area -->
<div id="drawer_wrapper">
<StackView />
</div>
<!-- Reserve Drawer Area -->
<StackPush to="/about">stack push component</StackPush>
<StackPop>stack push component</StackPop>
import { useStack } from "vue-stacked-ui"
const stack = useStack();
stack.push("/about/hoge")
stack.pop()
props.currentStack?.onBeforePop(() => {
return confirm("Realy close stack?")
});
This is the recommended way to register navigation guards from anywhere, even before stack initialization:
// In your router/index.ts or similar file
import { registerBeforeEachGuard } from "vue-stacked-ui"
// Register a global guard that will be applied to the stack
// Works even if called before the stack is initialized
registerBeforeEachGuard((to, from) => {
console.log(`Global guard: Navigating to ${to.path}`);
// Works with any authentication library
if (to.path.includes('admin') && !isAuthenticated()) {
return '/login';
}
return true;
});
If you have access to the stack instance, you can register navigation guards directly:
import { useStack } from "vue-stacked-ui"
const stack = useStack();
// Register a navigation guard similar to vue-router's beforeEach
// This will be called before any stack navigation (push, pop, replace)
stack.beforeEach((to, from) => {
// Access the route information
console.log(`Navigating from ${from?.name} to ${to.name}`);
// Cancel navigation by returning false
if (to.path.includes('forbidden')) {
return false;
}
// Redirect to another route by returning a route location
if (to.path.includes('redirect')) {
return '/alternative-page';
}
// Allow navigation by returning true or undefined
return true;
});