Intro
This was intended as a simple post about how I designed my app. But it turned into a full course into Figma, Figma components, and using the M3 figma kit to design.
You'll learn about ...
You'll find a step-by-step guide below.
However, if you just want an overview with the main highlights, check out this Youtube vid.
Also, if you're interested in design or code. I'll be documenting How I'm building my first app on indieDev, mstflotfy.com, medium/stack something.
Here's a link to the final prototype you can play with it and check it out yourself
A gif that shows the full prototype.
Outline
Steps Whys Important steps Important whys Should I use the components they made directly or should I use them to make my own components?
- Using them directly is faster at first.
- Until you want to customize them.
I decided that it's best to use this figma design kit and figma components to build my own components. Using them directly takes away from my freedom. I can make a prototype quickly with less work by making connections between components and pages. But using their system is limiting me. By not using their components directly I also lose some features, because they will be detached. However that is OK. By starting out with a wireframe I already know generally what I need. I can make their components as close to what I need as possible then detach and customize. And if I want to use some of their other features I can just implement it myself and use their work as a reference.
I put components in the same file as the design to simplify prototyping.
One thing I prefer to have in a component is to make a variant for states (for example, the hover state, the clicked state, ...), the M3 figma has this as properties (properties are great but they don't work with prototypes)
I can also build on their components rather than detach and start my own.
The building blocks are hidden, but they are there! That means I can edit them directly! That means I can just adjust the M3 components and I don't need to recreate my own, Perhaps!!!! However, I still think I need to cover them with my own just for prototyping purposes. Perhaps in the same page as the design. And also for theming without altering the building blocks too much. The picture is not entirely clear but it's coming.
I expect after I'm finished with this to have a few rules to help me work with M3 design system. And build above it.
There is a question that nags at me. Can I do this with apple design system as well. Or should I just stick to M3?!!!!! After visiting the apple website I can see that they only have a library for sketch that you can only access if you have sketch installed and no resources whatsoever for Figma. However by searching the Figma community I easily found an excellent IOS 16 kit by Joey Banks here. I didn't use it yet, but it seems really promising. I do think however that I'd still need to customize it a bit if I decide to use it.
For my situation I'll stick to M3. Here are the reasons.
A great solution. Finding the hidden building blocks and connect the enabled state to the hovering state, then connect the hovered state to the pressed state.
Also before adding any component to your pages in your pages/screen page, wrap the component into another. Then take instances of it in your screens. That way your can customize and theme any component without having to go all the way to the parents and to the building blocks. You can hide these components later or you can connect parts of them to your screens directly simplifying your prototypes even more.
Going to the "Icons buttons" and connecting the "standard, enabled" state to the "standard, hovered" state, and so on. No need to do this for all the styles (filled, tonal, and so on), just the one that I'll use.
Prototyping
Some mistakes become obvious when you prototype, but not when designing. When prototyping it is as close as it can get to using the real up. And suddenly you see everything, and you find the blind spots, and the missing details.
Things that do not make sense. And your bad planning and design are going to stand out like.
It's best to use a small sample of real data rather than rondom data. That way you can connect with the prototype and see what the app can and should do.
For example using real workout data or realistic data at least can got me to take the protype seriously and improve the design. Especially when designing the workout preview stats page.
- Import and image of the whole wireframe inside your Figma file.
- Take a screenshot of the wireframe of the specific page you're working on and place it next to you're design to avoid the back and forth scrolling.
Wireframe
Even though I made a lot of iteration to come up with the final wireframe.
I still rushed the last one, and I kept going to back to GoodNotes (The app I used to draw the wireframe) to make corrections then upload it again.
I uploaded the full image of the wireframe. While working on a new screen I needed the specific part to be next to it. I used to go back and forth a lot at the beginning which is ineffective. But eventually I just took a screen shot (cmd shift 4, on Mac. While holding the ctrl key to copy to clipboard) and pasted it next to the screen I am working on speeding up the process.
Like with everything the next step is build upon this one. If you scuff it you'll waste a lot of time going back to fix. And going back and forth between stages is not efficient. I guess some back and forth is unavoidable, but it's best to minize it as much as you could.
I should make a list of all the pages. So that when I'm designing I know which pages/screens are done and which ones I still have to work on.
Then each iteration I can just have a check list.
There is something missing here, that should be found somewhere in this file; Having to go back to the wireframe, rethink, and redraw some screens.
Every step builds on the step that comes before it. So if I scuff the wireframe the design is going to be painful, and if I rush the design coding is going to be painful. So I somewhat thought about the M3 components while I sketched I didn't know them the way I know them now, but I thought of native apps components as I won't on. I think if I make a wireframe now I'd probably know which component I'd need to use, if I base it on M3.
M3 Components
Inside the Component page in the Figma file, the m3 component are organized horizontally in an alphabetical order.
So you can easily find what you're looking for, if you know it's name. That's why I head to the m3 component page first to decide which component is suitable for what I need.
At first I headed to the components file in the M3 Figma Kit and searched for which component would work for what I needed. But I ended up opening the M3 components Docs and serched for the componet I needed there first.
Step 1 - A device frame
I'll develop for mobile first. When I was designing my website I developed for web first. Since I expected it would mostly be visited on desktop.
Now I expect to use this app mainly on mobile myself and others as well.
So I'll design in an iPhone 13 mini frame.
I added a frame and set its frame to an iPhone 13 mini, from the frame drop down menu in the design panel.
I grab a device frame component from the "Styles" page and put inside my new frame, resize it to fit, and constraint it to top & bottom, and right & left. That way if I change the frame size it will respond to the changes.
There are 2 ways to go about making this design responsive. I can use constraints on every element and minimal autolayout, or I can minimze constraints and rely mainly on autolayout. I think it's best to use autolayout mainly.
So I created a frame and named it "PageContent" which is going to hold all the other components I turned it into an Auto-layout frame (so I can easily manipulate the elments inside it) and I constraint it also to top & bottom, and left & right.
Next I grab another frame and put it inside the PagesContent frame. I call it Header. And also turn it into an auto-layout as well. To make sure it spreads across the whole width of the device I make its width "fill container" instead of fixed. So its width would spread to fill the width of its container, the PagesContent. However the PagesContent has some padding so I remove it
After removing the padding from the PagesComponetn the Header spreads properly inside it.
The Top App Bar Component
The first component I want to work on according to my wireframe is the top-app bar. Usually apps have a top app bar with a side menu, title, and perhaps some secondary menu on the right. But inspired by Google keep apps, I decided to steal a part of their design and combine the search bar insdiet the top app bar to save space. They also use this same coponent in Gmail. But I first noticed it in Google Keep.
I went to the components page. Found the Top App Bars compoents and
Then I didn't need to edit the icons for the "Top App Bars" Component, cause the icons component is already used in it. All I did was add a text property to make more convenient to add text. Again no need to it for every single style just the ones I'll use.
I grab an instance of the component just outside the "Top app bars" component and put in a frame to test it. Then I customize it the way i want to.
image description: A test frame with an instance of the "Top App Bars" component is just above the actual "Top App Bars" M3 component frame. ![[Pasted image 20221204014422.png]]
image description: An instance of the header component is inside a test frame in Present mode. The cursor hovers above an icon and its hover state can be seen. On the other side of the component there is an icon that is not hovered and does not show the hover effect. ![[Pasted image 20221204014501.png]]
![[Pasted image 20221204014700.png]]
Finally before, I use it inside my screens. I'll wrap this custom version of the component into a component. Put it my Screens page. Then take instances of it whenever I want to use it inside any of my screens. Again, this is to simplify theming and to simplify prototyping.
There is something with a trivial importance that I tend to do at this stage. Is to create a variant, remove it, add auto-layout frame, set it's padding to 10s. This gives me a distinct dashed frame around the component. Sounds like a lot of work, for not much return. But it literally takes me 3 seconds.
image description: The component is in the Pages or Screens Page. Above and outside a screen design. And an instance of it is used inside the screen. The component is surrounded by the purple dashed lines mentioned above. ![[Pasted image 20221204015320.png]]
Bottom Nav Bar
Next I wanted to add a bottom nav bar to my first screen. I went to the components page, then to the "Navigation Bars" components. Inside the "navigation-bar" component there's a "Building Block / segment" component. This group of building blocks is hidden so I unhide it and go to it to edit them.
So I connect each of the enabled states to their hovered ones. And each of the hovered states to their pressed ones.
Now I grabbed an instance of the "navigation-bar" component and put it in a temporary frame to present and test it.
And it's working except for the last one the righ the one with the badge!
I found more hidden building blocks! I just to extend the building blocks frame a bit towards the bottom. So I didn't make connections for all the labels
I had a feeling that some might feel that this is too much work at this point. But it's worth it. It will allow you to be able to have a realistic prototype of your app before you code it. And you'll get a feel of what it would be like to use it in real life. Allowing you to make more relevant changes and this will save time. Also this is much faster than building all those components from scratch yourself!
Now back to the Presntation test. And all of the buttons are working when hovering and pressing they change to the hover and pressed states.
Now it's time to customize our instance accordying to the wireframe I made. Before we reapeat the same process of turning it into our custom component that uses the M3 component as a building block.
I didn't find the icons I needed in the M3 icons. So I serached for an icons plugin. Found one called Material Design Icons, with loads of free icons. And I found a couple that could do for now. B
But they're too large. I cut them, moved to the Styles page and pasted them inside the Icons frame. All the icons in this frame are components and they have a 24 x 24 height and widths. So I turn these icons into components and adjust their dimensions. I also renamed them the same way as the other icons in the frame "Icons/name-of-icon"
Now when changing an icon compent instance inside any component I find my new icons.
My instance is working properly and I'm done customizing it. So I turn it into a component and move it to the Pages page. And I put an instance of it inside my first screen.
Ther is extra padding around it. So I need to fix this.
I fix it by setting the component and the component inside it to "fill contianer" horizonatally. So it spreads horizontally to fill the "PageContent" frame I put it inside. The "PageContent" frame has autolayout with the paddings set to 0 in all directions.
List
A red circle around the
List items are the closest thing to what I need but still not enough.
Again some parts of this component where hidden including the building blocks.
There is no need to make hover and click connections for this component. As the elements of it are just the ones that are going to be clickable. But its building blocks are focused on it's background, and also they are set as seprate components which are not possible to conect with hover and press.
Again for testing I put a temp frame above the Lists components, present and test as I go, if needed.
Unfortuanetly this is as close as I could get this component to waht I need. Figma allows you to customize an instance of a component only slightly, chaning color, changing fonts, ... But what I need is to add elements to it which is not allowed.
The only solution I can think of is to detach it as it is and build my own custom component that is sepearte from it.
While it's best to build upon their componetns this also gives me the freedom to fully customize it and to make it a great component to use.
So first I turn it into a new component.
But for the reps it's not going to be just text it could need to be have it's own component. As this is going to be an item in a list of workouts. So each item list will show us the date, the title of the exercise, an some quick top stats from the workout, like the max reps, max weight, distance, time, depending on the exercise. Perhaps a maximum of 5 stats. Probably it will be 3 max. but I'll just design for a max of 5. Those stats will also have highlights of red, green, or yellow, if it's better than the same exercise the last time out green, the same yellow, or worse red. So for this little quick stats I'll create a new component and put inside this one.
Here the actual component above the test frame with its instance.
So to solve the issue of the heighlight. I create another building block component. That has text with a colored background layer with three color variants and a text property to be able to quickly edit it.
I removed the 3rd small text and put an instance of the TextHighlight component and it's place. Then I duplicated it. However they are placed vertically since the frame holding all the workout info is an auto-layout frame, and it's in the vertical direction.
So I select the Quick stats only and add another auto-layout frame around them (by pressing Shift A) and set this frame to the horizontal direction.
However not all exercises will require all these stats, so I apply a boolean property to each to be able to toggle them on and off.
In the present mode the icon is not hovering, even though we've added a hover and press connection to the button icon component. But this is just an icon component not a button icon component. So I replace it with a button icon component just to get it to hover and press in the prototype.
And now it hovers and gets pressed in the prototype.
So I left the 2 components in the component page, as building blocks. Just above the Lists components by M2.
Then I took the instance I was testing with to the design file and turned it into a component and put it in my design page. Then I can take instances of it in the page.
I drop it into the "MyWorkoutLIst" frame. Inside the "Main" auto-layout frame that we created earlier. The one just underneath the header.
I change its frame Horizonatl resizing to fill contianer, and othe component inside it as well. And make sure the main frame has 0 horizontal and vertical paddings.
Then I make many copies of it and they all fall in place, just by clicking cmd c, cmd v, and that's why I prefer to use auto-layout for alignment. Once you set it right, it makes things easier for you.
Now I can just update some of the props to make it look a bit natural.
FAB (Floating Action Button)
Next we move to the last main piece of our page in when it's static that is the FAB.
I go to the components page agian. Locate the FAB components. I used the medium sized ones. So I make Internal connections between the enbled, hovered, and pressed states.
And again I take one instance into my Screens/Design page. Turn it into a component and take instances of it.
I then grab an instance of it and drop into the "MyWorkoutList" screen. At the bottom of it just above the bottom navigation bar. I select it (the FAB) and the bottom navigation-bar and add an autolayout frame around them and name it Footer.
I set the spacing between them to 15 for now.
It's unecessary to create a workaround like this.
Just create a swap overlay. If it dosn't work a manual overlay just on top the button.
Button
Testing the first screen
I press on the canvas to deselect everything. Then I make sure the presenting device is an iPhone 13 minim just like my frame/screen. Then I present the frame (MyWorkoutList)
Everything seem to be acting properly. Except that the Main frame holding the exercises list doesn't scroll.
So I get back to the canvas and I select the frame Main, I switch to prototype settings (Shift E
), then I set its Overflow scrolling to Vertical scrolling. That way any element that is inside this frame but extends, or overflows out of it can be scrolled vertically.
And now it's scrolling.
But! It's going above the top-nav-bar!!
To avoid this I select it and clip content.
This fixes the scrolling issue. But now the content is not showing underneath the FAB. If I try to push the frame Main down it pushes the footer outside the screen.
To fix this I give the FAB an Absolute position meaning it will still be a part of the Footer's frame but I can push it outside of it.
And this fixes the problem.
We'll also change the icon inside the FAB component in our page to an Add instead of Edit icon. This will update the instances in our page.
Calendar View
In this screen we can switch between displaying the exercises in a list view or a calendar view. So next I started working on creating the calendar view for this screen.
I start by duplicating this view. And renaming it to MyWorkoutsCal.
Almost everything is the same except for a few changes, mainly a calendar date picker, and underneath it exercises just for the selected date.
So I remove most of the exercises and leave 2 for a single date.
Next I head to the Components Page, grab an instance of the date picker I want, and place it in a test frame above the Date picker component.
I start by hiding some of the things I don't think I'll need from the instance.
Next I go to the building blocks component of the date picker. And I make the prototype connections for the hover, and pressed states.
Present the test component and it works.
Now the only thing missing is to add a property to the day's building blocks, that allows me to display or hide badges above the days where there are workouts. So the user would now which days to check out and which days to ignore.
So I grab an instance of the small badge component.
I go to the Default (day) building block variant and I past the badge inside its auto layout frame. The badge is placed outside the component.
So I switched its position to absolute and push it where I want it inside the compont.
This will add the badge to every instance where the Default day is used.
So I select the badge inside the Day component and add a boolean property to its layer that will make it hidden by default. And I can show it for some days.
I can now choose to show the badge only for certain days.
But this only works for the default day, and it breakes when hovering or pressing.
So I get back to the default day building block variant. I copy the badge and paste it to every single day component, just by selecting each one and pressing cmd v
. This automatically adds a badge, that is hidden by default with a boolean property to show and hide it.
And now I can present it, hover and press works.
I think this is good enough. So I turn my custom instance into a component, and move it to the Screens page.
I take an instance of it and put inside the "MyWorkoutsCal" screen. Inside the Main frame.
I select it and set its horizontal resizing to fill container.
The badges are not centered anymore! The solution is simple. I get back to the day's building block componet, select all the hidden page elments and change their constraints from top and left to top and center.
And the badges are centered again.
Now I adjust the toggle underneath the search bar. For this page the Calander should be selected and toggle disselected.
And also I make a prototype connection on click to navigate between the 2 pages.
Adding An exercise (FAB)
To avoid the FAB being out of position if the device is changed.
Make its constraints bottom and center or bottom and right & left.
I can do on top change to the clicked variant, but in this situation it doesn't look good. The text of the icons is not redeable.
The other option is to do on tap swap or open overlay. But this doesn't work betwen variants. And I can't get it to be placed properly. Perhaps because my component is not placed in an absolute position so it swaps the whole screen! and place the button in an awkward and unusable position.
I can fight with it. Till I figure it out but I am disinterested. So I resort to an easy fix workout.
All the FAB buttons in any screen will navigate to this one. The content is covered, as if it's blurred. And when I click on the x button it will just navigate back to whichever screen it came from.
Not a pretty solution. But it'll do.
Perhaps lowing the opacity jsut a little bit makes a bit obvious what is inteded.
Exercises List Screen
Not updated. I went back to the wireframing and uploaded a new image.
Now here's the adjusted exercise list screen wireframe
There is a problem with icons. They should be outlined when not selected, and when selected change to fill. That's a detail that I'll handle later but it should be noted.
Side Menu
Probably this could be its own vid.
The option is to click the menu button, from any page, and the side menu would be an overlay that is displayed above the content of that page/screen.
However using this method it will not automtically adjust it's height (size) if I change the device. I have to do it manually in this case.
There is a workound. Is to point the menu to a menu screen and cover the content of the screen with a clickable dark background (as if it were a blur layer) when clicked it just goes back to whatever page it came from. This way if we change the device when just select this menu screen with the screens and set it to the device we want.
I think an overlay an manually adjusting the height if the device is changed is the best of the 2 options.
Sections
A new Figma feature.
Just select a couple of frames that are related together right click and select create a section.
Not sure what that is about!!
The result is a much cleaner canvas.
And a much cleaner layer panel.
Handover
I am the one who will code it so there are some detials I can ignore. But I shouldn't ignore everything. Only the things that are too obvious, and it would be too much unecessary work to integrate them.
However, I want to start coding and as much as possible not have to make adjustments to the design.
Bottom Sheets
According to the M3 Docs bottom sheets are
surfaces containing supplementary content, anchored to the bottom of the screen.
I used the one without the scrim. A button can easily be connected to the bottom sheet with a on tap open overlay, from the bottom of the screen, and then check the option of adding a background behind the overlay.
With the scrim it's not possible to change its width!
So I ended up detaching the bottom sheet from it's main component to be able to put a list inside it and make it change its size according to the size of the items in the list.
And made my own component out of it.
Navigation Drawer
Menu
I decided to go with a menu rather than a bottom sheet for this one. Seems to be more common in this sort of situation in other apps, youtube an example.
Nice! Something new I discovered. Setting it to manual. Every time I tried to do this I didn't find this box that appears to be set manually. It was always hidden behind the interaction menu I guess so I never say it! Now this will simplify a lot of things.
This is a game changer! How did I not know that! What a fool! I went through a lot of trouble just because I never found this manual placement thing. Never! Damn! How much time have I wasted!!!!!!!!
Dialogs (Creating a delete full delete interaction using M3 components)
When the delete button is pressed. To delete a workout or exercise. The user should be promted with a confirmation message. The dialog coponent is perfect here.
Found the Dialogs component in the component page. And made a few edits to it. Grabbed an instance. Turned it into a component, just in case I added any changes on top of it later. And dropped the component in the design page.
It's not necessary to create another component on top of this one, but since I've done this for most of the other components. I should try to make things consistent.
So here's how I went about it:
- I made little adjustments to the original Dialog component. The ability to hide secodary text or title.
- Then I took an instance of it.
- I took it to the components page turned it into a component. (This is not necessary in this case)
- I took an instance of the component, and put it into the "Nav and Pop up" section.
- Then I made a connection from the "Delete workout" buttons inside both the menu and the bottom sheet. When I click them an overlay will open in the center of the screen containing the dialog. If I press cancel the dialog is closed.
- If I press Delete. The dialog will open another overlay at the very bottom and center of th page.
- This new overlay is snack (That just appears to show the user that the delete was successful).
- This snack overlay has an on-delay action (it waits for 1600ms) then without me doing a thing it navigates to the workouts list page.
- As for the snicker I went to m3 found it's the component I need to use. Then I headed to the components page. Found it. Made some adjustments. Took an instance of it. Pasted it in my design file. Turned it into a component. Took an instance of it in the "Nav" section, then made the mentioned above connections to it.
Responsive Table Using AutoLayout
Productivity
Instead of jumping in to the first area I notice. I take a different approach. I first notice an area (for example I need to add an extended FAB button at the bottom of the page, I need to go to the FAB component, and ...) Instead of heading document immediately. I just press "C" and write a comment of what I thing should be done, all the steps, just a quick comment. Then I move on to the next area, and the next. Till I run out of ideas for the current page. I am still tacking one page not the whole design/docuemnt.
Now, when I start actually working on the design. I can jsut head to each comment read it and have a good idea of what I want to do or try. Then move to the next. Not distracted but new ideas. Just tackling each one free of worry of other things I need to do on the page.
I don't need to spend time feeling lost as to what's next in between tasks. All the tasks are laid out in comments. And I can tackle them without delay in between. And I feel also less intimidated by the task at hand cause I can see upcoming steps.
If I have low energy and I feel resistance to work I can tackle the easier tasks first. All the tasks are laid out by comments so I can easily spot the easist place to start. If I have the energy I start by tackling the most intimdating. Getting it done with will speed up the whole process.
Using Sections
Having to use Figma's version history
In an effort to organize I put them all into a an auto-layout frame. Which broke the overlay connections. Having made all those connections it was ridiculous to go back and do everything again.
I didn't find an ideal version to get back to. But undoing the mistakes I've done I felt would be less work.
It was better to fix the mistake in this case.
Never mind.
Comments & Productivity
Instead of working at the very first task I see.
When tackling a new page. Before you start, or the moment you start feeling a bit lost and wander what you should do next. Instead of picking up the first thing your eyes fall upon. Write down a comment for each task that needs to be done.
Now you'll now exactly what you need to do to get this page done. You'll feel less lost, save time by batching this process, and also feel motivated to get all these comments resolved. It's like a visual task list.
When I'm done with a task I'll check mark it as resolved, until none are left.
The moment I notice a problem that needs to be fixed, or any task that needs to be done. I just write a comment, preferrably inside the partial wireframe, so I don't clutter a view with comments. So that I don't need to rediscover problems.
Perhaps it's best to put the unhandled comments above the screen itself. So that I wouldn't need to get back to the wireframe fragment.
Comments can be inserted inside frames. Make sure a comment is inside the frame you want. Otherwise if you move the frame around the comment will not move with it and will be left pointing nowhere!
I tackle each screen/page/view thoroughly with all its visible components and prototyping. Then I move to the next. If I have to come back to the same screen it would be for theming and minor adjustments. But the hard work for this page should be done.
Tut Ideas
- Function checkboxes using M3
Color
Generated colors using "M3 Theme Builder Plugin". Just doing that changed all the elements colors that I used, since they were already set with color styles with the same naming. Except for the very few custom colors that I had added.
I just gave it an image that I wanted to use as the base for generating the theme and it was done!
It generated the theme and changed the local color styles.
Also read the M3 Color System Guide
need to understand what is primary, on-primary, container, and on-container. Also need to understand elevation.
Date Picker
There's a lot to read about. The bottom line for the impatient, like myself, and thus often rushing and getting into trouble. But who care let's just get shit done as fast as possible, and deal with problems as they arise.