React material-ui: centering items on Toolbar - javascript

I am trying to implement a toolbar on a page in which I have three ToolbarGroup components:
<Toolbar>
<ToolbarGroup firstChild={true} float="left">
{prevButton}
</ToolbarGroup>
<ToolbarGroup>
{releaseBtn}
</ToolbarGroup>
<ToolbarGroup lastChild={true} float="right">
{nextButton}
</ToolbarGroup>
</Toolbar>
The general idea is that prevButton should render all the way to the left of the toolbar (it does), nextButton should render all the way to the right (it does)... and that releaseBtn should be centered on the toolbar (not currently happening).
Per the material-ui docs there doesn't appear to be some easy setting for centered={true}-- how can I accomplish this?
I've tried manually setting the style on the middle ToolbarGroup to margin: 0px auto but that doesn't seem to help.

If anyone runs into this in 2021 or later like I did, material-ui's Toolbar uses Flexbox under the hood, so all you have to do is apply a custom class (or override the default one in the theme):
.myToolbar {
justify-content: space-between;
}
space-between will distribute the children alongside the main horizontal axis:
(picture from https://css-tricks.com/snippets/css/a-guide-to-flexbox/)

The final solution for me was to do this:
<Toolbar>
<ToolbarGroup firstChild={true} float="left">
{prevButton}
</ToolbarGroup>
<ToolbarGroup style={{
float : 'none',
width : '200px',
marginLeft : 'auto',
marginRight : 'auto'
}}>
{releaseBtn}
</ToolbarGroup>
<ToolbarGroup lastChild={true} float="right">
{nextButton}
</ToolbarGroup>
</Toolbar>
I first had to set the middle ToolbarGroup with no float (not an option through the material-ui props) and then play with the width/margins. I imagine your mileage may vary depending on what you shove inside the ToolbarGroup.

In new versions of Material UI you can just use the sx prop:
https://mui.com/system/the-sx-prop/#main-content
<Toolbar sx={{ justifyContent: "space-between" }}> // or "center" for a single element
...
</Toolbar>

Related

having trouble passing margins to Material UI using styles

I am having trouble passing margin using mui styles to my components. Other styles are being passed just fine however when I try margins they do not seem to be applied to my site.
const useStyles = makeStyles({
tool: {
width:'100%',
display: 'inline-flex',
justifyContent: 'space-between',
},
lastBtn: {
marginLeft: 10,
marginRight: 50,
}
})
This is the definition before my function. Inside my function I have definted classes the following way.
const classes = useStyles();
Inside my main component i added
className={classes.root}
and it works just fine, so I know the issue is not styles hook. However the issue is that the same logic is not working for the button component. When I try doing the margins are not being applied.
<Button
className={classes.lastBtn}
variant='contained'
size='large'
onClick={() => navigate("/register")}
>
Register
</Button>
When i try to replace the styles hook declared earlier it is working just fine.
style={{ marginLeft: 10, marginRight: 50}}
Can anyone spot the mistake I am making? I have done tons of research and I am stuck with debugging this. It is very inefficient to use inline styling to create margins for my whole project.
Thank you

How can you ensure flex shrink in react-native (and how can you debug react-native styles in general)?

I'm running a RN app using native-base for styling. I have four elements on my homepage: a header, a tab view from vreact-native-tab-view that contains a ScrollView that takes up about 70% of the viewport, and two smaller 100% width elements at the bottom.
However, the scrollview fills up more than 100% of the viewport and the two smaller elements get pushed to the bottom.
I looked in my element inspector and can apply a flexShrink to some of the many divs, but I'm not sure which one that is in my code because it's div hell when you use react-native. React devtools also has the same problem, except it's View hell.
So, two questions:
How can I ensure the scroll container doesn't fill up more than it should on the page?
How can I effectively debug react native when both chrome and react dev tools are a mess?
For reference, here's how I've styled so far:
Home.tsx:
<View flex={1}> // applied a flex for the entire homepage
<TabView
navigationState={{ index, routes }}
renderScene={renderScene}
renderTabBar={renderTabBar}
onIndexChange={setIndex}
initialLayout={{ width: layout.width, height: "100%" }}
/>
<View width="100%">
<Center width="100%">
<StrengthSlider />
</Center>
<AdMobBanner
...props
/>
</View>
</View>
Teas.tsx:
<View flex={1} bg="white">
<ScrollCards teas={blackTeas} />
</View>
ScrollCards.tsx:
<ScrollView>
<Center>
{teas.length > 0 &&
teas.map((teaObj) => (
<TeaCard id={teaObj.id} teaData={teaObj.data} key={teaObj.id} />
))}
</Center>
</ScrollView>
EDIT:
Code Sandbox link: https://codesandbox.io/s/gracious-sammet-l4tqz?file=/src/App.js&resolutionWidth=402&resolutionHeight=675
Note that the admob footer remains underneath the cards content. It should be sticky and remain always at the bottom of the screen. I also noticed that when I'm not using the header from the MainStackNavigator the footer works as intended - i.e. it remains sticky at the bottom - but I don't see why using the header (AppBar) component should interfere with my footer.
The proper solution to get the result you want is to add a flexBasis to the TabView like:
<TabView
style={{ flexBasis: 0 }}
// rest of the code
/> ​
Why?
The TabView has a default style of flex: 1, overflow: 'hidden' (see source code) causing it to expanded to the size of its biggest child. The flexBasis prevents this and makes sure the tabview get the correct height.
Resource: This is a nice article about flexBasis vs width/height: https://mastery.games/post/the-difference-between-width-and-flex-basis/
Debugging styling in React-Native doesn't have the best developer experience. There are some things you can use to help you with debugging styling:
RN inspector: As Berci mentioned, React native has a dev menu where you can select "show inspector" that kinda acts like "inspect element" in a browser. It is a good tool to debug elements you can see, it also helps with debugging input/tab events.
Color: Most often I just use old fashioned colored borders & background to get a clear view of where elements are & their size/overlaps.
Comments & Simplify: Feel free to comment out components you're not interested in and replace complex components/views like ScrollCards with just a simple colored view. This can help prevent multiple behaviours from influencing the thing you're trying to debug
Browser inspect & React devtools: If you happen to run your RN app in the browser, then getting familiar with those tools will help you loads. Just keep in mind that React & React-Native isn't the same.
When you debug visuals, the best way is start at the top layer and work you way down. Color the elements & feel free to comment out elements to get you a clearer view of the problem. Keep digging down until you find the problem, don't be afraid to look into the source code of the packages you use, it often helps clarify (unexpected) behaviours.
You could try to replace
<View flex={1}> // applied a flex for the entire homepage
in Home.tsx with
<View flex="1 1 0">
Working example here (is your code with that line modified).
As for debugging I can only suggest what is already suggested on react native Debugging page. Have you tried React Developer Tools yet? In chrome you can also add it as an extension from this link.
I am not sure if there is any difference between chrome extension and the npm package but the extension was enough for me at least (for now).
The only problem is that I also struggled debugging on codesandbox since the extension is definitely not working on javascript online editors (but probably the npm package doesn't either for this specific case)
Try this - https://snack.expo.dev/fL0OgQ9uS
import React from 'react';
import { View, Image, StyleSheet,ScrollView,Text } from 'react-native';
const styles = StyleSheet.create({
container: {
paddingTop: 50,
flex:1,
backgroundColor:'aqua',
},
tinyLogo: {
width: 200,
height: 200,
},
header:{
backgroundColor:'green',
paddingBottom:20,
},
footer:{
backgroundColor:'green',
paddingTop:20,
}
});
const DisplayAnImage = () => {
return (
<View style={styles.container}>
<View style={styles.header}><Text>header</Text></View>
<ScrollView>
<Image
style={styles.tinyLogo}
source={require('#expo/snack-static/react-native-logo.png')}
/>
<Image
style={styles.tinyLogo}
source={require('#expo/snack-static/react-native-logo.png')}
/>
<Image
style={styles.tinyLogo}
source={require('#expo/snack-static/react-native-logo.png')}
/>
<Image
style={styles.tinyLogo}
source={require('#expo/snack-static/react-native-logo.png')}
/>
<Image
style={styles.tinyLogo}
source={require('#expo/snack-static/react-native-logo.png')}
/>
<Image
style={styles.tinyLogo}
source={require('#expo/snack-static/react-native-logo.png')}
/>
<Image
style={styles.tinyLogo}
source={require('#expo/snack-static/react-native-logo.png')}
/>
</ScrollView>
<View style={styles.footer}><Text>footer</Text></View>
</View>
);
}
export default DisplayAnImage;

Independent scroll time-picker on hover using react-slick

I am building a time picker using react-slick library for carousels like below:
Client asked me to have an ablity for scrolling time using mouse wheel. I managed to implement it, however when I scroll using mouse, all pickers scroll at once. The idea is to have each time picker independent scroll when hovering over them. Here is what I have so far:
My code
Can anyone assist me with that ?
2 things :
in your listener, you should use a boolean each time (if (e.target.closest('.slider1'))
you should use swiper if you need your sliders to be scrolled, it's built in. (https://swiperjs.com/react/)
Here is what you could do to allow a scroll and hide the scrollbar:
<div
style={{
overflow: 'hidden'
}}
>
<div
style={{
height: '159px',
width: '100px',
overflow: 'auto',
boxSizing: 'content-box',
paddingRight: '17px',
}}
>
<Slider
{...settings}
className='slider-entity hours'
ref={(slider) => (this.slider1 = slider)}
>
<div>12</div>
<div>13</div>
<div>14</div>
<div>15</div>
<div>16</div>
</Slider>
</div>
</div>
I added the style directly for simplicity.
Height and width are mandatory on the child for the box-sizing property to works.
I based my answer on this thread

Custom styling for MenuOption in React native popup menu

So I'm new to React (and JavaScript too for that matter). I'm creating an App using react native and currently trying to style my popup menu. (which looks like this: Popup menu image)
I want to change the style of the options (make the font size bigger and space them out and change the font color too). My code looks something like this:
<MenuProvider>
<Menu >
<MenuTrigger>
<Image
style={styles.menucontainer}
resizeMode="contain"
source={require('../assets/icon_more.png')}>
</Image>
</MenuTrigger>
<MenuOptions optionsContainerStyle={styles.optionsstyle}>
<MenuOption text= 'About' />
<MenuOption text= 'Help & Feedback'/>
<MenuOption text= 'Sign Out'/>
</MenuOptions>
</Menu>
</MenuProvider>
After checking
https://github.com/instea/react-native-popup-menu/blob/master/src/MenuOption.js
I found a prop customStyles. Just like I passed a styling object for MenuOptions as prop optionContainerStyle, I tried passing customStyles for MenuOption but that produced an error:
In this environment the sources for assign MUST be an object. This error is a performance optimization and not spec compliant.
Here is my styles code:
const styles = StyleSheet.create({
optionsstyle:{
marginTop: height*32/dev_dimension.h,
marginLeft: width*184/dev_dimension.w,
backgroundColor: '#fafafa',
width: width*168/dev_dimension.w,
height: height*160/dev_dimension.h,
flexDirection: 'row',
flex: 1,
justifyContent: 'space-between',
},
});
Can anyone tell what I'm doing wrong?
According to documentation the optionsContainerStyle are deprecated and I am not sure if they work properly. Try to use customStyles props instead as seen in StylingExample where you can find full example.
The thing is that customStyles is map of styles for different parts. Something like
<MenuOptions customStyles={{optionWrapper: { padding: 5}, optionText: styles.text}}>

React-Native - KeyboardAvoidingView - Error

I use the keyboardAvoidingView, to display inputs and used next focus. But, when i click in first input ( print label 1623 - Acidez ), this is hidden. How make show this?
<ReactNative.View key={this.state.selectedTabIndex}>
<ReactNative.ScrollView style={{ height: this.props.styles.height - 40 }}>
<ReactNative.KeyboardAvoidingView
keyboardVerticalOffset={0}
behavior="position"
contentContainerStyle={{ paddingTop: this.state.size }}
>
{this.tabs[this.state.selectedTabIndex].render()}
</ReactNative.KeyboardAvoidingView>
</ReactNative.ScrollView>
</ReactNative.View>
if you increase 'keyboardVerticalOffset' to bigger value like '100' of KeyboardAvoidingView to some bigger amount it would scroll up from keyboard thus avoiding it.I also spent much time in finding the right solution on internet but finally figure it out myself for 'react-native' version '0.50.4'.I got it working like this
<View style={…..}>
<ScrollView>
<KeyboardAvoidingView style={{ flex: 1 }}
keyboardVerticalOffset={100} behavior={"position"}>
</KeyboardAvoidingView>
</ScrollView>
</View>
keyboardVerticalOffset should be the distance between the top of the screen and the top of the KeyboardAvoidingView. If you're using flex, that number is going to be different depending on the size of the device you're viewing the app on.
The simplest approach I have found is to simply wrap the whole page with KeyboardAvoidingView. By making it your top-level wrapper, you will never have to worry about the keyboardVerticalOffset.
Experiment with the three behavior options from there until you get something that works.
What works today for me - on android - was..
<KeyboardAvoidingView
key={2}
keyboardVerticalOffset={0}
behavior={"padding"}
style={{
flex: 1,
overflow: "hidden",
height: "100%",
paddingTop: 0,
marginTop: 0,
borderTopWidth: 0,
}}
windowSize={1}
enabled
>
(...)
</KeyboardAvoidingView>

Categories

Resources