Skip to content

Commit

Permalink
feat: usePrefersColorScheme hook (#341)
Browse files Browse the repository at this point in the history
Co-authored-by: Guilherme Gazzo <guilherme@gazzo.xyz>
  • Loading branch information
Douglas Fabris and ggazzo authored Dec 3, 2020
1 parent 59ae517 commit f54a69d
Show file tree
Hide file tree
Showing 7 changed files with 280 additions and 6 deletions.
125 changes: 119 additions & 6 deletions packages/fuselage-hooks/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,20 +66,22 @@ yarn add @rocket.chat/fuselage-hooks
- [Parameters](#parameters-10)
- [usePosition](#useposition)
- [Parameters](#parameters-11)
- [usePrefersColorScheme](#usepreferscolorscheme)
- [Parameters](#parameters-12)
- [usePrefersReducedData](#useprefersreduceddata)
- [usePrefersReducedMotion](#useprefersreducedmotion)
- [useResizeObserver](#useresizeobserver)
- [Parameters](#parameters-12)
- [useSafely](#usesafely)
- [Parameters](#parameters-13)
- [useStableArray](#usestablearray)
- [useSafely](#usesafely)
- [Parameters](#parameters-14)
- [useLocalStorage](#uselocalstorage)
- [useStableArray](#usestablearray)
- [Parameters](#parameters-15)
- [useSessionStorage](#usesessionstorage)
- [useLocalStorage](#uselocalstorage)
- [Parameters](#parameters-16)
- [useToggle](#usetoggle)
- [useSessionStorage](#usesessionstorage)
- [Parameters](#parameters-17)
- [useToggle](#usetoggle)
- [Parameters](#parameters-18)
- [useUniqueId](#useuniqueid)

### useAutoFocus
Expand Down Expand Up @@ -228,6 +230,117 @@ Hook to deal and position an element using an anchor

Returns **PositionResult** The style containing top and left position

### usePrefersColorScheme

Hook to get the prefers-color-scheme value.

#### Parameters

- `scheme` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?**

Returns **[boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** `true` if the prefers-color-scheme matches

### usePrefersReducedData

Hook to get the prefers-reduce-data value.

Returns **[boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** `true` if the prefers-reduce-data is set reduce in the media queries that matches

### usePrefersReducedMotion

Hook to get the prefers-reduce-motion value.

Returns **[boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** `true` if the prefers-reduce-motion is set reduce in the media queries that matches

### useResizeObserver

Hook to track dimension changes in a DOM element using the ResizeObserver API.

#### Parameters

- `options` **UseResizeObserverOptions** (optional, default `{}`)
- `options.debounceDelay`

Returns **{ref: RefObject&lt;[Element](https://developer.mozilla.org/docs/Web/API/Element)>, contentBoxSize: ResizeObserverSize, borderBoxSize: ResizeObserverSize}** a triple containing the ref and the size information

### useSafely

Hook that wraps pairs of state and dispatcher to provide a new dispatcher
which can be safe and asynchronically called even after the component unmounted.

#### Parameters

- `pair` **\[S, (Dispatch&lt;A> | DispatchWithoutAction)]** the state and dispatcher pair which will be patched
- `pair.0`
- `pair.1`

Returns **\[S, D]** a state value and safe dispatcher pair

### useStableArray

Hook to create an array with stable identity if its elements are equal.

#### Parameters

- `array` **T** the array
- `compare` **function (a: T, b: T): [boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** the equality function that checks if two array elements are
equal (optional, default `Object.is`)

Returns **T** the passed array if the elements are NOT equals; the previously
stored array otherwise

### useLocalStorage

Hook to deal with localStorage

#### Parameters

- `key` the key associated to the value in the storage
- `initialValue` the value returned when the key is not found at the storage

Returns **any** a state and a setter function

### useSessionStorage

Hook to deal with sessionStorage

#### Parameters

- `key` the key associated to the value in the storage
- `initialValue` the value returned when the key is not found at the storage

Returns **any** a state and a setter function

### useToggle

Hook to create a toggleable boolean state.

#### Parameters

- `initialValue` **([boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean) | function (): [boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean))?** the initial value or the initial state generator function

Returns **\[[boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean), D]** a state boolean value and a state toggler function

### useUniqueId

Hook to keep a unique ID string.

Returns **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** the unique ID string

# &lt;&lt;&lt;&lt;&lt;&lt;&lt; HEAD

### usePrefersColorScheme

Hook to get the prefers-color-scheme value.

#### Parameters

- `scheme` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)?**

Returns **[boolean](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Boolean)** `true` if the prefers-color-scheme matches

=======

### usePrefersReducedData

Hook to get the prefers-reduce-data value.
Expand Down
1 change: 1 addition & 0 deletions packages/fuselage-hooks/docs/fuselage-hooks.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
| [useMergedRefs](./fuselage-hooks.usemergedrefs.md) | Hook to merge refs and callbacks refs into a single callback ref. Useful when your component need a internal ref while receiving a forwared ref. |
| [useMutableCallback](./fuselage-hooks.usemutablecallback.md) | Hook to create a stable callback from a mutable one. |
| [usePosition](./fuselage-hooks.useposition.md) | Hook to deal and position an element using an anchor |
| [usePrefersColorScheme](./fuselage-hooks.usepreferscolorscheme.md) | Hook to get the prefers-color-scheme value. |
| [usePrefersReducedData](./fuselage-hooks.useprefersreduceddata.md) | Hook to get the prefers-reduce-data value. |
| [usePrefersReducedMotion](./fuselage-hooks.useprefersreducedmotion.md) | Hook to get the prefers-reduce-motion value. |
| [useResizeObserver](./fuselage-hooks.useresizeobserver.md) | Hook to track dimension changes in a DOM element using the ResizeObserver API. |
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<!-- Do not edit this file. It is automatically generated by API Documenter. -->

[Home](./index.md) &gt; [@rocket.chat/fuselage-hooks](./fuselage-hooks.md) &gt; [usePrefersColorScheme](./fuselage-hooks.usepreferscolorscheme.md)

## usePrefersColorScheme variable

Hook to get the prefers-color-scheme value.

<b>Signature:</b>

```typescript
usePrefersColorScheme: (scheme?: string) => boolean
```
1 change: 1 addition & 0 deletions packages/fuselage-hooks/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export * from './useMediaQuery';
export * from './useMergedRefs';
export * from './useMutableCallback';
export * from './usePosition';
export * from './usePrefersColorScheme';
export * from './usePrefersReducedData';
export * from './usePrefersReducedMotion';
export * from './useResizeObserver';
Expand Down
34 changes: 34 additions & 0 deletions packages/fuselage-hooks/src/usePrefersColorScheme.server.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/**
* @jest-environment node
*/

import { FunctionComponent, createElement, StrictMode } from 'react';
import { renderToString } from 'react-dom/server';

import { usePrefersColorScheme } from '.';

describe('usePrefersColorScheme hook on server', () => {
it('should return false without matchMedia mocked', () => {
let matches: boolean;
const TestComponent: FunctionComponent = () => {
matches = usePrefersColorScheme();
return null;
};

renderToString(createElement(StrictMode, {}, createElement(TestComponent)));

expect(matches).toBe(false);
});

it('should return false with matchMedia mocked', () => {
let matches: boolean;
const TestComponent: FunctionComponent = () => {
matches = usePrefersColorScheme();
return null;
};

renderToString(createElement(StrictMode, {}, createElement(TestComponent)));

expect(matches).toBe(false);
});
});
101 changes: 101 additions & 0 deletions packages/fuselage-hooks/src/usePrefersColorScheme.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import { createElement, FunctionComponent, StrictMode } from 'react';
import { render } from 'react-dom';
import { act } from 'react-dom/test-utils';

import { usePrefersColorScheme } from '.';
import matchMediaMock from './__mocks__/matchMedia';

describe('usePrefersColorScheme hook', () => {
let container: HTMLDivElement;

beforeEach(() => {
container = document.createElement('div');
document.body.appendChild(container);
});

afterEach(() => {
container.remove();
container = null;
});

it('should return false on the initial call', () => {
let matches: boolean;

const TestComponent: FunctionComponent = () => {
matches = usePrefersColorScheme();
return null;
};

act(() => {
render(
createElement(StrictMode, {}, createElement(TestComponent)),
container
);
});

expect(matches).toBe(false);
});

it('should return true with matchMedia mocked and anything set', () => {
window.matchMedia = jest.fn((media) =>
matchMediaMock(media, '(prefers-color-scheme: light)')
);

let matches: boolean;
const TestComponent: FunctionComponent = () => {
matches = usePrefersColorScheme();
return null;
};

act(() => {
render(
createElement(StrictMode, {}, createElement(TestComponent)),
document.createElement('div')
);
});

expect(matches).toBe(true);
});

it('should return true with matchMedia mocked and light scheme set', () => {
window.matchMedia = jest.fn((media) =>
matchMediaMock(media, '(prefers-color-scheme: light)')
);

let matches: boolean;
const TestComponent: FunctionComponent = () => {
matches = usePrefersColorScheme('light');
return null;
};

act(() => {
render(
createElement(StrictMode, {}, createElement(TestComponent)),
document.createElement('div')
);
});

expect(matches).toBe(true);
});

it('should return true with matchMedia mocked and dark scheme set', () => {
window.matchMedia = jest.fn((media) =>
matchMediaMock(media, '(prefers-color-scheme: dark)')
);

let matches: boolean;
const TestComponent: FunctionComponent = () => {
matches = usePrefersColorScheme('dark');
return null;
};

act(() => {
render(
createElement(StrictMode, {}, createElement(TestComponent)),
document.createElement('div')
);
});

expect(matches).toBe(true);
});
});
11 changes: 11 additions & 0 deletions packages/fuselage-hooks/src/usePrefersColorScheme.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { useMediaQuery } from '.';

/**
* Hook to get the prefers-color-scheme value.
*
* @returns `true` if the prefers-color-scheme matches
* @public
*/

export const usePrefersColorScheme = (scheme?: string): boolean =>
useMediaQuery(`(prefers-color-scheme: ${!scheme ? 'light' : scheme})`);

0 comments on commit f54a69d

Please sign in to comment.