- Target specific projects only. Solution-wide commands are too slow unless explicitly requested.
- Keep diffs small and focused. Avoid repo-wide rewrites unless explicitly asked.
- Do not add new heavy dependencies or packages without approval.
- Do not make speculative large changes when the intent is unclear. Ask a clarifying question or propose a short plan instead.
- Follow
src/.editorconfig. - Treat warnings as errors. Do not ignore analyzer warnings.
- Do not run solution-wide build, test, or format commands unless explicitly requested.
- Do not make
dotnet cleanpart of the normal local loop. Use it only when incremental build state is clearly stale or corrupted. - If no code, project, test, docs app, or asset-pipeline inputs changed, do not call
dotnet. Changes limited to files such asREADME.md, changelog text, issue templates, or other repo metadata do not require restore, build, test, or format. - Prefer a single scoped
dotnet buildordotnet testcommand as the first verification step. Split build and test only when you will reuse the build outputs for multiple test runs. - Do not build
src/MudBlazor/MudBlazor.csprojimmediately before testingsrc/MudBlazor.UnitTests/MudBlazor.UnitTests.csproj; the test project already buildsMudBlazor,MudBlazor.UnitTests.Shared, andMudBlazor.UnitTests.Viewer.
src/contains the product code and nearly all project work. Expect the main library, docs app, tests, analyzers, benchmarks, and related support projects to live here.src/MudBlazor/is the core component library. Most component, utility, styling,TScripts, andwwwrootchanges land here.src/MudBlazor.UnitTests*contains test projects and test support code. Look here for component tests, shared test infrastructure, viewer-only helpers, and docs-related tests.src/MudBlazor.Docs*contains the documentation site, examples, and docs build support. Update docs here when component behavior or public API changes.src/MudBlazor.Analyzers*contains analyzer, code-fix, and analyzer-test projects.- Repo-wide build configuration is centered in
src/, especiallysrc/Directory.Build.*andsrc/.editorconfig. - Tooling and automation live primarily in
tools/,.config/, and.github/. - Treat
bin/,obj/,TestResults/, generated files, and similar outputs as build artifacts unless the task explicitly targets them.
- The required .NET SDK is defined in
global.json; use that version to restore, build, and test this repository. - The library targets
net8.0,net9.0, andnet10.0. - Verify the active SDK with
dotnet --version.
- Components:
src/MudBlazor/MudBlazor.csprojandsrc/MudBlazor.UnitTests/MudBlazor.UnitTests.csproj - Docs:
src/MudBlazor.Docs.Compiler/MudBlazor.Docs.Compiler.csproj,src/MudBlazor.Docs/MudBlazor.Docs.csproj,src/MudBlazor.Docs.Server/MudBlazor.Docs.Server.csproj, andsrc/MudBlazor.Docs.WasmHost/MudBlazor.Docs.WasmHost.csproj - Docs tests:
src/MudBlazor.UnitTests.Docs/MudBlazor.UnitTests.Docs.csproj - Analyzers and code fixes:
src/MudBlazor.Analyzers/MudBlazor.Analyzers.csproj,src/MudBlazor.Analyzers.CodeFixes/MudBlazor.Analyzers.CodeFixes.csproj, andsrc/MudBlazor.UnitTests.Analyzers/MudBlazor.UnitTests.Analyzers.csproj
Do not run restore automatically at the start of every session. Reuse existing assets in the working tree.
Run restore only when restore inputs changed, when the target project's obj/project.assets.json is missing, or when a --no-restore build or test fails because restore data is stale.
Restore only the project graph you are about to validate:
dotnet restore src/MudBlazor.UnitTests/MudBlazor.UnitTests.csproj
dotnet restore src/MudBlazor.UnitTests.Analyzers/MudBlazor.UnitTests.Analyzers.csproj
dotnet restore src/MudBlazor.UnitTests.Docs/MudBlazor.UnitTests.Docs.csproj
dotnet restore src/MudBlazor.Docs.Server/MudBlazor.Docs.Server.csproj
dotnet tool restore --tool-manifest .config/dotnet-tools.jsonRe-run dotnet restore if any of these change:
-
*.csproj -
src/Directory.Build.* -
Directory.Packages.props, if added later -
NuGet.Configor other NuGet restore configuration files, if added later -
If
.config/dotnet-tools.jsonchanges, run:
dotnet tool restore --tool-manifest .config/dotnet-tools.json- If
src/package.jsonorsrc/bun.lockchanges, run a normal scoped build withoutSkipBunCompilefor the affected project so the frontend asset pipeline runs.
- For a single validation pass, prefer one filtered
dotnet testcommand. This builds the component library plus the relevant test graph and runs the selected tests in one invocation. - Use
/p:SkipBunCompile=truein this loop because it targets C#, Razor, and test validation that does not depend on regenerated frontend assets.
dotnet test src/MudBlazor.UnitTests/MudBlazor.UnitTests.csproj --filter "FullyQualifiedName~MenuTests" --no-restore /p:SkipBunCompile=true --nologo --blame-hang --blame-hang-timeout 30s- If you expect to run multiple filtered test commands against the same edits, build once and then reuse the outputs with
--no-build:
dotnet build src/MudBlazor.UnitTests/MudBlazor.UnitTests.csproj --no-restore /p:SkipBunCompile=true --nologo
dotnet test src/MudBlazor.UnitTests/MudBlazor.UnitTests.csproj --filter "FullyQualifiedName~MenuTests" --no-build --no-restore --nologo --blame-hang --blame-hang-timeout 30s
dotnet test src/MudBlazor.UnitTests/MudBlazor.UnitTests.csproj --filter "FullyQualifiedName~PopoverTests" --no-build --no-restore --nologo --blame-hang --blame-hang-timeout 30s- Frontend asset builds use the local
bundotnet.clitool from.config/dotnet-tools.json, not a separately installed global Bun. - If Bun-related commands fail after tool or config changes, re-run
dotnet tool restore --tool-manifest .config/dotnet-tools.json. /p:SkipBunCompile=trueskips the Bun-driven frontend asset compilation steps that normally run during build.- Use it when the goal is to validate .NET, C#, or Razor changes and you do not need regenerated frontend assets as part of verification.
- It is typically safe for C#-only changes, Razor logic or markup changes, test changes, and documentation-only changes.
- Do not use it when changes touch
TScripts, styles, CSS, SCSS, asset pipeline inputs, or tooling files that affect frontend bundles such assrc/package.jsonorsrc/bun.lock. - Do not use it when the change depends on rebuilt generated JavaScript, CSS, or other static assets being present or up to date.
- If you are unsure whether the build output depends on regenerated frontend assets, run the normal scoped build without
SkipBunCompile.
Formatting is required for changed files:
dotnet format <project.csproj> --no-restore --include <path/to/changed/files>-
Run
dotnet formatonce near the end of the task after edits have stabilized. Do not put format into the normal edit-build-test loop. -
If
src/.editorconfigchanged, format the wholesrctree instead of only changed files:
dotnet format src --no-restore- For repository metadata or prose-only changes outside the build inputs, such as
README.md,CHANGELOG.md, or.github/text-only edits: do not rundotnet. - For component
.csor.razorchanges with behavior coverage: prefer a single filtereddotnet testagainstsrc/MudBlazor.UnitTests/MudBlazor.UnitTests.csprojwith/p:SkipBunCompile=true. Buildsrc/MudBlazor.UnitTests/MudBlazor.UnitTests.csprojfirst only when you plan to reuse the outputs for multiple test filters. - For component
.csor.razorchanges that only need compile validation: buildsrc/MudBlazor/MudBlazor.csprojwith/p:SkipBunCompile=true. - For
TScriptsorStyles: run a normal scoped project build. - For docs changes: build the relevant docs project. Avoid docs host run loops during agent verification.
- For docs example or API-page changes that need parity with CI, run
dotnet test src/MudBlazor.UnitTests.Docs/MudBlazor.UnitTests.Docs.csproj /p:GenerateDocsTests=true. - For analyzer or code-fix changes: prefer a single filtered
dotnet testfromsrc/MudBlazor.UnitTests.Analyzers/MudBlazor.UnitTests.Analyzers.csproj. Build that project first only when you plan multiple filtered test runs. - Prefer the narrowest relevant test filter over running an entire test project.
- Use
dotnet clean <project.csproj>only when incremental outputs are clearly stale or corrupted.
- Component parameters must be auto-properties only. Do not put logic in getters or setters.
- Do not overwrite component parameters directly. Use the backing
ParameterState<T>and update through.ValueorSetValueAsync. - Do not set other component parameters via
@ref(BL0005). Use declarative binding instead. - Use
ParameterState<T>for parameter updates and change handlers. - Parameters managed through the parameter-state framework should be annotated with
[Parameter, ParameterState].
- Use
CssBuilderfor classes and styles. - Use CSS variables and design tokens. Do not hard-code colors.
- Prefer positive parameter names. Avoid names like
DisableGutters; preferGutters.
- Add XML
<summary>documentation for all public properties. - Prefer concise summaries that describe behavior, not "Gets or sets..." boilerplate.
- Add
<remarks>for public parameters when useful, including the default value when relevant. - Add the appropriate
[Category(CategoryTypes....)]attribute to public component parameters.
Example:
/// <summary>
/// Uses compact vertical padding.
/// </summary>
/// <remarks>
/// Defaults to <c>false</c>.
/// </remarks>
[Parameter]
[Category(CategoryTypes.Radio.Appearance)]
public bool Dense { get; set; }or
/// <summary>
/// Prevents interaction with background elements while this list is open.
/// </summary>
/// <remarks>
/// Defaults to <see cref="PopoverOptions.ModalOverlay" />.
/// </remarks>
[Parameter]
[Category(CategoryTypes.FormComponent.ListBehavior)]
public bool? Modal { get; set; }- Register parameters in the constructor with
CreateRegisterScope(). - Use
.WithParameter(...),.WithEventCallback(...), and.WithChangeHandler(...)where appropriate. - Put reaction logic in the change handler, not in the property setter.
- Prefer method-group handlers for shared logic.
Example:
private readonly ParameterState<bool> _expandedState;
[Parameter]
public bool Expanded { get; set; }
[Parameter]
public EventCallback<bool> ExpandedChanged { get; set; }
public MudExample()
{
using var registerScope = CreateRegisterScope();
_expandedState = registerScope.RegisterParameter<bool>(nameof(Expanded))
.WithParameter(() => Expanded)
.WithEventCallback(() => ExpandedChanged)
.WithChangeHandler(OnExpandedChangedAsync);
}
private Task ToggleAsync()
{
return _expandedState.SetValueAsync(!_expandedState.Value);
}- Add
[CascadingParameter] public bool RightToLeft { get; set; }when layout depends on direction. - Follow best ARIA practices without adding noise.
- Ensure keyboard navigation works for interactive components.
- Provide accessible names for interactive controls through a label,
aria-label, oraria-labelledby. - Components with logic require bUnit tests and a docs page at
src/MudBlazor.Docs/Pages/Components/<ComponentName>.razor.
- Order examples from simple to complex.
- Collapse examples longer than 15 lines by default.
- Prefer minimal, focused examples that demonstrate one concept at a time.
- Keep docs in sync with behavior and parameter changes.
- Docs examples are exercised by generated tests, so they must render without exceptions.
- Generated docs tests are emitted as
Generated/*.generated.csfiles and must not be edited by hand. MudBlazor.UnitTests.Docsdoes not generate docs tests in the default local build unlessGenerateDocsTests=true.
- Avoid breaking changes whenever possible.
- Prefer additive APIs, safe defaults, or obsoleting old behavior.
- If a breaking change is required, call it out explicitly in the PR description and update docs and tests accordingly.
- For parameter renames or removals, consider
[Obsolete]with a clear message and migration path.
- Run the narrowest relevant test filter first.
- Test logic rather than full HTML snapshots.
- Keep tests isolated so they can run in parallel.
- If a test modifies shared or static state, restore it in
[TearDown]. - Use
[NonParallelizable]only when isolation is not feasible. - Prefer
TimeProviderorFakeTimeProvideroverTask.Delay.
- Never cache
Find()orFindAll()results. Re-query after interactions. - Always use
InvokeAsync()for parameter changes or method calls. - Prefer async interactions such as
ClickAsync,ChangeAsync,BlurAsync, andInputAsyncover sync methods.
- Test components belong in
src/MudBlazor.UnitTests.Viewer/TestComponents/<ComponentName>/. - Unit tests belong in
src/MudBlazor.UnitTests/Components/<ComponentName>Tests.cs. - Add a viewer test component only when the scenario is too cumbersome to express directly in bUnit C# syntax. In those cases, add the viewer component first, then the unit test.
- Test names must not use
TestorAsyncsuffixes, must not containTest_in the middle, and must not end with trailing underscores. - Reference tests:
TextTests.cs,ApiMemberTableTests.cs.
- Fix new warnings instead of suppressing them.
- Keep
src/MudBlazor/TScripts/entrypoint.jsin sync with files insrc/MudBlazor/TScripts/exceptentrypoint.js.
Before finishing, verify all of the following:
- Formatting was run for changed files when formatting-relevant files under
src/changed. - The relevant target project builds cleanly with no new warnings when code, docs app, analyzer, or asset inputs changed.
- Tests were updated and run when behavior changed.
- Docs were updated when component behavior or public API changed.
- No new dependencies were added without approval.