NativeBase: How to set colorScheme of Input? - react-native

I want to change the colorScheme of a NativeBase Input component.
Other components, like button, slider or checkbox, have a prop "colorScheme" which, if set, changes all the associated colors of that component. Input does not have that prop.
These approaches would technically work:
Setting colors for border, background etc. manually
-> But it would be a lot or work and pretty ugly
Changing the primary color in the theme
-> But maybe I want to have two different color schemes for Input on the same page, so it would not make sense to change the theme.
So, what is the best way to easily change all the associated colors of an Input component, without setting all colors manually or changing the overall theme?

I've never used NativeBase ( but now I'll take a look, thanks for this discovery... )
I highly recommend you to have a read at the Customizing Components doc which provide a way to do what you're looking for...
You can create a "variant" which is a predefined theme for a specific component. You have to define it in your customized theme ( If you don't use a <NativeBaseProvider theme={theme} /> yet check this )
export default function () {
const theme = extendTheme({
components: {
Input: {
variants: {
otherColorInput: ({ colorScheme }) => {
return {
bg: /*otherColorToSet*/ ,
};
},
},
},
},
});
return (
<NativeBaseProvider theme={theme}>{/* components */}</NativeBaseProvider>
);
};
Then you can call you new Input like this :
<Input variant="otherColorInput">

Related

React Native - What's the best way to provide a global theme?

I've started using RN recently and have been doing some research on the implementation of themes and/or a dark-light mode. Here's roughly how I understand the two main options so far:
Context: Easy setup and can be accessed via hook inside the component that needs it. I count things like the React Navigation themes since that works, in essence, the same way(?)
Styled Components: Essentially just replacing the components with custom ones that access the current theme and that can then be set up to change their props on toggle if needed.
What I don't like about context, is that (the way I understand it) it wouldn't let me access the theme when using a StyleSheet, since that's outside the component. With the styled components on the other hands I'm not sure if I can cover all options inside my custom components, wouldn't I still need some sort of hook in each component anyway?
I was also thinking about just saving the current theme into my Store (in my case Zustand), together with an action that lets me toggle to a dark-mode. But so far, I haven't really seen anyone else do that, is there a downside to doing it that way?
It's not hard to pass context to your stylesheet, it just requires a bit of extra boilerplate. Something like the below:
import ThemeContext from '<path>';
export default () => {
const theme = useContext(ThemeContext);
const stylesWithTheme = styles(theme);
return <Text style={stylesWithTheme.text>Hi</Text>;
}
const styles = theme => StyleSheet.create({
text: {
color: themeStyles.color[theme];
}
});
const themeStyles = {
color: {
dark: '#FFF',
light: '#000',
},
};
I don't think using styled components would be a big departure from the above scheme.
If you did store your theme in state, and define your styles within the body of the component, that could be a savings in boilerplate. It's up to you whether having your styles in the component body is acceptable.
Side note, if you're already using a state manager, I would recommend not mixing it with the Context API without knowing more. It's simpler to have one solution there.

Set alternative palette to default theme in native base

I want to set a default theme in Native Base, and have seen a lot of links to official customisation docs and the nativebase customiser. But they're all dead.
Native Base already provides a default theme with a bunch of colours. When you launch an app, by default it seems to have the cyan colour palette. All I want to do is switch from cyan to one of their other colour swatches, so that by default all the colours come from, say, amber.
I know there's the option to set default colours with extendTheme -- is that the only option? Extend the theme and manually add in all the hex codes I want? Or can I just set the theme to amber somewhere and all the colours will be applied?
I had the same issue i wanted to be able to create a primary theme colors and switch the theme without typing out all the colors so far this solution is working for me to select colors from the existing default theme.
const {colors} = extendTheme(colors);
const currentColor = colors.green;
const theme = extendTheme({
colors: {
// Add new color
primary: currentColor,
},
config: {
// Changing initialColorMode to 'dark
useSystemColorMode: false,
initialColorMode: 'dark',
},
});
export default function App() {
return (
<NativeBaseProvider theme={theme}>
<NavigationContainer>
<App />
</NavigationContainer>
</NativeBaseProvider>
);
}

How to conditionally change a color of a row in detailslist?

I'm looking at customitemrows but there isn't much documentation.
I have a table and if a row was created by a current user, I want to change the color from black to grey. I can do that with style. I understand how to conditionally change color in customitemcolumns but can't extrapolate it to rows.
I got to:
_onRenderRow = (props) => {
return props.item['creatorUid'].match("QDN6k4pLXkea2qRM9mS7vM6whBE3")?
<DetailsRow {...props} style={{color:"#FF0000"}}/>
:
<DetailsRow {...props}/>
}
but the color doesn't change
<DetailsList
items={ items }
columns={ columns }
onRenderRow={ (props, defaultRender) => (
<div className='red'>
{defaultRender({...props, className: 'red'})}
</div>
) }
/>
<DetailsList
items={ items }
columns={ columns }
onRenderRow={ (props, defaultRender) => (
<div className='red'>
{defaultRender({...props, styles: {root: {background: 'red'}}})}
</div>
) }
/>
https://codepen.io/vitalius1/pen/pQmpVO
Here you can see 2 methods achieve what you ask for.
First is passing a regular className and have it override the default styles. If you need to override the hover states or anything else you would have to inspect in dev tools and target the appropriate classes.
Second is what is actually recommended and used internally to apply the default styles. With this method when you want to override the hover states or anything else, you would need to provide styles to each style area (in the example root is one of them). For a list of style areas available to each row follow this link. For an example on usage of the selectors for hover states follow this link.
Note: With the second method you can also pass a style function to make use of the IDetailsRowStyleProps as seen here. This way you can have a very dynamic style depending on the state of the component

React Select 2 - Portal menu positioning

Is it possible to take control of React-Select 2's menu positioning? I'm using it inside React Virtualized table rows but then I'm rendering the dropdown to a portal outside of the row. I have set menuPosition to fixed but React-Select 2 has delayed automatic positioning which is far too slow, so I would like to take control of the positioning myself.
You can override the Components styles by adding a styles prop to your Select, targeting the component. React-Select uses emotionCSS for styling, rather than classes, so it can key off of state changes.
const styles = {
menuPortal: (base, state) => {
let overrideProps = {};
// do something here
return Object.assign(base, overrideProps);
}
};
<Select styles={styles} />
You can find additional info in the Styles section of the documentation.

How to implement a user selectable theme / style in react native?

If user has selected light-theme, and switches to dark-theme, then all scenes will immediately render to using the dark-theme.
I am using react-native-router-flux if this helps.
Thanks in advance,
Different approaches are possible. One of them is to use React context. Generally it should be used with caution but theming is one of the official examples where it is suitable.
Theming is a good example of when you might want an entire subtree to have access to some piece of information
So the example might look like
class App extends Component {
getChildContext() {
return {theme: { primaryColor: "purple" }};
}
...
}
App.childContextTypes = {
theme: React.PropTypes.object
};
where you set the context for rest of your application and then you use it in your components
class Button extends Component {
render() {
return <TouchableHighlight underlayColor={this.context.theme.primaryColor}>...
}
}
Button.contextTypes = {
theme: React.PropTypes.object
};
If you want to switch theme, you can set context based on your state/props that can be based on user selection.
Currently we are dealing with same questions and therefore we have starting prototyping library called react-native-themeable.
The idea is to use context to store theme and (re)implement RN components so they can replace original components but supports theming.
Example of theme switching you can find in https://github.com/instea/react-native-themeable/blob/master/examples/src/SwitchTheme.js
You can start by creating one JS file containing two objects that have the colors for each theme. Then just use one as a default and if the user picks another theme save it in the database or using local storage and pull the relevant object.
export const theme1 = {
blue: '#fddd',
red: '#ddddd',
buttonColor: '#fff'
}
export const theme2 = {
blue: '#fddd',
red: '#ddddd'
buttonColor: '#fff'
}
Then just import the relevant file:
import * as themes from 'Themes'
const currentTheme = this.props.currentTheme ? this.props.currentTheme : 'theme1'
const styles = StyleSheet.create({
button: {
color: themes[currentTheme].buttonColor
},
})
Wouldn’t it be great if you could import a colors object directly, and modify the object every time you change the theme and have those new colors propagate to the entire app? Then your components wouldn’t need to have any special theme logic. I was able to achieve this using a combination of AsyncStorage, forced app restart, and async module loading.