Write your own flexible custom border image component in react native

After talking about my Box component in previous articles, I was asked repeatedly to make a quick writeup about how I built it. In the end, the setup for using it isn’t quite as simple as I thought it might turn out when I started this project.

As you can’t simply use 9-Patch images / capInsets for this kind of flexibility when using custom and complex border frame images, a lot of styles and stuff is needed to get it working. Maybe going through the process of designing this component makes it a bit clearer how to use it.

If you want to code along, you can either clone/download my expo-playground project from GitHub at this tag or start a new project from scratch.

My code examples will be based on the expo-playground so you might need to download a few image files from my project or create your own.

Creating a new Box component: step 1

We’ll also add a few base styles to make the Box outlines visible and test our setup. Pass down the children nodes as a prop and we’re done here.

If you run npm start now and open the project on your emulator or test device, you’ll see our simple Box with black border, white background and our child text component.

made box styleable via setup

Inside our component, we add the new prop to the prop-types and grab its attributes via destructuring. By replacing those with a default value added by a logical OR we can update our component styles accordingly.

I’ve added a defaultSetup via Box.defaultProps in case the setup prop is missing when Box is used.

added 4 sides and 4 corners to our component with temp styles

We are going to map over our array of cardinal directions and as we’re going to need the name and object of each, I’m adding an id attribute to each, containing the name of the object as a string.

There are two alternatives to including those id attributes. We could iterate over an array of strings instead of objects and then map them to the object in question but I’m not a big fan of eval() and it’s newer alternative, not even hidden deep within my own code with no possible harmful user input anywhere near it. Alternatively, we could keep our object array and get the key names of our key/value pairs but in the end it’s much more easy, faster and especially more readable if you simply include and use the name of the object as a string in this case.

added base styles for sides and corners and location-based variations

Don’t forget to replace our temp styles with the styles of our respective cardinal element.

changed logical OR to nullish coalescing operator

As this is only included in ES2020, make sure to check your Babel (or Metro or any other transpiler you might be using) to know and understand ES2020.

As you can see, our background is now bleeding out and visible on all sides even beyond our frame’s borders. Let’s fix that.

added custom offset to second example in code

added optional default offset based on border width

This way user styles will win but if missing, our component will default to the known border thickness.

added background images for border tiles

For this step, you need to grab the demoFrameFubar assets from my project here. If you follow that link, you should find a folder with 8 images and an index.js file. Take all of those including the index file and save them in your own asset folder in the project. We won’t be using the index file right now but it will be useful later on.

Import all images from the assets and use the cardinal directions again when naming the imported files.

While we’re at it, let’s update the setupSimple AND setupOffset with our newly imported images and new dimensions. Quick tip, both are identical, so copy n paste to save some time here.

Ain’t that pretty? … you gotta love programmers art!

switched out inline config for border images to imported one

Kick out all those cardinal direction attributes and image imports and replace them by importing the index file from the asset folder and spread it into our setups.

I cut off this one, it’s repetitive… don’t forget the setupOffset!

added new example and scale option

We’ll start with the comic one for now and I’ll explain why in a moment. Also for now only change one of our two boxes to use the new assets while the other one should continue to use the old Fubar frame.

If you hit save and preview the result… rest assured that it is not entirely your fault that your screen might look like a jumbled mess of sprites right now. When we imported our new frame images, we didn’t check the size and apparently the comic frame is much larger. We can’t use it like this but maybe we can scale it down a bit. If you were perceptive enough you might have spotted the “scale: 0.2" line in our last step. Currently, this doesn’t do anything so let’s go back to our component and add an option to scale things down (or up) as defined in our setup.

added 2 scaled examples of warning frame with offset

As you can see, in our last example the E and W sides are inset a bit and the N and S borders stretch to the very end of our frame. Our corner pieces are partly transparent and only add a boundary and some grunge to our top and bottom warning bars.

You can find the finished code on GitHub. I’ve created a tag for this tutorial here: expo-playground v1.1 Finished Box tutorial

This setup is quite powerful as it allows us to use lots of variations with different combinations. If you add a few decorations on top and a nice background, you can create lots of beautiful Boxes.

Working with the Box in projects

If you want to use the box or one of my other reusable components in your projects, I’m currently finalising the first release of my rn-gui framework and over the next couple of weeks, I’m gonna add more of my home brewed elements to the framework, one piece at a time, as I still need to add tests, documentation and such before I release them as production-ready to the public. I will set up a GitHub page providing an overview of planned and implemented features and solutions and if you are a patreon of mine, you can even vote on the priority of the planned components or add suggestions to the backlog.

Some words about me:

And if you feel really supportive right now, you can always support me on patreon, thus allowing me to continue to write tutorials and offer support in the comments section.

I’m a Web / App Developer & father 👨‍👩‍👧 doing freelance and part-time agency work since 2003, 💻 building stuff on the side 🕹 and attending conferences 🎟