FullStack Labs

Please Upgrade Your Browser.

Unfortunately, Internet Explorer is an outdated browser and we do not currently support it. To have the best browsing experience, please upgrade to Microsoft Edge, Google Chrome or Safari.
Upgrade
Welcome to FullStack Labs. We use cookies to enable better features on our website. Cookies help us tailor content to your interests and locations and provide many other benefits of the site. For more information, please see our Cookies Policy and Privacy Policy.

Creating a Box Component in React Native with Styled Systems

Written by 
,
Creating a Box Component in React Native with Styled Systems
blog post background
Recent Posts
From Recommendations to Immersive Try-Ons: AI's Role in Consumer Goods
Mastering Agile Project Management: Navigate Success with a Large Team
Driving Excellence in QA: Continuous Improvement and Postman Best Practices

Enforce consistent theme use throughout your application with a reusable Box component.

Table of contents

What is a theme?

A theme is a series of configurable design constraints such as colors, typographies, font sizes, font weights, spacing scale, etc.

Why is a theme important?

When it comes to design, consistency is key to making a final product that looks polished. Sharing the same color palette, spacing between elements, and breakpoints across all components goes a long way in creating a pleasant UI. You can, of course, achieve this without implementing a theme, but being constrained by your theme will make it harder to deviate from it. It will also make it easier to make decisions as you build. Instead of asking yourself if a support text looks better at 15px or 16px, you simply stick to your scale. In that case, it’s either a small text or a regular text. 

The Box component

The box component is the basic building block to implement our theme in our application. We can think of it as a `View` with special style props that will receive the keys on the theme object and map them to their corresponding values.

Let’s start by creating a new React Native app with expo-cli:

	
expo init BoxApp
	

Follow the instructions on your console and pick the blank template under managed workflow.

After the installation completes, switch to your project’s folder and run

	
yarn add styled-system @emotion/core @emotion/native emotion-theming
	

Now let’s add a theme file for our application:

	
/* theme.js */
export default {
 space: [0, 4, 8, 16, 32, 64, 128, 256, 512],
 fontSizes: {
   xs: 12,
   sm: 14,
   md: 16,
   lg: 24,
   xl: 32,
 },
 fontWeights: {
   body: "400",
   heading: "700",
   bold: "900",
 },
 lineHeights: {
   body: 1.5,
   heading: 1.125,
 },
 colors: {
   text: "#1F2933",
   white: "#fff",
   background: "#E4E7EB",
   primary: "#07c",
   secondary: "#30c",
   muted: "#f6f6f6",
 },
 shadows: {
   sm: {
     shadowColor: "#000",
     shadowOffset: {
       width: 0,
       height: 1,
     },
     shadowOpacity: 0.2,
     shadowRadius: 1.41,

     elevation: 2,
   },

   md: {
     shadowColor: "#000",
     shadowOffset: {
       width: 0,
       height: 2,
     },
     shadowOpacity: 0.23,
     shadowRadius: 2.62,

     elevation: 4,
   },
 },
};
	

We’ll be using the Styled System library to build our Box. Styled System provides a collection of utility functions that allows us to map styles to component properties based on a global theme object.

Let’s go ahead and create a file, system.js under src/utils to put some of the boilerplate necessary to create our components:

	
/* utils/system.js */
import {
 space,
 color,
 layout,
 flexbox,
 border,
 position,
 shadow,
 compose,
} from "styled-system";

export const viewProps = compose(
 layout,
 color,
 space,
 border,
 position,
 shadow,
 flexbox
);
	

Now we can create a Box.js file under a components directory:

-- CODE language-jsx keep-markup --
/* components/Box.js */

import
React from "react";

import
styled from "@emotion/native";

import
{ viewProps } from "../utils/system";

import
{ useTheme } from "emotion-theming";

const
StyledBox = styled.View(viewProps);

/* Since shadows in React Native consist of multiple properties,
we include this function to help us map them from one key to
multiple values. */


functionmapShadowToStyle
(key, theme) {

const
_obj = theme.shadows[key];

if
(!_obj) return {};

return
_obj;

}

exportconst
Box = React.forwardRef((props, ref) => {

const
{ shadow, style, children, ...rest } = props;

const
theme = useTheme();

const
_shadow = shadow && mapShadowToStyle(shadow, theme);

return
(

  <styledbox ref="{ref}" {...rest}="" style="{[style," {="" ..._shadow="" }]}=""></styledbox>

    {children}

  

  );

});

Box.displayName = "Box";

Great, now let’s go back to our App.js and start using our Box component. But first, we have to make sure to include a ThemeProvider so that Styled System can pull in our global theme and apply it to the Box. Once we’ve done that we can put our newly created Box component into action:

-- CODE language-jsx keep-markup --

import
{ StatusBar } from "expo-status-bar";

import
React from "react";

import
{ Text } from "react-native";

import
{ ThemeProvider } from "emotion-theming";

import
theme from "./src/theme";

import
{ Box } from "./src/components/Box";

export
default function App() {

  return (

    <themeprovider theme="{theme}"></themeprovider>

      <box flex="{1}" alignitems="center" backgroundcolor="background"></box>

        <box margintop="{6}" padding="{4}" backgroundcolor="primary" shadow="md"></box>

          <text style="{{" color:="" "white"="" }}="">Hello from a box component!</text>

        

      

      <statusbar style="auto"></statusbar>

    

  );

}

Notice that the numerical values we’re using on the margin and padding properties don’t map to pixels, but instead use the values defined previously on our space scale:  

-- CODE language-jsx keep-markup --
space: [0, 4, 8, 16, 32, 64, 128, 256, 512]

We can also make use of our color palette and reference it directly on the backgroundColor properties and even use the shadows on our theme! 

What about text?

It would certainly be nice if in the example above we could also use our theme to render the message. Since React Native requires us to place text inside Text components (unlike web browsers, where any element can have inner text), we can’t use our Box to replace Text components.

Personally, I don’t find it as useful to define a general purpose text component. Instead, I prefer defining typographic components that have a clear purpose, such as Heading, Content, etc.

Let’s look at a possible implementation for a Heading component:

-- CODE language-jsx keep-markup --

import
styled from "@emotion/native";import React from "react";

import
{
  typography,
  space,
  color,
  layout,
  flexbox,
  border,
  fontSize,
  fontWeight,
  compose,
} from "styled-system";

exportconst
textProps = compose(
  typography,
  space,
  color,
  layout,
  flexbox,
  border
);


exportconst
StyledText = styled.Text(textProps);


exportfunctionHeading
({
  color = "text",
  size = "xl",
  fontWeight = "heading",
  ...props
}) {

return
(
    
      color={color}
      fontWeight={fontWeight}
      fontSize={size}
      {...props}
    />
  );
}

Heading.displayName = "Heading";

Great, now we have a Heading with some useful defaults that we can reuse in our application. Let’s go back to our App.js and include this Heading component:

-- CODE language-jsx keep-markup --

/* App.js */


... 

<box flex="{1}" alignitems="center" backgroundcolor="background"></box>
  
<heading mt="{4}">I'm a Heading!</heading>
    
  <box margintop="{6}" padding="{4}" backgroundcolor="primary" shadow="md"></box>
    
    <text style="{{" color:="" "white"="" }}="">Hello from a box component!</text>

  


...

Going back to our app, we can see it in action:

Conclusion

These two components will give us a solid foundation to build on our theme and implement a design system throughout our application. From here, we could reuse them to implement layout primitives such as a Stack, Inline, or Grid, and typography components such as SubHeading, Content or TextLink. The theme object can also be extended with your brand colors, new shadows and much more. Hopefully you can use this foundation to create awesome components in your React Native app!

Using techniques like what is listed above, we have had the opportunity to address clients’ concerns and they love it! If you are interested in joining our team, please visit our Careers page.

Written by
People having a meeting on a glass room.
Join Our Team
We are looking for developers committed to writing the best code and deploying flawless apps in a small team setting.
view careers
Desktop screens shown as slices from a top angle.
Case Studies
It's not only about results, it's also about how we helped our clients get there and achieve their goals.
view case studies
Phone with an app screen on it.
Our Playbook
Our step-by-step process for designing, developing, and maintaining exceptional custom software solutions.
VIEW OUR playbook
FullStack Labs Icon

Let's Talk!

We’d love to learn more about your project.
Engagements start at $75,000.

company name
name
email
phone
Type of project
How did you hear about us?
Thank you! Your submission has been received!
Oops! Something went wrong while submitting the form.