How to customize material design theme in React Native using Paper?

Total
0
Shares

React-native-paper provides a default theme which is used automatically. But if you want to customize that, then you need to provide theme prop in <provider> component. This prop holds the custom theme. Use it like this –

import * as React from 'react';
import { DefaultTheme, Provider as PaperProvider } from 'react-native-paper';
import App from './src/App';

const theme = {
  ...DefaultTheme,
};

export default function Main() {
  return (
    <PaperProvider theme={theme}>
      <App />
    </PaperProvider>
  );
}

In the above code snippet we have used theme prop in <PaperProvider> component. This prop holds theme object which we have declared in line 5. For this example we are using the default theme without any customization.

When we need to do the customization, we do that in theme object. For example, changing colors, fonts, typography etc.

What is PaperProvider?

PaperProvider is nothing but an alias of Provider component of react-native-paper. We are using this name because if you use Redux then it also has a component with name Provider and same names will clash.

To customize the theme, we change theme object like this –

const theme = {
  ...DefaultTheme,
  roundness: 2,
  colors: {
    ...DefaultTheme.colors,
    primary: '#3498db',
    accent: '#f1c40f',
  },
};

You can see that we are including the whole DefaultTheme first. This is because we need to provide all the theme properties in this object. First we included all of them by spreading DefaultTheme and then change the properties we need to customize, like roundness or colors.

What properties can we customize in the theme?

Here is the list of properties that we can customize –

const theme = {
  dark: true, 
          // Set dark theme
  mode: 'adaptive' | 'exact',
          // adaptive - According to material guidelines
          // exact - According to your custom theme
  roundness: 3, 
          // roundness of components like buttons
  colors: {
     primary: '#FF0000',
     accent: '#FFFF00',
     background: '#FFFFFF',
     surface: '#EEEEEE',
     text: '#000000',
     disabled: '#aaaaaa',
     placeholder: '#cccccc',
     backdrop: '#333333',
          // backdrop means the modal overlay
     onSurface: '#111111',
          // background color of snackbars
     notification: '#aa0000',
          // background color of badge
  },
  fonts: {
     regular: 'Open Sans',
     medium: 'Open Sans',
     light: 'Open Sans',
     thin: 'Open Sans',
  },
  animation: {
     scale: 2,
          // Scale for animations
  }
}

Can we add a self defined property in theme object?

Yes. We can add a user defined property in theme object. Like this –

const theme = {
    ...DefaultTheme,
    // 👇 A custom property 
    myCustomFlag: true,

    colors: {
        ...DefaultTheme.colors,
        // 👇 Nested custom property
        myCustomColor: '#123456',
    }
}

In the above code we are setting two self defined custom properties – theme.myCustomFlag and theme.colors.myCustomColor.

How to access theme properties throughout the application code?

React-native-paper provides a hook – useTheme(). In any component we can get the theme object using this hook. Like this –

import * as React from 'react';
import { useTheme } from 'react-native-paper';

function MyComponent(props) {
  const { colors } = useTheme();
  return <Text style={{ 
            color: colors.primary 
         }}>Yo!</Text>;
}

This way, you can access your self defined custom properties too.

Can we apply custom theme to a single component?

Sure we can. Every component holds theme prop where we can pass the customized theme. Check the below code –

import * as React from 'react';
import { Button } from 'react-native-paper';

export default function FancyButton(props) {
  return <Button theme={{ 
             roundness: 3,
             fonts: { medium: 'Open Sans' } 
          }} {...props} />;
}

From the above code you can see that we have changed the theme properties in Button component. This won’t change the other Buttons in the app but only FancyButton.

Why we didn’t pass complete theme?

If you remember, we said that we need to provide all the theme properties but in above code we only provided roundness and fonts properties. This is because react-native-paper merge the application theme and these properties and then pass to the component.