diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index dbc87aff..c68ba7f9 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -25,7 +25,7 @@ jobs: - name: Setup .NET uses: actions/setup-dotnet@v4 with: - dotnet-version: '9.0.x' + dotnet-version: '10.0.x' - name: Restore (with retry) uses: nick-fields/retry@v3 @@ -34,17 +34,19 @@ jobs: max_attempts: 3 retry_wait_seconds: 15 command: | - dotnet restore src/PleasantUI/PleasantUI.csproj + dotnet restore generators/PleasantUI.Localization.Generator/PleasantUI.Localization.Generator.csproj + dotnet restore analyzers/PleasantUI.Localization.Analyzer/PleasantUI.Localization.Analyzer.csproj dotnet restore src/PleasantUI.DataGrid/PleasantUI.DataGrid.csproj - dotnet restore src/PleasantUI.MaterialIcons/PleasantUI.MaterialIcons.csproj dotnet restore src/PleasantUI.ToolKit/PleasantUI.ToolKit.csproj + dotnet restore src/PleasantUI/PleasantUI.csproj - name: Build run: | - dotnet build src/PleasantUI/PleasantUI.csproj --configuration Release --no-restore + dotnet build generators/PleasantUI.Localization.Generator/PleasantUI.Localization.Generator.csproj --configuration Release --no-restore + dotnet build analyzers/PleasantUI.Localization.Analyzer/PleasantUI.Localization.Analyzer.csproj --configuration Release --no-restore dotnet build src/PleasantUI.DataGrid/PleasantUI.DataGrid.csproj --configuration Release --no-restore - dotnet build src/PleasantUI.MaterialIcons/PleasantUI.MaterialIcons.csproj --configuration Release --no-restore dotnet build src/PleasantUI.ToolKit/PleasantUI.ToolKit.csproj --configuration Release --no-restore + dotnet build src/PleasantUI/PleasantUI.csproj --configuration Release --no-restore - name: Verify packages exist run: | @@ -52,7 +54,7 @@ jobs: find src/ -name "*.nupkg" 2>/dev/null | sort FAILED=0 - for project in PleasantUI PleasantUI.DataGrid PleasantUI.MaterialIcons PleasantUI.ToolKit; do + for project in PleasantUI PleasantUI.DataGrid PleasantUI.ToolKit; do FOUND=$(find "src/$project" -name "*.nupkg" 2>/dev/null | head -1) if [ -z "$FOUND" ]; then echo "ERROR: No .nupkg found anywhere under src/$project" @@ -75,7 +77,6 @@ jobs: path: | src/PleasantUI/bin/Release/*.nupkg src/PleasantUI.DataGrid/bin/Release/*.nupkg - src/PleasantUI.MaterialIcons/bin/Release/*.nupkg src/PleasantUI.ToolKit/bin/Release/*.nupkg if-no-files-found: error @@ -107,7 +108,7 @@ jobs: - name: Setup .NET uses: actions/setup-dotnet@v4 with: - dotnet-version: '9.0.x' + dotnet-version: '10.0.x' - name: Publish to NuGet (Trusted Publishing, with retry) uses: nick-fields/retry@v3 diff --git a/.github/workflows/canary-release.yml b/.github/workflows/canary-release.yml index c915d28b..13d97b11 100644 --- a/.github/workflows/canary-release.yml +++ b/.github/workflows/canary-release.yml @@ -117,7 +117,7 @@ jobs: - name: Setup .NET uses: actions/setup-dotnet@v4 with: - dotnet-version: '9.0.x' + dotnet-version: '10.0.x' - name: Restore (with retry) uses: nick-fields/retry@v3 @@ -126,10 +126,11 @@ jobs: max_attempts: 3 retry_wait_seconds: 15 command: | - dotnet restore src/PleasantUI/PleasantUI.csproj + dotnet restore generators/PleasantUI.Localization.Generator/PleasantUI.Localization.Generator.csproj + dotnet restore analyzers/PleasantUI.Localization.Analyzer/PleasantUI.Localization.Analyzer.csproj dotnet restore src/PleasantUI.DataGrid/PleasantUI.DataGrid.csproj - dotnet restore src/PleasantUI.MaterialIcons/PleasantUI.MaterialIcons.csproj dotnet restore src/PleasantUI.ToolKit/PleasantUI.ToolKit.csproj + dotnet restore src/PleasantUI/PleasantUI.csproj - name: Modify Package.props with canary version run: | @@ -147,10 +148,11 @@ jobs: - name: Build run: | - dotnet build src/PleasantUI/PleasantUI.csproj --configuration Release --no-restore + dotnet build generators/PleasantUI.Localization.Generator/PleasantUI.Localization.Generator.csproj --configuration Release --no-restore + dotnet build analyzers/PleasantUI.Localization.Analyzer/PleasantUI.Localization.Analyzer.csproj --configuration Release --no-restore dotnet build src/PleasantUI.DataGrid/PleasantUI.DataGrid.csproj --configuration Release --no-restore - dotnet build src/PleasantUI.MaterialIcons/PleasantUI.MaterialIcons.csproj --configuration Release --no-restore dotnet build src/PleasantUI.ToolKit/PleasantUI.ToolKit.csproj --configuration Release --no-restore + dotnet build src/PleasantUI/PleasantUI.csproj --configuration Release --no-restore - name: Build single-file example app uses: nick-fields/retry@v3 @@ -196,7 +198,7 @@ jobs: find src/ -name "*.nupkg" 2>/dev/null | sort FAILED=0 - for project in PleasantUI PleasantUI.DataGrid PleasantUI.MaterialIcons PleasantUI.ToolKit; do + for project in PleasantUI PleasantUI.DataGrid PleasantUI.ToolKit; do FOUND=$(find "src/$project" -name "*.nupkg" 2>/dev/null | head -1) if [ -z "$FOUND" ]; then echo "ERROR: No .nupkg found anywhere under src/$project" @@ -212,7 +214,7 @@ jobs: - name: Rename packages with canary version run: | CANARY_VERSION="${{ steps.version.outputs.canary_version }}" - for project in PleasantUI PleasantUI.DataGrid PleasantUI.MaterialIcons PleasantUI.ToolKit; do + for project in PleasantUI PleasantUI.DataGrid PleasantUI.ToolKit; do for pkg in src/$project/bin/Release/*.nupkg; do if [ -f "$pkg" ]; then BASE_NAME=$(basename "$pkg" .nupkg) @@ -741,7 +743,6 @@ jobs: 'Always end with a Packages section listing:' \ '- PleasantUI' \ '- PleasantUI.DataGrid' \ - '- PleasantUI.MaterialIcons' \ '- PleasantUI.ToolKit' \ '' \ 'Add an Example App section noting that a single-file example application is included in the canary release artifacts for testing the canary build.' \ @@ -788,7 +789,6 @@ jobs: printf '\n### Packages\n' printf '- PleasantUI\n' printf '- PleasantUI.DataGrid\n' - printf '- PleasantUI.MaterialIcons\n' printf '- PleasantUI.ToolKit\n' printf '\n### Example App\n\n' printf 'A single-file example application is included in the canary release artifacts for this build.\n' @@ -815,7 +815,6 @@ jobs: printf '\n### Packages\n' printf '- PleasantUI\n' printf '- PleasantUI.DataGrid\n' - printf '- PleasantUI.MaterialIcons\n' printf '- PleasantUI.ToolKit\n' printf '\n### Example App\n\n' printf 'A single-file example application is included in the canary release artifacts for this build.\n' @@ -856,7 +855,7 @@ jobs: const owner = context.repo.owner; const repo = context.repo.repo; - const body = `## Canary Release Build\n\n${notes}\n\n### Release Artifacts\n\nDownload all canary release artifacts (NuGet packages + example app) from the workflow run page:\n\n[Download Artifacts](https://github.com/${owner}/${repo}/actions/runs/${runId})\n\nThe "canary-release-artifacts" artifact includes:\n- PleasantUI NuGet packages\n- PleasantUI.DataGrid NuGet packages\n- PleasantUI.MaterialIcons NuGet packages\n- PleasantUI.ToolKit NuGet packages\n- PleasantUI Example app (Linux x64)`; + const body = `## Canary Release Build\n\n${notes}\n\n### Release Artifacts\n\nDownload all canary release artifacts (NuGet packages + example app) from the workflow run page:\n\n[Download Artifacts](https://github.com/${owner}/${repo}/actions/runs/${runId})\n\nThe "canary-release-artifacts" artifact includes:\n- PleasantUI NuGet packages\n- PleasantUI.DataGrid NuGet packages\n- PleasantUI.ToolKit NuGet packages\n- PleasantUI Example app (Linux x64)`; await github.rest.issues.createComment({ issue_number: context.issue.number, @@ -888,7 +887,6 @@ jobs: echo "The \`canary-release-artifacts\` artifact includes:" echo "- PleasantUI NuGet packages" echo "- PleasantUI.DataGrid NuGet packages" - echo "- PleasantUI.MaterialIcons NuGet packages" echo "- PleasantUI.ToolKit NuGet packages" echo "- PleasantUI Example app (Linux x64)" if [ "${{ steps.pr_comment.outcome }}" == "failure" ]; then diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 10a422b5..636ed538 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -93,7 +93,7 @@ jobs: if: steps.tag_check.outputs.exists == 'false' uses: actions/setup-dotnet@v4 with: - dotnet-version: '9.0.x' + dotnet-version: '10.0.x' - name: Restore (with retry) if: steps.tag_check.outputs.exists == 'false' @@ -103,18 +103,20 @@ jobs: max_attempts: 3 retry_wait_seconds: 15 command: | - dotnet restore src/PleasantUI/PleasantUI.csproj + dotnet restore generators/PleasantUI.Localization.Generator/PleasantUI.Localization.Generator.csproj + dotnet restore analyzers/PleasantUI.Localization.Analyzer/PleasantUI.Localization.Analyzer.csproj dotnet restore src/PleasantUI.DataGrid/PleasantUI.DataGrid.csproj - dotnet restore src/PleasantUI.MaterialIcons/PleasantUI.MaterialIcons.csproj dotnet restore src/PleasantUI.ToolKit/PleasantUI.ToolKit.csproj + dotnet restore src/PleasantUI/PleasantUI.csproj - name: Build if: steps.tag_check.outputs.exists == 'false' run: | - dotnet build src/PleasantUI/PleasantUI.csproj --configuration Release --no-restore + dotnet build generators/PleasantUI.Localization.Generator/PleasantUI.Localization.Generator.csproj --configuration Release --no-restore + dotnet build analyzers/PleasantUI.Localization.Analyzer/PleasantUI.Localization.Analyzer.csproj --configuration Release --no-restore dotnet build src/PleasantUI.DataGrid/PleasantUI.DataGrid.csproj --configuration Release --no-restore - dotnet build src/PleasantUI.MaterialIcons/PleasantUI.MaterialIcons.csproj --configuration Release --no-restore dotnet build src/PleasantUI.ToolKit/PleasantUI.ToolKit.csproj --configuration Release --no-restore + dotnet build src/PleasantUI/PleasantUI.csproj --configuration Release --no-restore - name: Verify packages exist if: steps.tag_check.outputs.exists == 'false' @@ -123,7 +125,7 @@ jobs: find src/ -name "*.nupkg" 2>/dev/null | sort FAILED=0 - for project in PleasantUI PleasantUI.DataGrid PleasantUI.MaterialIcons PleasantUI.ToolKit; do + for project in PleasantUI PleasantUI.DataGrid PleasantUI.ToolKit; do FOUND=$(find "src/$project" -name "*.nupkg" 2>/dev/null | head -1) if [ -z "$FOUND" ]; then echo "ERROR: No .nupkg found anywhere under src/$project" @@ -665,7 +667,6 @@ jobs: 'Always end with a Packages section listing:' \ '- PleasantUI' \ '- PleasantUI.DataGrid' \ - '- PleasantUI.MaterialIcons' \ '- PleasantUI.ToolKit' \ '' \ '---' \ @@ -709,7 +710,6 @@ jobs: printf '\n### Packages\n' printf '- PleasantUI\n' printf '- PleasantUI.DataGrid\n' - printf '- PleasantUI.MaterialIcons\n' printf '- PleasantUI.ToolKit\n' } > /tmp/release_notes.md echo "Using simple commit-based release notes (AI generation skipped)." @@ -729,7 +729,6 @@ jobs: printf '\n### Packages\n' printf '- PleasantUI\n' printf '- PleasantUI.DataGrid\n' - printf '- PleasantUI.MaterialIcons\n' printf '- PleasantUI.ToolKit\n' } > /tmp/release_notes.md echo "WARNING: AI release notes generation failed. Used commit-based fallback." @@ -753,7 +752,6 @@ jobs: files: | src/PleasantUI/bin/Release/*.nupkg src/PleasantUI.DataGrid/bin/Release/*.nupkg - src/PleasantUI.MaterialIcons/bin/Release/*.nupkg src/PleasantUI.ToolKit/bin/Release/*.nupkg - name: Confirm release created @@ -774,7 +772,6 @@ jobs: for pkg in \ src/PleasantUI/bin/Release/*.nupkg \ src/PleasantUI.DataGrid/bin/Release/*.nupkg \ - src/PleasantUI.MaterialIcons/bin/Release/*.nupkg \ src/PleasantUI.ToolKit/bin/Release/*.nupkg; do echo "Pushing $pkg" dotnet nuget push "$pkg" \ diff --git a/PleasantUI.sln b/PleasantUI.sln index 714bf104..c05dd4ef 100644 --- a/PleasantUI.sln +++ b/PleasantUI.sln @@ -12,24 +12,31 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PleasantUI.DataGrid", "src\ EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PleasantUI.Example", "samples\PleasantUI.Example\PleasantUI.Example.csproj", "{59DC0F4B-421E-407D-9435-F6ED14765634}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "designer", "designer", "{EBAC1577-CFD7-477C-848E-86BFFC345D90}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PleasantUI.ToolKit", "src\PleasantUI.ToolKit\PleasantUI.ToolKit.csproj", "{722B39BB-1CBF-4762-A5C5-439F4EB3A781}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PleasantUI.Designer", "designer\PleasantUI.Designer\PleasantUI.Designer.csproj", "{88C264B9-51D4-41CF-AEC0-24F5075FA6B8}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "_build", "_build", "{D6E493DE-5180-4BA0-B122-D155A5934D08}" + ProjectSection(SolutionItems) = preProject + build\Package.props = build\Package.props + build\PleasantUI.targets = build\PleasantUI.targets + build\PleasantUI.Localization.Analyzer.targets = build\PleasantUI.Localization.Analyzer.targets + build\PleasantUI.Localization.Generator.targets = build\PleasantUI.Localization.Generator.targets + EndProjectSection EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "generators", "generators", "{941F7A66-EFCB-4141-97CA-A0B779ED1BB4}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "generators", "generators", "{77203EAD-CB0D-4D37-B8E7-2F2BA0A1B1EF}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PleasantUI.MaterialIcons", "src\PleasantUI.MaterialIcons\PleasantUI.MaterialIcons.csproj", "{2ABE0576-837B-4D1B-970D-00B52BF0E078}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PleasantUI.Localization.Generator", "generators\PleasantUI.Localization.Generator\PleasantUI.Localization.Generator.csproj", "{967BBBAA-7F6F-4DA6-A8E5-9F0A70DFF684}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PleasantUI.MaterialIcons.SourceGenerator", "generators\PleasantUI.MaterialIcons.SourceGenerator\PleasantUI.MaterialIcons.SourceGenerator.csproj", "{9FDFD065-7664-4E0C-B928-D7FC8B074EDD}" +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "analyzers", "analyzers", "{20ECD7A9-C3D1-41AA-A8BB-640E3B28BBC0}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PleasantUI.ToolKit", "src\PleasantUI.ToolKit\PleasantUI.ToolKit.csproj", "{722B39BB-1CBF-4762-A5C5-439F4EB3A781}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PleasantUI.Localization.Analyzer", "analyzers\PleasantUI.Localization.Analyzer\PleasantUI.Localization.Analyzer.csproj", "{A519CDCF-2774-4FD9-AE5F-0F6B62F7C346}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "build", "build", "{D6E493DE-5180-4BA0-B122-D155A5934D08}" - ProjectSection(SolutionItems) = preProject - build\Package.props = build\Package.props - EndProjectSection +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "_tests", "_tests", "{80E17402-8124-43B7-A0BB-E939CDD20E21}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "analyzers", "analyzers", "{6B8337BF-8256-47CF-836E-C5A3C745D931}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PleasantUI.Localization.Analyzer.Tests", "tests\analyzers\PleasantUI.Localization.Analyzer.Tests\PleasantUI.Localization.Analyzer.Tests.csproj", "{D3E71BE9-D438-48ED-A99D-EF30AEFD66A5}" EndProject -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "common", "common", "{4BCCA866-A31E-49B1-AB79-B9C94651D295}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PleasantUI.Tests", "tests\PleasantUI.Tests\PleasantUI.Tests.csproj", "{A6230EC5-60E1-41E8-BE8E-CA9A82D7F835}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -57,29 +64,35 @@ Global {59DC0F4B-421E-407D-9435-F6ED14765634}.Debug|Any CPU.Build.0 = Debug|Any CPU {59DC0F4B-421E-407D-9435-F6ED14765634}.Release|Any CPU.ActiveCfg = Release|Any CPU {59DC0F4B-421E-407D-9435-F6ED14765634}.Release|Any CPU.Build.0 = Release|Any CPU - {88C264B9-51D4-41CF-AEC0-24F5075FA6B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {88C264B9-51D4-41CF-AEC0-24F5075FA6B8}.Debug|Any CPU.Build.0 = Debug|Any CPU - {88C264B9-51D4-41CF-AEC0-24F5075FA6B8}.Release|Any CPU.ActiveCfg = Release|Any CPU - {88C264B9-51D4-41CF-AEC0-24F5075FA6B8}.Release|Any CPU.Build.0 = Release|Any CPU - {2ABE0576-837B-4D1B-970D-00B52BF0E078}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2ABE0576-837B-4D1B-970D-00B52BF0E078}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2ABE0576-837B-4D1B-970D-00B52BF0E078}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2ABE0576-837B-4D1B-970D-00B52BF0E078}.Release|Any CPU.Build.0 = Release|Any CPU - {9FDFD065-7664-4E0C-B928-D7FC8B074EDD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {9FDFD065-7664-4E0C-B928-D7FC8B074EDD}.Debug|Any CPU.Build.0 = Debug|Any CPU - {9FDFD065-7664-4E0C-B928-D7FC8B074EDD}.Release|Any CPU.ActiveCfg = Release|Any CPU - {9FDFD065-7664-4E0C-B928-D7FC8B074EDD}.Release|Any CPU.Build.0 = Release|Any CPU {722B39BB-1CBF-4762-A5C5-439F4EB3A781}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {722B39BB-1CBF-4762-A5C5-439F4EB3A781}.Debug|Any CPU.Build.0 = Debug|Any CPU {722B39BB-1CBF-4762-A5C5-439F4EB3A781}.Release|Any CPU.ActiveCfg = Release|Any CPU {722B39BB-1CBF-4762-A5C5-439F4EB3A781}.Release|Any CPU.Build.0 = Release|Any CPU + {967BBBAA-7F6F-4DA6-A8E5-9F0A70DFF684}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {967BBBAA-7F6F-4DA6-A8E5-9F0A70DFF684}.Debug|Any CPU.Build.0 = Debug|Any CPU + {967BBBAA-7F6F-4DA6-A8E5-9F0A70DFF684}.Release|Any CPU.ActiveCfg = Release|Any CPU + {967BBBAA-7F6F-4DA6-A8E5-9F0A70DFF684}.Release|Any CPU.Build.0 = Release|Any CPU + {A519CDCF-2774-4FD9-AE5F-0F6B62F7C346}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A519CDCF-2774-4FD9-AE5F-0F6B62F7C346}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A519CDCF-2774-4FD9-AE5F-0F6B62F7C346}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A519CDCF-2774-4FD9-AE5F-0F6B62F7C346}.Release|Any CPU.Build.0 = Release|Any CPU + {D3E71BE9-D438-48ED-A99D-EF30AEFD66A5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D3E71BE9-D438-48ED-A99D-EF30AEFD66A5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D3E71BE9-D438-48ED-A99D-EF30AEFD66A5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D3E71BE9-D438-48ED-A99D-EF30AEFD66A5}.Release|Any CPU.Build.0 = Release|Any CPU + {A6230EC5-60E1-41E8-BE8E-CA9A82D7F835}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A6230EC5-60E1-41E8-BE8E-CA9A82D7F835}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A6230EC5-60E1-41E8-BE8E-CA9A82D7F835}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A6230EC5-60E1-41E8-BE8E-CA9A82D7F835}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(NestedProjects) = preSolution {71BFCFA6-B53E-4F28-819F-51CB26516B5A} = {BEE78D8A-ED3D-4D34-9B29-43D5BB953D40} {91F6CDD0-6925-4289-90EC-8BDD245F7BD0} = {BEE78D8A-ED3D-4D34-9B29-43D5BB953D40} {59DC0F4B-421E-407D-9435-F6ED14765634} = {BEE78D8A-ED3D-4D34-9B29-43D5BB953D40} - {88C264B9-51D4-41CF-AEC0-24F5075FA6B8} = {EBAC1577-CFD7-477C-848E-86BFFC345D90} - {9FDFD065-7664-4E0C-B928-D7FC8B074EDD} = {941F7A66-EFCB-4141-97CA-A0B779ED1BB4} - {2ABE0576-837B-4D1B-970D-00B52BF0E078} = {4BCCA866-A31E-49B1-AB79-B9C94651D295} + {967BBBAA-7F6F-4DA6-A8E5-9F0A70DFF684} = {77203EAD-CB0D-4D37-B8E7-2F2BA0A1B1EF} + {A519CDCF-2774-4FD9-AE5F-0F6B62F7C346} = {20ECD7A9-C3D1-41AA-A8BB-640E3B28BBC0} + {6B8337BF-8256-47CF-836E-C5A3C745D931} = {80E17402-8124-43B7-A0BB-E939CDD20E21} + {D3E71BE9-D438-48ED-A99D-EF30AEFD66A5} = {6B8337BF-8256-47CF-836E-C5A3C745D931} + {A6230EC5-60E1-41E8-BE8E-CA9A82D7F835} = {80E17402-8124-43B7-A0BB-E939CDD20E21} EndGlobalSection EndGlobal diff --git a/README.md b/README.md index 7cb5f909..1bcd1621 100644 --- a/README.md +++ b/README.md @@ -5,21 +5,27 @@ -![Imgur](https://i.imgur.com/7HXbYEo.png) +![Imgur](https://i.imgur.com/o40rAoq.png) # 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. +PleasantUI is a cross-platform UI theme and control library for [Avalonia](https://github.com/AvaloniaUI/Avalonia), inspired by Microsoft Fluent Design, Google Material 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. +## 🏛️ Philosophy + +The philosophy is to provide the user with a _**pleasant**_ experience in using applications built on this library. This library isn't intended to be compared to other design principles or other UI libraries. If the interface looks good, then this library is doing its job. + +This library may also contain elements from other design principles or UI libraries if it makes the interface _**pleasant**_ enough (but with due attribution, of course). + ## ✨ Features -### Complete Fluent-style control theming +### Complete 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: +Every standard Avalonia control is receiving a complete overhaul: rounded corners, multi-layered fills, smooth transitions on hover and click, and accent color integration: | Control | Control | Control | |---|---|---| @@ -47,7 +53,6 @@ Controls built from scratch that go beyond what Avalonia ships: | `InformationBlock` | Compact pill-shaped label combining an icon and a value | ![Imgur](https://i.imgur.com/SX0BZ2k.png) | | `MarkedTextBox` / `MarkedNumericUpDown` | Input controls with inline label/unit markers | None | | `RippleEffect` | Material-style ripple click feedback | ![Imgur](https://i.imgur.com/2WtIPvj.gif) | -| `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. | ![Imgur](https://i.imgur.com/DGP3nDR.png) | | `InstallWizard` | A multi-step installation wizard with a sidebar step list, progress bar, and Back / Next / Cancel navigation. | ![Imgur](https://i.imgur.com/bbgKH3L.png) | @@ -69,6 +74,7 @@ Controls built from scratch that go beyond what Avalonia ships: - `{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 +- A localization key analyzer is included. You won't miss any unused keys in your applications! ## Packages @@ -147,10 +153,10 @@ Detailed reference docs for each control are in the [`docs/`](docs/) folder: Published on NuGet: ```xml - - - - + + + + ``` @@ -267,9 +273,9 @@ string title = Localizer.TrDefault("DialogTitle", "Confirm"); ```xml - @@ -34,5 +35,5 @@ - + diff --git a/samples/PleasantUI.Example/Views/Pages/ControlPages/ButtonPageView.axaml b/samples/PleasantUI.Example/Views/Pages/ControlPages/ButtonPageView.axaml index 36436fa5..219d58ea 100644 --- a/samples/PleasantUI.Example/Views/Pages/ControlPages/ButtonPageView.axaml +++ b/samples/PleasantUI.Example/Views/Pages/ControlPages/ButtonPageView.axaml @@ -8,14 +8,14 @@ -