跳至主要内容

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

  1. 用戶點擊 Sidebar 頂部的「收合」按鈕(<< 圖示)

Then: 預期結果(收合狀態)

  • 寬度: 從 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

  1. 用戶再次點擊收合按鈕(>> 圖示)

Then: 預期結果(展開狀態)

  • 寬度: 從 64px 擴展至 256px
  • 選單項目: 顯示圖示 + 文字
  • 收合按鈕: 圖示變更為 <<(收合圖示)

Main Content 外觀變化

  • 左側 Margin: 從 ml-[64px] 增加至 ml-[256px]

LocalStorage 更新

localStorage.setItem('sidebar-collapsed', 'false');

額外場景: 手機版 Hamburger 選單

Given: 手機版瀏覽器

  • 視窗寬度: 375px(< 768px)
  • Sidebar 狀態: 預設隱藏

When: 操作

  1. 用戶點擊 Header 左側的 Hamburger 圖示(三條橫線 ☰)

Then: 預期結果

  • 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