From 7f42c40efc0c73cac6d49563259a447f60d0965f Mon Sep 17 00:00:00 2001 From: gahusb Date: Wed, 27 May 2026 01:55:58 +0900 Subject: [PATCH] feat(saju-ui-v2): useViewportMode hook (1024px breakpoint) + 3 tests --- src/pages/saju/_shell/useViewportMode.js | 16 ++++++++++ src/pages/saju/_shell/useViewportMode.test.js | 32 +++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 src/pages/saju/_shell/useViewportMode.js create mode 100644 src/pages/saju/_shell/useViewportMode.test.js diff --git a/src/pages/saju/_shell/useViewportMode.js b/src/pages/saju/_shell/useViewportMode.js new file mode 100644 index 0000000..1d4c3de --- /dev/null +++ b/src/pages/saju/_shell/useViewportMode.js @@ -0,0 +1,16 @@ +import { useState, useEffect } from 'react'; + +export default function useViewportMode() { + const [mode, setMode] = useState(() => + typeof window !== 'undefined' && window.innerWidth >= 1024 ? 'desktop' : 'mobile' + ); + useEffect(() => { + const onResize = () => { + const next = window.innerWidth >= 1024 ? 'desktop' : 'mobile'; + setMode((prev) => (prev === next ? prev : next)); + }; + window.addEventListener('resize', onResize); + return () => window.removeEventListener('resize', onResize); + }, []); + return mode; +} diff --git a/src/pages/saju/_shell/useViewportMode.test.js b/src/pages/saju/_shell/useViewportMode.test.js new file mode 100644 index 0000000..22d015f --- /dev/null +++ b/src/pages/saju/_shell/useViewportMode.test.js @@ -0,0 +1,32 @@ +import { renderHook, act } from '@testing-library/react'; +import { describe, it, expect, beforeEach } from 'vitest'; +import useViewportMode from './useViewportMode'; + +describe('useViewportMode', () => { + beforeEach(() => { + window.innerWidth = 800; + }); + + it('returns mobile when width < 1024', () => { + window.innerWidth = 1023; + const { result } = renderHook(() => useViewportMode()); + expect(result.current).toBe('mobile'); + }); + + it('returns desktop when width >= 1024', () => { + window.innerWidth = 1024; + const { result } = renderHook(() => useViewportMode()); + expect(result.current).toBe('desktop'); + }); + + it('updates on resize', () => { + window.innerWidth = 800; + const { result } = renderHook(() => useViewportMode()); + expect(result.current).toBe('mobile'); + act(() => { + window.innerWidth = 1200; + window.dispatchEvent(new Event('resize')); + }); + expect(result.current).toBe('desktop'); + }); +});