Stop war.How to help
Back

ynotes-packages

As yNotes was getting bigger and bigger, it became hard to keep a consistent design across the whole app. So I made a Flutter package to help with that. It features components, theming and more.
As yNotes was getting bigger and bigger, it became hard to keep a consistent design across the whole app. So I made a Flutter package to help with that. It features components, theming and more.

Table of contents


Motivation

As I started to get involved in yNotes’ development, I noticed plenty of inconsistencies concerning the ui. The fonts were not the same everywhere, as well as colors and so on. So I decided to create a package that would actually keep all of this kind of stuff consistent and independent from the app in itself.

Categories

Little by little, the library evolved into a collection of small packages.

Components

First of all, it contains components that are used absolutely everywhere in the app. When starting the library, I was tempted to code every component and then use them in the app. But I quickly realized it didn’t really make sense so instead, I decided to list any components that would be useful to build, and actually build them as I needed.

Config

I personally don’t like to use the context to access the theme, it feels too verbose and means it can only be used in widgets. An example of the default way of accessing the theme is:

Theme.of(context).colorScheme.secondary

My approach is to have a global theme variable and when updated, refresh the whole widget tree. It might not be the best for performance reasons but so far it was working quite well in yNotes.

In order to refresh the whole widget tree, I needed to provide a widget that would handle that by listening to the theme changes. This is the YApp widget. I couldn’t find why but it needs to be wrapped in Responsive (exported from another library you can learn more about).

Here is how to use it:

import 'package:flutter/material.dart';
import 'package:ynotes_packages/config.dart';

void main() {
    WidgetsFlutterBinding.ensureInitialized();
    runApp(MyApp());
}

// It could be a statful widget but it's not needed
// for this example
class MyApp extends StatelessWidget {
    const MyApp({Key? key}) : super(key: key);

    @override
    Widget build(BuildContext context) {
        // The widget
        return Responsive(builder: (context) => YApp(
            initialTheme: 0,
            themes: themes // See the theme documentation to know more
            builder: (context) => MaterialApp(...);
        ));
    }
}
main.dart

Under the hood, it listen to changes thanks to the ChangeNotifierProvider and Consumer widgets from provider. Its child is then rebuilt by generating a unique key. Here is the source code:

part of config;

typedef _YAppBuild = Widget Function(BuildContext context);

/// A widget that setups the flutter_responsive_breakpoints and theme packages.
///
/// Usage: Wrap MaterialApp with this widget.
class YApp extends StatefulWidget {
  final _YAppBuild builder;
  final List<YTheme> themes;
  final int initialTheme;
  const YApp({Key? key, required this.builder, required this.themes, required this.initialTheme}) : super(key: key);

  @override
  State<YApp> createState() => _YAppState();
}

class _YAppState extends State<YApp> {
  @override
  Widget build(BuildContext context) {
    theme = YCurrentTheme(currentTheme: widget.initialTheme, themes: widget.themes);
    return ChangeNotifierProvider.value(
      value: theme,
      child: Consumer<YCurrentTheme>(builder: (context, _, __) {
        final Key key = UniqueKey();
        return Responsive(
          key: key,
          builder: (context) => widget.builder(context),
        );
      }),
    );
  }
}
lib/src/config/widget.dart

Theme

This part of the library exposes a theme global variable that can be used to access the current theme. Themes must be provided to the YApp widget.

Source code available here.

Utilities

As a web developer, I really enjoy the way Tailwind CSS works. It allows to work within a set of values, which is improves consistency. So I made my own quickly in Dart with border radius, font size, font weight, letter spacing and scale.

Settings

Until then, we were relying on a fork of settings_ui which provides great settings ui for each OS. But I felt it didn’t fit well in yNotes since we didn’t use native styling depending on the OS. So like for the components, I created the lib to have consistent settings across platforms.

Wrapping up

Developing a components library as well as a design system was definitely a great experience. I learned a lot and will inspired by this work in the future.

To learn more about using the library, Head over to the documentation.

Type
Package
Technologies
Dart, Flutter

Get in touch

If you wish to talk, or chat about an existing / upcoming project, feel free to reach out with any of the below methods.

Profile picture
Florian
LEFEBVRE
French self-taught fullstack developer.

© 2022 Florian LEFEBVRE. All rights reserved.

Loading...