feat(shell): fluid layout with collapsible sidebar drawer + fix query-tool MultiSelect
Convert portal shell from block-centered (max-width 1600px) layout to full-viewport fluid flexbox with collapsible sidebar: desktop push-mode (240px → 0), mobile overlay drawer with backdrop. Rename .content → .shell-content to avoid CSS collision with page-level classes. Override page-level max-width constraints when embedded in shell. Also replace native <select multiple> in query-tool with shared MultiSelect component for equipment and workcenter group filters, matching resource-status/history UX. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
70
openspec/specs/collapsible-sidebar-drawer/spec.md
Normal file
70
openspec/specs/collapsible-sidebar-drawer/spec.md
Normal file
@@ -0,0 +1,70 @@
|
||||
## Purpose
|
||||
Define stable requirements for collapsible-sidebar-drawer.
|
||||
|
||||
## Requirements
|
||||
|
||||
### Requirement: Sidebar SHALL be collapsible via a toggle button
|
||||
The portal shell SHALL provide a toggle button in the header that collapses and expands the sidebar. On desktop viewports (>900px), collapsing SHALL animate the sidebar width from 240px to 0px using push mode, causing the content area to resize and fill the freed space. Expanding SHALL reverse the animation.
|
||||
|
||||
#### Scenario: Desktop sidebar collapse
|
||||
- **WHEN** a user clicks the sidebar toggle button on a desktop viewport
|
||||
- **AND** the sidebar is currently expanded
|
||||
- **THEN** the sidebar width SHALL animate to 0px over 300ms
|
||||
- **THEN** the content area SHALL expand to fill the full viewport width
|
||||
|
||||
#### Scenario: Desktop sidebar expand
|
||||
- **WHEN** a user clicks the sidebar toggle button on a desktop viewport
|
||||
- **AND** the sidebar is currently collapsed
|
||||
- **THEN** the sidebar width SHALL animate to 240px over 300ms
|
||||
- **THEN** the content area SHALL shrink to accommodate the sidebar
|
||||
|
||||
### Requirement: Mobile sidebar SHALL use overlay drawer mode
|
||||
On mobile viewports (<=900px), the sidebar SHALL behave as a fixed-position overlay drawer that slides in from the left, with a semi-transparent backdrop covering the content area.
|
||||
|
||||
#### Scenario: Mobile sidebar open
|
||||
- **WHEN** a user taps the toggle button on a mobile viewport
|
||||
- **AND** the sidebar is currently hidden
|
||||
- **THEN** the sidebar SHALL slide in from the left as a fixed overlay (280px width)
|
||||
- **THEN** a semi-transparent backdrop SHALL appear behind the sidebar and above the content
|
||||
|
||||
#### Scenario: Mobile sidebar close via backdrop
|
||||
- **WHEN** a user taps the backdrop overlay
|
||||
- **THEN** the sidebar SHALL slide out to the left
|
||||
- **THEN** the backdrop SHALL fade out
|
||||
|
||||
#### Scenario: Mobile sidebar close via Escape key
|
||||
- **WHEN** the mobile sidebar overlay is open
|
||||
- **AND** a user presses the Escape key
|
||||
- **THEN** the sidebar SHALL close
|
||||
|
||||
#### Scenario: Mobile sidebar closes on navigation
|
||||
- **WHEN** the mobile sidebar overlay is open
|
||||
- **AND** a user clicks a navigation link
|
||||
- **THEN** the sidebar SHALL automatically close after the route change
|
||||
|
||||
### Requirement: Sidebar state SHALL persist within the browser session
|
||||
The collapsed/expanded state of the desktop sidebar SHALL be persisted to `sessionStorage` so that the preference survives page refreshes within the same browser tab.
|
||||
|
||||
#### Scenario: State persistence on refresh
|
||||
- **WHEN** a user collapses the sidebar and refreshes the page
|
||||
- **THEN** the sidebar SHALL remain collapsed after reload
|
||||
|
||||
#### Scenario: New tab starts expanded
|
||||
- **WHEN** a user opens the portal in a new browser tab
|
||||
- **THEN** the sidebar SHALL default to expanded regardless of other tabs' state
|
||||
|
||||
### Requirement: Sidebar transitions SHALL respect reduced-motion preference
|
||||
All sidebar transitions (width animation, overlay slide, backdrop fade) SHALL be disabled when the user has `prefers-reduced-motion: reduce` enabled.
|
||||
|
||||
#### Scenario: Reduced motion disables sidebar animation
|
||||
- **WHEN** the user's OS or browser has reduced-motion enabled
|
||||
- **AND** the user toggles the sidebar
|
||||
- **THEN** the sidebar state SHALL change instantly without animation
|
||||
|
||||
### Requirement: Toggle button SHALL be accessible
|
||||
The sidebar toggle button SHALL include `aria-label` and `aria-expanded` attributes for screen reader accessibility.
|
||||
|
||||
#### Scenario: Screen reader announces toggle state
|
||||
- **WHEN** a screen reader user focuses the toggle button
|
||||
- **THEN** the button SHALL announce its current expanded/collapsed state via `aria-expanded`
|
||||
- **THEN** the button SHALL have an `aria-label` describing its purpose
|
||||
@@ -2,12 +2,29 @@
|
||||
Define stable requirements for spa-shell-navigation.
|
||||
## Requirements
|
||||
### Requirement: Portal SHALL provide a SPA shell driven by Vue Router
|
||||
The portal frontend SHALL use a single SPA shell entry and Vue Router to render page modules without iframe embedding, and SHALL route each page through either native route-view integration or a temporary wrapper component.
|
||||
The portal frontend SHALL use a single SPA shell entry and Vue Router to render page modules without iframe embedding, and SHALL route each page through native route-view integration. The shell layout SHALL use a full-viewport fluid layout with flexbox, removing all max-width constraints and block-centered styling. The main content area (`.shell-content`) SHALL fill available space as a flex child, and the sidebar SHALL be a collapsible flex child that pushes content when expanded on desktop. The content area class SHALL be `.shell-content` (not `.content`) to avoid CSS collision with page-level `.content` classes.
|
||||
|
||||
#### Scenario: Drawer navigation renders integrated route view
|
||||
- **WHEN** a user clicks a sidebar page entry whose migration mode is `native`
|
||||
- **THEN** the active route SHALL be updated through Vue Router
|
||||
- **THEN** the main content area SHALL render the corresponding page module inside shell route-view without iframe usage
|
||||
- **THEN** the content area SHALL fill the available viewport width minus the sidebar width (if sidebar is expanded)
|
||||
|
||||
#### Scenario: Shell layout fills full viewport
|
||||
- **WHEN** the portal shell renders
|
||||
- **THEN** the shell SHALL span the full viewport width with no max-width constraint
|
||||
- **THEN** the header SHALL span edge-to-edge with no border-radius
|
||||
- **THEN** the sidebar and content area SHALL have no outer borders or border-radius
|
||||
|
||||
#### Scenario: Page-level max-width constraints are removed when embedded
|
||||
- **WHEN** a page module registered in the shell route contracts renders inside `.shell-content`
|
||||
- **THEN** page-level max-width constraints SHALL be overridden to allow full-width rendering
|
||||
- **THEN** page-level duplicate padding SHALL be removed to avoid double spacing
|
||||
- **THEN** standalone page rendering (outside the shell) SHALL remain unaffected
|
||||
|
||||
#### Scenario: Shell content class avoids collision with page-level classes
|
||||
- **WHEN** a page module that uses its own `.content` class renders inside the shell
|
||||
- **THEN** the shell's content wrapper (`.shell-content`) SHALL NOT interfere with the page's `.content` styling
|
||||
|
||||
#### Scenario: Wrapper route remains available during migration
|
||||
- **WHEN** a user clicks a sidebar page entry whose migration mode is `wrapper`
|
||||
|
||||
@@ -4,13 +4,19 @@ Define stable requirements for tailwind-design-system.
|
||||
## Requirements
|
||||
|
||||
### Requirement: Frontend styles SHALL be governed by Tailwind design tokens
|
||||
The frontend SHALL define a Tailwind-based design token system for color, spacing, typography, radius, and elevation to ensure consistent styling across modules.
|
||||
The frontend SHALL define a Tailwind-based design token system for color, spacing, typography, radius, and elevation to ensure consistent styling across modules. The `--portal-shell-max-width` CSS variable SHALL be set to `none` to support the fluid layout. A `--portal-sidebar-width` variable SHALL be added for sidebar width reference. The `.u-content-shell` utility class SHALL use `width: 100%` instead of `max-width` constraint.
|
||||
|
||||
#### Scenario: Shared token usage across modules
|
||||
- **WHEN** two report modules render equivalent UI elements (e.g., card, filter chip, primary button)
|
||||
- **THEN** they SHALL use the same token-backed style semantics
|
||||
- **THEN** visual output SHALL remain consistent across modules
|
||||
|
||||
#### Scenario: Fluid layout tokens
|
||||
- **WHEN** the portal shell renders
|
||||
- **THEN** `--portal-shell-max-width` SHALL resolve to `none`
|
||||
- **THEN** `--portal-sidebar-width` SHALL resolve to `240px`
|
||||
- **THEN** `.u-content-shell` SHALL apply `width: 100%` without max-width constraint
|
||||
|
||||
### Requirement: Tailwind migration SHALL support coexistence with legacy CSS
|
||||
The migration SHALL allow Tailwind and existing page CSS to coexist during phased rollout without breaking existing pages.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user