Skip to content

Commit

Permalink
Implement iOS "Cancel" button
Browse files Browse the repository at this point in the history
  • Loading branch information
Jon-edge committed Nov 29, 2024
1 parent a1a8747 commit 5f06ba6
Show file tree
Hide file tree
Showing 4 changed files with 214 additions and 22 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## Unreleased

- changed: (iOS) `SimpleTextInput` back chevron replaced with "Cancel" button
- added: `isBuiltInAsset` param for 'Exchange_Shift_Success' tracking event

## 4.17.2
Expand Down
81 changes: 77 additions & 4 deletions src/__tests__/modals/__snapshots__/WalletListModal.test.tsx.snap
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,8 @@ exports[`WalletListModal should render with loading props 1`] = `
<View
style={
{
"alignItems": "center",
"flex": 1,
"flexDirection": "row",
}
}
Expand Down Expand Up @@ -220,6 +222,7 @@ exports[`WalletListModal should render with loading props 1`] = `
"borderWidth": 1,
"flexDirection": "row",
"flexGrow": 1,
"flexShrink": 1,
"paddingHorizontal": 22,
"paddingVertical": 17,
},
Expand Down Expand Up @@ -308,7 +311,7 @@ exports[`WalletListModal should render with loading props 1`] = `
<View
size={
{
"value": undefined,
"value": 0,
}
}
style={
Expand All @@ -318,8 +321,8 @@ exports[`WalletListModal should render with loading props 1`] = `
"aspectRatio": 1,
},
{
"opacity": undefined,
"width": undefined,
"opacity": 0,
"width": 0,
},
]
}
Expand All @@ -329,7 +332,7 @@ exports[`WalletListModal should render with loading props 1`] = `
{
"color": "#FFFFFF",
"fontFamily": "Material Icons",
"fontSize": 22,
"fontSize": 0,
"fontStyle": "normal",
"fontWeight": "normal",
}
Expand Down Expand Up @@ -466,6 +469,76 @@ exports[`WalletListModal should render with loading props 1`] = `
</View>
</View>
</View>
<View
isFocused={false}
style={
{
"alignItems": "center",
"justifyContent": "center",
"marginLeft": 11,
"opacity": 0,
"width": 0,
}
}
>
<View
accessibilityState={
{
"busy": undefined,
"checked": undefined,
"disabled": undefined,
"expanded": undefined,
"selected": undefined,
}
}
accessibilityValue={
{
"max": undefined,
"min": undefined,
"now": undefined,
"text": undefined,
}
}
accessible={true}
collapsable={false}
focusable={true}
hitSlop={17}
onClick={[Function]}
onResponderGrant={[Function]}
onResponderMove={[Function]}
onResponderRelease={[Function]}
onResponderTerminate={[Function]}
onResponderTerminationRequest={[Function]}
onStartShouldSetResponder={[Function]}
style={
{
"margin": -22,
"opacity": 1,
"padding": 22,
}
}
testID="undefined.cancelButton"
>
<Text
ellipsizeMode="clip"
numberOfLines={1}
style={
{
"color": "#00f1a2",
"flexShrink": 0,
"fontFamily": "Quicksand-Regular",
"fontSize": 22,
"includeFontPadding": false,
"minWidth": 90,
"textAlign": "center",
"whiteSpace": "nowrap",
}
}
>
Cancel
</Text>
</View>
</View>
</View>
</View>
</View>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,8 @@ exports[`CreateWalletSelectCrypto should render with loading props 1`] = `
<View
style={
{
"alignItems": "center",
"flex": 1,
"flexDirection": "row",
}
}
Expand Down Expand Up @@ -354,6 +356,7 @@ exports[`CreateWalletSelectCrypto should render with loading props 1`] = `
"borderWidth": 1,
"flexDirection": "row",
"flexGrow": 1,
"flexShrink": 1,
"paddingHorizontal": 22,
"paddingVertical": 17,
},
Expand Down Expand Up @@ -442,7 +445,7 @@ exports[`CreateWalletSelectCrypto should render with loading props 1`] = `
<View
size={
{
"value": undefined,
"value": 0,
}
}
style={
Expand All @@ -452,8 +455,8 @@ exports[`CreateWalletSelectCrypto should render with loading props 1`] = `
"aspectRatio": 1,
},
{
"opacity": undefined,
"width": undefined,
"opacity": 0,
"width": 0,
},
]
}
Expand All @@ -463,7 +466,7 @@ exports[`CreateWalletSelectCrypto should render with loading props 1`] = `
{
"color": "#FFFFFF",
"fontFamily": "Material Icons",
"fontSize": 22,
"fontSize": 0,
"fontStyle": "normal",
"fontWeight": "normal",
}
Expand Down Expand Up @@ -601,6 +604,76 @@ exports[`CreateWalletSelectCrypto should render with loading props 1`] = `
</View>
</View>
</View>
<View
isFocused={false}
style={
{
"alignItems": "center",
"justifyContent": "center",
"marginLeft": 11,
"opacity": 0,
"width": 0,
}
}
>
<View
accessibilityState={
{
"busy": undefined,
"checked": undefined,
"disabled": undefined,
"expanded": undefined,
"selected": undefined,
}
}
accessibilityValue={
{
"max": undefined,
"min": undefined,
"now": undefined,
"text": undefined,
}
}
accessible={true}
collapsable={false}
focusable={true}
hitSlop={17}
onClick={[Function]}
onResponderGrant={[Function]}
onResponderMove={[Function]}
onResponderRelease={[Function]}
onResponderTerminate={[Function]}
onResponderTerminationRequest={[Function]}
onStartShouldSetResponder={[Function]}
style={
{
"margin": -22,
"opacity": 1,
"padding": 22,
}
}
testID="undefined.cancelButton"
>
<Text
ellipsizeMode="clip"
numberOfLines={1}
style={
{
"color": "#00f1a2",
"flexShrink": 0,
"fontFamily": "Quicksand-Regular",
"fontSize": 22,
"includeFontPadding": false,
"minWidth": 90,
"textAlign": "center",
"whiteSpace": "nowrap",
}
}
>
Cancel
</Text>
</View>
</View>
</View>
<RCTScrollView
automaticallyAdjustContentInsets={false}
Expand Down
73 changes: 59 additions & 14 deletions src/components/themed/SimpleTextInput.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as React from 'react'
import { useMemo } from 'react'
import { TextInput, TouchableOpacity, View } from 'react-native'
import { Platform, TextInput, TouchableOpacity, View } from 'react-native'
import Animated, {
interpolate,
interpolateColor,
Expand All @@ -15,6 +15,7 @@ import Animated, {

import { useHandler } from '../../hooks/useHandler'
import { MarginRemProps, useMarginRemStyle } from '../../hooks/useMarginRemStyle'
import { lstrings } from '../../locales/strings'
import { EdgeTouchableWithoutFeedback } from '../common/EdgeTouchableWithoutFeedback'
import { styled, styledWithRef } from '../hoc/styled'
import { AnimatedIconComponent, ChevronBackAnimated, CloseIconAnimated } from '../icons/ThemedIcons'
Expand Down Expand Up @@ -111,6 +112,7 @@ export const SimpleTextInput = React.forwardRef<SimpleTextInputRef, SimpleTextIn

const hasIcon = Icon != null
const hasValue = value !== ''
const isIos = Platform.OS === 'ios'

const [isFocused, setIsFocused] = React.useState(false)

Expand Down Expand Up @@ -172,7 +174,7 @@ export const SimpleTextInput = React.forwardRef<SimpleTextInputRef, SimpleTextIn
if (onSubmitEditing != null) onSubmitEditing()
})

const backIconSize = useDerivedValue(() => interpolate(focusAnimation.value, [0, 1], [0, themeRem]))
const backIconSize = useDerivedValue(() => (isIos ? 0 : interpolate(focusAnimation.value, [0, 1], [0, themeRem])))
const leftIconSize = useDerivedValue(() => (hasIcon ? (hasValue ? 0 : interpolate(focusAnimation.value, [0, 1], [themeRem, 0])) : 0))
const rightIconSize = useDerivedValue(() => (hasValue ? themeRem : focusAnimation.value * themeRem))

Expand Down Expand Up @@ -234,12 +236,24 @@ export const SimpleTextInput = React.forwardRef<SimpleTextInputRef, SimpleTextIn
</TouchContainer>
</InputContainerView>
</EdgeTouchableWithoutFeedback>
{isIos && (
<CancelButton isFocused={isFocused}>
<TouchContainer hitSlop={theme.rem(0.75)} accessible onPress={handleDonePress} testID={`${testID}.cancelButton`}>
<CancelText numberOfLines={1} ellipsizeMode="clip">
{lstrings.string_cancel_cap}
</CancelText>
</TouchContainer>
</CancelButton>
)}
</ContainerView>
)
})

const ContainerView = styled(View)({
flexDirection: 'row'
flexDirection: 'row',
alignItems: 'center',
flexGrow: 1,
flexShrink: 1
})

const InputContainerView = styled(Animated.View)<{
Expand Down Expand Up @@ -268,19 +282,23 @@ const InputContainerView = styled(Animated.View)<{
borderRadius: theme.rem(theme.textInputBorderRadius),
flexDirection: 'row',
flexGrow: 1,
flexShrink: 1,
paddingHorizontal: theme.rem(1),
paddingVertical: theme.rem(0.75)
},
useAnimatedStyle(() => ({
backgroundColor: interpolateInputBackgroundColor(focusAnimation, disableAnimation),
borderColor: interpolateOutlineColor(focusAnimation, disableAnimation),
opacity: interpolate(scale.value, [1, 0.5], [1, 0]),
transform: [
{
scale: interpolate(scale.value, [1, 0], [1, 0.75])
}
]
}))
useAnimatedStyle(() => {
'worklet'
return {
backgroundColor: interpolateInputBackgroundColor(focusAnimation, disableAnimation),
borderColor: interpolateOutlineColor(focusAnimation, disableAnimation),
opacity: interpolate(scale.value, [1, 0.5], [1, 0]),
transform: [
{
scale: interpolate(scale.value, [1, 0], [1, 0.75])
}
]
}
})
]
})

Expand Down Expand Up @@ -324,11 +342,38 @@ const InputField = styledWithRef(AnimatedTextInput)<{
})

const TouchContainer = styled(TouchableOpacity)(theme => ({
// Increase tappable area with padding, while net 0 with negative margin to visually appear as if 0 margins/padding
// Increase tappable area with padding, while net 0 with negative margin to
// visually appear as if 0 margins/padding
padding: theme.rem(1),
margin: -theme.rem(1)
}))

const CancelButton = styled(Animated.View)<{
isFocused: boolean
}>(theme => ({ isFocused }) => {
const width = theme.rem(4)
return {
alignItems: 'center',
justifyContent: 'center',
marginLeft: theme.rem(0.5),
opacity: isFocused ? 1 : 0,
width: isFocused ? width : 0
}
})

const CancelText = styled(Animated.Text)(theme => {
return {
color: theme.textInputIconColorFocused,
fontFamily: theme.fontFaceDefault,
fontSize: theme.rem(1),
includeFontPadding: false,
textAlign: 'center',
whiteSpace: 'nowrap',
minWidth: theme.rem(4),
flexShrink: 0
}
})

function useAnimatedColorInterpolateFn(fromColor: string, toColor: string, disabledColor: string) {
const interpolateFn = useMemo(() => {
return (focusValue: SharedValue<number>, disabledValue: SharedValue<number>) => {
Expand Down

0 comments on commit 5f06ba6

Please sign in to comment.