CraftUI is a design system library for .NET MAUI, giving developers a fully customizable and maintainable set of UI components, free from external dependencies and package managers. Just integrate the code directly into your project and shape it exactly to your needs, now and forever.
Relying on a package is always a trade-off that should be carefully considered. While packages provide convenience, they often introduce hidden risks:
- Popular libraries like MediatR and MassTransit eventually moved to paid models, creating unexpected costs.
- Package updates can introduce regressions or breaking changes that disrupt stable codebases.
- Some projects become abandoned, leaving you with outdated dependencies and no support.
- Version conflicts between packages can create complex dependency hell scenarios.
- You lose visibility and control over the underlying code, making debugging and customization harder.
With CraftUI, you own the code from day one. No hidden surprises, no lock-in, no external constraints. You’re free to evolve it at your own pace and ensure long-term stability and maintainability.
📅 I’m currently working on an article, a video, and a script that will guide you through all the steps required to start a new project with CraftUI or integrate it into an existing one. Estimated delivery: 06/2025.
MAUI Supported platforms |
---|
✔️ Android |
✔️ iOS |
CraftUI provides a set of reusable UI controls to accelerate your .NET MAUI development while keeping full control over customization and code ownership.
Key properties available in the CfButton:
- IsLoading Shows a progress bar at the bottom
Both Button and CfButton have two main styles available:
- PlainPrimary(Cf)Button - Text-only button with primary color text and transparent background
- FilledPrimary(Cf)Button - Solid button with primary color background and contrasting text
<controls:CfButton
Text="Load 5s Data Demo"
IsLoading="{Binding DemoOneCommand.Notifier.ShowLoader}"
Command="{Binding DemoOneCommand}" />
Key properties available in the CfEntry:
- Label Provides a text label above the input field
- Error Displays validation error messages
- IsRequired Indicates if the field requires input
- Info Shows additional information text below the input
- ActionIconSource Adds an icon button inside the entry
- ActionIconCommand Command executed when the action icon is tapped
- IsLoading Shows a loading indicator when data is being fetched
<controls:CfEntry
Label="First name or Last name"
Text="{Binding FullName, Mode=TwoWay}"
Error="{Binding ValidationResult,
Converter={StaticResource ShowErrorConverter},
ConverterParameter={x:Static page:EntryPageViewModelValidator.FullNameProperty}}"
IsRequired="True"
ActionIconSource="demo_info.png"
ActionIconCommand="{Binding FullnameInfoCommand}"/>
Key properties available in the CfPicker:
- Label Provides a text label above the picker field
- SelectedItem Two-way binding to the selected item from ItemsSource
- ItemsSource The collection of items to display in the picker
- ItemDisplay Defines which property of the ItemsSource objects should be displayed
- TapCommand Command executed when the picker is tapped or an item is selected
- IsLoading Shows a loading indicator when data is being fetched
<controls:CfPicker
Label="Country"
SelectedItem="{Binding Country}"
ItemsSource="{Binding CountriesLoader.Result}"
ItemDisplay="{x:Static page:PickerPageViewModel.CountryDisplayProperty}"
TapCommand="{Binding CountrySelectedCommand}"
IsLoading="{Binding CountriesLoader.ShowLoader}" />
For key properties, refer to CfPicker.
<controls:CfPickerPopup
Label="Country"
SelectedItem="{Binding Country}"
ItemsSource="{Binding CountriesLoader.Result}"
ItemDisplay="{x:Static page:PickerPageViewModel.CountryDisplayProperty}"
TapCommand="{Binding CountrySelectedCommand}"
IsLoading="{Binding CountriesLoader.ShowLoader}"/>
Key properties available in the CfProgressBar:
- Progress Float value between 0.0 and 1.0 that represents the progress level
- ProgressColor Defines the color of the progress indicator
- BaseColor Sets the background color of the progress bar
- UseGradient Boolean flag to enable a gradient effect on the progress indicator
- GradientColor Defines the start color for the gradient (when UseGradient is true)
- RoundCaps Boolean flag to enable rounded ends on the progress bar
- UseRange Boolean flag to display a specific range rather than progress from left to right
- LowerRangeValue When UseRange is true, defines the start position of the highlighted range (0-1)
- UpperRangeValue When UseRange is true, defines the end position of the highlighted range (0-1)
<controls:CfProgressBar
Progress="{Binding CurrentProgress}"
UseGradient="True"
GradientColor="{StaticResource Primary200}"
ProgressColor="{StaticResource Primary600}"
RoundCaps="True"
HeightRequest="20"
Style="{StaticResource ProgressBarStyle}" />
Key properties available in the CfDatePicker:
- PlaceHolder: Text displayed when no date is selected, the default value I used is "/ . / . /".
- NullableDate: The selected date that can be null, allowing the field to be cleared.
- Format: Defines how the selected date is displayed (e.g., "dd/MM/yyyy").
- MinimumDate: Sets the earliest selectable date in the picker.
- MaximumDate: Sets the latest selectable date in the picker.
- ShowClearButton: Determines whether the clear (X) button is visible to reset the date.
<controls:CfDatePicker
Label="Select a date (with min/max)"
NullableDate="{Binding RangeDateNullable}"
MinimumDate="{Binding MinimumDate}"
MaximumDate="{Binding MaximumDate}"
ShowClearButton="True"
Info="Pick a date between yesterday dans 30 days ahead."/>
CfCollectionPopup is a custom Popup control that displays a list of selectable items in a bottom-sheet style interface.
- Title Sets the header text displayed at the top of the popup
- ItemsSource The collection of items to display in the popup list
- SelectedItem The currently selected item (two-way bindable)
- ItemDisplay Defines which property of the items should be displayed as text
This component forms the foundation for the CfPickerPopup control and is used throughout the application to provide consistent selection experiences. Additional implementation examples can be found in the Use Cases section of the Demo app.
I wrote articles to explain how I built this library. If you’re curious about the backstage, have a look here.
- MAUI (Library Part 1) Create a Custom Entry using SkiaSharp
- MAUI (Library Part 2) Info & Error states with FluentValidation
- MAUI (Library Part 3) Loading state with Picker Label
- MAUI (Library Part 4) Custom Picker with Collection View and Popup
- MAUI (Library Part 5) Extending Control Behavior with Button
- MAUI (Library Part 6) Custom Button with Progress Bar
- MAUI (CraftUI Part 7) Custom Date Picker Nullable