TouchableOpacity breaks styling - reactjs

I'm attempting to create navigation in React Native. I've made a custom component that consists of an image and some text. Before applying TouchableOpacity the styling works fine. But after I apply it to one of the components, this happens.
All of the code can be found here, ready to run.
I'd like that the component titles MojQR doesn't deform, but stays like the rest of them. Currently, as seen in the code, the TouchableOpacity is only applied to MojQR

You have a problem with the styling you are using. When you set the dimensions (width, height) to take a percentage, it will take the percentage from the component that is wrapping it. That's why when you added TouchableOpacity it mess all the styling. You have 2 options, change the styling pattern you are using or make a simple change that can change the width dynamically from MenuItem like so:
//App.js
<TouchableOpacity style={styles.touchableContainer} onPress={() => navigation.navigate('Details')}>
<MenuItem itemImage={require('./app/img/QR_code_for_mobile_English_Wikipedia.svg.png')} children='Moj QR' isWrapped={true} />
</TouchableOpacity>
...
//And the styling inside your style object
touchableContainer: {
width: '50%'
}
In the code above, you add that prop that will be used to change the styles in
//MenuItem.js
//change the wrapper for this one:
<View style={this.props.isWrapped ? {...styles.menuItem, width: '100%'} : styles.menuItem}>
...
//And add the flexGrow property to your styles.menuItem
menuItem: {
width: '50%',
height: '33.3333%',
padding: 10,
flexGrow: 1,
},

Related

How to merge styles defined in defaultProps with inline styles in React Native?

I have to define some default styling on the Text component provided by React. I am doing this like:
#ts-ignore
Text.defaultProps.style = {fontWeight: '100'}
I have to define some other styling on the Text component which is specific to where the Text component is used. But when I try to provide style in Text component using inline style, it seems to override the defaultProps.style that I had.
<Text style={{color: 'white'}}> // this text only has white color but not fontWeight that was defined in defaultProps.
Is there a way to merge both of them while using the Text component provided by react?
I have tried the following:
<Text style={{...this.props.style, color:'white'}}>
I have also tried this:
<Text style={[this.props.style, {color:'white'}]} >
Both of these don't seem to work.
The styles are getting overwritten because the defaults are not merged with styles. If no styles are passed in, the default will be used, but if you pass in any styles, the default object is overwritten with the new style object.
Generally I would discourage you from setting default props on a built-in component. It can make the code hard to follow, and it's not helping you in the way you want. Besides, React was built for this. Here's a Typescript example:
interface Props {
style?: StyleProp<TextStyle>;
children?: string;
}
const defaultStyle = StyleSheet.create({
default: {
color: 'black',
}
});
const MyText: React.FC<Props> = ({ style, children }) => {
return <Text style={[ defaultStyles.default, style ]}>{children}</Text>
}
When you put styles into an array as above, they will get progressively merged from beginning to end. So if you write
<MyText style={{ color: 'white' }}>Text</MyText>
the prop style will overwrite the color in your default style. However, if you do
<MyText style={{ textDecoration: 'underline' }}>Text</MyText>
the final stylesheet will be merged, and have both the color and textDecoration properties. See the docs for more.

How to set material ui datagrid column sort icon as always be visible?

Here is codesandbox. I am trying to have the ability to sort by the first name and last name The default Datagrid only shows the sort icon when hovering. Is there a way I can set it to be always visible? Thanks for the help!
you can use .MuiDataGrid-iconButtonContainer. however Material-UI doesn't provided default icon for unsorted list. I have forked your demo and updated it. added icon for unsorted list too. please check codesandbox
This is what I did:
const StyledDataGrid = styled(DataGrid)(() => ({
'& .MuiDataGrid-iconButtonContainer': {
marginLeft: '2px',
visibility: 'visible !important',
width: 'auto !important',
},
}))
I created a styled component which adds some custom styling to DataGrid. Specifically to always show the icon and take up width for it. Using !important is not recommended, but doesn't harm in this case.
I must add, this only works with using custom sort icons, like so:
<StyledDataGrid
components={{
ColumnSortedAscendingIcon,
ColumnSortedDescendingIcon,
ColumnUnsortedIcon,
}}
/>
If you don't want to use custom icons, I'm sure it's doable, you just need to play with CSS bit more.
Add the below code in .scss file. (.MuiDataGrid-sortIcon is pre-defined class of Mui Datagrid). Hope it helps!
.MuiDataGrid-sortIcon {
opacity: inherit !important;
}
You can use the sx prop in DataGrid like so:
<DataGrid
sx={{
'.MuiDataGrid-iconButtonContainer': {
visibility: 'visible',
},
'.MuiDataGrid-sortIcon': {
opacity: 'inherit !important',
},
}}
In my case, I had to style both the iconButtonContainer and sortIcon make sure it's always visible.

Adding touchableOpacity to an Image component

Simple question: How do I add a TouchableOpacity component to an image? This is the way I'm doing it:
<View style = { styles.categoryContainer }>
<TouchableOpacity
onPress = {() => navigation.navigate('xScreen')}
>
<Image
style = {styles.categoriesImages}
source = {require('./img/xImage.png')}
/>
</TouchableOpacity>
These are the styles that are mapped to the components:
categoryContainer: {
flex: 1,
flexDirection: 'column',
margin: 10,
},
categoriesImages: {
display: 'flex',
height: 70,
width: 70
},
When I run the app on expo, the image simply disappears. Removing the TouchableOpacity component brings the image back.
Maybe someone can provide an explanation as to why this doesn't work? Thanks a lot!
I'm just assuming this is the problem, but without the styles it's a bit hard to really know.
Basically your Image must have a width and height in percentage, and you wrapped the image with TouchableOpacity, which doesn't have "size". So you have two ways to solve your issue:
You map a style to TouchableOpacity with the width and height of your
styles.categoriesImages and the Image will simply have 100% on both
width and height
Define a width and height for the image that's not a percentage but an actual value, and the TouchableOpacity will simply adapt to it's content size

Material-UI Drawer: How to position drawer in a specific div

I am using Material-UI React Drawer. Is there a way I can have the drawer confined to a specific section of my page instead of occupying the entire window? I have tried giving the root component an absolute position instead of fixed but this does not change the placement of the drawer.
<div className="confirmation-drawer">
<Drawer
anchor="top"
open={state.top}
onClose={toggleDrawer('top', false)}>
<!-- Drawer content goes here -->
</Drawer>
</div>
I need the drawer inside the .confirmation-drawer div and not the entire page. Any help would be highly appreciated.
The code below worked for me. It uses the preferred one-off styling method in the MUI docs. Transitions work without any additional tweaks. Of course make sure you have a 'relative' element up in the DOM tree.
<Drawer
sx={{
'& .MuiDrawer-root': {
position: 'absolute'
},
'& .MuiPaper-root': {
position: 'absolute'
},
}}
>
</Drawer>
what #Jon Deavers said is true, though there is a workaround. you can find the z-index of the drawer overlay (1300 in may case) and set a higher z-index to the component you wish to be on top. then just set paddings inside the drawer so all it's content is visible.
as i said its merely a workaround but i hope it helps somebody.
try this:
import {styled, Drawer as MuiDrawer} from '#mui/material'
const Drawer = styled(MuiDrawer)({
position: "relative", //imp
width: 240, //drawer width
"& .MuiDrawer-paper": {
width: 240, //drawer width
position: "absolute", //imp
transition: "none !important"
}
})
If you want transitions then use collapse.
<Collapse orientation='horizontal' in={open} >
<Box> ... </Box>
</Collapse>
The Drawer component is a nav menu component that is designed to overlay the application and not to be nested inside a container. It will always appear over your other content.
If you are looking to have a dynamic element in which you can hide information and other interactive components you may want to take a look at the Accordion component from MUI.
https://material-ui.com/api/accordion/
That will allow you to have a small "drawer"-like element that other components can be hidden inside of.

Is there a way to wrap background color around text in react-native?

Currently, this is what I am trying to avoid. As you can see the background color runs until the end of the width. It would be nice for the background color to surround the text.
I looked a tons of examples and I don't really see where they wrap background color around the text itself
<Text style={{backgroundColor:'blue'}}> TTeexxtt </Text>
I tried with flexWrap and it doesn't work just like so
<Text style={{backgroundColor:'blue', flexWrap:'wrap'}}> TTeexxtt </Text>
As always, thank you
Views in react native default to an alignItems prop of stretch. What does this mean though?
All children of your view will stretch to fill the width of their parent, with considerations for margin.
If you set the alignItems property of your parent view to something other than stretch, such as center, flex-start, or flex-end you will see the background color only extend around your actual text.
You can also use alignSelf on your Text views to adjust individual items.
Here is an example snack
https://snack.expo.io/#ajthyng/vengeful-celery
import * as React from 'react';
import { Text, View, StyleSheet } from 'react-native';
const BGText = props => {
const { background } = props;
return <Text style={{backgroundColor: background, ...props.style}}>{props.children}</Text>;
}
export default class App extends React.Component {
render() {
return (
<View style={{flex: 1, backgroundColor: 'white', alignItems: 'stretch', marginTop: 23}}>
<BGText background='pink' style={{marginRight: 16}}>I am some text</BGText>
<BGText background='orange' style={{alignSelf: 'flex-start', marginLeft: 16}} >My BG Color is short</BGText>
</View>
);
}
}

Resources