Section Navigation (Tabs)
In addition to having links in the sidebar, you can add a tabs bar along the top of each page.
[Demo]
This allows you to create navigation in two dimensions - e.g. in the sidebar you may have the main models and their related lookup tables:
- Accounts
- Account Statuses
- Account Types
- Contacts
- Contact Roles
Then for each of these 5 sections you may have some or all of the following tabs:
- List (i.e. the index page)
- New
- Export
- Logs (i.e. audit logs)
- Bin (i.e. soft-deleted records)
Whether you choose to put these links directly in the sidebar or section nav will depend on the size/complexity of the application, but you should be consistent throughout the application to avoid confusing users.
Creating a Section Links Component
Since each section nav bar will be used on more than one page, the first thing to do is create a component. Generally it will be in resources/vue/<Section>/SectionNav<Section>.vue, e.g. resources/vue/Examples/SectionNavExamples.vue.
The basic structure is:
<script>
import SectionNav from '@alberon/nexus/vue/SectionNav';
import SectionNavLink from '@alberon/nexus/vue/SectionNavLink';
export default {
components: {
SectionNav,
SectionNavLink,
},
props: {
// For PhpStorm
},
}
</script>
<template>
<SectionNav :href="$route('examples.index')" title="Examples">
...
</SectionNav>
</template>
Title
The title and href props are both optional, but they are recommended to make it clear which section the user is currently in and make it easy for them to get back to the main page.
The title will be displayed on the far left of the tabs, styled as a title not a tab.
You should either include the href in all sections or no sections, to be consistent.
Links (Tabs)
Within the section navigation you can include any number of tabs, though you generally don't want too many as they will wrap on small screens.
<SectionNav :href="$route('examples.index')" title="Examples">
<SectionNavLink
active="examples.index"
:href="$route('examples.index')"
text="List"
/>
...
</SectionNav>
The props (active, href, text, link-class) are similar to sidebar links.
Right-Aligned Links (Tabs)
For low-priority or admin-only tabs such as "Logs" and "Bin", you can use the #right slot to position them on the right of the screen:
<SectionNav :href="$route('examples.index')" title="Examples">
...
<template #right>
<SectionNavLink
v-if="$page.props.section_userCan.AuditExamples"
active="examples.all-logs"
:href="$route('examples.all-logs')"
text="Audit Logs"
/>
</template>
</SectionNav>
Conditionally Show/Hide Links
Like the sidebar, you can conditionally hide/show links with v-if (example above).
However, instead of adding the data to the application-side InertiaServiceProvider, you should add it to the constructor of the relevant controller:
class ExampleController extends Controller
{
public function __construct()
{
Inertia::share('section_userCan', fn() => user_can([
Permission::AuditExamples,
]));
}
...
}
The section_ prefix should be used to ensure section data doesn't conflict with either global or per-action data.
The fn() => closure is required to ensure the permissions are not evaluated until after the request has completed. (Without it, they will be evaluated before the request starts, at which point Auth::user() returns null.)
If a section has multiple controllers, consider extracting the Inertia::share(...) code to a trait or support class so you can reuse it instead of duplicating it.
Component Reference
<SectionNav>
Props:
title(String) - An optional title to display to the left of the tabs.href(String) - An optional URL to link the title to.
Slots:
- default - The links (tabs) to display on the left.
#right- The links (tabs) to display on the right.
Events: None.
<SectionNavLink>
Props:
href(String - required) - The URL to link to.text(String - required) - The link text.active- (Boolean, String or Array) - Either a boolean to say whether the link is active or not, or a string/array of route name patterns that should be treated as active.link-class- (String, Array or Object) - Classes to add to the<a>tag.
Slots: None.
Events: None.