Skip to content

Commit

Permalink
feat(react): usePreferredColocScheme 신규 훅 추가 (#322)
Browse files Browse the repository at this point in the history
* feat(react): usePreferredColocScheme 신규 훅 추가

* docs(react): usePreferredColorScheme 문서 수정

* docs: 문서 수정

* docs: 문서 수정
  • Loading branch information
ssi02014 authored Jul 11, 2024
1 parent e6ed357 commit 1559db7
Show file tree
Hide file tree
Showing 8 changed files with 120 additions and 13 deletions.
5 changes: 5 additions & 0 deletions .changeset/tidy-eagles-kiss.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@modern-kit/react': minor
---

feat(react): usePreferredColocScheme 신규 훅 추가 - @ssi02014
10 changes: 4 additions & 6 deletions docs/docs/react/hooks/useMediaQuery.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { useMediaQuery } from '@modern-kit/react';

# useMediaQuery

Resize 시에도 동작하며, 미디어 쿼리 문자열의 분석 결과를 쉽게 확인 할 수 있는 커스텀 훅입니다.
미디어 쿼리 문자열의 분석 결과를 쉽게 확인 할 수 있는 커스텀 훅입니다.

<br />

Expand All @@ -11,17 +11,15 @@ Resize 시에도 동작하며, 미디어 쿼리 문자열의 분석 결과를

## Interface
```ts title="typescript"
const useMediaQuery: (query: string) => {
isMatch: boolean;
}
const useMediaQuery: (query: string, defaultValue?: boolean) => boolean
```
## Usage
```tsx title="typescript"
import { useMediaQuery } from '@modern-kit/react';

const Example = () => {
const { isMatch } = useMediaQuery('(min-width: 768px)');
const isMatch = useMediaQuery('(min-width: 768px)');

return (
<div>
Expand All @@ -36,7 +34,7 @@ const Example = () => {
```

export const Example = () => {
const { isMatch } = useMediaQuery('(min-width: 768px)');
const isMatch = useMediaQuery('(min-width: 768px)');
return (
<div>
<p>브라우저 너비를 수정해보세요!</p>
Expand Down
66 changes: 66 additions & 0 deletions docs/docs/react/hooks/usePreferredColorScheme.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import { usePreferredColorScheme } from '@modern-kit/react';

# usePreferredColorScheme

사용자의 색상 스킴 선호도(**[prefers-coloc-scheme](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme)**) 에 따라 `dark`, `light`, 또는 `no-preference`를 반환합니다.

- ligth: 사용자가 시스템에 `ligth` 테마를 사용하는 것을 선호하거나 선호하는 테마를 알리지 않았을 때 반환합니다.
- dark: 사용자가 시스템에 `dark` 테마를 사용하는 것을 선호한다고 알렸을 때 반환합니다.

사용자는 `운영체제 설정`이나 `사용자 에이전트 설정`에서 선호하는 테마를 지정 할 수 있습니다.

<br />

## Code
[🔗 실제 구현 코드 확인](https://github.com/modern-agile-team/modern-kit/blob/main/packages/react/src/hooks/usePreferredColorScheme/index.ts)

## Interface

```ts title="typescript"
const usePreferredColorScheme: () => "dark" | "light"
```
## Usage
```tsx title="typescript"
import { usePreferredColorScheme } from '@modern-kit/react';

const Example = () => {
const colorScheme = usePreferredColorScheme();

return (
<div>
<p>OS 시스템 설정에서 테마를 변경해보세요.</p>
<p>ColorScheme: <b>{colorScheme}</b></p>
</div>
);
};
```

## Example

export const Example = () => {
const colorScheme = usePreferredColorScheme();

return (
<div>
<p>OS 시스템 설정에서 테마를 변경해보세요.</p>
<p>ColorScheme: <b>{colorScheme}</b></p>
</div>
);
};

<Example />

<br />

## Image
### 1. Light Theme
![스크린샷 2024-07-10 오후 8 09 33](https://github.com/modern-agile-team/modern-kit/assets/64779472/79c6298b-72f1-4f50-b644-93762d4d59e1)

<br />

### 2. Dark Theme
![스크린샷 2024-07-10 오후 8 09 39](https://github.com/modern-agile-team/modern-kit/assets/64779472/ab735906-9f8c-4e8e-9688-f6cde1786ec9)

## Note
- [Prefers Color Scheme - MDN](https://developer.mozilla.org/en-US/docs/Web/CSS/@media/prefers-color-scheme)
1 change: 1 addition & 0 deletions packages/react/src/hooks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export * from './useMergeRefs';
export * from './useMouse';
export * from './useNetwork';
export * from './useOnClickOutside';
export * from './usePreferredColorScheme';
export * from './usePreservedCallback';
export * from './usePreservedState';
export * from './usePrevious';
Expand Down
10 changes: 6 additions & 4 deletions packages/react/src/hooks/useMediaQuery/index.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,17 @@
import { isClient } from '@modern-kit/utils';
import { useCallback, useEffect, useState } from 'react';

const getMatchMedia = (query: string) => {
const getMatchMedia = (query: string, defaultValue?: boolean) => {
if (defaultValue != null) return defaultValue;

if (isClient()) {
return window.matchMedia(query).matches;
}
return false;
};

export const useMediaQuery = (query: string) => {
const [isMatch, setIsMatch] = useState(getMatchMedia(query));
export const useMediaQuery = (query: string, defaultValue?: boolean) => {
const [isMatch, setIsMatch] = useState(getMatchMedia(query, defaultValue));

const handleChange = useCallback(() => {
setIsMatch(getMatchMedia(query));
Expand All @@ -23,5 +25,5 @@ export const useMediaQuery = (query: string) => {
return () => matchMedia.removeEventListener('change', handleChange);
}, [query, handleChange]);

return { isMatch };
return isMatch;
};
6 changes: 3 additions & 3 deletions packages/react/src/hooks/useMediaQuery/useMediaQuery.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,20 @@ describe('useMediaQuery', () => {
it('should return true for matches when query matches', () => {
const { result } = renderHook(() => useMediaQuery('(min-width: 600px)'));

expect(result.current.isMatch).toBe(true);
expect(result.current).toBe(true);
});

it('should return false when query does not match', () => {
const { result } = renderHook(() => useMediaQuery('(min-width: 599px)'));

expect(result.current.isMatch).toBe(false);
expect(result.current).toBe(false);
});

it('should return false for isMatch when not in a client environment', () => {
vi.spyOn(ModernKitUtils, 'isClient').mockReturnValue(false);

const { result } = renderHook(() => useMediaQuery('(min-width: 600px)'));

expect(result.current.isMatch).toBe(false);
expect(result.current).toBe(false);
});
});
7 changes: 7 additions & 0 deletions packages/react/src/hooks/usePreferredColorScheme/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { useMediaQuery } from '../useMediaQuery';

export const usePreferredColorScheme = () => {
const isDark = useMediaQuery('(prefers-color-scheme: dark)');

return isDark ? 'dark' : 'light';
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { renderHook } from '@testing-library/react';
import { usePreferredColorScheme } from '.';
import { useMediaQuery } from '../useMediaQuery';
import { Mock } from 'vitest';

vi.mock('../useMediaQuery', () => ({
useMediaQuery: vi.fn(),
}));

describe('usePreferredColorScheme', () => {
it('should return "dark" when prefers-color-scheme is dark', () => {
(useMediaQuery as Mock).mockImplementation((query: string) => {
return query === '(prefers-color-scheme: dark)';
});

const { result } = renderHook(() => usePreferredColorScheme());
expect(result.current).toBe('dark');
});

it('should return "light" when prefers-color-scheme is light', () => {
(useMediaQuery as Mock).mockImplementation((query: string) => {
return query === '(prefers-color-scheme: light)';
});

const { result } = renderHook(() => usePreferredColorScheme());
expect(result.current).toBe('light');
});
});

0 comments on commit 1559db7

Please sign in to comment.