# 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 `` 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. `` 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` ```js 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` ```vue
``` Notes: - `Settings` is 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 `
` (with `hideSidebar` / `openSidebar` / `mobile`) is left untouched; it still affects the `` slot even when sidebar is hidden, which is harmless. ### 3. Fullscreen styling for `` Add a scoped SCSS rule: ```scss .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 `` truly fills the viewport. `` 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 `` internals or any page component. ## Error / Edge Cases - `roles` is `undefined` or `null` → `?.includes('common')` returns `undefined`, `?? false` collapses to `false`. Safe. - `roles` is a non-array → `Array.prototype.includes` would throw. The user store initializes `roles: []`, 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 → `useUserStore` is repopulated via `getInfo()` 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: 1. **Admin role**: log in as a user without `common` in roles. All four chrome areas render as before. 2. **Common role**: log in as a user with `common` in roles. Only `` is visible, filling the viewport edge-to-edge. 3. **Negative variant**: log in as a user with `['common', 'other-role']` — chrome still hidden (array `.includes` semantics). 4. **Page interaction**: inside ``, 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 `isCommonUser` into a `useUserStore` getter 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 `common` user), introduce per-route meta and gate on it. Not a current requirement.