Style
The Style Module aims to address common challenges in Flutter app development, such as maintaining a consistent visual style across the application, handling theme variations, and applying styles to individual widgets. By providing a centralized styling system, the Style Module enables developers to focus on building the app's functionality while ensuring a polished and cohesive user interface.
Emphasis
The Style Module introduces the concept of "emphasis", which allows you to control the visual prominence of components within your application. Emphasis is divided into three levels: subtle
, regular
, and strong
. By applying the appropriate emphasis level to a component, you can guide the user's attention and create a clear visual hierarchy.
For example:
StyledButton.subtle(...) // Renders a button that should not draw much attention.
StyledButton(...) // Renders a button with the default emphasis.
StyledButton.strong(...) // Renders a button with high prominence.
Color Palette
The ColorPalette
functionality enables dynamic color selection based on the background color and emphasis level. It simplifies the process of choosing contrasting colors for text and other elements against different backgrounds, ensuring readability and visual harmony.
final colorPalette = context.colorPalette();
final textColor = colorPalette.foreground.regular; // Use foreground.strong for an emphasized text, or foreground.subtle for subtle text.
final buttonBackgroundColor = colorPalette.background.regular; // Use background.strong or background.subtle to define emphasis.
final buttonTextColor = buttonBackgroundColor.foreground.regular; // [buttonBackgroundColor] is both a `Color` and a `ColorPalette`, so you can see what the text's foreground color should be.
With the ColorPalette
, you can use a set of colors that automatically adapt to the background color of a widget. This means that text and other elements will always be legible and visually appealing, regardless of the background they are placed on. The emphasis level allows you to further fine-tune the color selection based on the desired prominence of an element.
Using Pre-built StyleComponents will automatically update the ColorPalette
in the widget tree so that children widgets have an appropriate understanding of parent's background color.
Existing Styles
Flood provides two built-in styles: DeltaStyle
and FlatStyle
. These styles offer a solid foundation for creating visually appealing and consistent user interfaces. To demonstrate, a screenshot of a Todo app is pasted alongside each style.
DeltaStyle
DeltaStyle
is a modern and sleek style inspired by this Figma board (opens in a new tab). It supports both light and dark themes well.
final style = DeltaStyle(
primaryColor: Color(0xff9333ea),
backgroundColor: Color(0xff181A20),
);
FlatStyle
FlatStyle
is a versatile and lightweight style that emphasizes simplicity and efficiency. You can see an example of it in action in Valet (opens in a new tab). It only supports dark themes for now.
final style = FlatStyle(
primaryColor: Color(0xff9333ea),
backgroundColor: Color(0xff181A20),
);
Both DeltaStyle
and FlatStyle
serve as excellent starting points for creating beautiful and functional user interfaces. You can choose the style that aligns with your design vision and customize it further to match your specific requirements.
StyleComponents
The building-blocks the Style Module are Style
s, which render StyleComponent
s. A StyleComponent
is a Widget that doesn't render itself, but relies on the current Style
passed through the Widget tree to render it. There are many pre-built StyleComponent
s with implementations already created and ready for use.
Pre-Built StyleComponents
The Style Module includes a variety of pre-built StyleComponent
s:
- StyledText: Streamlines text styling by offering a concise syntax for applying attributes such as bold, strong emphasis, alignment, and style, reducing verbosity and enhancing code readability.
- StyledList: Simplifies the creation of lists by allowing the composition of attributes for columns and rows. It provides a concise way to define the appearance and behavior of list elements.
- StyledContainer: Serves as a base container that accepts an optional emphasis and can be fully customized. It passes a new ColorPalette to its children, ensuring they are styled correctly based on the container's emphasis.
- StyledCard: An opinionated card component that supports emphasis and consists of a header, body, leading, trailing, children, and actions. It is designed to display a piece of content in a visually appealing and structured manner.
- StyledButton: A button component that can be emphasized and contains a label, icon, and an onPressed callback. It intelligently handles the loading state when the onPressed callback returns a Future, preventing multiple presses and displaying a loading indicator while the action is being processed.
- Input Fields: A collection of form field components, including StyledTextField, StyledCheckbox, StyledDateTimePicker, StyledOptionField, and StyledRadioField. These fields support emphasis and are used to capture user input effectively.
- StyledPage: A component for creating structured and customizable pages with a title, actions, and body. Supports regular and refreshable variants, enhancing the user experience.
- StyledMessage: A message component that can be displayed at the bottom of the page using
context.showMessage()
. It functions as a toast, providing informative or feedback messages to the user. - StyledDialog: A dialog component that appears from the bottom of the page, offering confirmation functionality through
StyledDialog.yesNo()
. It can also contain a custom body with any desired widgets, allowing for flexible dialog content.
There are more that aren't documented here as well. For those with access to Flood's source code, feel free to explore the style
package to see the other pre-built components.
To learn more about how to use the pre-built StyleComponents in your UIs, refer to the presentation layer of the Example Todo (opens in a new tab) app.
Customization
You can define your own StyleComponent
by simply extending StyleComponent
, and adding StyleComponentRenderer
s to your Style
to render them. Here's an example:
class StyledHeader extends StyleComponent {
final String? text;
StyledHeader(this.text);
}
class MyCustomStyleHeaderRenderer with IsTypedStyleRenderer<StyledHeader> {
@override
Widget renderTyped(BuildContext context, StyledHeader component) {
return StyledText.xl(component.text);
}
}
final style = FlatStyle()
..addRenderer(MyCustomStyleHeaderRenderer());
Instead of creating StyleComponent
s for every new component in your app, it's recommended to just create a Widget that composes multiple pre-built StyleComponent
s together. StyleComponent
s should only represent the building-blocks of a Style
, and more complex widgets should just use the existing StyleComponent
s.
Dynamic Styling
The Style Module supports dynamic styling, allowing you to change your app's style at runtime. This feature enables you to implement themes like light/dark mode or custom styles such as high-contrast or color-blind modes.
Initial Style Setup
When initializing your app, you can set an initial style and define a styleLoader
for asynchronous style loading:
await appPondContext.register(FloodAppComponent(
style: initialStyle, // Style to use during the splash screen.
styleLoader: () async {
// Load style based on user preferences or other factors
return await loadUserPreferredStyle();
},
));
Changing Style at Runtime
You can switch styles during runtime using the StyleAppComponent
:
context.styleAppComponent.style = newStyle;
This allows you to implement features like a theme switcher or apply user-specific styles dynamically.
Styleguide
The Style Module includes a powerful tool called the Styleguide
that allows you to preview and test the appearance of different components in your application. The Styleguide
provides a visual reference for designers and developers, ensuring consistency and adherence to the defined style.
To access the Styleguide
, you can navigate to /_styleguide
in your app. Check out the Url Bar Module to see how to navigate to that page within a mobile device.
Use with Pond
While you don't need to use the Style Module with Pond, it's recommended as Pond will automatically take care of setting the top-most Provider
necessary for your widgets to locate what the current Style
is.
Simply pass in the Style
into the FloodAppComponent
.
await appPondContext.register(FloodAppComponent(style: style));