4.7 KiB
Hide Layout Chrome for common Role Users
Date: 2026-08-04 Status: Approved (design phase)
Goal
When the logged-in user's role list contains "common", hide all layout chrome — left sidebar, top navbar, tags view, and the floating Settings button — leaving only <app-main /> filling the viewport. Non-common users see the existing full layout unchanged.
Trigger Condition
useUserStore().roles (array) includes the string "common".
The check is roles.includes('common'). A user with ['admin', 'common'] is treated as common because the array includes it; only roles where common is present trigger the new behavior.
Scope
- Applies to all routes, unconditionally.
- No per-route opt-out, no per-route opt-in.
- Only the layout chrome is affected.
<app-main />keeps rendering any page contents exactly as before.
Files Touched
Only one file: src/layout/index.vue.
No stores, no router, no permission utilities, no new files.
Design
1. Add a isCommonUser computed in src/layout/index.vue
import useUserStore from '@/store/modules/user'
const isCommonUser = computed(() =>
useUserStore().roles?.includes('common') ?? false
)
Defensive ?.includes so an undefined roles collapses to false rather than throwing.
2. Gate the four chrome elements with v-if
<sidebar v-if="!sidebar.hide && !isCommonUser" class="sidebar-container" />
<div :class="{ hasTagsView: needTagsView, sidebarHide: sidebar.hide, fullscreen: isCommonUser }" class="main-container">
<div :class="{ 'fixed-header': fixedHeader }">
<navbar v-if="!isCommonUser" @setLayout="setLayout" />
<tags-view v-if="needTagsView && !isCommonUser" />
</div>
<app-main />
<settings v-if="!isCommonUser" ref="settingRef" />
</div>
Notes:
Settingsis hidden even though the original requirement listed only sidebar / navbar / tagsview. The user explicitly confirmed in brainstorming that Settings should also be hidden for cleanliness.- The outer
<div :class="classObj">(withhideSidebar/openSidebar/mobile) is left untouched; it still affects the<sidebar>slot even when sidebar is hidden, which is harmless.
3. Fullscreen styling for <app-main />
Add a scoped SCSS rule:
.main-container.fullscreen {
position: absolute;
inset: 0;
width: 100% !important;
height: 100% !important;
margin-left: 0 !important;
}
This overrides any inherited width / margin-left from the sidebar-open state so <app-main /> truly fills the viewport.
<app-main /> internals (page padding, scoped styles) are not touched. If a future page wants a chrome-less padding experience, it owns that decision.
Out of Scope
- Not changing user store APIs.
- Not adding a getter to
useUserStore(single use site — YAGNI). - Not introducing a second layout component or per-route layout switching.
- Not modifying router meta or permission middleware.
- Not changing
<app-main />internals or any page component.
Error / Edge Cases
rolesisundefinedornull→?.includes('common')returnsundefined,?? falsecollapses tofalse. Safe.rolesis a non-array →Array.prototype.includeswould throw. The user store initializesroles: [], so this is only a risk if a future change sets it to a non-array. No mitigation needed; treat as a contract violation.- User role changes mid-session (does not happen in this app) → computed reacts automatically, layout re-renders. Reactive by design.
- Page refresh →
useUserStoreis repopulated viagetInfo()during router guard; the computed is reactive and picks up the new value on next render. No flicker handling needed because the layout renders after auth is resolved.
Testing
The repo has no frontend unit / e2e tests configured (package.json scripts only cover dev / build). Verification is manual:
- Admin role: log in as a user without
commonin roles. All four chrome areas render as before. - Common role: log in as a user with
commonin roles. Only<app-main />is visible, filling the viewport edge-to-edge. - Negative variant: log in as a user with
['common', 'other-role']— chrome still hidden (array.includessemantics). - Page interaction: inside
<app-main />, the page's own links / buttons / forms work normally.
Future Considerations (not implemented)
- If a second role-driven layout variant appears (e.g. compact admin view), lift
isCommonUserinto auseUserStoregetter and consider per-route layout meta. - If pages ever need to opt out of fullscreen (e.g. a "preview" page that wants the chrome visible for a
commonuser), introduce per-route meta and gate on it. Not a current requirement.