Skip to content

Commit

Permalink
Add a new playground component to rntester (facebook#46632)
Browse files Browse the repository at this point in the history
Summary:
Pull Request resolved: facebook#46632

Changelog: [rntester] Add Playground to RNTester for testing out features & submitting reproducers.

**Context**

- Adding the Playground from Catalyst to RNTester
- This should help folks test React Native features for a particular version

**Change**

- Add a new playground component to RNTester
- Add a new reducer action for opening an example from navbar press
- Fixed typing issues
- Add icon from this fb asset pack: https://www.internalfb.com/assets/set/facebook_icons/nucleus-beaker/variant_outline-size_24?q=beaker
- Matched background color using this imagemagick script

**dark**
```
convert input.png -fill 'rgb(178,180,186)' -colorize 100% output.png
```
**light**
```
convert input.png -fill 'rgb(81,82,84)' -colorize 100% output.png
```

Reviewed By: NickGerleman

Differential Revision: D61972594
  • Loading branch information
shwanton authored and facebook-github-bot committed Sep 24, 2024
1 parent 0cb32d5 commit 3589cd0
Show file tree
Hide file tree
Showing 13 changed files with 148 additions and 16 deletions.
23 changes: 18 additions & 5 deletions packages/rn-tester/js/RNTesterAppShared.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

import type {RNTesterModuleInfo} from './types/RNTesterTypes';

import {title as PlaygroundTitle} from './examples/Playground/PlaygroundExample';
import RNTesterModuleContainer from './components/RNTesterModuleContainer';
import RNTesterModuleList from './components/RNTesterModuleList';
import RNTesterNavBar, {navBarHeight} from './components/RNTesterNavbar';
Expand All @@ -36,6 +37,7 @@ import {
useColorScheme,
} from 'react-native';
import * as NativeComponentRegistry from 'react-native/Libraries/NativeComponent/NativeComponentRegistry';
import type {ScreenTypes} from 'RNTesterTypes';

// In Bridgeless mode, in dev, enable static view config validator
if (global.RN$Bridgeless === true && __DEV__) {
Expand Down Expand Up @@ -127,11 +129,22 @@ const RNTesterApp = ({
);

const handleNavBarPress = React.useCallback(
(args: {screen: string}) => {
dispatch({
type: RNTesterNavigationActionsType.NAVBAR_PRESS,
data: {screen: args.screen},
});
(args: {screen: ScreenTypes}) => {
if (args.screen === 'playgrounds') {
dispatch({
type: RNTesterNavigationActionsType.NAVBAR_OPEN_MODULE_PRESS,
data: {
key: 'PlaygroundExample',
title: PlaygroundTitle,
screen: args.screen,
},
});
} else {
dispatch({
type: RNTesterNavigationActionsType.NAVBAR_PRESS,
data: {screen: args.screen},
});
}
},
[dispatch],
);
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
36 changes: 33 additions & 3 deletions packages/rn-tester/js/components/RNTesterNavbar.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,14 @@
*/

import type {RNTesterTheme} from './RNTesterTheme';
import type {ScreenTypes} from 'RNTesterTypes';

import {RNTesterThemeContext} from './RNTesterTheme';
import * as React from 'react';
import {Image, Pressable, StyleSheet, Text, View} from 'react-native';

type NavBarOnPressHandler = ({screen: ScreenTypes}) => void;

/* $FlowFixMe[missing-local-annot] The type annotation(s) required by Flow's
* LTI update could not be added via codemod */
const NavbarButton = ({
Expand Down Expand Up @@ -54,7 +57,7 @@ const ComponentTab = ({
handleNavBarPress,
theme,
}: $TEMPORARY$object<{
handleNavBarPress: (data: {screen: string}) => void,
handleNavBarPress: NavBarOnPressHandler,
isComponentActive: boolean,
theme: RNTesterTheme,
}>) => (
Expand All @@ -70,12 +73,33 @@ const ComponentTab = ({
/>
);

const PlaygroundTab = ({
isComponentActive,
handleNavBarPress,
theme,
}: $TEMPORARY$object<{
handleNavBarPress: NavBarOnPressHandler,
isComponentActive: boolean,
theme: RNTesterTheme,
}>) => (
<NavbarButton
testID="playground-tab"
label="Playground"
handlePress={() => handleNavBarPress({screen: 'playgrounds'})}
activeImage={theme.NavBarPlaygroundActiveIcon}
inactiveImage={theme.NavBarPlaygroundInactiveIcon}
isActive={isComponentActive}
theme={theme}
iconStyle={styles.componentIcon}
/>
);

const APITab = ({
isAPIActive,
handleNavBarPress,
theme,
}: $TEMPORARY$object<{
handleNavBarPress: (data: {screen: string}) => void,
handleNavBarPress: NavBarOnPressHandler,
isAPIActive: boolean,
theme: RNTesterTheme,
}>) => (
Expand All @@ -92,7 +116,7 @@ const APITab = ({
);

type Props = $ReadOnly<{|
handleNavBarPress: (data: {screen: string}) => void,
handleNavBarPress: NavBarOnPressHandler,
screen: string,
isExamplePageOpen: boolean,
|}>;
Expand All @@ -106,6 +130,7 @@ const RNTesterNavbar = ({

const isAPIActive = screen === 'apis' && !isExamplePageOpen;
const isComponentActive = screen === 'components' && !isExamplePageOpen;
const isPlaygroundActive = screen === 'playgrounds';

return (
<View>
Expand All @@ -115,6 +140,11 @@ const RNTesterNavbar = ({
handleNavBarPress={handleNavBarPress}
theme={theme}
/>
<PlaygroundTab
isComponentActive={isPlaygroundActive}
handleNavBarPress={handleNavBarPress}
theme={theme}
/>
<APITab
isAPIActive={isAPIActive}
handleNavBarPress={handleNavBarPress}
Expand Down
6 changes: 6 additions & 0 deletions packages/rn-tester/js/components/RNTesterTheme.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ export type RNTesterTheme = {
NavBarComponentsInactiveIcon: ImageSource,
NavBarAPIsActiveIcon: ImageSource,
NavBarAPIsInactiveIcon: ImageSource,
NavBarPlaygroundActiveIcon: ImageSource,
NavBarPlaygroundInactiveIcon: ImageSource,
...
};

Expand Down Expand Up @@ -90,6 +92,8 @@ export const RNTesterLightTheme = {
NavBarComponentsInactiveIcon: require('./../assets/bottom-nav-components-icon-light.png'),
NavBarAPIsActiveIcon: require('./../assets/bottom-nav-apis-icon-dark.png'),
NavBarAPIsInactiveIcon: require('./../assets/bottom-nav-apis-icon-light.png'),
NavBarPlaygroundActiveIcon: require('./../assets/bottom-nav-playgrounds-icon-dark.png'),
NavBarPlaygroundInactiveIcon: require('./../assets/bottom-nav-playgrounds-icon-light.png'),
};

export const RNTesterDarkTheme = {
Expand Down Expand Up @@ -129,6 +133,8 @@ export const RNTesterDarkTheme = {
NavBarComponentsInactiveIcon: require('./../assets/bottom-nav-components-icon-dark.png'),
NavBarAPIsActiveIcon: require('./../assets/bottom-nav-apis-icon-light.png'),
NavBarAPIsInactiveIcon: require('./../assets/bottom-nav-apis-icon-dark.png'),
NavBarPlaygroundActiveIcon: require('./../assets/bottom-nav-playgrounds-icon-dark.png'),
NavBarPlaygroundInactiveIcon: require('./../assets/bottom-nav-playgrounds-icon-light.png'),
};

export const themes = {light: RNTesterLightTheme, dark: RNTesterDarkTheme};
Expand Down
18 changes: 18 additions & 0 deletions packages/rn-tester/js/examples/Playground/PlaygroundExample.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @format
* @flow strict-local
*/

import type {RNTesterModuleExample} from '../../types/RNTesterTypes';

import Playground from './RNTesterPlayground';

export const title = Playground.title;
export const framework = 'React';
export const description = 'Test out new features and ideas.';
export const examples: Array<RNTesterModuleExample> = [Playground];
35 changes: 35 additions & 0 deletions packages/rn-tester/js/examples/Playground/RNTesterPlayground.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @format
* @oncall react_native
*/

import type {RNTesterModuleExample} from '../../types/RNTesterTypes';

import * as React from 'react';
import {StyleSheet, Text, View} from 'react-native';

function Playground() {
return (
<View style={styles.container}>
<Text>Edit "RNTesterPlayground.js" to change this file</Text>
</View>
);
}

const styles = StyleSheet.create({
container: {
padding: 10,
},
});

export default ({
title: 'Playground',
name: 'playground',
render: (): React.Node => <Playground />,
}: RNTesterModuleExample);
2 changes: 1 addition & 1 deletion packages/rn-tester/js/types/RNTesterTypes.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export type ExamplesList = $ReadOnly<{|
apis: $ReadOnlyArray<SectionData<RNTesterModuleInfo>>,
|}>;

export type ScreenTypes = 'components' | 'apis' | null;
export type ScreenTypes = 'components' | 'apis' | 'playgrounds' | null;

export type ComponentList = null | {components: string[], apis: string[]};

Expand Down
12 changes: 10 additions & 2 deletions packages/rn-tester/js/utils/RNTesterList.android.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
'use strict';

import type {RNTesterModuleInfo} from '../types/RNTesterTypes';
import type {RNTesterModule} from 'RNTesterTypes';

import ReactNativeFeatureFlags from 'react-native/Libraries/ReactNative/ReactNativeFeatureFlags';

Expand Down Expand Up @@ -365,9 +366,16 @@ if (ReactNativeFeatureFlags.shouldEmitW3CPointerEvents()) {
});
}

const Modules: any = {};
const Playgrounds: Array<RNTesterModuleInfo> = [
{
key: 'PlaygroundExample',
module: require('../examples/Playground/PlaygroundExample'),
},
];

const Modules: {[key: string]: RNTesterModule} = {};

APIs.concat(Components).forEach(Example => {
[...APIs, ...Components, ...Playgrounds].forEach(Example => {
Modules[Example.key] = Example.module;
});

Expand Down
13 changes: 10 additions & 3 deletions packages/rn-tester/js/utils/RNTesterList.ios.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
'use strict';

import type {RNTesterModuleInfo} from '../types/RNTesterTypes';
import type {RNTesterModule} from 'RNTesterTypes';

import ReactNativeFeatureFlags from 'react-native/Libraries/ReactNative/ReactNativeFeatureFlags';

Expand Down Expand Up @@ -345,10 +346,16 @@ if (ReactNativeFeatureFlags.shouldEmitW3CPointerEvents()) {
});
}

const Modules: {...} = {};
const Playgrounds: Array<RNTesterModuleInfo> = [
{
key: 'PlaygroundExample',
module: require('../examples/Playground/PlaygroundExample'),
},
];

const Modules: {[key: string]: RNTesterModule} = {};

APIs.concat(Components).forEach(Example => {
// $FlowFixMe[prop-missing]
[...APIs, ...Components, ...Playgrounds].forEach(Example => {
Modules[Example.key] = Example.module;
});

Expand Down
3 changes: 2 additions & 1 deletion packages/rn-tester/js/utils/RNTesterList.js.flow
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,10 @@
'use strict';

import type {RNTesterModuleInfo} from '../types/RNTesterTypes';
import type {RNTesterModule} from 'RNTesterTypes';

declare const APIs: Array<RNTesterModuleInfo>;
declare const Components: Array<RNTesterModuleInfo>;
declare const Modules: {...};
declare const Modules: {[key: string]: RNTesterModule};

module.exports = {APIs, Components, Modules};
15 changes: 14 additions & 1 deletion packages/rn-tester/js/utils/RNTesterNavigationReducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ export const RNTesterNavigationActionsType = {
MODULE_CARD_PRESS: 'MODULE_CARD_PRESS',
EXAMPLE_CARD_PRESS: 'EXAMPLE_CARD_PRESS',
EXAMPLE_OPEN_URL_REQUEST: 'EXAMPLE_OPEN_URL_REQUEST',
NAVBAR_OPEN_MODULE_PRESS: 'NAVBAR_OPEN_MODULE_PRESS',
};

const getUpdatedRecentlyUsed = ({
Expand Down Expand Up @@ -77,6 +78,16 @@ export const RNTesterNavigationReducer = (
hadDeepLink: false,
};

case RNTesterNavigationActionsType.NAVBAR_OPEN_MODULE_PRESS:
return {
...state,
activeModuleKey: key,
activeModuleTitle: title,
activeModuleExampleKey: null,
screen,
hadDeepLink: true,
};

case RNTesterNavigationActionsType.MODULE_CARD_PRESS:
return {
...state,
Expand All @@ -99,7 +110,6 @@ export const RNTesterNavigationReducer = (

case RNTesterNavigationActionsType.BACK_BUTTON_PRESS:
// Go back to module or list.
// If there was a deeplink navigation, pressing Back should bring us back to the root.
return {
...state,
activeModuleExampleKey: null,
Expand All @@ -112,6 +122,8 @@ export const RNTesterNavigationReducer = (
? state.activeModuleTitle
: null,
hadDeepLink: false,
// If there was a deeplink navigation, pressing Back should bring us back to the root.
screen: state.hadDeepLink ? 'components' : state.screen,
};

case RNTesterNavigationActionsType.EXAMPLE_OPEN_URL_REQUEST:
Expand All @@ -121,6 +133,7 @@ export const RNTesterNavigationReducer = (
activeModuleTitle: title,
activeModuleExampleKey: exampleKey,
hadDeepLink: true,
screen: 'components',
};

default:
Expand Down
1 change: 1 addition & 0 deletions packages/rn-tester/js/utils/testerStateUtils.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import RNTesterList from './RNTesterList';
export const Screens = {
COMPONENTS: 'components',
APIS: 'apis',
PLAYGROUNDS: 'playgrounds',
};

export const initialNavigationState: RNTesterNavigationState = {
Expand Down

0 comments on commit 3589cd0

Please sign in to comment.