https://github.com/onebeld/pleasantui
Graphical user interface library for Avalonia with its own controls
https://github.com/onebeld/pleasantui
avalonia avaloniaui c-sharp control controls csharp design dotnet interface library netstandard nuget pleasant style styled-components styles theme ui user-interface xaml
Last synced: about 2 months ago
JSON representation
Graphical user interface library for Avalonia with its own controls
- Host: GitHub
- URL: https://github.com/onebeld/pleasantui
- Owner: Onebeld
- License: mit
- Created: 2023-05-01T11:52:50.000Z (about 3 years ago)
- Default Branch: main
- Last Pushed: 2024-12-04T12:37:48.000Z (over 1 year ago)
- Last Synced: 2025-01-31T07:03:37.794Z (over 1 year ago)
- Topics: avalonia, avaloniaui, c-sharp, control, controls, csharp, design, dotnet, interface, library, netstandard, nuget, pleasant, style, styled-components, styles, theme, ui, user-interface, xaml
- Language: C#
- Homepage:
- Size: 4.76 MB
- Stars: 32
- Watchers: 2
- Forks: 1
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- Funding: .github/FUNDING.yml
- License: LICENSE
Awesome Lists containing this project
README






# PleasantUI
> **Repositories:** [Original (Onebeld)](https://github.com/Onebeld/PleasantUI) · [Fork (ghudulf)](https://github.com/ghudulf/PleasantUI)
PleasantUI is a cross-platform UI theme and control library for [Avalonia](https://github.com/AvaloniaUI/Avalonia), inspired by Microsoft Fluent Design and the WinUI/UWP visual language. It completely re-styles every standard Avalonia control and adds a suite of custom controls, a multi-theme engine with custom theme support, a reactive localization system, and a custom window chrome — all AOT-compatible with no `rd.xml` required.
The project has been in active development since 2021, originally as part of the [Regul](https://github.com/Onebeld/Regul) and [Regul Save Cleaner](https://github.com/Onebeld/RegulSaveCleaner) projects.
## ✨ Features
### Complete Fluent-style control theming
Every standard Avalonia control gets a full Fluent Design makeover — rounded corners, layered fill colors, smooth pointer-over and pressed transitions, and accent color integration:
| Control | Control | Control |
|---|---|---|
| Button (+ AppBar, Accent, Danger variants) | CheckBox | RadioButton |
| ToggleButton / ToggleSwitch | RepeatButton / ButtonSpinner | Slider |
| TextBox / AutoCompleteBox | NumericUpDown | ComboBox / DropDownButton |
| Calendar / CalendarDatePicker / TimePicker | DataGrid | ListBox / TreeView |
| Expander | TabControl / TabItem | ScrollBar / ScrollViewer |
| ProgressBar | Menu / ContextMenu | ToolTip |
| Carousel | Separator | NotificationCard |
### Custom Pleasant controls
Controls built from scratch that go beyond what Avalonia ships:
| Control | Description | Demo |
|-----------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------|
| `PleasantWindow` | Custom window chrome with a Fluent title bar, subtitle, custom icon/title content, optional blur, content-extends-into-titlebar, and macOS caption override | None |
| `NavigationView` / `NavigationViewItem` | Collapsible side navigation panel, similar to WinUI NavigationView | None |
| `PleasantTabView` / `PleasantTabItem` | Chromium-style tab strip with add/close buttons and scrollable tab bar | None |
| `ContentDialog` | Modal overlay dialog with bottom button panel and smooth scroll content area | None |
| `PleasantSnackbar` | Temporary non-intrusive notification bar |  |
| `ProgressRing` | Circular progress indicator — both determinate and indeterminate with animated arc |  |
| `OptionsDisplayItem` | Settings-style row with header, description, icon, action button slot, navigation chevron, and expandable content |  |
| `InformationBlock` | Compact pill-shaped label combining an icon and a value |  |
| `MarkedTextBox` / `MarkedNumericUpDown` | Input controls with inline label/unit markers | None |
| `RippleEffect` | Material-style ripple click feedback |  |
| `SmoothScrollViewer` | ScrollViewer with inertia gesture support | None |
| `PleasantMiniWindow` | Lightweight floating window | None |
| `Timeline` | Displays a list of events in chronological order along a vertical axis. Supports four layout modes, custom icons, and five severity types. |  |
| `InstallWizard` | A multi-step installation wizard with a sidebar step list, progress bar, and Back / Next / Cancel navigation. |  |
| `PleasantMenu` | A customizable flyout menu with a title, optional info badges, a grid of large icon buttons, and a footer bar with small utility buttons. |  |
| `PathPicker` | Combines a read-only TextBox with a browse button. Supports OpenFile, SaveFile, and OpenFolder modes, optional multi-select, file-type filters, and two-way binding on the selected path text. |  |
| `PopConfirm` | Wraps any trigger control and shows a small popup with a header, body, and Confirm / Cancel buttons before executing a command. |  |
### Theme engine
- Built-in themes: **Light**, **Dark**, **Mint**, **Strawberry**, **Ice**, **Sunny**, **Spruce**, **Cherry**, **Cave**, **Lunar**
- **System** mode — follows the OS light/dark preference automatically
- **Custom themes** — create, edit, export, import, and persist your own color palettes via the built-in `ThemeEditorWindow`
- Accent color follows the OS accent or can be overridden per-user; light/dark variants and gradient pairs are generated automatically
- Settings are persisted to disk automatically on desktop; mobile apps can save manually
### Localization system
- `Localizer` singleton backed by .NET `ResourceManager` — add any number of `.resx` resource files
- `{Localize Key}` AXAML markup extension binds reactively — switching language updates every bound string instantly without reloading views
- `Localizer.TrDefault(key, fallback)` for safe lookups that fall back to a raw string instead of an error message
- `LocalizationChanged` event for view models and code-behind to react to language switches
## Packages
| Package | Description |
|---|---|
| `PleasantUI` | Core theme, all control styles, Pleasant controls, theme engine, localization |
| `PleasantUI.ToolKit` | `MessageBox`, `ThemeEditorWindow`, color picker utilities |
| `PleasantUI.MaterialIcons` | Material Design icon geometry library for use with `PathIcon` |
| `PleasantUI.DataGrid` | Fluent-styled DataGrid extension |
## 📖 Documentation
Detailed reference docs for each control are in the [`docs/`](docs/) folder:
| Doc | Controls |
|---|---|
| [PleasantWindow](docs/PleasantWindow.md) | `PleasantWindow`, `IPleasantSplashScreen` |
| [PleasantMiniWindow](docs/PleasantMiniWindow.md) | `PleasantMiniWindow` |
| [PleasantTitleBar](docs/PleasantTitleBar.md) | `PleasantTitleBar` |
| [PleasantCaptionButtons](docs/PleasantCaptionButtons.md) | `PleasantCaptionButtons` |
| [NavigationView](docs/NavigationView.md) | `NavigationView`, `NavigationViewItem` |
| [PleasantTabView](docs/PleasantTabView.md) | `PleasantTabView`, `PleasantTabItem` |
| [ContentDialog](docs/ContentDialog.md) | `ContentDialog` |
| [MessageBox](docs/MessageBox.md) | `MessageBox` (ToolKit) |
| [PleasantDialog](docs/PleasantDialog.md) | `PleasantDialog` (ToolKit) |
| [CrashReportDialog](docs/CrashReportDialog.md) | `CrashReportDialog` |
| [StepDialog](docs/StepDialog.md) | `StepDialog` |
| [PleasantSnackbar](docs/PleasantSnackbar.md) | `PleasantSnackbar` |
| [ProgressRing](docs/ProgressRing.md) | `ProgressRing` |
| [OptionsDisplayItem](docs/OptionsDisplayItem.md) | `OptionsDisplayItem` |
| [InformationBlock](docs/InformationBlock.md) | `InformationBlock` |
| [Timeline](docs/Timeline.md) | `Timeline`, `TimelineItem` |
| [InstallWizard](docs/InstallWizard.md) | `InstallWizard`, `WizardStep` |
| [PathPicker](docs/PathPicker.md) | `PathPicker` |
| [PopConfirm](docs/PopConfirm.md) | `PopConfirm` |
| [PleasantMenu](docs/PleasantMenu.md) | `PleasantMenu`, `PleasantMenuItem`, `PleasantMenuFooterItem` |
| [PleasantMenuFlyout](docs/PleasantMenuFlyout.md) | `PleasantMenuFlyout` |
| [PleasantFlyout](docs/PleasantFlyout.md) | `PleasantFlyout` |
| [PinCode](docs/PinCode.md) | `PinCode` |
| [SelectionList](docs/SelectionList.md) | `SelectionList`, `SelectionListItem` |
| [RippleEffect](docs/RippleEffect.md) | `RippleEffect` |
| [SmoothScrollViewer](docs/SmoothScrollViewer.md) | `SmoothScrollViewer` |
| [MarkedInputs](docs/MarkedInputs.md) | `MarkedTextBox`, `MarkedNumericUpDown` |
| [MarkedTextBox](docs/MarkedTextBox.md) | `MarkedTextBox` |
| [MarkedNumericUpDown](docs/MarkedNumericUpDown.md) | `MarkedNumericUpDown` |
| [PleasantDatePicker](docs/PleasantDatePicker.md) | `PleasantDatePicker` |
| [PleasantBorder](docs/PleasantBorder.md) | `PleasantBorder` |
| [BackdropBlurBorder](docs/BackdropBlurBorder.md) | `BackdropBlurBorder` |
| [ShadowBorder](docs/ShadowBorder.md) | `ShadowBorder` |
| [PleasantTrayPopup](docs/PleasantTrayPopup.md) | `PleasantTrayPopup`, `StatusItem` |
| [DataGrid](docs/DataGrid.md) | `PleasantUI.DataGrid` package |
| [PropertyGrid](docs/PropertyGrid.md) | `PropertyGrid`, `PropertyRow` |
| [CommandBar](docs/CommandBar.md) | `CommandBar`, `CommandBarButton`, `CommandBarToggleButton` |
| [BreadcrumbBar](docs/BreadcrumbBar.md) | `BreadcrumbBar`, `BreadcrumbBarItem` |
| [PleasantDrawer](docs/PleasantDrawer.md) | `PleasantDrawer` |
| [DashboardCard](docs/DashboardCard.md) | `DashboardCard` |
| [DownloadPanel](docs/DownloadPanel.md) | `DownloadPanel` |
| [LogViewerPanel](docs/LogViewerPanel.md) | `LogViewerPanel` |
| [TerminalPanel](docs/TerminalPanel.md) | `TerminalPanel` |
| [TreeViewPanel](docs/TreeViewPanel.md) | `TreeViewPanel`, `TreeViewSection` |
| [ItemListPanel](docs/ItemListPanel.md) | `ItemListPanel` |
| [VirtualizingWrapPanel](docs/VirtualizingWrapPanel.md) | `VirtualizingWrapPanel` |
| [PleasantView](docs/PleasantView.md) | `PleasantView` |
| [PleasantSplashScreen](docs/PleasantSplashScreen.md) | `PleasantSplashScreen` |
| [ModalWindowHost](docs/ModalWindowHost.md) | `ModalWindowHost` |
| [ThemePreviewVariantScope](docs/ThemePreviewVariantScope.md) | `ThemePreviewVariantScope` |
| [Localization](docs/Localization.md) | `Localizer`, `{Localize}` markup extension |
| [Theme Engine](docs/ThemeEngine.md) | `PleasantTheme`, custom themes, color tokens |
## 🚀 Getting Started
### Install
**Package List (Avalonia 12)**
Published on NuGet:
```xml
```
### Add the theme
In your `App.axaml`, add `PleasantTheme` to your styles:
```xml
```
### Initialize correctly
Make sure `AvaloniaXamlLoader.Load(this)` is called in `Initialize()`:
```csharp
public partial class App : Application
{
public override void Initialize()
{
AvaloniaXamlLoader.Load(this); // required
}
public override void OnFrameworkInitializationCompleted()
{
if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop)
{
desktop.MainWindow = new MainWindow
{
DataContext = new MainWindowViewModel(),
};
}
base.OnFrameworkInitializationCompleted();
}
}
```
### Use PleasantWindow
Replace `Window` with `PleasantWindow` to get the custom Fluent title bar:
```csharp
using PleasantUI.Controls;
public partial class MainWindow : PleasantWindow
{
public MainWindow() => InitializeComponent();
}
```
```xml
```
Key `PleasantWindow` properties:
| Property | Type | Description |
|---|---|---|
| `TitleBarType` | `Classic` / `ClassicExtended` | Title bar layout style |
| `ExtendsContentIntoTitleBar` | `bool` | Lets content render behind the title bar |
| `Subtitle` | `string` | Secondary text shown next to the title |
| `DisplayIcon` | `object` | Custom icon content in the title bar |
| `DisplayTitle` | `object` | Custom title content (e.g. a `PathIcon`) |
| `EnableBlur` | `bool` | Acrylic/blur window background |
| `CaptionButtons` | enum | Which caption buttons to show |
| `LeftTitleBarContent` | `object` | Content injected left of the title |
## 🌍 Localization
Register your `.resx` resource managers in your `Application` constructor:
```csharp
public App()
{
Localizer.AddRes(new ResourceManager(typeof(Properties.Localizations.App)));
Localizer.ChangeLang("en");
}
```
Use `{Localize Key}` in AXAML — updates live when the language changes:
```xml
```
Switch language at runtime:
```csharp
Localizer.ChangeLang("ru");
```
Safe lookup with fallback in code-behind:
```csharp
string title = Localizer.TrDefault("DialogTitle", "Confirm");
```
## 🔲 Button variants
```xml
```
## 📃 OptionsDisplayItem
```xml
```
## 🖼️ Screenshots
[Regul Save Cleaner](https://github.com/Onebeld/RegulSaveCleaner)

[OlibKey](https://github.com/Onebeld/OlibKey)

## ❤️ Credits
- [Avalonia](https://github.com/AvaloniaUI/Avalonia)
- Some controls inspired by PieroCastillo's [Aura.UI](https://github.com/PieroCastillo/Aura.UI)
- [ProgressRing](https://github.com/ymg2006/FluentAvalonia.ProgressRing) by ymg2006
- Built with [JetBrains Rider](https://www.jetbrains.com/rider/)