File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
File name
Commit message
Commit date
import { useThemePreference } from '@/app/(protected)/(basic)/_hooks/use-theme-preference';
import { IconButton } from '@/components/ui/icon-button';
import styles from './theme-toggle-button.module.scss';
/**
* 헤더 우측 테마 토글 버튼 — 아이콘 3종(모니터/해/달)을 항상 DOM에 전부 렌더하고,
* `theme-toggle-button.module.scss`가 `<html data-theme>` 값에 따라 CSS만으로 하나만 보이게
* 한다. 서버·클라이언트 출력이 항상 동일해 hydration 불일치가 없다 — React state로 아이콘을
* 고르지 않는다.
*
* 표시 전환은 아이콘·라벨 쌍을 감싸는 래퍼에 건다(아이콘이나 `sr-only` 라벨 각각에 걸지
* 않는다). 숨겨진 쪽은 라벨도 함께 사라져야 스크린리더가 현재 선택 하나만 읽는다.
*
* `IconButton`에 `label`을 넘기지 않는다 — `aria-label`은 내용을 덮어쓰므로, 넘기면 테마에
* 따라 바뀌는 `sr-only` 텍스트가 무시된다.
*/
export function ThemeToggleButton() {
const { cycleThemePreference } = useThemePreference();
return (
<IconButton onClick={cycleThemePreference}>
<span className={`${styles.icon} ${styles.system}`}>
<i className="fox-ico fox-ico-Monitor" aria-hidden="true" />
<span className={styles.srOnly}>테마 변경 (현재: 시스템 설정)</span>
</span>
<span className={`${styles.icon} ${styles.light}`}>
<i className="fox-ico fox-ico-Sun" aria-hidden="true" />
<span className={styles.srOnly}>테마 변경 (현재: 라이트)</span>
</span>
<span className={`${styles.icon} ${styles.dark}`}>
<i className="fox-ico fox-ico-Moon" aria-hidden="true" />
<span className={styles.srOnly}>테마 변경 (현재: 다크)</span>
</span>
</IconButton>
);
}