From 32d6ace11c13d2f13b983401c005acb74148bee3 Mon Sep 17 00:00:00 2001 From: Cal Leung Date: Mon, 18 Jul 2022 18:12:30 -0700 Subject: [PATCH 1/2] Create PickerItem component --- .../PickerItem/PickerItem.stories.tsx | 25 ++++++++++++ .../PickerItem/PickerItem.styles.ts | 39 +++++++++++++++++++ .../components/PickerItem/PickerItem.test.tsx | 15 +++++++ .../components/PickerItem/PickerItem.tsx | 30 ++++++++++++++ .../components/PickerItem/PickerItem.types.ts | 24 ++++++++++++ .../components/PickerItem/README.md | 23 +++++++++++ .../__snapshots__/PickerItem.test.tsx.snap | 30 ++++++++++++++ .../components/PickerItem/index.ts | 1 + storybook/storyLoader.js | 4 +- 9 files changed, 190 insertions(+), 1 deletion(-) create mode 100644 app/component-library/components/PickerItem/PickerItem.stories.tsx create mode 100644 app/component-library/components/PickerItem/PickerItem.styles.ts create mode 100644 app/component-library/components/PickerItem/PickerItem.test.tsx create mode 100644 app/component-library/components/PickerItem/PickerItem.tsx create mode 100644 app/component-library/components/PickerItem/PickerItem.types.ts create mode 100644 app/component-library/components/PickerItem/README.md create mode 100644 app/component-library/components/PickerItem/__snapshots__/PickerItem.test.tsx.snap create mode 100644 app/component-library/components/PickerItem/index.ts diff --git a/app/component-library/components/PickerItem/PickerItem.stories.tsx b/app/component-library/components/PickerItem/PickerItem.stories.tsx new file mode 100644 index 00000000000..1e03d51db79 --- /dev/null +++ b/app/component-library/components/PickerItem/PickerItem.stories.tsx @@ -0,0 +1,25 @@ +/* eslint-disable no-console */ +import React from 'react'; +import { Alert, StyleSheet, View } from 'react-native'; +import { storiesOf } from '@storybook/react-native'; +import PickerItem from './PickerItem'; +import { mockTheme } from '../../../util/theme'; +import BaseText, { BaseTextVariant } from '../BaseText'; + +const styles = StyleSheet.create({ + wrappedContent: { + height: 50, + flex: 1, + backgroundColor: mockTheme.colors.background.alternative, + alignItems: 'center', + justifyContent: 'center', + }, +}); + +storiesOf('Component Library / PickerItem', module).add('Default', () => ( + Alert.alert('Pressed picker!')}> + + {'Wrapped Content'} + + +)); diff --git a/app/component-library/components/PickerItem/PickerItem.styles.ts b/app/component-library/components/PickerItem/PickerItem.styles.ts new file mode 100644 index 00000000000..b49121c552c --- /dev/null +++ b/app/component-library/components/PickerItem/PickerItem.styles.ts @@ -0,0 +1,39 @@ +import { StyleSheet, ViewStyle } from 'react-native'; +import { PickerItemStyleSheetVars } from './PickerItem.types'; +import { Theme } from '../../../util/theme/models'; + +/** + * Style sheet function for PickerItem component. + * + * @param params Style sheet params. + * @param params.theme App theme from ThemeContext. + * @param params.vars Inputs that the style sheet depends on. + * @returns StyleSheet object. + */ +const styleSheet = (params: { + theme: Theme; + vars: PickerItemStyleSheetVars; +}) => { + const { vars, theme } = params; + const { colors } = theme; + const { style } = vars; + return StyleSheet.create({ + base: Object.assign( + { + flexDirection: 'row', + alignItems: 'center', + paddingHorizontal: 16, + borderWidth: 1, + borderColor: colors.border.default, + borderRadius: 4, + backgroundColor: colors.background.default, + } as ViewStyle, + style, + ) as ViewStyle, + dropdownIcon: { + marginLeft: 16, + }, + }); +}; + +export default styleSheet; diff --git a/app/component-library/components/PickerItem/PickerItem.test.tsx b/app/component-library/components/PickerItem/PickerItem.test.tsx new file mode 100644 index 00000000000..533237aab95 --- /dev/null +++ b/app/component-library/components/PickerItem/PickerItem.test.tsx @@ -0,0 +1,15 @@ +import React from 'react'; +import { View } from 'react-native'; +import { shallow } from 'enzyme'; +import PickerItem from './PickerItem'; + +describe('PickerItem', () => { + it('should render correctly', () => { + const wrapper = shallow( + + + , + ); + expect(wrapper).toMatchSnapshot(); + }); +}); diff --git a/app/component-library/components/PickerItem/PickerItem.tsx b/app/component-library/components/PickerItem/PickerItem.tsx new file mode 100644 index 00000000000..2db6d4a8fff --- /dev/null +++ b/app/component-library/components/PickerItem/PickerItem.tsx @@ -0,0 +1,30 @@ +/* eslint-disable react/prop-types */ +import React from 'react'; +import { TouchableOpacity } from 'react-native'; +import { useStyles } from '../../hooks'; +import Icon, { IconName, IconSize } from '../Icon'; +import styleSheet from './PickerItem.styles'; +import { PickerItemProps } from './PickerItem.types'; + +const PickerItem: React.FC = ({ + style, + children, + ...props +}) => { + const { styles, theme } = useStyles(styleSheet, { style }); + const { colors } = theme; + + return ( + + {children} + + + ); +}; + +export default PickerItem; diff --git a/app/component-library/components/PickerItem/PickerItem.types.ts b/app/component-library/components/PickerItem/PickerItem.types.ts new file mode 100644 index 00000000000..9e2e918c699 --- /dev/null +++ b/app/component-library/components/PickerItem/PickerItem.types.ts @@ -0,0 +1,24 @@ +import { StyleProp, TouchableOpacityProps, ViewStyle } from 'react-native'; + +/** + * PickerItem component props. + */ +export interface PickerItemProps extends TouchableOpacityProps { + /** + * Callback to trigger when pressed. + */ + onPress: () => void; + /** + * Escape hatch for applying extra styles. Only use if absolutely necessary. + */ + style?: StyleProp; + /** + * Content to wrap for multiselect. + */ + children: React.ReactNode; +} + +/** + * Style sheet input parameters. + */ +export type PickerItemStyleSheetVars = Pick; diff --git a/app/component-library/components/PickerItem/README.md b/app/component-library/components/PickerItem/README.md new file mode 100644 index 00000000000..6c41bd8b1c8 --- /dev/null +++ b/app/component-library/components/PickerItem/README.md @@ -0,0 +1,23 @@ +# PickerItem + +PickerItem is a wrapper component used for providing a dropdown icon next to wrapped content. + +## Props + +This component extends `TouchableOpacityProps` from React Native's [TouchableOpacityProps Component](https://reactnative.dev/docs/touchableOpacity). + +### `onPress` + +Callback to trigger when pressed. + +| TYPE | REQUIRED | +| :-------------------------------------------------- | :------------------------------------------------------ | +| function | Yes | + +### `children` + +Content to wrap for multiselect. + +| TYPE | REQUIRED | +| :-------------------------------------------------- | :------------------------------------------------------ | +| ReactNode | Yes | diff --git a/app/component-library/components/PickerItem/__snapshots__/PickerItem.test.tsx.snap b/app/component-library/components/PickerItem/__snapshots__/PickerItem.test.tsx.snap new file mode 100644 index 00000000000..f14c9baa1e5 --- /dev/null +++ b/app/component-library/components/PickerItem/__snapshots__/PickerItem.test.tsx.snap @@ -0,0 +1,30 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`PickerItem should render correctly 1`] = ` + + + + +`; diff --git a/app/component-library/components/PickerItem/index.ts b/app/component-library/components/PickerItem/index.ts new file mode 100644 index 00000000000..438d1e21a7f --- /dev/null +++ b/app/component-library/components/PickerItem/index.ts @@ -0,0 +1 @@ +export { default } from './PickerItem'; diff --git a/storybook/storyLoader.js b/storybook/storyLoader.js index 253a22551bf..55f2290c331 100644 --- a/storybook/storyLoader.js +++ b/storybook/storyLoader.js @@ -26,6 +26,7 @@ function loadStories() { require('../app/component-library/components/Link/Link.stories'); require('../app/component-library/components/MultiselectListItem/MultiselectListItem.stories'); require('../app/component-library/components/NetworkAvatar/NetworkAvatar.stories'); + require('../app/component-library/components/PickerItem/PickerItem.stories'); require('../app/component-library/components/SelectableListItem/SelectableListItem.stories'); require('../app/component-library/components/TabBar/TabBar.stories'); require('../app/component-library/components/TabBarItem/TabBarItem.stories'); @@ -57,12 +58,13 @@ const stories = [ '../app/component-library/components/Link/Link.stories', '../app/component-library/components/MultiselectListItem/MultiselectListItem.stories', '../app/component-library/components/NetworkAvatar/NetworkAvatar.stories', + '../app/component-library/components/PickerItem/PickerItem.stories', '../app/component-library/components/SelectableListItem/SelectableListItem.stories', '../app/component-library/components/TabBar/TabBar.stories', '../app/component-library/components/TabBarItem/TabBarItem.stories', '../app/component-library/components/Tag/Tag.stories', '../app/component-library/components/TagUrl/TagUrl.stories', - '../app/component-library/components/TokenAvatar/TokenAvatar.stories' + '../app/component-library/components/TokenAvatar/TokenAvatar.stories', ]; module.exports = { From 2df13746af054f0970197e72ea42d2e310debae6 Mon Sep 17 00:00:00 2001 From: Cal Leung Date: Mon, 18 Jul 2022 19:23:08 -0700 Subject: [PATCH 2/2] Create picker account component --- .../PickerAccount/PickerAccount.constants.ts | 3 ++ .../PickerAccount/PickerAccount.stories.tsx | 19 +++++++ .../PickerAccount/PickerAccount.styles.ts | 36 +++++++++++++ .../PickerAccount/PickerAccount.test.tsx | 22 ++++++++ .../PickerAccount/PickerAccount.tsx | 52 +++++++++++++++++++ .../PickerAccount/PickerAccount.types.ts | 33 ++++++++++++ .../components/PickerAccount/README.md | 39 ++++++++++++++ .../__snapshots__/PickerAccount.test.tsx.snap | 46 ++++++++++++++++ .../components/PickerAccount/index.ts | 1 + .../components/PickerItem/README.md | 2 +- storybook/storyLoader.js | 2 + 11 files changed, 254 insertions(+), 1 deletion(-) create mode 100644 app/component-library/components/PickerAccount/PickerAccount.constants.ts create mode 100644 app/component-library/components/PickerAccount/PickerAccount.stories.tsx create mode 100644 app/component-library/components/PickerAccount/PickerAccount.styles.ts create mode 100644 app/component-library/components/PickerAccount/PickerAccount.test.tsx create mode 100644 app/component-library/components/PickerAccount/PickerAccount.tsx create mode 100644 app/component-library/components/PickerAccount/PickerAccount.types.ts create mode 100644 app/component-library/components/PickerAccount/README.md create mode 100644 app/component-library/components/PickerAccount/__snapshots__/PickerAccount.test.tsx.snap create mode 100644 app/component-library/components/PickerAccount/index.ts diff --git a/app/component-library/components/PickerAccount/PickerAccount.constants.ts b/app/component-library/components/PickerAccount/PickerAccount.constants.ts new file mode 100644 index 00000000000..54ba17e471b --- /dev/null +++ b/app/component-library/components/PickerAccount/PickerAccount.constants.ts @@ -0,0 +1,3 @@ +export const TEST_ACCOUNT_ADDRESS = + '0x2990079bcdEe240329a520d2444386FC119da21a'; +export const TEST_ACCOUNT_NAME = 'Orangefox.eth'; diff --git a/app/component-library/components/PickerAccount/PickerAccount.stories.tsx b/app/component-library/components/PickerAccount/PickerAccount.stories.tsx new file mode 100644 index 00000000000..b7d7f4c8626 --- /dev/null +++ b/app/component-library/components/PickerAccount/PickerAccount.stories.tsx @@ -0,0 +1,19 @@ +/* eslint-disable no-console */ +import React from 'react'; +import { Alert } from 'react-native'; +import { storiesOf } from '@storybook/react-native'; +import PickerAccount from './PickerAccount'; +import { + TEST_ACCOUNT_ADDRESS, + TEST_ACCOUNT_NAME, +} from './PickerAccount.constants'; +import { AccountAvatarType } from '../AccountAvatar'; + +storiesOf('Component Library / PickerAccount', module).add('Default', () => ( + Alert.alert('Pressed account picker!')} + /> +)); diff --git a/app/component-library/components/PickerAccount/PickerAccount.styles.ts b/app/component-library/components/PickerAccount/PickerAccount.styles.ts new file mode 100644 index 00000000000..122518a2a56 --- /dev/null +++ b/app/component-library/components/PickerAccount/PickerAccount.styles.ts @@ -0,0 +1,36 @@ +import { StyleSheet, ViewStyle } from 'react-native'; +import { PickerAccountStyleSheetVars } from './PickerAccount.types'; +import { Theme } from '../../../util/theme/models'; + +/** + * Style sheet function for PickerAccount component. + * + * @param params Style sheet params. + * @param params.theme App theme from ThemeContext. + * @param params.vars Inputs that the style sheet depends on. + * @returns StyleSheet object. + */ +const styleSheet = (params: { + theme: Theme; + vars: PickerAccountStyleSheetVars; +}) => { + const { vars, theme } = params; + const { colors } = theme; + const { style } = vars; + return StyleSheet.create({ + base: Object.assign({} as ViewStyle, style) as ViewStyle, + accountAvatar: { + marginRight: 16, + }, + accountAddressLabel: { + color: colors.text.alternative, + }, + cellAccount: { + flex: 1, + flexDirection: 'row', + marginVertical: 16, + }, + }); +}; + +export default styleSheet; diff --git a/app/component-library/components/PickerAccount/PickerAccount.test.tsx b/app/component-library/components/PickerAccount/PickerAccount.test.tsx new file mode 100644 index 00000000000..8bd671d26ca --- /dev/null +++ b/app/component-library/components/PickerAccount/PickerAccount.test.tsx @@ -0,0 +1,22 @@ +import React from 'react'; +import { shallow } from 'enzyme'; +import PickerAccount from './PickerAccount'; +import { + TEST_ACCOUNT_ADDRESS, + TEST_ACCOUNT_NAME, +} from './PickerAccount.constants'; +import { AccountAvatarType } from '../AccountAvatar'; + +describe('PickerAccount', () => { + it('should render correctly', () => { + const wrapper = shallow( + , + ); + expect(wrapper).toMatchSnapshot(); + }); +}); diff --git a/app/component-library/components/PickerAccount/PickerAccount.tsx b/app/component-library/components/PickerAccount/PickerAccount.tsx new file mode 100644 index 00000000000..08d68002eb8 --- /dev/null +++ b/app/component-library/components/PickerAccount/PickerAccount.tsx @@ -0,0 +1,52 @@ +/* eslint-disable react/prop-types */ +import React from 'react'; +import { View } from 'react-native'; +import { useStyles } from '../../hooks'; +import AccountAvatar from '../AccountAvatar'; +import BaseText, { BaseTextVariant } from '../BaseText'; +import PickerItem from '../PickerItem'; +import styleSheet from './PickerAccount.styles'; +import { PickerAccountProps } from './PickerAccount.types'; +import { BaseAvatarSize } from '../BaseAvatar'; +import { formatAddress } from '../../../util/address'; + +const PickerAccount = ({ + style, + accountAddress, + accountName, + accountAvatarType, + ...props +}: PickerAccountProps) => { + const { styles } = useStyles(styleSheet, { style }); + const shortenedAddress = formatAddress(accountAddress, 'short'); + + const renderCellAccount = () => ( + + + + + {accountName} + + + {shortenedAddress} + + + + ); + + return ( + + {renderCellAccount()} + + ); +}; + +export default PickerAccount; diff --git a/app/component-library/components/PickerAccount/PickerAccount.types.ts b/app/component-library/components/PickerAccount/PickerAccount.types.ts new file mode 100644 index 00000000000..4bc0073bfd0 --- /dev/null +++ b/app/component-library/components/PickerAccount/PickerAccount.types.ts @@ -0,0 +1,33 @@ +import { StyleProp, TouchableOpacityProps, ViewStyle } from 'react-native'; +import { AccountAvatarType } from '../AccountAvatar'; + +/** + * PickerAccount component props. + */ +export interface PickerAccountProps extends TouchableOpacityProps { + /** + * Callback to trigger when pressed. + */ + onPress: () => void; + /** + * An Ethereum wallet address. + */ + accountAddress: string; + /** + * AccountAvatar variants. + */ + accountAvatarType: AccountAvatarType; + /** + * Name of the account. + */ + accountName: string; + /** + * Escape hatch for applying extra styles. Only use if absolutely necessary. + */ + style?: StyleProp; +} + +/** + * Style sheet input parameters. + */ +export type PickerAccountStyleSheetVars = Pick; diff --git a/app/component-library/components/PickerAccount/README.md b/app/component-library/components/PickerAccount/README.md new file mode 100644 index 00000000000..292b0560ae1 --- /dev/null +++ b/app/component-library/components/PickerAccount/README.md @@ -0,0 +1,39 @@ +# PickerAccount + +PickerAccount is a component used for accessing account selection. + +## Props + +This component extends `TouchableOpacityProps` from React Native's [TouchableOpacityProps Component](https://reactnative.dev/docs/touchableOpacity). + +### `onPress` + +Callback to trigger when pressed. + +| TYPE | REQUIRED | +| :-------------------------------------------------- | :------------------------------------------------------ | +| function | Yes | + +### `accountAddress` + +An Ethereum wallet address. + +| TYPE | REQUIRED | +| :-------------------------------------------------- | :------------------------------------------------------ | +| string | Yes | + +### `accountName` + +Name of the account. + +| TYPE | REQUIRED | +| :-------------------------------------------------- | :------------------------------------------------------ | +| string | Yes | + +### `children` + +Content to wrap in PickerAccount. + +| TYPE | REQUIRED | +| :-------------------------------------------------- | :------------------------------------------------------ | +| ReactNode | Yes | diff --git a/app/component-library/components/PickerAccount/__snapshots__/PickerAccount.test.tsx.snap b/app/component-library/components/PickerAccount/__snapshots__/PickerAccount.test.tsx.snap new file mode 100644 index 00000000000..043dda64efa --- /dev/null +++ b/app/component-library/components/PickerAccount/__snapshots__/PickerAccount.test.tsx.snap @@ -0,0 +1,46 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`PickerAccount should render correctly 1`] = ` + + + + + + Orangefox.eth + + + 0x2990...a21a + + + + +`; diff --git a/app/component-library/components/PickerAccount/index.ts b/app/component-library/components/PickerAccount/index.ts new file mode 100644 index 00000000000..e4b68eaec5d --- /dev/null +++ b/app/component-library/components/PickerAccount/index.ts @@ -0,0 +1 @@ +export { default } from './PickerAccount'; diff --git a/app/component-library/components/PickerItem/README.md b/app/component-library/components/PickerItem/README.md index 6c41bd8b1c8..6230477bdb2 100644 --- a/app/component-library/components/PickerItem/README.md +++ b/app/component-library/components/PickerItem/README.md @@ -16,7 +16,7 @@ Callback to trigger when pressed. ### `children` -Content to wrap for multiselect. +Content to wrap in PickerItem. | TYPE | REQUIRED | | :-------------------------------------------------- | :------------------------------------------------------ | diff --git a/storybook/storyLoader.js b/storybook/storyLoader.js index 55f2290c331..8647c79bf7f 100644 --- a/storybook/storyLoader.js +++ b/storybook/storyLoader.js @@ -26,6 +26,7 @@ function loadStories() { require('../app/component-library/components/Link/Link.stories'); require('../app/component-library/components/MultiselectListItem/MultiselectListItem.stories'); require('../app/component-library/components/NetworkAvatar/NetworkAvatar.stories'); + require('../app/component-library/components/PickerAccount/PickerAccount.stories'); require('../app/component-library/components/PickerItem/PickerItem.stories'); require('../app/component-library/components/SelectableListItem/SelectableListItem.stories'); require('../app/component-library/components/TabBar/TabBar.stories'); @@ -58,6 +59,7 @@ const stories = [ '../app/component-library/components/Link/Link.stories', '../app/component-library/components/MultiselectListItem/MultiselectListItem.stories', '../app/component-library/components/NetworkAvatar/NetworkAvatar.stories', + '../app/component-library/components/PickerAccount/PickerAccount.stories', '../app/component-library/components/PickerItem/PickerItem.stories', '../app/component-library/components/SelectableListItem/SelectableListItem.stories', '../app/component-library/components/TabBar/TabBar.stories',