Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 | 1x 15x 12x 12x 8x 3x 5x 12x 8x 2x 6x 6x 9x 6x 6x 5x 5x 1x 1x 12x | import { useEffect, useState } from "react";
/**
* The user's preferred color scheme.
*/
export type ColorScheme = "light" | "dark";
/**
* Options for the usePreferredColorScheme hook.
*/
export interface UsePreferredColorSchemeOptions {
/**
* Scheme returned on the server / when `matchMedia` is unavailable.
* @default "light"
*/
defaultScheme?: ColorScheme;
/**
* When `true` (default), the real `matchMedia` value is read synchronously on
* the first client render. Set to `false` to render `defaultScheme` on the
* first client render too and defer the real read to a post-commit effect —
* this avoids a React hydration mismatch when the server rendered
* `defaultScheme` but the user's system preference differs.
* @default true
*/
initializeWithValue?: boolean;
}
const DARK_QUERY = "(prefers-color-scheme: dark)";
function isSupported(): boolean {
return (
typeof window !== "undefined" && typeof window.matchMedia === "function"
);
}
/**
* Tracks the user's OS/browser color-scheme preference
* (`prefers-color-scheme`), returning `"light"` or `"dark"` and updating live
* when the system setting changes.
*
* This is the primitive that reflects the *system* preference; for a full
* theme with manual override and persistence use `useDarkMode`.
*
* @param options - Configuration (`defaultScheme`, `initializeWithValue`)
* @returns `"light"` or `"dark"`
*
* @example
* ```tsx
* const scheme = usePreferredColorScheme();
* return <div className={scheme === "dark" ? "theme-dark" : "theme-light"} />;
* ```
*/
export function usePreferredColorScheme(
options: UsePreferredColorSchemeOptions = {}
): ColorScheme {
const { defaultScheme = "light", initializeWithValue = true } = options;
const [scheme, setScheme] = useState<ColorScheme>(() => {
if (!initializeWithValue || !isSupported()) {
return defaultScheme;
}
return window.matchMedia(DARK_QUERY).matches ? "dark" : "light";
});
useEffect(() => {
if (!isSupported()) {
return;
}
const mediaQueryList = window.matchMedia(DARK_QUERY);
const handleChange = () => {
setScheme(mediaQueryList.matches ? "dark" : "light");
};
handleChange();
if (typeof mediaQueryList.addEventListener === "function") {
mediaQueryList.addEventListener("change", handleChange);
return () => mediaQueryList.removeEventListener("change", handleChange);
}
mediaQueryList.addListener(handleChange);
return () => mediaQueryList.removeListener(handleChange);
}, []);
return scheme;
}
|