Core UI
Reusing the UI You Have Built
Last updated
Reusing the UI You Have Built
Last updated
Building a UI template from Figma in Flutter is quite labor-intensive, from typography, font styles, colors, to the widgets used in the application. Typically, in personal projects, we tend to reuse interface templates we've created before to save time on app development, for example, web and app applications with nearly identical interfaces. Separating reusable interface code into a different part of the application is a clean coding method and also applies knowledge of object-oriented programming. Additionally, it can be transformed into multiple themes within your app.
Take a look at thewebsite . It is built with Flutter, and I will walk you through how I structured a separate UI for my web application.
As shown in the image, I placed all UI components inside the packages directory outside the lib
folder and named it web_ui_core
. You can also see several other core UI packages around it, which I plan to reuse in future projects.
You might be wondering how I synchronize these packages across different projects. The answer is: I use Git to manage them. I will explain this in more detail in the article about packages.
The image above shows how I implemented a UI package for this website. The same approach applies to the UI of my mobile applications.
I divide it into five main parts:
artist
folder – This includes colors, SVG transformations, gradient effects, shadows, and styles for widgets. I have written a short article about switching between dark and light themes.
widget
folder – This contains reusable widgets.
Here’s an example of a search input field (search_text_field
) that I created. I also take screenshots of widgets for future reference, making it easier for colleagues to find and reuse components instead of rewriting them.
sub_widget
folder – This holds secondary UI components such as dialogs and bottom sheets. Common dialogs include confirmation dialogs, notification dialogs, and date-time pickers.
From the structure outlined above, you may notice that there are quite a few directories. To manage this efficiently, I use Mason. If you're unfamiliar with Mason, check out my article here:
Now, I will guide you through how I set up my personal core UI package.
The first step is to create a package that will contain the UI components you plan to add. Name it ..._ui_core
so that you can easily distinguish UI core packages from other core packages. Check out my article on how I organize my packages.
Create a packages
folder outside the lib
directory and then run the following command:
Next, add some libraries to improve code clarity and maintainability by running:
analysis_options.yaml
Replace the contents of analysis_options.yaml
in your package with:
This ensures that the package follows the same analysis_options.yaml
as the entire project. I will share the analysis_options.yaml
file I used in the project that powers this website.
I will use Mason to generate the code template I introduced at the beginning of this article.
Then, copy the folders inside out_site_lib
into the lib
folder of the package.
flutter_gen_runner
This library makes working with assets much easier and helps minimize mistakes. Check out my article on coding faster for more details.
I have already preconfigured all the necessary settings for flutter_gen_runner
in the template.
In the project's pubspec.yaml
file, add:
After setting everything up, you may notice that a ui_core
package is missing. This is a core package, but it won't cause issues if you remove it and create your own version.
I will cover the missing components in a later section. Since the ui_core
library requires an in-depth explanation, I will introduce it in an upcoming article.
I have written a dedicated article on this topic, which you can find here:
Details on the isDarkMode
variable:
Usage:
One common issue we face is that font sizes need to adjust based on screen size. For example, the font size on mobile and web differs. You can see this effect directly on this website—font sizes dynamically change depending on whether the screen is large or small.
Here’s how I handle it:
In the code above, you can see that I calculate the horizontal scaling ratio (webRatio
) by dividing the current screen width by the width designed in Figma. However, I keep this ratio within the range of 0.75 to 1 to ensure that the text does not become too small when the screen size is reduced.
Additionally, I use GoogleFonts for easy font management. You can add your own custom fonts by referring to my comments in the code.
Usage Example:
You can fully customize the text style to match your design system. Here’s an example of customizing the color:
Using screen scaling ratios and Figma-based dimensions is common when designing custom widgets. Here’s an example of how I combine colors, text styles, and scaling ratios into a custom widget:
For more details, check out my article on responsive screen design at here.
One of the indispensable parts of a UI kit is the icons. I love using SVGs because of their light weight and simplicity. If an icon is complex, I tend to prefer using PNGs over SVGs.
Then run this command to generate the icon paths in the gen folder:
This way, using icons becomes much easier while ensuring the accuracy of the icon paths.
Change to:
This is how I implement a UI package, keeping it separate from the lib
directory for easier maintenance, scalability, and cleaner code organization.
To learn more about how I synchronize packages across projects without manually copying files, check out my article on package management at here.
assets
folder – This contains colors, SVG icons, and UI-related images. Any images unrelated to the UI are stored elsewhere. I use the package to automatically generate asset paths in the gen
folder, making them easily accessible and reducing errors. I will explain this in more detail later.
You can also refer to my code template and create your own, as this article does not cover some core libraries. Here is my template: .
I recommend using the package, which helps enforce clean code practices following . I will cover this in more detail in my article LINK.
simplifies asset management and reduces errors. Run the following command:
I use to simplify the process of creating these icons. First, I save them in the assets folder, then configure them in the package's pubspec.yaml file as follows:
You can find more detailed setup instructions on the library's website:
|
widget
folder