mirror of
https://github.com/zoriya/react-native-web.git
synced 2026-05-16 04:10:30 +00:00
committed by
Nicolas Gallagher
parent
cecacbc3ac
commit
324995ec2b
@@ -6,6 +6,7 @@ module.exports = {
|
||||
Animated: true,
|
||||
AppRegistry: true,
|
||||
AppState: true,
|
||||
Appearance: true,
|
||||
BackHandler: true,
|
||||
Button: true,
|
||||
CheckBox: true,
|
||||
@@ -64,5 +65,6 @@ module.exports = {
|
||||
processColor: true,
|
||||
render: true,
|
||||
unmountComponentAtNode: true,
|
||||
useColorScheme: true,
|
||||
useWindowDimensions: true
|
||||
};
|
||||
|
||||
@@ -0,0 +1,63 @@
|
||||
import { Meta, Preview } from '@storybook/addon-docs/blocks';
|
||||
import * as Stories from './examples';
|
||||
|
||||
<Meta title="APIs|Appearance" />
|
||||
|
||||
# Appearance
|
||||
|
||||
The Appearance module exposes information about the user's appearance
|
||||
preferences, such as their preferred color scheme (light or dark). In
|
||||
`react-native-web` this is achieved using the `prefers-color-scheme` media query.
|
||||
|
||||
## Methods
|
||||
|
||||
### getColorScheme()
|
||||
|
||||
You can use the Appearance module to determine if the user prefers a dark color
|
||||
scheme:
|
||||
|
||||
```js
|
||||
const colorScheme = Appearance.getColorScheme();
|
||||
if (colorScheme === 'dark') {
|
||||
// Use dark color scheme
|
||||
}
|
||||
```
|
||||
|
||||
Although the color scheme is available immediately, this may change (e.g.
|
||||
scheduled color scheme change at sunrise or sunset). Any rendering logic or
|
||||
styles that depend on the user preferred color scheme should try to call this
|
||||
function on every render, rather than caching the value.
|
||||
|
||||
## Hooks
|
||||
|
||||
### useColorScheme
|
||||
|
||||
The `useColorScheme` React hook provides and subscribes to color scheme updates
|
||||
from the Appearance module. The return value indicates the current user
|
||||
preferred color scheme. The value may be updated later, either through direct
|
||||
user action (e.g. theme selection in device settings) or on a schedule (e.g.
|
||||
light and dark themes that follow the day/night cycle).
|
||||
|
||||
Supported color schemes:
|
||||
|
||||
- `'light'`: The user prefers a light color theme.
|
||||
- `'dark'`: The user prefers a dark color theme.
|
||||
- `null`: The user has not indicated a preferred color theme.
|
||||
|
||||
```js
|
||||
import * as React from 'react';
|
||||
import { Text, useColorScheme } from 'react-native';
|
||||
|
||||
const MyComponent = () => {
|
||||
const colorScheme = useColorScheme();
|
||||
return <Text>Your color scheme is: {colorScheme}</Text>;
|
||||
};
|
||||
```
|
||||
|
||||
This produces:
|
||||
|
||||
<Preview withSource="none">
|
||||
<Story name="colorScheme">
|
||||
<Stories.colorSchemeText />
|
||||
</Story>
|
||||
</Preview>
|
||||
@@ -0,0 +1,7 @@
|
||||
import * as React from 'react';
|
||||
import { Text, useColorScheme } from 'react-native';
|
||||
|
||||
export default function ColorSchemeText() {
|
||||
const colorScheme = useColorScheme();
|
||||
return <Text>Your color scheme is: {colorScheme}</Text>;
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
export { default as colorSchemeText } from './ColorSchemeText';
|
||||
@@ -0,0 +1,60 @@
|
||||
/**
|
||||
* Copyright (c) Nicolas Gallagher.
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import { canUseDOM } from 'fbjs/lib/ExecutionEnvironment';
|
||||
|
||||
export type ColorSchemeName = 'light' | 'dark';
|
||||
|
||||
export type AppearancePreferences = {|
|
||||
colorScheme: ColorSchemeName
|
||||
|};
|
||||
|
||||
type AppearanceListener = (preferences: AppearancePreferences) => void;
|
||||
type DOMAppearanceListener = (ev: MediaQueryListEvent) => any;
|
||||
|
||||
function getQuery(): MediaQueryList | null {
|
||||
return canUseDOM && window.matchMedia != null
|
||||
? window.matchMedia('(prefers-color-scheme: dark)')
|
||||
: null;
|
||||
}
|
||||
|
||||
const query = getQuery();
|
||||
const listenerMapping = new WeakMap<AppearanceListener, DOMAppearanceListener>();
|
||||
|
||||
const Appearance = {
|
||||
getColorScheme(): ColorSchemeName {
|
||||
return query && query.matches ? 'dark' : 'light';
|
||||
},
|
||||
|
||||
addChangeListener(listener: AppearanceListener): void {
|
||||
let mappedListener = listenerMapping.get(listener);
|
||||
if (!mappedListener) {
|
||||
mappedListener = ({ matches }: MediaQueryListEvent) => {
|
||||
listener({ colorScheme: matches ? 'dark' : 'light' });
|
||||
};
|
||||
listenerMapping.set(listener, mappedListener);
|
||||
}
|
||||
if (query) {
|
||||
query.addListener(mappedListener);
|
||||
}
|
||||
},
|
||||
|
||||
removeChangeListener(listener: AppearanceListener): void {
|
||||
const mappedListener = listenerMapping.get(listener);
|
||||
if (mappedListener) {
|
||||
if (query) {
|
||||
query.removeListener(mappedListener);
|
||||
}
|
||||
listenerMapping.delete(listener);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default Appearance;
|
||||
@@ -0,0 +1,27 @@
|
||||
/**
|
||||
* Copyright (c) Nicolas Gallagher.
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow
|
||||
*/
|
||||
|
||||
import * as React from 'react';
|
||||
import type { ColorSchemeName } from '../Appearance';
|
||||
import Appearance from '../Appearance';
|
||||
|
||||
export default function useColorScheme(): ColorSchemeName {
|
||||
const [colorScheme, setColorScheme] = React.useState(Appearance.getColorScheme());
|
||||
|
||||
React.useEffect(() => {
|
||||
function listener(appearance) {
|
||||
setColorScheme(appearance.colorScheme);
|
||||
}
|
||||
Appearance.addChangeListener(listener);
|
||||
return () => Appearance.removeChangeListener(listener);
|
||||
});
|
||||
|
||||
return colorScheme;
|
||||
}
|
||||
+2
@@ -9,6 +9,7 @@ export { default as NativeModules } from './exports/NativeModules';
|
||||
export { default as AccessibilityInfo } from './exports/AccessibilityInfo';
|
||||
export { default as Alert } from './exports/Alert';
|
||||
export { default as Animated } from './exports/Animated';
|
||||
export { default as Appearance } from './exports/Appearance';
|
||||
export { default as AppRegistry } from './exports/AppRegistry';
|
||||
export { default as AppState } from './exports/AppState';
|
||||
export { default as BackHandler } from './exports/BackHandler';
|
||||
@@ -73,4 +74,5 @@ export { default as TVEventHandler } from './exports/TVEventHandler';
|
||||
export { default as DeviceEventEmitter } from './exports/DeviceEventEmitter';
|
||||
|
||||
// hooks
|
||||
export { default as useColorScheme } from './exports/useColorScheme';
|
||||
export { default as useWindowDimensions } from './exports/useWindowDimensions';
|
||||
|
||||
Reference in New Issue
Block a user