I have a custom component for Buttons using NativeBase, and it seems work great initially; once I restart the project, the default style for the button I have set no longer works. To fix this, I have to manually set a variation, and then remove it, like so :
<Button variation="random" /> // Sets the variation to something random
<Button /> // delete the variation section of button, and now the default loads
I have it set up like so:
export const style = extendTheme({
components:{
Button: {
baseStyle: {
rounded: 'lg',
},
defaultProps: {
size: 'sm',
colorScheme: 'green',
_text: {
color: 'white',
fontSize: '30px',
...fonts.h1, //custom font
margin: -2,
}
},
}
}
Then, within App.js:
const style = style // from import
return (
<NativeBaseProvider theme={style}>
<NavigationContainer>
<StackNavigator>
...etc.
)
And finally, in another file:
<Button />
Why is this occurring? I assume it has something to do with NativeBaseProvider wrapping everything in App.js, instead of just wrapping each individual file using the custom components with it.
Thanks!
Related
I was previously using Material UI's Button component, which has the disable property. Basically that prop allows the button to be disabled based on a boolean. So if true, then it is disabled. However, now I want to switch to the Material UI Link component which is also a button, but it looks like a text. It does the same thing a button does, but looks like a link. However, it does not have the disable property or it seems because I dont see it as a possible property in the Material UI docs. Is there any work around for this?
*Note - This is not from the React Router Dom library. I am using the Link from Material UI Library for React. Just so there is no confusion.
<Link
hover
underline="hover"
variant="body2"
onClick={
this.buyAll
}>
Buy All Products
</Link>
Material-UI's Link renders as an <a> element by default. If you want it to render as a <button> (which would be appropriate when you are specifying onClick and not specifying href), then you need to specify component="button". Once you have done that, the disabled prop will work as expected with the caveat that Material-UI's Link doesn't have any styling for a "disabled" look; so if you want the link to look different when it is disabled, you will need to customize the styles for that state.
Below is a working example including some sample disabled styling:
import React from "react";
import { makeStyles, withStyles } from "#material-ui/core/styles";
import MuiLink from "#material-ui/core/Link";
import Typography from "#material-ui/core/Typography";
const useStyles = makeStyles((theme) => ({
root: {
"& > * + *": {
marginLeft: theme.spacing(2)
}
}
}));
const Link = withStyles({
root: {
"&[disabled]": {
color: "grey",
cursor: "default",
"&:hover": {
textDecoration: "none"
}
}
}
})(MuiLink);
export default function Links() {
const classes = useStyles();
return (
<Typography className={classes.root}>
<Link component="button" onClick={() => console.log("hello")}>
Link
</Link>
<Link
component="button"
disabled
onClick={() =>
console.log(
"I'm disabled so this doesn't appear in the console when this is clicked."
)
}
>
Disabled Link
</Link>
</Typography>
);
}
Thank #RyanCogswell. I tried to improve his answer by defining a custom theme, based on MUI's default theme and using pointer-events: none:
import { createTheme } from '#mui/material/styles'
const { palette } = createTheme() // MUI's default theme
const theme = createTheme({ // Our app's custom theme
MuiLink: {
styleOverrides: {
root: {
'&[disabled]': {
color: palette.action.disabled,
pointerEvents: 'none',
},
},
},
},
})
import { Link } from '#mui/material'
//...
<Link
disabled
to='https://stackoverflow.com/a/72479343/5318303'
>
Disabled link
</Link>
I have an array with objects before, I applied icons from fontAwesome as a value, it looked like this
const SideBarColors = [
{
IconStyle: {
Icon: faDotCircle,
}
}
]
Then in another component I got this icon like this
<FontAwesomeIcon icon={SideBarStyle.Icon} />
Now I use a different approach (React Icons), the point is that now I create icons in this way
<BsBraces />
In this case, I cannot assign this icon inside the object as a value, it gives an error
IconStyle: {
IconTitle: <BsBraces />
}
What should I do in this case?
You just need to :
IconStyle: {
IconTitle: BsBraces
}
without the </>
Apply it to JSX like:
<IconStyles.IconTitle />
I'm using Material-UI with my React application. I'm also using styled components and I'm viewing the app in a Chrome browser. The issue I'm having doesn't occur when using a Firefox browser.
When applying the overflow attribute in my styled component, I'm seeing this blue line towards the bottom of the modal. This only appears when I'm playing with the size of my browser window. As I gradually bring my browser window closer to normal size, the line goes away. I'm not sure why this is or what I can do to fix it.
Here is a snippet of my code:
export const ScrollableModal = styled(MUIModal)(() => ({
overflow: 'scroll',
}));
const Modal = ({ title, children, actionsLeft, actionsRight, ...rest }) => {
const wrappedTitle =
typeof title === 'string' ? <Typography>{title}</Typography> : title;
return (
<ScrollableModal {...rest}>
<Container>
I've left the rest out because it's not relevant to my question.
Here is a screenshot of what I'm describing:
I guess that's the outline property what they mentioned in the documentation for simple modal:
Notice that you can disable the outline (often blue or gold) with the outline: 0 CSS property.
First needs to be added to the current style:
const useStyles = makeStyles({
modal: {
textAlign: 'center',
width: '35vw',
backgroundColor: 'white',
opacity: 0.8,
outline: 0, // add / remove
}
});
Then it can be applied on the Container just like the following in the render:
const styles = useStyles();
return <>
<Modal open={true}>
<Container className={styles.modal}>
<p>Simple Modal</p>
</Container>
</Modal>
</>
Result by adding and removing outline property with value 0:
I guess with styled components just create a styled Container with opacity: 0 if you don't want to use makeStlyes for this purpose.
That resolved the issue for me.
I hope that helps!
I'm developing a React project using the material-ui library. I'm currently trying to add a drawer which is working fine for me. However, I'm trying to change the background color of this drawer. I've heard that the way to do this is by changing the color of the drawer's paper. I've tried adding the following tag to my CSS object:
const styles = theme => ({
background:"BLUE"
Then I reference this object in my render function using the classNames library:
render(){
const { classes } = this.props;
return(
<div className={styles.root}>
<CssBaseline />
<Drawer
variant="permanent"
className={classNames(classes.drawer, {
[classes.drawerOpen]: this.state.open,
[classes.drawerClose]: !this.state.open
})}
classes = {{
paper: classNames({
background:classes.background,
[classes.drawerOpen]: this.state.open,
[classes.drawerClose]: !this.state.open
})
}}
However, when I run this on localhost, the paper is still a plain old white. Am I missing something about the classNames library or is a special case of the paper tag? Thanks in advance and let me know if I should supply more info than this.
You have a couple issues in the code shown in your question.
For your styles, you need something more like the following:
const styles = theme => ({
drawerPaper: { background: "blue" }
});
In this case, "drawerPaper" is the key for my class name and then the object to the right contains the CSS properties for that class. When passed into withStyles, this will generate CSS like the following:
<style>
.classname-generated-for-drawerPaper-key: {
background: blue;
}
</style>
You had a class name key of "background" with the string "BLUE" as the CSS properties which will end up with CSS like the following:
<style>
.classname-generated-for-background-key: {
0: B;
1: L;
2: U;
3: E;
}
</style>
which of course is not valid CSS and will have no effect on the paper.
The second issue is in how you specify the classes:
classes = {{
paper: classNames({
background:classes.background,
[classes.drawerOpen]: this.state.open,
[classes.drawerClose]: !this.state.open
})
}}
When you pass an object to classNames, the keys of the object are the class names and the associated value controls (based on whether it is falsey or truthy) whether the class name should be included. With the syntax you used, classes.background will always be truthy which means that the class "background" (rather than the generated class name in classes.background) will be included which will have no effect since a "background" class hasn't been defined.
Instead you should have:
classes = {{
paper: classNames(classes.drawerPaper, {
[classes.drawerOpen]: this.state.open,
[classes.drawerClose]: !this.state.open
})
}}
which will unconditionally include classes.drawerPaper.
Here is a modified version of one of the Drawer demos, but with the background color of the drawer changed to blue: https://codesandbox.io/s/wqlwyk7p4l
If you're using global theme = createTheme( the color of a background paper can be set as following
const theme = createTheme({
palette: {
{
primary: colors.blue,
background: {
default: colors.grey[50],
paper: colors.common.white,
},
// ...
I'm working on a React Native app and many screens has forms with text input fields.
When I press the text input, the keyboard opens. I created a floating InputAccessory component which appears at the top of the keyboard to dismiss it, with the button "Done" on it.
However now that I have this accessory, when I click an input field or press the "Next" button on the keyboard to go to the next field, the ScrollView scrolls to align the bottom of the text input with the top of the keyboard. With this floating accessory it poses problems as you can see below you can't see the content of the text input because of this accessory, and I'd like to have the scrollview scrolling a bit more to display the entire text input.
I could probably do the calculation for this and run the .scrollTo() method from the ScrollView component but this pattern is very common to my entire app and I'm looking for an elegant solution that could be generic enough every single time I import a text input and focus on it.
Do you have any suggestion?
Thanks
I got the same issue before and i have 2 different solutions , Both of them worked for me.
1- Using react-native-keyboard-aware-scroll-view , Note that this library will already contain scrollView so you remove your own scroll view and use
<KeyboardAwareScrollView>
<View>
<TextInput />
</View>
</KeyboardAwareScrollView>
You can also check documentation for more info.
This solution is easier as you don't need to handle anything by yourself, but i think you will have some issues if you want to include scrollView inside it.
2- I once created a component AvoidKeyboard that actually does something similar to your solution, but it used to translate top the whole view with the keyboard height value, this solution worked perfectly also for me.
Implementation
import React, { Component } from 'react';
import { Animated, Easing, Keyboard } from 'react-native';
import PropTypes from 'prop-types';
class AvoidKeyboard extends Component {
constructor(props) {
super(props);
this.state = {
animatedViewHeight: new Animated.Value(0),
viewHeight: 0,
};
this.setViewHeightOnce = this.setViewHeightOnce.bind(this);
this.keyboardWillShow = this.keyboardWillShow.bind(this);
this.keyboardWillHide = this.keyboardWillHide.bind(this);
this.keyboardDidShowListener = Keyboard.addListener('keyboardWillShow', this.keyboardWillShow);
this.keyboardDidHideListener = Keyboard.addListener('keyboardWillHide', this.keyboardWillHide);
}
componentWillUnmount() {
this.keyboardDidShowListener && this.keyboardDidShowListener.remove();
this.keyboardDidHideListener && this.keyboardDidHideListener.remove();
}
setViewHeightOnce(event) {
const { height } = event.nativeEvent.layout;
if (this.state.viewHeight === 0) {
const avoidPaddingBottom = 15;
this.setState({
viewHeight: height + avoidPaddingBottom,
animatedViewHeight: new Animated.Value(height + avoidPaddingBottom),
});
}
}
keyboardWillShow(e) {
const { viewHeight } = this.state;
if (viewHeight) {
requestAnimationFrame(() => { // eslint-disable-line no-undef
Animated.timing(this.state.animatedViewHeight, {
toValue: (viewHeight - e.endCoordinates.height),
duration: 200,
delay: 0,
easing: Easing.inOut(Easing.ease),
}).start();
});
}
}
keyboardWillHide() {
requestAnimationFrame(() => { // eslint-disable-line no-undef
Animated.timing(this.state.animatedViewHeight, {
toValue: this.state.viewHeight,
duration: 200,
delay: 0,
easing: Easing.inOut(Easing.ease),
}).start();
});
}
render() {
let animatedHeight;
const { viewHeight } = this.state;
if (viewHeight > 0) {
animatedHeight = { maxHeight: this.state.animatedViewHeight };
}
return (
<Animated.View
style={[{ flex: 1, justifyContent: 'flex-end' }, animatedHeight]}
onLayout={this.setViewHeightOnce}
>
{this.props.children}
</Animated.View>
);
}
}
AvoidKeyboard.propTypes = {
children: PropTypes.node.isRequired,
};
export default AvoidKeyboard;
Now you just need to wrap your component or screen inside AvoidKeyboard and your screen height will shrink once keyboard is open, and you will be able to scroll the screen
I have had a lot of problems with keyboard in IOS. No KeyboardSpacer, react-native-keyboard-aware-scroll-view and more packages solved it.
Recently I discovered react-native-keyboard-manager and it solved all my problems without one line of code, also in modals and more (I don't have nothing to do with the author, but this package saved me the day). Give it a change.
I found a solution which doesn't involve hacky animation change.
When the keyboard opens, what I decided to do is to add some margin at the bottom of the ScrollView which correspond to the height of the InputAccessory. I then remove this margin when the keyboard closes. It looks like something like this:
import KeyboardListener from 'react-native-keyboard-listener';
...
render() [
<ScrollView
key={1}
style={{ marginBottom: this.state.scrollViewMarginBottom }}
/>,
<InputAccessory key={2} onLayout={...} />,
<KeyboardListener
key={3}
onWillShow={() => this.setState({ scrollViewMarginBottom: inputAccessoryHeight });
onWillHide={() => this.setState({ scrollViewMarginBottom: 0 })
/>
]
I was facing the same issue and reading online I figured out the following solution
For Android
Go to your AndroidManifest.xml and add android:windowSoftInputMode="adjustPan"
<activity
android:name=".MainActivity"
android:windowSoftInputMode="adjustPan">
.....
</activity>
For IOS
Just follow the instructions in this repo.
https://github.com/douglasjunior/react-native-keyboard-manager.
Hope this helps. :)