Shared Element animation using showModal and dismiss gesture [react-native-navigation/wix] - wix-react-native-navigation

I'm trying to create an instagram story like screen, when you press the story the sharedElement transition is triggered and then in StoryScreen, if you perform the dismiss gesture, the screen will disappear with the sharedElement transition as well.
I'd like to achieve a transparent background, in order to scale the detail screen and see the under screen before releasing the gesture and dismissing it, so the best solution, and the only one that allow transparent background screens, is using showModal with the following options, as show in the library playground folder:
Navigation.showModal({
component: {
name: "StoriesScreen",
options: {
animations: {
showModal: {
alpha: {
from: 0,
to: 1,
duration: SET_DURATION,
},
sharedElementTransitions: [
{
fromId: `image.1.from`,
toId: `image.1.to`,
duration: SET_DURATION,
interpolation: { type: "spring", ...SPRING_CONFIG },
},
],
},
dismissModal: {
alpha: {
from: 1,
to: 0,
duration: SET_DURATION,
},
sharedElementTransitions: [
{
fromId: `image.1.to`,
toId: `image.1.from`,
duration: SET_DURATION,
interpolation: { type: "spring", ...SPRING_CONFIG },
},
],
},
},
},
},
});
/* From component */
<TouchableOpacity onPress={onPress} style={SIZE}>
<Image
nativeID="image.1.from"
style={{ flex: 1 }}
source={{ uri: A }}
/>
</TouchableOpacity>
/* Destination component */
<Image
nativeID="image.1.to"
style={{ flex: 1 }}
source={{
uri: "https://cdn.we-wealth.com/-/media/Images/social/porsche-356-quando-il-fascino-speedster-conquisto-lamerica.png?rev=9c55b0db85954d18bf4b818784682d26&modified=20201126232413",
}}
/>
(Invoke Navigation.dismissModal(componentId) to dismiss through gesture).
But here's the result:
https://user-images.githubusercontent.com/64473929/161373445-4b4a7f4e-fad0-4468-8a0e-d992f5e57c9f.MP4
Then if I instead us push, the sharedElement transition works, but I can't achieve the transparent background.
So since this #6647 suggests that the sharedElement is supported by modals too, there's and error in my code.
UPDATE
I'm using screens wrapped inside a Wrapper because of I need Redux and SafeAreaContext, here' the wrapper I'm using for each screen:
const ScreenWrapper = (Component) => {
return function inject(props) {
return (
<Provider store={store}>
<PersistGate loading={<></>} persistor={persistor}>
<NavigationProvider value={{ componentId: props.componentId }}>
<SafeAreaProvider>
<Component {...props} />
</SafeAreaProvider>
</NavigationProvider>
</PersistGate>
</Provider>
);
};
};

It seems that SafeAreaContext cause the error, so I've uninstalled it and instead of wrapping all screens inside it, I've replaced the useSafeAreaContext hook with react-native-static-safe-area-insets.

Related

How to override nested child component styling in MaterialUI v5?

I have a ToggleButton component that has custom styling. I want to make that Toggle Button component look differently only when it's used as a child (inside) a ToggleButtonGroup. Here is how I'd call the ToggleButtonGroup component:
<ToggleButtonGroup onChange={()=>{}} ariaLabel='platform'>
<ToggleButton label='Japan' value='1' selected={true}/>
<ToggleButton label='China' value='2' selected={false}/>
<ToggleButton label='Brazil' value='3' selected={false}/>
</ToggleButtonGroup>
Here is the code for my ToggleButtonGroup component:
const StyledToggleGroup = styled(ToggleOptionsGroup)(
({ theme: { palette, spacing } }) => ({
height: spacing(10),
borderRadius: '6px',
boxShadow: 'none',
'&:hover': {
boxShadow: 'none',
},
'&.MuiToggleButtonGroup-root':{
gap: '0px'
},
'&.MuiToggleButton-standard':{
backgroundColor:'red',
},
'&.MuiToggleButtonGroup-grouped.Mui-selected': {
backgroundColor:'green',
}
})
);
const ToggleButtonGroup:React.FC<ToggleButtonGroupProps> = ({children, onChange, ariaLabel}) =>{
return(
<StyledToggleGroup
exclusive
onChange={onChange}
aria-label={ariaLabel}>
{children}
</StyledToggleGroup>
)
}
However, the last two classes:
'&.MuiToggleButton-standard':{
backgroundColor:'red',
},
'&.MuiToggleButtonGroup-grouped.Mui-selected': {
backgroundColor:'green',
}
don't really change anything.
How can I change the styling of my ToggleButton component only when it's passed as a child to the ToggleButtonGroup component?
It seems that class names are correct according to MUI document, the posted code should just need to specify these as children of StyledToggleGroup with a descendant combinator after & for the styles to work:
Tested in a simple demo here: stackblitz
"& .MuiToggleButton-standard": {
backgroundColor: "hotpink",
},
"& .MuiToggleButtonGroup-grouped.Mui-selected": {
backgroundColor: "lightblue",
},

Adding a background image to nav Link in React using useState

I was able to get the background image to show up when the link was clicked, however it is showing up on all the links once clicked. All the links have a different background image, but depending on which one is clicked all the links get the background image of the link clicked. I only want the appropriate background image to show while on page of link clicked
const navLinks = [
{ title: `HOME`, path: `/`, bgI: `${homePaintBackground}` },
{ title: `EVENTS`, path: `/events`, bgI: `${eventsPaintBackground}` },
{ title: `ARTISTS`, path: `/artists`, bgI: `${artistPaintBackground}` },
{
title: `CONTACT US`,
path: `/contactUs`,
bgI: `${contactUsPaintBackground}`,
},
]
const Nav = () => {
const classes = useStyles()
const [bgI] = navLinks
const [backgroundImage, setBackgroundImage] = useState(bgI)
const css = {
backgroundImage: `url(${backgroundImage})`,
marginBottom: '-20px',
width: '20%',
height: '80%',
backgroundSize: 'cover',
backgroundRepeat: 'no-repeat',
}
return ( ...
{navLinks.map(({ title, path, bgI }) => (
<Link
// active={bgI}
to={path}
key={title}
// value={bgI}
className={classes.linkText}
style={css}
onClick={() => setBackgroundImage(`${bgI}`)}
>
Thank you for any help you may be able to provide.

How to add animation to a view changing its height in react native?

I am trying to increase and decrease the height of a rectangle depending on several conditions... The task is completed, however, I want to make the height changes smoothly and gradually.
How could I do that in react native while my CSS is dynamically changing?
getBarStyle() {
if (this.state.value < this.state.minValue) {
return {
height: 0
};
}
let accurateHeight;
accurateHeight = (this.state.value * (this.state.graphHeight - lineDiffValue);
return {
height: accurateHeight,
transition: "height 2s"
};
}
render() {
return (
<View style={[styles.rectangle, this.getBarStyle()]} />
)
}
Firstly, create an Animated.Value with the starting value of the View.
constructor() {
this.animatedValue = new Animated.Value(50);
}
Then, create a function which will animated the height. The example below will animate from 50 to 100.
startAnimation = () => {
Animated.timing(this.animatedValue, {
toValue: 100
}).start();
}
Finally, pass your animated style to your View. You need to use Animated.View, not View.
render() {
return (
<Animated.View style={{ height: this.animatedValue }} />
)
}
Don't forget to import { Animated } from 'react-native';
Error
<Animated.View style={{ height: this.animatedValue }} />
error: Style property 'height' is not supported by native animated module.
As the React-Native documentation said, you can only animate non-layout properties. Transform property is supported so you can use transform.scaleY instead of changing the height :((
so..
Try my solution
constructor(props: any)
{
this.state.isDisplay = true;
this.state.animatedView = new Animated.Value(100);
this.state.animatedViewInterpolate =
this.state.animatedView.interpolate({ inputRange: [0, 100], outputRange: ["0%", "100%"] });
this.animateDuration = 500;
}
onPressDisplayView()
{
if (this.state.isDisplay)
{
Animated.timing(this.state.animatedView, { toValue: 0, duration: this.animateDuration }).start(() =>
{
this.setState({ isDisplay: false });
});
}
else
{
Animated.timing(this.state.animatedView, { toValue: 100, duration: this.animateDuration }).start(() =>
{
this.setState({ isDisplay: true });
});
}
}
render()
{
return(
<View style={{flex: 1}}>
<Button onPress={() => {this.onPressDisplayView()}}>Display</Button>
<View style={{ height: this.state.animatedViewInterpolate, backgroundColor: '#F00' }}>
<Text>HelloWorld!</Text>
</View>
</View>);
}
use interpolate
I wrote this without running. maybe work or not :)

Change outline for OutlinedInput with React material-ui

Quick note: this is not a duplicate of How to change outline color of Material UI React input component?
With material-ui (React) I am unable to delete the outline on hover or focus. The reason I am using this input is to request add a little red border when a warning occurs. I can change the focused and hover styles. This is tested in the following image:
Where this CSS is applied when the input is focused:
outlinedInputFocused: {
borderStyle: 'none',
borderColor: 'red',
outlineWidth: 0,
outline: 'none',
backgroundColor: 'green'
},
Component
<OutlinedInput
disableUnderline={true}
notched={true}
id="adornment-weight"
classes={{root: classes.outlinedInput, focused: classes.outlinedInputFocused}}
value={this.state.budgetValue}
onChange={evt => this.updateBudgetValue(evt)}
onKeyPress={evt => this.handleKeyPress(evt)}
endAdornment={<InputAdornment sposition="end">BTC</InputAdornment>}
/>
As you can see the color of the image is green, but there is still an outline. Even though the outlineWidth is 0 and outline is set to none in the CSS. How can I change / disable this outline?
The key to understanding how to override these styles is to look at how they are defined in the Material-UI source code. The question you referenced also shows some of the syntax needed.
Below is an abbreviated version (I left out the styles that are not related to the outline) of the styles from OutlinedInput.js:
export const styles = theme => {
const borderColor =
theme.palette.type === 'light' ? 'rgba(0, 0, 0, 0.23)' : 'rgba(255, 255, 255, 0.23)';
return {
/* Styles applied to the root element. */
root: {
position: 'relative',
'& $notchedOutline': {
borderColor,
},
'&:hover:not($disabled):not($focused):not($error) $notchedOutline': {
borderColor: theme.palette.text.primary,
// Reset on touch devices, it doesn't add specificity
'#media (hover: none)': {
borderColor,
},
},
'&$focused $notchedOutline': {
borderColor: theme.palette.primary.main,
borderWidth: 2,
},
'&$error $notchedOutline': {
borderColor: theme.palette.error.main,
},
'&$disabled $notchedOutline': {
borderColor: theme.palette.action.disabled,
},
},
/* Styles applied to the root element if the component is focused. */
focused: {},
/* Styles applied to the root element if `disabled={true}`. */
disabled: {},
/* Styles applied to the root element if `error={true}`. */
error: {},
/* Styles applied to the `NotchedOutline` element. */
notchedOutline: {}
};
};
The "outline" of OutlinedInput is controlled via the border on the NotchedOutline component nested within it. In order to impact that nested element, you need to define a "notchedOutline" class (even if empty) that you can then use to target that element for the different states (e.g. focused, hover) of the parent.
Here's an example that fully removes the border:
import React from "react";
import ReactDOM from "react-dom";
import OutlinedInput from "#material-ui/core/OutlinedInput";
import InputAdornment from "#material-ui/core/InputAdornment";
import { withStyles } from "#material-ui/core/styles";
const styles = theme => ({
root: {
"& $notchedOutline": {
borderWidth: 0
},
"&:hover $notchedOutline": {
borderWidth: 0
},
"&$focused $notchedOutline": {
borderWidth: 0
}
},
focused: {},
notchedOutline: {}
});
function App(props) {
const { classes } = props;
return (
<div className="App">
<OutlinedInput
disableUnderline={true}
notched={true}
id="adornment-weight"
classes={classes}
value={1}
endAdornment={<InputAdornment sposition="end">BTC</InputAdornment>}
/>
</div>
);
}
const StyledApp = withStyles(styles)(App);
const rootElement = document.getElementById("root");
ReactDOM.render(<StyledApp />, rootElement);
You can use inline style like this:
<MyComponent style={{outline: 'none'}} />
2.4.7 Focus Visible: Any keyboard operable user interface has a mode of operation where the keyboard focus indicator is visible. (Level AA)
https://www.w3.org/TR/2008/REC-WCAG20-20081211/#navigation-mechanisms-focus-visible
https://www.w3.org/WAI/WCAG21/quickref/?versions=2.0#qr-navigation-mechanisms-focus-visible
OutlinedInput is desined in such a way that you can't turn off its outline you have to use TextField with variant 'outlined' as default and 'none' on focus.
You can see the example of Outlined Input Adornments using TextField here

View css not going till the top Iphone X

Screen Shot of Iphone Iv'e been trying to make my view background color go till the top on the iPhone x but still can figure out how to do this I still have a white section on the top.
import React from 'react'
import { View, Text, ActivityIndicator, StyleSheet } from 'react-
native'
import firebase from 'firebase';
export default class Loading extends React.Component {
componentDidMount() {
// firebase.auth().onAuthStateChanged(user => {
// this.props.navigation.navigate(user ? 'Main' : 'Login')
// }) // for now to solve problem
}
render() {
return (
<View style={styles.container}>
<Text>Loading</Text>
<ActivityIndicator size="large" />
</View>
)
}
};
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#2C3E50',
justifyContent: 'center',
alignItems: 'center',
}
});
I would very much like the background color to go to the top as well
I haven't run your code but I'm assuming that the issue is the switchNavigator is showing a header. If this is the case then you want to change the color of the navigator within the screen that you are on.
So within your Loading class:
export default class Loading extends React.Component {
// Add this:
static navigationOptions = {
headerStyle: {
backgroundColor: '#2C3E50',
},
};
componentDidMount() {}
render() {
return (
<View style={styles.container}>
<Text>Loading</Text>
<ActivityIndicator size="large" />
</View>
)
}
};
Reference: https://reactnavigation.org/docs/en/headers.html#adjusting-header-styles
That may be header of stack navigator(very less probability).. or may be with "safeViewiOS"... This may be also a issue with react navigation. Using flex:1 usually takes the screen acc to flex property .. This is surely a inherited property. not a problem with flex or CSS
Try adding :
forceInset={{ bottom: 'never', top: "never" }}>

Resources