{"id":28443140,"url":"https://github.com/synaperesearchsystemscorp/synapsers.mudblazor.thememanager.saver","last_synced_at":"2026-01-20T17:52:56.470Z","repository":{"id":295643848,"uuid":"990759932","full_name":"SynapeResearchSystemsCorp/Synapsers.MudBlazor.ThemeManager.Saver","owner":"SynapeResearchSystemsCorp","description":"🎨 Enhanced MudBlazor ThemeManager with powerful theme saving \u0026 persistence capabilities. Design, customize, save \u0026 manage themes for Blazor applications with JSON file storage, localStorage integration \u0026 automatic persistence.","archived":false,"fork":false,"pushed_at":"2025-05-29T20:17:55.000Z","size":6378,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-06-06T07:01:40.928Z","etag":null,"topics":["blazor","blazor-client","blazor-components","blazor-server","blazor-webassembly","component","component-library","components","csharp","hacktoberfest","material","netcore","wasm"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/SynapeResearchSystemsCorp.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-05-26T15:35:26.000Z","updated_at":"2025-05-29T20:17:58.000Z","dependencies_parsed_at":"2025-05-26T16:59:58.555Z","dependency_job_id":"c2f63490-deaa-4b6b-b253-9e0be6cb495e","html_url":"https://github.com/SynapeResearchSystemsCorp/Synapsers.MudBlazor.ThemeManager.Saver","commit_stats":null,"previous_names":["dorofino/mudblazor.thememanager.saver","synaperesearchsystemscorp/synapsers.mudblazor.thememanager.saver"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/SynapeResearchSystemsCorp/Synapsers.MudBlazor.ThemeManager.Saver","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SynapeResearchSystemsCorp%2FSynapsers.MudBlazor.ThemeManager.Saver","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SynapeResearchSystemsCorp%2FSynapsers.MudBlazor.ThemeManager.Saver/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SynapeResearchSystemsCorp%2FSynapsers.MudBlazor.ThemeManager.Saver/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SynapeResearchSystemsCorp%2FSynapsers.MudBlazor.ThemeManager.Saver/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/SynapeResearchSystemsCorp","download_url":"https://codeload.github.com/SynapeResearchSystemsCorp/Synapsers.MudBlazor.ThemeManager.Saver/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/SynapeResearchSystemsCorp%2FSynapsers.MudBlazor.ThemeManager.Saver/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":262585781,"owners_count":23332721,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["blazor","blazor-client","blazor-components","blazor-server","blazor-webassembly","component","component-library","components","csharp","hacktoberfest","material","netcore","wasm"],"created_at":"2025-06-06T07:00:33.957Z","updated_at":"2026-01-20T17:52:56.436Z","avatar_url":"https://github.com/SynapeResearchSystemsCorp.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Synapsers MudBlazor ThemeManager Saver\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"src/Synapsers.MudBlazor.ThemeManager.Saver/Synapsers.MudBlazor.ThemeManager.Saver.webp\" alt=\"Synapsers MudBlazor Theme Manager Saver\" style=\"max-width: 100%; height: auto;\"\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://github.com/SynapeResearchSystemsCorp/Synapsers.MudBlazor.ThemeManager.Saver/stargazers\"\u003e\n    \u003cimg src=\"https://img.shields.io/github/stars/SynapeResearchSystemsCorp/Synapsers.MudBlazor.ThemeManager.Saver\" alt=\"GitHub Repo stars\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://github.com/SynapeResearchSystemsCorp/Synapsers.MudBlazor.ThemeManager.Saver/commits/main\"\u003e\n    \u003cimg src=\"https://img.shields.io/github/last-commit/SynapeResearchSystemsCorp/Synapsers.MudBlazor.ThemeManager.Saver\" alt=\"GitHub last commit\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://github.com/SynapeResearchSystemsCorp/Synapsers.MudBlazor.ThemeManager.Saver/graphs/contributors\"\u003e\n    \u003cimg src=\"https://img.shields.io/github/contributors/SynapeResearchSystemsCorp/Synapsers.MudBlazor.ThemeManager.Saver\" alt=\"Contributors\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://www.nuget.org/packages/Synapsers.MudBlazor.ThemeManager.Saver/\"\u003e\n    \u003cimg src=\"https://img.shields.io/nuget/v/Synapsers.MudBlazor.ThemeManager.Saver.svg\" alt=\"NuGet version\"\u003e\n  \u003c/a\u003e\n  \u003ca href=\"https://www.nuget.org/packages/Synapsers.MudBlazor.ThemeManager.Saver/\"\u003e\n    \u003cimg src=\"https://img.shields.io/nuget/dt/Synapsers.MudBlazor.ThemeManager.Saver.svg\" alt=\"NuGet downloads\"\u003e\n  \u003c/a\u003e\n\u003c/p\u003e\n\n\u003e **Enhanced Fork**: This project is an enhanced fork of the original [MudBlazor ThemeManager](https://github.com/MudBlazor/ThemeManager) with robust theme saving and persistence capabilities for Blazor applications.\n\n## Overview\n\n**Synapsers MudBlazor ThemeManager Saver** is a comprehensive solution for designing, customizing, saving, and managing themes in MudBlazor-based applications. It addresses a key limitation of the original ThemeManager by providing a flexible, extensible persistence framework for user themes and preferences.\n\n---\n\n## ✨ Features\n\n- **Visual Theme Editor**: Intuitive UI for customizing all MudBlazor theme properties (colors, typography, layout, etc.)\n- **Persistence Framework**: Save and load themes using browser localStorage, server file system, or custom providers\n- **Dark/Light Mode**: Full support for toggling and persisting dark/light mode\n- **Theme Presets**: Easily manage and apply common theme configurations\n- **Production-Ready**: Error handling, validation, versioning, and extensibility\n- **Extensible**: Add your own storage providers or extend theme models\n\n---\n\n## Architecture \u0026 Core Components\n\n- **MudThemeManager**: Main component for theme editing and preview\n- **ThemeManagerTheme**: Model representing all theme properties (colors, typography, layout, etc.)\n- **ThemePersistenceService**: Handles saving/loading themes (JSON, file, localStorage, etc.)\n- **ThemeStateService**: Manages current theme state, initialization, and change notifications\n- **Extensions**: Utility methods and serialization helpers\n\n---\n\n## How It Works\n\n1. **User customizes theme** in the UI (colors, fonts, layout, etc.)\n2. **ThemeManagerTheme** model is updated and previewed live\n3. **ThemePersistenceService** saves the theme to the chosen storage (localStorage, file, etc.)\n4. **ThemeStateService** loads and applies the theme on app startup, and notifies components of changes\n5. **Dark/Light mode** and all preferences are persisted and restored automatically\n\n---\n\n## Usage \u0026 Integration\n\n### 1. Register Services\n\n```csharp\n// In Program.cs\nbuilder.Services.AddMudServices();\nbuilder.Services.AddThemePersistence(); // Registers ThemePersistenceService and ThemeStateService\n```\n\n### 2. Add to Layout\n\n```razor\n@using Synapsers.MudBlazor.ThemeManager.Saver\n@inject ThemeStateService ThemeStateService\n\n\u003cMudThemeProvider Theme=\"ThemeStateService.ThemeManager.Theme\" @bind-IsDarkMode=\"ThemeStateService.IsDarkMode\" /\u003e\n\u003cMudThemeManagerButton OnClick=\"@((e) =\u003e OpenThemeManager(true))\" /\u003e\n\u003cMudThemeManager Open=\"_themeManagerOpen\" OpenChanged=\"OpenThemeManager\" Theme=\"ThemeStateService.ThemeManager\" ThemeChanged=\"UpdateThemeAsync\" IsDarkMode=\"ThemeStateService.IsDarkMode\" /\u003e\n```\n\n### 3. Persisting Themes\n\n- **Browser (localStorage):**\n  - Uses JSInterop to save/load JSON theme data\n- **Server (File System):**\n  - Saves/loads JSON files in `wwwroot` or a configurable path\n- **Custom Providers:**\n  - Implement your own by extending `ThemePersistenceService`\n\n### 4. Example: Save/Load Theme (localStorage)\n\n```csharp\npublic async Task SaveThemeToLocalStorage(ThemeManagerTheme theme)\n{\n    var json = JsonSerializer.Serialize(theme, new JsonSerializerOptions { WriteIndented = true });\n    await JSRuntime.InvokeVoidAsync(\"localStorage.setItem\", \"mudblazor-theme\", json);\n}\n\npublic async Task\u003cThemeManagerTheme\u003e LoadThemeFromLocalStorage()\n{\n    var json = await JSRuntime.InvokeAsync\u003cstring\u003e(\"localStorage.getItem\", \"mudblazor-theme\");\n    return string.IsNullOrEmpty(json) ? new ThemeManagerTheme() : JsonSerializer.Deserialize\u003cThemeManagerTheme\u003e(json);\n}\n```\n\n### 5. Example: Save/Load Theme (File System)\n\n```csharp\npublic async Task SaveThemeToFile(ThemeManagerTheme theme, string filePath)\n{\n    var json = JsonSerializer.Serialize(theme, new JsonSerializerOptions { WriteIndented = true });\n    await File.WriteAllTextAsync(filePath, json);\n}\n\npublic async Task\u003cThemeManagerTheme\u003e LoadThemeFromFile(string filePath)\n{\n    if (!File.Exists(filePath)) return new ThemeManagerTheme();\n    var json = await File.ReadAllTextAsync(filePath);\n    return JsonSerializer.Deserialize\u003cThemeManagerTheme\u003e(json) ?? new ThemeManagerTheme();\n}\n```\n\n---\n\n## Theme Presets\n\nYou can define and use theme presets for quick switching:\n\n```csharp\npublic static class ThemePresets\n{\n    public static ThemeManagerTheme DefaultLight =\u003e new() { /* ... */ };\n    public static ThemeManagerTheme MaterialDark =\u003e new() { /* ... */ };\n    public static Dictionary\u003cstring, ThemeManagerTheme\u003e GetAllPresets() =\u003e new() {\n        { \"Default Light\", DefaultLight },\n        { \"Material Dark\", MaterialDark }\n    };\n}\n```\n\n---\n\n## Advanced Features\n\n- **Validation**: Ensure theme data is valid before saving\n- **Comparison**: Compare two themes for equality\n- **Versioning**: Add version info to saved themes for migration\n- **Automatic/Manual Save**: Save on every change or on demand\n\n---\n\n## Best Practices\n\n1. Always validate theme data before saving\n2. Use try-catch for all persistence operations\n3. Register your persistence service in `Program.cs`\n4. Use the `ThemeChanged` event for automatic saving\n5. Consider file permissions and backup for server-side storage\n\n---\n\n## Example Theme JSON\n\n```json\n{\n  \"themeManagerTheme\": {\n    \"theme\": {\n      \"paletteLight\": { \"primary\": \"#1976d2\", ... },\n      \"paletteDark\": { \"primary\": \"#2196f3\", ... }\n    },\n    \"fontFamily\": \"Roboto\",\n    \"defaultBorderRadius\": 4,\n    \"defaultElevation\": 1,\n    \"appBarElevation\": 25,\n    \"drawerElevation\": 2,\n    \"drawerClipMode\": \"Never\",\n    \"rtl\": false\n  },\n  \"isDarkMode\": false\n}\n```\n\n---\n\n## Project Structure\n\n- **Components/**\n  - `MudThemeManager.razor` - Main theme management UI\n  - `MudThemeManagerButton.razor` - Button to open the theme manager\n  - `MudThemeManagerColorItem.razor` - Color picker for palette items\n- **Models/**\n  - `ThemeManagerTheme.cs` - Theme model\n  - `ThemePaletteColor.cs` - Color representation\n  - `ThemeUpdatedValue.cs` - Value object for updates\n- **Services/**\n  - `ThemePersistenceService.cs` - Theme persistence logic\n  - `ThemeStateService.cs` - Theme state and notification\n- **Extensions/**\n  - Utility and serialization helpers\n\n---\n\n## Getting Started\n\n1. Add the package: `dotnet add package Synapsers.MudBlazor.ThemeManager.Saver`\n2. Register services in `Program.cs`\n3. Add the components to your layout\n4. Choose and configure your persistence method\n5. Enjoy persistent, user-friendly theme management in your MudBlazor app!\n\n---\n\n## Contributing \u0026 Support\n\nContributions are welcome! See [CONTRIBUTING.md](CONTRIBUTING.md) for details.\n\n---\n\n## License\n\nMIT License. See [LICENSE](LICENSE).\n\n---\n\n## Acknowledgments\n\n- [MudBlazor](https://mudblazor.com/) for the original ThemeManager\n- All contributors and users who helped improve this project\n\n\n\n\n\n\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsynaperesearchsystemscorp%2Fsynapsers.mudblazor.thememanager.saver","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsynaperesearchsystemscorp%2Fsynapsers.mudblazor.thememanager.saver","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsynaperesearchsystemscorp%2Fsynapsers.mudblazor.thememanager.saver/lists"}