Scenario 2: Sidebar 收合與展開
User Story: US-003: 基礎 Layout 與導航
Given: 系統初始狀態
桌面版瀏覽器
- 視窗寬度: 1440px(≥ 1024px)
- Sidebar 狀態: 展開(預設)
- LocalStorage:
sidebar-collapsed: false
已登入店員
{
"userId": "user-001",
"email": "staff@florist.com",
"name": "王小明",
"roles": ["ROLE_STAFF"]
}
When: 執行操作
操作 1: 收合 Sidebar
- 用戶點擊 Sidebar 頂部的「收合」按鈕(
<<圖示)
Then: 預期結果(收合狀態)
Sidebar 外觀變化
- 寬度: 從 256px 縮小至 64px
- 選單項目: 僅顯示圖示,隱藏文字
- 收合按鈕: 圖示變更為
>>(展開圖示)
範例: 選單項目顯示
展開狀態: [🏠] 首頁
收合狀態: [🏠]
Main Content 外觀變化
- 左側 Margin: 從
ml-[256px]減少至ml-[64px] - 寬度: 自動擴展填滿可用空間
LocalStorage 更新
localStorage.setItem('sidebar-collapsed', 'true');
過渡動畫
- 使用 CSS Transition(duration: 300ms)
- Easing:
ease-in-out
.sidebar {
transition: width 300ms ease-in-out;
}
.main-content {
transition: margin-left 300ms ease-in-out;
}
When: 執行操作(續)
操作 2: 展開 Sidebar
- 用戶再次點擊收合按鈕(
>>圖示)
Then: 預期結果(展開狀態)
Sidebar 外觀變化
- 寬度: 從 64px 擴展至 256px
- 選單項目: 顯示圖示 + 文字
- 收合按鈕: 圖示變更為
<<(收合圖示)
Main Content 外觀變化
- 左側 Margin: 從
ml-[64px]增加至ml-[256px]
LocalStorage 更新
localStorage.setItem('sidebar-collapsed', 'false');
額外場景: 手機版 Hamburger 選單
Given: 手機版瀏覽器
- 視窗寬度: 375px(< 768px)
- Sidebar 狀態: 預設隱藏
When: 操作
- 用戶點擊 Header 左側的 Hamburger 圖示(三條橫線 ☰)
Then: 預期結果
Sidebar 行為
- Sidebar 從左側滑入(Overlay 模式)
- 寬度: 256px
- 動畫:
translateX(-100%) → translateX(0) - z-index: 1001(覆蓋在內容上方)
背景遮罩
- 顯示半透明黑色遮罩 (
bg-black/50) - z-index: 1000
- 點擊遮罩可關閉 Sidebar
關閉 Sidebar
方式 1: 點擊背景遮罩
方式 2: 點擊 Sidebar 內的關閉按鈕(✕ 圖示)
方式 3: 點擊任意選單項目(自動導航並關閉)
動畫: translateX(0) → translateX(-100%)
自動化測試範例
Cypress E2E 測試
describe('US-003 Scenario 2: Sidebar toggle', () => {
beforeEach(() => {
cy.login('staff@florist.com', 'Password123!');
cy.visit('/');
});
it('should collapse and expand sidebar on desktop', () => {
cy.viewport(1440, 900); // 桌面尺寸
// 驗證初始狀態(展開)
cy.get('[data-testid="sidebar"]').should('have.class', 'expanded');
cy.get('[data-testid="sidebar"]').should('have.css', 'width', '256px');
// 點擊收合按鈕
cy.get('[data-testid="sidebar-toggle"]').click();
// 驗證收合狀態
cy.get('[data-testid="sidebar"]').should('have.class', 'collapsed');
cy.get('[data-testid="sidebar"]').should('have.css', 'width', '64px');
// 驗證 LocalStorage
cy.window().then((win) => {
expect(win.localStorage.getItem('sidebar-collapsed')).to.equal('true');
});
// 點擊展開按鈕
cy.get('[data-testid="sidebar-toggle"]').click();
// 驗證展開狀態
cy.get('[data-testid="sidebar"]').should('have.class', 'expanded');
cy.get('[data-testid="sidebar"]').should('have.css', 'width', '256px');
});
it('should show hamburger menu on mobile', () => {
cy.viewport(375, 667); // iPhone SE 尺寸
// 驗證初始狀態(Sidebar 隱藏)
cy.get('[data-testid="sidebar"]').should('not.be.visible');
// 點擊 Hamburger 圖示
cy.get('[data-testid="hamburger-button"]').click();
// 驗證 Sidebar 滑入
cy.get('[data-testid="sidebar"]').should('be.visible');
cy.get('[data-testid="sidebar-overlay"]').should('be.visible');
// 點擊遮罩關閉
cy.get('[data-testid="sidebar-overlay"]').click();
// 驗證 Sidebar 滑出
cy.get('[data-testid="sidebar"]').should('not.be.visible');
});
});
最後更新: 2025-10-31