Skip to content

Commit 399cf89

Browse files
committed
📱(frontend) add hook store useResponsiveStore
useResponsiveStore is a hook store that provides the current screen size and the current device type.
1 parent f081f78 commit 399cf89

File tree

3 files changed

+73
-0
lines changed

3 files changed

+73
-0
lines changed

src/frontend/apps/impress/src/core/AppProvider.tsx

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
import { CunninghamProvider } from '@openfun/cunningham-react';
22
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
3+
import { useEffect } from 'react';
34

45
import { useCunninghamTheme } from '@/cunningham';
56
import '@/i18n/initI18n';
7+
import { useResponsiveStore } from '@/stores/';
68

79
import { Auth } from './auth/';
810

@@ -25,6 +27,15 @@ const queryClient = new QueryClient({
2527
export function AppProvider({ children }: { children: React.ReactNode }) {
2628
const { theme } = useCunninghamTheme();
2729

30+
const initializeResizeListener = useResponsiveStore(
31+
(state) => state.initializeResizeListener,
32+
);
33+
34+
useEffect(() => {
35+
const cleanupResizeListener = initializeResizeListener();
36+
return cleanupResizeListener;
37+
}, [initializeResizeListener]);
38+
2839
return (
2940
<QueryClientProvider client={queryClient}>
3041
<CunninghamProvider theme={theme}>
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './useResponsiveStore';
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import { create } from 'zustand';
2+
3+
export type ScreenSize = 'small-mobile' | 'mobile' | 'tablet' | 'desktop';
4+
5+
export interface UseResponsiveStore {
6+
isMobile: boolean;
7+
isSmallMobile: boolean;
8+
screenSize: ScreenSize;
9+
screenWidth: number;
10+
setScreenSize: (size: ScreenSize) => void;
11+
initializeResizeListener: () => () => void;
12+
}
13+
14+
const initialState = {
15+
isMobile: false,
16+
isSmallMobile: false,
17+
screenSize: 'desktop' as ScreenSize,
18+
screenWidth: 0,
19+
};
20+
21+
export const useResponsiveStore = create<UseResponsiveStore>((set) => ({
22+
isMobile: initialState.isMobile,
23+
isSmallMobile: initialState.isSmallMobile,
24+
screenSize: initialState.screenSize,
25+
screenWidth: initialState.screenWidth,
26+
setScreenSize: (size: ScreenSize) => set(() => ({ screenSize: size })),
27+
initializeResizeListener: () => {
28+
const resizeHandler = () => {
29+
const width = window.innerWidth;
30+
if (width < 560) {
31+
set({
32+
screenSize: 'small-mobile',
33+
isMobile: true,
34+
isSmallMobile: true,
35+
});
36+
} else if (width < 768) {
37+
set({ screenSize: 'mobile', isMobile: true, isSmallMobile: false });
38+
} else if (width >= 768 && width < 1024) {
39+
set({ screenSize: 'tablet', isMobile: false, isSmallMobile: false });
40+
} else {
41+
set({ screenSize: 'desktop', isMobile: false, isSmallMobile: false });
42+
}
43+
44+
set({ screenWidth: width });
45+
};
46+
47+
const debouncedResizeHandler = () => {
48+
setTimeout(() => {
49+
resizeHandler();
50+
}, 300);
51+
};
52+
53+
window.addEventListener('resize', debouncedResizeHandler);
54+
55+
resizeHandler();
56+
57+
return () => {
58+
window.removeEventListener('resize', debouncedResizeHandler);
59+
};
60+
},
61+
}));

0 commit comments

Comments
 (0)