Goal
I want to create a Fibonacci grid pattern component in React that can the user can use and add elements to in any orientation.
React Component ⚛️
I started by creating a React Component called /code FibonacciGrid, and then added a couple of states.
- Orientation is an enum that is either horizontal or vertical.
- nBoxes for specifying the number of boxes/elements in the grid (It should be a multiple of 3)
- elementResolution which holds the width and height of the grid specified by the user.
Grid vs Flex Layouts
Grid layout was my initial choice when I got started with this as it’s called FibonacciGrid after all and a grid looks like it’ll be the obvious choice right? … well wrong because for the design that I made, I only needed to worry about 3 elements (Probably could’ve been done easily by grid but I already did something like it with flex and I love ❤️ flex. So flex is a go; here’s the orientation that I’m aiming for:
I’m going to nest this layout in itself as you can see here:
You can see how it keeps nesting a new FibView, yeah I’m calling that now. Getting back to what's at hand, if the user sets the number of views/boxes to more than 3 then we’ll have to nest another view and repeat the process.
Design
I made this
Orientation Wars
Making the view have one behavior is simple enough, but now I need to make it dynamic.
I set up a lot of variables and this function changes the variables on orientation change….
And it worked, for the horizontal view, but not for the Vertical (as expected 🤪).
Here’s how it looked:
and that's even after I applied a little bit of React Wizardry.
if so then add it to the bottom of the flex row direction, ah yeah I did that too, now I change the flex-direction depending on the orientation.
Need to fix the vertical orientation issue
OMG!!! So I was adding the 1 view to the same flex that contains the other two views, so I ended up with the 3 views with a 37% height and that was the issue.
Reverse/Flip Orientations
Vertical reverse and horizontal reverse,
The end result should be like the one on the figure on the left, after changing a few things I set up the view to change the size to a fixed width and height based on its orientation.
For some reason, I got the following figures on the right, not the same but close. Now starts the game of trial and error.
HorizontalReverse
That was an easy one, I just needed to add one line to the condition that adds the large view to the end.
{(orientation === OrientationEnum.vertical ||
orientation === OrientationEnum.horizontalReverse) && (
<div
onto the next one…
VerticalReverse
Now
Orientation Expansion
So as I was figuring out what to do I noticed that I missed a couple of orientations 4 to be exact. I was contemplating whether to implement them now or not as they’ll add an extra level of complexity, knowing me I just had to do it. This btw was a side project of a side project soooooo… let’s get into it.
I went and added the extra orientations and worked out a nifty new way to figure it all out.
Flip (the nifty way)
Now it’s getting complicated, but don’t worry I think I figured a way to simplify things.
I added a new variable flip which will just vertically flip all of the original 4 orientations, you can ask me why don’t I make flip-horizontal and flip-vertical, and to that, I say shhhh, not now but that is the future plan. (Something for another day).
I leave this here as there is something more important that I need to do.
Important Change
As of now most of the views are working well, I thought there should be some style added to them.
I went and downloaded a couple of beautiful images from Unsplash from these amazing artists, check their work in the links below.
Photos by Freguesia de Estrela on Unsplash
Photo by Milad Fakurian on Unsplash
Photo by Daniel J. SchwarzHire on
Photo by Marek Piwnicki on Unsplash
OK, let’s address the elephant in the room (🦣 me) not you 🐘 yeah you, seriously though we need to now add children to the FibView. I’m now faced with a choice either to implement adding children to the view which is the whole point of this or add the images in the fibview itself, hmmmm.. Well as you know by now I usually take the harder route and give up midway, but that’s what what we’re gonna do right now.
So as I never did this before I jumped into React’s docs and I think it’s gonna be something like this
<FibView>
<img src="1.png"></img>
<img src="2.png"></img>
<img src="3.png"></img>
<img src="4.png"></img>
<img src="5.png"></img>
</FibView>
Then in the view we’ll get the children just like what we do with ContextProviders, so something like this
SomeContextProvider(props: PropsWithChildren) {
...
{props.children}
...
}
And after a little digging, it is actually the way, you gotta love modular systems.
I added the children to my view like so
export default function FibonacciView({
_orientation, children
}: PropsWithChildren<FibonacciViewProps>)
However, now I have an issue, I need to add the children to different parts of the view, then I need to use an array of children which thankfully react got us covered on that by using 'Children.toArray(children)` .
After that, I styled the images to fill the view they’re assigned to, and then onto the assigning children to their views, then recursion which I’m trying not to think about right now. 🙆♂️
The above are the 4 main orientations, I got distracted by this and didn’t do the flip. I should also have a gap setup for the view and restrict the number of children based on the total view height, but these are problems for another day and hopefully 🙏 I’ll be adding them as the days go by.
Back to Flip or BackFlip
I’m sorry 🥲
Flip horizontal
Flip horizontal Reverse
I had to fix the Horizontal reverse as it was actually flip in the original view. To be honest, the code is getting more complicated, but my concern is not the complexity, it’s the readability of it and for that, I’m going to create a new /(Link to section)structure to further modularize the views.
Flip Vertical
Now I’m getting the hang of it, Vertical flip works like a charm.
Flex is acting up
I noticed a weird behavior
Flip Vertical Reverse
I’m so glad that everything is coming to fruition, yet I still don’t like the way it’s coded, I need to figure out a way to make it more simple to understand and use.
Aside
I’m thinking of designating different parts of the view as zones and then making different views then assigning them to the appropriate zone, I still don’t know. Please let me know your thoughts
Weird Typescript issue
{((orientation === OrientationEnum.horizontal && flip) ||
orientation === OrientationEnum.horizontal ||
OMGGGG
I just realized that I need to write the component in Javascript.
Putting it outThere
I asked around to see how to create an npm react component for everyone to use and luckily I got a great answer from one pf the communities about where to look, and it was Vite.
After some research and checking the reviews I found that the Vite solution might have some issues with SSR (Server Side Rendering) and embedding CSS on the server like in NextJs, now I needed a faster more efficient way.
Onto the Recursion
I figured I had to finish the recursion before I bundle it.
I’m currently trying to figure out a way that will fix the sizing as I want to dynamically set the size of the fibView and then pass a % size recursively for the views
Refactoring...
I had to refactor a couple of states within the fibView:
const [orientation, setOrientation] = useState<OrientationEnum>(_orientation);
And now I’m using a prop to set it from the parent to be able to dynamically change it.
const [elementResolution, setElementResolution] = useState<ViewResolution>(
getViewResolution(orientation, _viewResolution)
);
This also was another change for the same reason as it’ll help in the recursive step to be able to dynamically change the size and orientation of the view. Maybe I’ll revert to the original, but these states didn’t make sense as I just set them up and didn’t change them after that.
export type FibonacciViewProps = {
orientation: OrientationEnum;
_flip?: boolean;
_changeOrientation?: () => void
_viewResolution: ViewResolution;
};
This is the updated view properties… for now.
Hotfix for height
Height ap
Back to the recursion
I’ll check if we have more than 3 views I’ll have to create a child FibView recursively.
So for example If I add 8 views like so
<FibView>
<img src="1.png"></img>
<img src="2.png"></img>
<img src="3.png"></img>
<img src="4.png"></img>
<img src="5.png"></img>
<img src="6.png"></img>
<img src="7.png"></img>
<img src="8.png"></img>
</FibView>
2 should be displayed on the biggest views and then the remaining 6 images should be passed to the next FibView that's inside the smallest view which will display 2 images and have another FibView with the rest and so on.
Now that I’m thinking about it I don’t know if this is the best way to do it
HMMMMMMM
Now that I have gotten myself into this rabbit hole, I need to figure out an algorithm to calculate the next fibView in the recursion. I’ll take the horizontal view as a test case
Take a step back (Working out the sizes of the views)
Apparently, a parent’s height needs to be determined in order for the child to use percentages, so now I’ll refactor the code in a way to retrieve the actual height of an element and cascade the effect for all of the children.
After a lot of refactoring, I managed to make it work somehow.
But now I have a better idea, instead of supplying the width and height ///


























Top comments (0)