Skip to content

Commit

Permalink
feat: expose subscribeToMotionChange and add cookieName option
Browse files Browse the repository at this point in the history
  • Loading branch information
kentcdodds committed Nov 22, 2023
1 parent 3061efe commit 54c8ff4
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 3 deletions.
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -149,9 +149,10 @@ export async function loader({ request }: DataFunctionArgs) {

Hints include:

- `@epic-web/client-hints/color-scheme`
- `@epic-web/client-hints/color-scheme` (also exports `subscribeToSchemeChange`)
- `@epic-web/client-hints/time-zone`
- `@epic-web/client-hints/reduced-motion`
- `@epic-web/client-hints/reduced-motion` (also exports
`subscribeToMotionChange`)

## FAQ

Expand Down
8 changes: 7 additions & 1 deletion src/color-scheme.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,19 @@ export const clientHint = {
},
} as const satisfies ClientHint<'dark' | 'light'>

/**
* Subscribe to changes in the user's color scheme preference. Optionally pass
* in a cookie name to use for the cookie that will be set if different from the
* default.
*/
export function subscribeToSchemeChange(
subscriber: (value: 'dark' | 'light') => void,
cookieName = clientHint.cookieName,
) {
const schemaMatch = window.matchMedia('(prefers-color-scheme: dark)')
function handleThemeChange() {
const value = schemaMatch.matches ? 'dark' : 'light'
document.cookie = `${clientHint.cookieName}=${value}`
document.cookie = `${cookieName}=${value}`
subscriber(value)
}
schemaMatch.addEventListener('change', handleThemeChange)
Expand Down
21 changes: 21 additions & 0 deletions src/reduced-motion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,24 @@ export const clientHint = {
return value === 'reduce' ? 'reduce' : 'no-preference'
},
} as const satisfies ClientHint<'reduce' | 'no-preference'>

/**
* Subscribe to changes in the user's motion preference. Optionally pass
* in a cookie name to use for the cookie that will be set if different from the
* default.
*/
export function subscribeToMotionChange(
subscriber: (value: 'reduce' | 'no-preference') => void,
cookieName = clientHint.cookieName,
) {
const motionMatch = window.matchMedia('(prefers-reduced-motion: reduce)')
function handleThemeChange() {
const value = motionMatch.matches ? 'reduce' : 'no-preference'
document.cookie = `${cookieName}=${value}`
subscriber(value)
}
motionMatch.addEventListener('change', handleThemeChange)
return function cleanupSchemaChange() {
motionMatch.removeEventListener('change', handleThemeChange)
}
}

0 comments on commit 54c8ff4

Please sign in to comment.