Skip to content

Commit

Permalink
feat: adjust Menu (#3118)
Browse files Browse the repository at this point in the history
  • Loading branch information
lukewalczak committed Jun 8, 2022
1 parent 65e36e1 commit 377ab3b
Show file tree
Hide file tree
Showing 6 changed files with 987 additions and 53 deletions.
36 changes: 25 additions & 11 deletions example/src/Examples/MenuExample.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ import {
List,
TouchableRipple,
useTheme,
MD2Colors,
MD3Colors,
} from 'react-native-paper';
import ScreenWrapper from '../ScreenWrapper';

Expand Down Expand Up @@ -68,14 +66,14 @@ const MenuExample = ({ navigation }: Props) => {
anchor={
<Appbar.Action
icon={MORE_ICON}
color={isV3 ? MD2Colors.white : MD3Colors.primary100}
onPress={_toggleMenu('menu1')}
{...(!isV3 && { color: 'white' })}
/>
}
>
<Menu.Item onPress={() => {}} title="Undo" />
<Menu.Item onPress={() => {}} title="Redo" />
<Divider />
<Divider style={isV3 && styles.md3Divider} />
<Menu.Item onPress={() => {}} title="Cut" disabled />
<Menu.Item onPress={() => {}} title="Copy" disabled />
<Menu.Item onPress={() => {}} title="Paste" />
Expand All @@ -92,22 +90,35 @@ const MenuExample = ({ navigation }: Props) => {
</Button>
}
>
<Menu.Item icon="undo" onPress={() => {}} title="Undo" />
<Menu.Item icon="redo" onPress={() => {}} title="Redo" />
<Divider />
<Menu.Item leadingIcon="undo" onPress={() => {}} title="Undo" />
<Menu.Item leadingIcon="redo" onPress={() => {}} title="Redo" />

<Divider style={isV3 && styles.md3Divider} />

<Menu.Item
icon="content-cut"
leadingIcon="content-cut"
onPress={() => {}}
title="Cut"
disabled
/>
<Menu.Item
icon="content-copy"
leadingIcon="content-copy"
onPress={() => {}}
title="Copy"
disabled
/>
<Menu.Item icon="content-paste" onPress={() => {}} title="Paste" />
<Menu.Item
leadingIcon="content-paste"
onPress={() => {}}
title="Paste"
/>
{isV3 && (
<Menu.Item
trailingIcon="share-variant"
onPress={() => {}}
title="Share"
/>
)}
</Menu>
</View>
<Menu
Expand All @@ -117,7 +128,7 @@ const MenuExample = ({ navigation }: Props) => {
>
<Menu.Item onPress={() => {}} title="Item 1" />
<Menu.Item onPress={() => {}} title="Item 2" />
<Divider />
<Divider style={isV3 && styles.md3Divider} />
<Menu.Item onPress={() => {}} title="Item 3" disabled />
</Menu>
<List.Section style={styles.list} title="Contextual menu">
Expand Down Expand Up @@ -148,6 +159,9 @@ const styles = StyleSheet.create({
alignCenter: {
alignItems: 'center',
},
md3Divider: {
marginVertical: 8,
},
});

export default MenuExample;
7 changes: 7 additions & 0 deletions src/components/Menu/Menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {
findNodeHandle,
NativeEventSubscription,
} from 'react-native';
import color from 'color';

import { withTheme } from '../../core/theming';
import type { $Omit } from '../../types';
Expand Down Expand Up @@ -572,6 +573,12 @@ class Menu extends React.Component<Props, State> {
[
styles.shadowMenuContainer,
shadowMenuContainerStyle,
theme.isV3 && {
backgroundColor: color(theme.colors.surface)
.mix(color(theme.colors.primary), 0.08)
.rgb()
.string(),
},
contentStyle,
] as StyleProp<ViewStyle>
}
Expand Down
126 changes: 84 additions & 42 deletions src/components/Menu/MenuItem.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import color from 'color';
import * as React from 'react';
import {
StyleProp,
Expand All @@ -10,23 +9,42 @@ import {
import Icon, { IconSource } from '../Icon';
import TouchableRipple from '../TouchableRipple/TouchableRipple';
import Text from '../Typography/Text';
import { black, white } from '../../styles/themes/v2/colors';
import { withTheme } from '../../core/theming';
import type { Theme } from '../../types';
import {
getContentMaxWidth,
getMenuItemColor,
MAX_WIDTH,
MIN_WIDTH,
} from './utils';

type Props = {
/**
* Title text for the `MenuItem`.
*/
title: React.ReactNode;
/**
* Icon to display for the `MenuItem`.
* @renamed Renamed from 'icon' to 'leadingIcon' in v3.x
*
* Leading icon to display for the `MenuItem`.
*/
leadingIcon?: IconSource;
/**
* @supported Available in v3.x with theme version 3
*
* Trailing icon to display for the `MenuItem`.
*/
icon?: IconSource;
trailingIcon?: IconSource;
/**
* Whether the 'item' is disabled. A disabled 'item' is greyed out and `onPress` is not called on touch.
*/
disabled?: boolean;
/**
* @supported Available in v3.x with theme version 3
*
* Sets min height with densed layout.
*/
dense?: boolean;
/**
* Function to execute on press.
*/
Expand Down Expand Up @@ -68,19 +86,21 @@ type Props = {
*
* const MyComponent = () => (
* <View style={{ flex: 1 }}>
* <Menu.Item icon="redo" onPress={() => {}} title="Redo" />
* <Menu.Item icon="undo" onPress={() => {}} title="Undo" />
* <Menu.Item icon="content-cut" onPress={() => {}} title="Cut" disabled />
* <Menu.Item icon="content-copy" onPress={() => {}} title="Copy" disabled />
* <Menu.Item icon="content-paste" onPress={() => {}} title="Paste" />
* <Menu.Item leadingIcon="redo" onPress={() => {}} title="Redo" />
* <Menu.Item leadingIcon="undo" onPress={() => {}} title="Undo" />
* <Menu.Item leadingIcon="content-cut" onPress={() => {}} title="Cut" disabled />
* <Menu.Item leadingIcon="content-copy" onPress={() => {}} title="Copy" disabled />
* <Menu.Item leadingIcon="content-paste" onPress={() => {}} title="Paste" />
* </View>
* );
*
* export default MyComponent;
* ```
*/
const MenuItem = ({
icon,
leadingIcon,
trailingIcon,
dense,
title,
disabled,
onPress,
Expand All @@ -91,79 +111,100 @@ const MenuItem = ({
accessibilityLabel,
theme,
}: Props) => {
const disabledColor = color(theme.dark ? white : black)
.alpha(0.32)
.rgb()
.string();
const { titleColor, iconColor, underlayColor } = getMenuItemColor({
theme,
disabled,
});
const { isV3 } = theme;

const containerPadding = isV3 ? 12 : 8;

const textColor = theme.isV3 ? theme.colors.onSurface : theme.colors.text;
const iconWidth = isV3 ? 24 : 40;

const titleColor = disabled
? disabledColor
: color(textColor).alpha(0.87).rgb().string();
const minWidth = MIN_WIDTH - (isV3 ? 12 : 16);

const iconColor = disabled
? disabledColor
: color(textColor).alpha(0.54).rgb().string();
const maxWidth = getContentMaxWidth({
isV3,
iconWidth,
leadingIcon,
trailingIcon,
});

return (
<TouchableRipple
style={[styles.container, style]}
style={[
styles.container,
{ paddingHorizontal: containerPadding },
dense && styles.md3DenseContainer,
style,
]}
onPress={onPress}
disabled={disabled}
testID={testID}
accessibilityLabel={accessibilityLabel}
accessibilityRole="menuitem"
accessibilityState={{ disabled }}
underlayColor={underlayColor}
>
<View style={styles.row}>
{icon ? (
<View style={[styles.item, styles.icon]} pointerEvents="box-none">
<Icon source={icon} size={24} color={iconColor} />
{leadingIcon ? (
<View
style={[!isV3 && styles.item, { width: iconWidth }]}
pointerEvents="box-none"
>
<Icon source={leadingIcon} size={24} color={iconColor} />
</View>
) : null}
<View
style={[
styles.item,
!isV3 && styles.item,
styles.content,
icon ? styles.widthWithIcon : null,
{ minWidth, maxWidth },
isV3 &&
(leadingIcon
? styles.md3LeadingIcon
: styles.md3WithoutLeadingIcon),
contentStyle,
]}
pointerEvents="none"
>
<Text
variant="bodyLarge"
selectable={false}
numberOfLines={1}
style={[styles.title, { color: titleColor }, titleStyle]}
style={[!isV3 && styles.title, { color: titleColor }, titleStyle]}
>
{title}
</Text>
</View>
{isV3 && trailingIcon ? (
<View
style={[!isV3 && styles.item, { width: iconWidth }]}
pointerEvents="box-none"
>
<Icon source={trailingIcon} size={24} color={iconColor} />
</View>
) : null}
</View>
</TouchableRipple>
);
};

MenuItem.displayName = 'Menu.Item';

const minWidth = 112;
const maxWidth = 280;
const iconWidth = 40;

const styles = StyleSheet.create({
container: {
paddingHorizontal: 8,
minWidth,
maxWidth,
minWidth: MIN_WIDTH,
maxWidth: MAX_WIDTH,
height: 48,
justifyContent: 'center',
},
md3DenseContainer: {
height: 32,
},
row: {
flexDirection: 'row',
},
icon: {
width: iconWidth,
},
title: {
fontSize: 16,
},
Expand All @@ -172,11 +213,12 @@ const styles = StyleSheet.create({
},
content: {
justifyContent: 'center',
minWidth: minWidth - 16,
maxWidth: maxWidth - 16,
},
widthWithIcon: {
maxWidth: maxWidth - (iconWidth + 48),
md3LeadingIcon: {
marginLeft: 12,
},
md3WithoutLeadingIcon: {
marginLeft: 4,
},
});

Expand Down
Loading

0 comments on commit 377ab3b

Please sign in to comment.