Creating circular menus with react-planet

innFactory GmbH
5 min readMay 3, 2020

Today we are happy to introduce a new open source library for react that allows you to build circular menus in a very easy and handy way.

The highly customizable lib can be found here: https://github.com/innFactory/react-planet

Live-Demo: https://innfactory.github.io/react-planet

In the following article we will show you some examples and give you an overview of the possibilities and functionalities of react-planet.

The concept

The name “planet” let you think about things like orbit or satellites. So with this naming the concept is very easy to understand. In the middle we always have a planet. The planet is the base component of the lib. It has a various amount of satellites around which you can pass as react children. The satellites stick to one orbit which can be hidden. If a planet switches from state close to open, the orbit and the satellites fly out to the given radius.

Install the npm package and add it to your project

Just install react-planet with the following line. Type this into your terminal while you are in your project folder:

npm install — save react-planet

Basic Example

The following example is made with just a few lines of code. The planet component can take any divs as children and render it as satellites. The planet component is defined with the centerComponent. With the prop autoclose the planet handles the open state by itself. Alternatively, you can handle the open state from outside with the open, onClick and onClose props.

import { Planet } from 'react-planet';export function MyPlanet() {    return (        <Planet centerContent={            <div                style={{                    height: 100,                    width: 100,                    borderRadius: '50%',                    backgroundColor: '#1da8a4',            }}/>}            open            autoClose        >            <div                style={{                    height: 70,                    width: 70,                    borderRadius: '50%',                    backgroundColor: '#9257ad',                }}
/>
<div style={{ height: 70, width: 70, borderRadius: '50%', backgroundColor: '#9257ad',
}}
/> </Planet> );}

Change the orbit

With the props orbitRadius you can change how far the satellites can fly out. If you also set a rotation angle the satellites will have a different position.

<Planet centerContent={div style={...yourStlye}/>}
open
orbitRadius={120}
rotation={30}
>

You also can hide the orbit with the hideOrbit boolean prop. But now we will look how a custom orbit is made. With the prop orbitStyle you can set a function which receives the default orbit style. This default style can be overwritten partially or replaced completely. In the following example we override some css styles. Btw if you want to have more satellites you only have to add some more div to the planet’s children.

<Planet
orbitStyle={defaultStyle => ({
...defaultStyle,
borderWidth: 4,
borderStyle: 'dashed',
borderColor: '#6f03fc',
})}
centerContent={<div className={classes.planetSmall} />}
open
>
<div className={classes.satellite1} />
<div className={classes.satellite2} />
<div className={classes.satellite3} />
</Planet>

Weird satellites and their orientation

If you have made some very special shapes for the satellites you may want to keep the angle where a satellite is placed and rotate it. For this case you can set the rotation behavior with the satelliteOrientation prop to “DEFAULT”, “INSIDE”, “OUTSIDE” or “READABLE”. The last one is a mix between inside and outside. The top satellites are turned inside and the bottom ones are turned outside so it’s comfortable to read the text on it.

<Planet
// set one of the orientations
satelliteOrientation="INSIDE"

Bring it to life

You can give the planet a little organic behavior if you set the satellites or the planet dragable. There is always a combination of the prop dragablePlanet and dragRadiusPlanet (dragableSatellites and dragRadiusSatellites) where you can set the drag ability and with the radius the intensity. In addition the planet will bounce on open state changes if the prop bounce is set.

<Planet
dragablePlanet
dragRadiusPlanet={20}
bounce

Planetception

Theoretically you could build a whole file explorer with react-planet. You can nest a planet into a planet, into a planet and into a planet… So a planet can also be a satellite. This brings us to following example which shows some kind of submenu.

Fake the space

If you plan to make half things only you can add some empty divs to your planet. Invisible divs takes the same space as the visible ones. Combine this behavior with the rotation prop and you get something like the following example:

<Planet
centerContent={<YourButton0 />}
hideOrbit
autoClose
orbitRadius={60}
bounceOnClose
rotation={105}
// the bounce direction is minimal visible
// but on close it seems the button wobbling a bit to the bottom
bounceDirection="BOTTOM"
>
<YourButton1 />
<YourButton2 />
<YourButton3 />
<div />
<div />
<div />
<div />
</Planet>

Alter the physics

We have seen the we could change the drag and bounce by the specific radius. The open and close mechanism could be altered by setting different physic values. The library behind the animation is react-spring (which has an awesome hook api). We exposed the values of the react-spring animation to the planet so you can change it by yourself:

<Planet
mass={4}
tension={500}
friction={19}

Summary

To the code: https://github.com/innFactory/react-planet

Live-Demo: https://innfactory.github.io/react-planet

--

--

innFactory GmbH

Software & Cloud Engineering Experts based in Rosenheim | Germany — We blog about: Scala, TypeScript, Dart, akka, play, react, flutter, gce, aws, azure, cloud..