Repository navigation
Make ShrinkLabel configurable on MudBlazor field components #177
Description
Problem / motivation
Reported by @bdsoko in #146 after .WithVariant(...) shipped in v3.1.0:
While using, I set the variant to 'Text' and noticed that the label does not float. I believe it's because ShrinkLabel property is hardcoded to 'true'. Any chance this can be customizable as well.
Confirmed. ShrinkLabel="true" is hardcoded at 12 sites across FormCraft.ForMudBlazor, with no way for a consumer to override it:
| File | Line |
|---|---|
Fields/TextField/MudBlazorTextFieldComponent.razor |
25 |
Fields/NumericField/MudBlazorNumericFieldComponent.razor |
22 |
Fields/NumericField/MudBlazorNullableNumericFieldComponent.razor |
22 |
Fields/SelectField/MudBlazorSelectFieldComponent.razor |
18 |
Fields/SelectField/MudBlazorMultiSelectFieldComponent.razor |
18 |
Fields/DateTimeField/MudBlazorDateTimeFieldComponent.razor |
16 |
Fields/DateTimeField/MudBlazorDateOnlyFieldComponent.razor |
15 |
Fields/DateTimeField/MudBlazorTimeOnlyFieldComponent.razor |
15 |
Fields/AutocompleteField/MudBlazorAutocompleteFieldComponent.razor |
18 |
Fields/LookupField/MudBlazorLookupFieldComponent.razor |
16 |
Features/CustomFields/MudBlazorColorPickerComponent.razor |
15 |
Features/CollectionField/CollectionFieldComponent.razor.cs (AddCommonFieldAttributes) |
271 |
ShrinkLabel="true" permanently pins the label above the input. That reads correctly for Variant.Outlined (the default, where the label sits in the notch of the border) and acceptably for Variant.Filled. For Variant.Text it removes the one affordance the variant relies on: the label is meant to sit inside the input as a placeholder and float up on focus/value. The result is a floating label over an input that has no border to anchor it — visually orphaned, and exactly what @bdsoko is seeing.
This makes the v3.1.0 Variant feature only two-thirds useful: Variant.Text is selectable but not presentable.
Proposed solution
Make ShrinkLabel configurable through the same channel Variant already uses — a field-level builder extension plus a form-level default, resolved through AdditionalAttributes. The v3.1.0 work built exactly this plumbing (MudBlazorFieldComponentBase.EffectiveVariant, FormCraftCascadingValues.DefaultVariant, FormCraftComponent.DefaultVariant); this rides it rather than inventing a second mechanism.
New public surface, all in FormCraft.ForMudBlazor:
// Field-level (FieldBuilderExtensions) — sibling of WithVariant
.AddField(x => x.Name, field => field
.WithLabel("Name")
.WithVariant(Variant.Text)
.WithShrinkLabel(false)) // label floats on focus/value
// Form-level (FormCraftComponent<TModel>) — sibling of DefaultVariant
<FormCraftComponent TModel="MyModel"
Model="@model"
Configuration="@config"
DefaultVariant="Variant.Text"
DefaultShrinkLabel="false" />Precedence mirrors Variant exactly: field-level wins over form-level, form-level over the built-in default, and the built-in default stays true so no existing form changes appearance.
Alternatives considered
- Derive
ShrinkLabelfrom the variant (ShrinkLabel = variant != Variant.Text) — zero new API and it fixes the reported symptom with no consumer action. Rejected: it is unoverridable magic, it silently changes rendering for anyone already onVariant.Textwho wanted the pinned label, and it couples two independent MudBlazor properties forever. - Form-level parameter only, no field-level extension — smaller surface, but breaks the symmetry with
Variant/MinDate/MaxDateand can't express a single field that differs from the form. - Expose the raw
ShrinkLabelattribute via.WithAttribute("ShrinkLabel", false)— already technically possible for renderers readingAdditionalAttributes, but it is undiscoverable, untyped, and today no component reads that key.
Area
FormCraft.ForMudBlazor — field rendering
Related: #146 (the Variant request this follows up on, shipped in v3.1.0), #148 (render-pipeline consolidation that made this well-contained)
🧠 Brainstorm
Problem / context
ShrinkLabel is a MudBlazor MudBaseInput property. When true, the label is permanently rendered in its shrunk position (above the input); when false, MudBlazor animates it from inside the input to above it on focus or when a value is present.
FormCraft hardcodes it to true in 12 places. That choice predates configurable variants — when every field was Variant.Outlined, a pinned label was the only correct rendering, so the constant was invisible. v3.1.0 (#146) let consumers pick Variant.Text and Variant.Filled, and the constant became a visible defect: Variant.Text renders a floating label with no border to anchor it.
Prior art in this very repo is decisive. The v3.1.0 change already established the mechanism for "a MudBlazor presentation property, configurable per field with a form-level default":
FormCraftCascadingValues.DefaultVariant— the cascading-value name (FormCraft.ForMudBlazor/Fields/MudBlazorFieldComponentBase.cs:17)MudBlazorFieldComponentBase<TModel,TValue>.FormDefaultVariant—[CascadingParameter](:34)MudBlazorFieldComponentBase.EffectiveVariant— the three-tier resolver (:42)FormCraftComponent<TModel>.DefaultVariant—[Parameter], defaultsVariant.Outlined(Features/FormContainer/FormCraftComponent.razor.cs:53)- The
<CascadingValue TValue="Variant?" …>wrapper (Features/FormContainer/FormCraftComponent.razor:12) FieldBuilderExtensions.WithVariant— one line,builder.WithAttribute("Variant", variant)(Extensions/FieldBuilderExtensions.cs:133)CollectionFieldComponent.GetItemFieldVariant— theRenderTreeBuilderpath's own resolver (Features/CollectionField/CollectionFieldComponent.razor.cs:278)
So the question isn't how to plumb this. It's what shape the fix should take.
Approaches
A. Mirror Variant exactly — .WithShrinkLabel(bool) + DefaultShrinkLabel.
Add EffectiveShrinkLabel to MudBlazorFieldComponentBase, a second cascading value, a form parameter, and a one-line builder extension; swap the 12 constants for @EffectiveShrinkLabel.
Pros: the API a FormCraft user already knows — they learned it three weeks ago from WithVariant; explicit, typed, discoverable via IntelliSense; per-field granularity; default true means byte-identical rendering for every existing form. The 12 call sites are already the exact sites that were touched for Variant, so the diff is mechanical and reviewable.
Cons: ~6 files of plumbing for one boolean, and the consumer must set two things (DefaultVariant="Variant.Text" and DefaultShrinkLabel="false") to get the look they want.
B. Derive it from the variant — ShrinkLabel = EffectiveVariant != Variant.Text.
One expression on the base class, zero public API.
Pros: smallest possible change; @bdsoko's case is fixed with no code on their side; arguably "the right default" for all three variants.
Cons: unoverridable — the next issue is "I want Variant.Text with a pinned label" and there's no answer; it silently changes rendering for anyone who already adopted Variant.Text in v3.1.0; it welds two independent MudBlazor properties together, so MudBlazor's own semantics and FormCraft's diverge. It also answers a question nobody asked: the request is "can this be customizable as well", not "please guess for me".
C. Form-level parameter only.
DefaultShrinkLabel on FormCraftComponent, no field extension.
Pros: half the plumbing; covers the reported case, which is form-wide.
Cons: asymmetric with Variant for no principled reason, and unable to express a mixed form — which is precisely the scenario .WithVariant was added to support (a Variant.Text search box among outlined fields).
Recommendation
A, with true as the resolved default.
The deciding argument is consistency of the mental model. A consumer who has learned "field-level .WithX(...) beats form-level DefaultX, and the built-in default preserves v3.0 rendering" should be able to apply that rule to any MudBlazor presentation property FormCraft exposes. B and C each break that rule in a different direction — B by making the property non-configurable after having just made its sibling configurable, C by dropping a tier. A costs about 6 small files and buys a surface that needs no explaining.
B's appeal — "it should just look right" — is better served by documentation than by hidden coupling: the README bullet and the XML docs should say plainly that Variant.Text usually wants ShrinkLabel="false", and show the two-line snippet. That teaches the pairing without welding it.
Worth folding in while here: Fields/LovField/MudBlazorLovFieldComponent.razor honors EffectiveVariant (line 17) but is the only one of the 13 variant-aware components that never sets ShrinkLabel at all — so it silently renders with MudBlazor's false today while its 12 siblings pin the label. That asymmetry is a latent bug regardless of this feature; see Task 5, which flags it as a deliberate decision rather than folding it in silently.
📋 Spec
Goal
Let consumers control MudBlazor's ShrinkLabel per field and per form, with the current behavior (true) as the resolved default, so Variant.Text can render with a properly floating label.
Scope
- A field-level
.WithShrinkLabel(bool shrinkLabel = true)extension inFormCraft.ForMudBlazor. - A form-level
DefaultShrinkLabelparameter onFormCraftComponent<TModel>, cascaded. EffectiveShrinkLabelonMudBlazorFieldComponentBase<TModel, TValue>resolving the three tiers.- All 12 hardcoded sites switched to the resolved value.
- The
RenderTreeBuilderpath inCollectionFieldComponent(item fields inside collections). - XML docs on every new member; a README feature bullet documenting the
Variant.Textpairing.
Non-goals
- Changing the default rendering of any existing form.
ShrinkLabelresolves totruewhen unconfigured; the two existing parity assertions (RenderPipelineParityTests.cs:237and:257, bothShrinkLabel.ShouldBeTrue()) stay green untouched and serve as the back-compat guard. - Auto-deriving
ShrinkLabelfromVariant(rejected approach B). - Exposing other
MudBaseInputstyling properties (Margin,Immediate,Typo) — same pattern would apply, but each deserves its own issue and its own default-preservation argument. - The two file-upload components (
MudBlazorFileUploadFieldComponent,MudBlazorMultipleFileUploadComponent): they renderMudButton/MudFileUpload, which have noShrinkLabel.
Public surface
namespace FormCraft.ForMudBlazor;
public static class FormCraftCascadingValues
{
public const string DefaultVariant = "FormCraftDefaultVariant";
// new
public const string DefaultShrinkLabel = "FormCraftDefaultShrinkLabel";
}
public abstract class MudBlazorFieldComponentBase<TModel, TValue> : FieldComponentBase<TModel, TValue>
{
[CascadingParameter(Name = FormCraftCascadingValues.DefaultVariant)]
public Variant? FormDefaultVariant { get; set; }
// new
[CascadingParameter(Name = FormCraftCascadingValues.DefaultShrinkLabel)]
public bool? FormDefaultShrinkLabel { get; set; }
protected Variant EffectiveVariant =>
GetAttribute<Variant?>("Variant") ?? FormDefaultVariant ?? Variant.Outlined;
// new
protected bool EffectiveShrinkLabel =>
GetAttribute<bool?>("ShrinkLabel") ?? FormDefaultShrinkLabel ?? true;
}
public static class FieldBuilderExtensions
{
// new
public static FieldBuilder<TModel, TValue> WithShrinkLabel<TModel, TValue>(
this FieldBuilder<TModel, TValue> builder,
bool shrinkLabel = true)
where TModel : new()
=> builder.WithAttribute("ShrinkLabel", shrinkLabel);
}
public partial class FormCraftComponent<TModel>
{
[Parameter] public Variant DefaultVariant { get; set; } = Variant.Outlined;
// new
[Parameter] public bool DefaultShrinkLabel { get; set; } = true;
}Resolution
flowchart TD
A["MudBlazor input needs ShrinkLabel"] --> B{"field's AdditionalAttributes<br/>contains 'ShrinkLabel'?<br/><i>.WithShrinkLabel(...)</i>"}
B -->|yes| C["use that value<br/><b>field-level wins</b>"]
B -->|no| D{"cascaded FormDefaultShrinkLabel<br/>has a value?<br/><i>DefaultShrinkLabel param</i>"}
D -->|yes| E["use the form-level default"]
D -->|no| F["use <b>true</b><br/>preserves v3.0/v3.1 rendering"]
GetAttribute<bool?>("ShrinkLabel") unboxes a stored bool into bool? correctly — the same mechanism GetAttribute<Variant?>("Variant") already relies on in production (FieldComponentBase.GetAttribute<T> at FormCraft/Components/FieldComponentBase.cs:163 uses value is T typedValue, and a boxed value type satisfies an is T? check).
Files
Modify (core plumbing)
FormCraft.ForMudBlazor/Fields/MudBlazorFieldComponentBase.cs— cascading-value name,[CascadingParameter],EffectiveShrinkLabelFormCraft.ForMudBlazor/Extensions/FieldBuilderExtensions.cs—WithShrinkLabel, placed next toWithVariant(currently line 133)FormCraft.ForMudBlazor/Features/FormContainer/FormCraftComponent.razor.cs—DefaultShrinkLabelparameterFormCraft.ForMudBlazor/Features/FormContainer/FormCraftComponent.razor— nested<CascadingValue TValue="bool?" …>around the existingVariantcascade
Modify (the 12 hardcoded sites) — ShrinkLabel="true" → ShrinkLabel="@EffectiveShrinkLabel" in the 11 .razor files listed in Problem / motivation, and builder.AddAttribute(startIndex, "ShrinkLabel", true) → the resolved value in CollectionFieldComponent.razor.cs:271, via a GetItemFieldShrinkLabel(field) helper mirroring GetItemFieldVariant (:278).
Create (tests)
FormCraft.ForMudBlazor.UnitTests/Fields/ShrinkLabelConfigurationTests.cs— modeled onVariantConfigurationTests.cs, reusing itsRenderForm+MudPopoverProviderhelper for picker components
Validation rules
- Unconfigured field, unconfigured form →
ShrinkLabel == true(every component type). .WithShrinkLabel(false)→falseon that field only; siblings staytrue.DefaultShrinkLabel="false"→falseon all fields lacking their own setting.- Field-level beats form-level in both directions (
.WithShrinkLabel(true)on aDefaultShrinkLabel="false"form, and vice versa). - Collection item fields honor both tiers through the
RenderTreeBuilderpath.
Edge cases
.WithShrinkLabel()with no argument — defaults totrue, matchingAsPassword(enableVisibilityToggle: true)'s convention in the same file.- Non-
boolvalue under the"ShrinkLabel"key (a consumer having used.WithAttribute("ShrinkLabel", "true")) —value is bool?fails, so it falls through to the form default. Silent, and correct: no throw on a presentation attribute. - A consumer already calling
.WithAttribute("ShrinkLabel", false)— starts being honored by this change. That is the intended fix, not a regression, but it is a behavior change for anyone who wrote that line speculatively; worth a release-note line. Variant.Text+ShrinkLabel="true"— stays reachable, and remains the default. Anyone who adoptedVariant.Textin v3.1.0 sees no change unless they opt in.- LOV field — see Task 5; it is the one component whose current
ShrinkLabelis effectivelyfalse, so aligning it is a visual change, not a no-op.
Assumptions
- No issue form template exists in this repo (
.github/ISSUE_TEMPLATE/is absent —.github/holds onlybanner.pngand 4 workflows), so the fields above follow the conventional feature-request shape rather than a live YAML form. - Target release is v3.1.x / v3.2.0 (additive, no breaking change). Latest tag is
v3.1.0; base branch isdev. - The MudBlazor version in use exposes
ShrinkLabelon every component touched here (MudBaseInputdescendants + the pickers), which the 12 existing hardcoded usages already prove.
🛠️ Implementation plan
For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (
- [ ]) syntax for tracking.
Goal: make MudBlazor's ShrinkLabel configurable per field and per form, resolving to true when unset, so Variant.Text can render a floating label (follow-up to #146).
Architecture: FormCraft core stays UI-framework-agnostic — every change in this plan lands in FormCraft.ForMudBlazor or its test project; nothing in FormCraft/ is touched. Configuration flows one way: FieldBuilder → IFieldConfiguration.AdditionalAttributes → renderer component. The form-level default travels by cascading value, never by service or static state.
Tech stack: .NET 8 / 9 / 10 multi-target, Blazor, MudBlazor, xUnit + bUnit + Shouldly (MudBlazorTestBase).
Global constraints:
- Base branch
dev; commit asPhilippe Matray <phmatray@gmail.com>; conventional commits (feat:,test:,docs:). - Default rendering must not change.
RenderPipelineParityTests.cs:237and:257assertShrinkLabel.ShouldBeTrue()— they must stay green unmodified. Editing them to accommodate the change means the change is wrong. - Additive only: no existing public member is renamed, removed, or has its default altered.
- Mirror
Variantnaming exactly (WithShrinkLabel/DefaultShrinkLabel/FormDefaultShrinkLabel/EffectiveShrinkLabel) — a reader who knows one must be able to predict the other. - Suite:
dotnet test FormCraft.ForMudBlazor.UnitTests/FormCraft.ForMudBlazor.UnitTests.csproj; single class via--filter "FullyQualifiedName~ShrinkLabelConfigurationTests". - Full
dotnet build+dotnet testgreen before the final commit.
Task 1: Field-level .WithShrinkLabel(...), honored by the text field
Proves the whole chain end-to-end on one component before rolling out.
Files: modify FormCraft.ForMudBlazor/Fields/MudBlazorFieldComponentBase.cs, FormCraft.ForMudBlazor/Extensions/FieldBuilderExtensions.cs, FormCraft.ForMudBlazor/Fields/TextField/MudBlazorTextFieldComponent.razor (line 25); create FormCraft.ForMudBlazor.UnitTests/Fields/ShrinkLabelConfigurationTests.cs.
Interfaces: MudBlazorFieldComponentBase<TModel,TValue>.EffectiveShrinkLabel => GetAttribute<bool?>("ShrinkLabel") ?? FormDefaultShrinkLabel ?? true; FieldBuilderExtensions.WithShrinkLabel<TModel,TValue>(this FieldBuilder<TModel,TValue>, bool shrinkLabel = true).
- Step 1: Write the failing tests in
ShrinkLabelConfigurationTests.cs(copyVariantConfigurationTests.cs's class shape and itsRenderFormhelper):TextField_Should_Default_To_ShrinkLabel_TrueandWithShrinkLabel_False_Should_Apply_To_TextField, assertingcomponent.FindComponent<MudTextField<string>>().Instance.ShrinkLabel. - Step 2: Run
dotnet test FormCraft.ForMudBlazor.UnitTests/FormCraft.ForMudBlazor.UnitTests.csproj --filter "FullyQualifiedName~ShrinkLabelConfigurationTests"→ FAIL (WithShrinkLabeldoes not exist). - Step 3: Add
FormCraftCascadingValues.DefaultShrinkLabel = "FormCraftDefaultShrinkLabel", the[CascadingParameter(Name = …)] public bool? FormDefaultShrinkLabel, andEffectiveShrinkLabeltoMudBlazorFieldComponentBase.cs— XML docs mirroring theVariantmembers directly above. - Step 4: Add
WithShrinkLabeltoFieldBuilderExtensions.csimmediately afterWithVariant(line 139), with XML docs whose<example>shows theVariant.Textpairing. - Step 5: In
MudBlazorTextFieldComponent.razor, changeShrinkLabel="true"(line 25) toShrinkLabel="@EffectiveShrinkLabel". - Step 6: Re-run the filtered suite → PASS.
- Step 7: Run the full
FormCraft.ForMudBlazor.UnitTestssuite → PASS, confirmingRenderPipelineParityTestsis still green with no edits. - Step 8: Commit:
feat(mudblazor): add .WithShrinkLabel field extension honored by text field.
Task 2: Form-level DefaultShrinkLabel + precedence
Files: modify FormCraft.ForMudBlazor/Features/FormContainer/FormCraftComponent.razor.cs (near DefaultVariant, line 53), FormCraft.ForMudBlazor/Features/FormContainer/FormCraftComponent.razor (the cascade at line 12); modify ShrinkLabelConfigurationTests.cs.
Interfaces: FormCraftComponent<TModel>.DefaultShrinkLabel — [Parameter] public bool, default true; cascaded as TValue="bool?" under FormCraftCascadingValues.DefaultShrinkLabel.
- Step 1: Write failing tests:
DefaultShrinkLabel_False_Should_Apply_To_Fields_Without_Explicit_Setting,FieldLevel_WithShrinkLabel_Should_Override_FormLevel_DefaultShrinkLabel(fieldtrueover formfalse, and fieldfalseover formtrue). - Step 2: Run the filtered suite → FAIL (no
DefaultShrinkLabelparameter). - Step 3: Add the
DefaultShrinkLabel[Parameter]toFormCraftComponent.razor.cswith XML docs pointing at.WithShrinkLabel(...). - Step 4: In
FormCraftComponent.razor, nest a<CascadingValue TValue="bool?" Name="@FormCraftCascadingValues.DefaultShrinkLabel" Value="@DefaultShrinkLabel">around the existingVariantcascade — and add the matching closing tag at the end of the markup. - Step 5: Re-run the filtered suite → PASS.
- Step 6: Commit:
feat(mudblazor): add form-level DefaultShrinkLabel parameter.
Task 3: Roll out to the remaining 10 .razor components
Files: modify Fields/NumericField/MudBlazorNumericFieldComponent.razor (22), Fields/NumericField/MudBlazorNullableNumericFieldComponent.razor (22), Fields/SelectField/MudBlazorSelectFieldComponent.razor (18), Fields/SelectField/MudBlazorMultiSelectFieldComponent.razor (18), Fields/DateTimeField/MudBlazorDateTimeFieldComponent.razor (16), Fields/DateTimeField/MudBlazorDateOnlyFieldComponent.razor (15), Fields/DateTimeField/MudBlazorTimeOnlyFieldComponent.razor (15), Fields/AutocompleteField/MudBlazorAutocompleteFieldComponent.razor (18), Fields/LookupField/MudBlazorLookupFieldComponent.razor (16), Features/CustomFields/MudBlazorColorPickerComponent.razor (15); modify ShrinkLabelConfigurationTests.cs.
Interfaces: none new — each site swaps the literal for @EffectiveShrinkLabel.
- Step 1: Write failing per-component tests covering numeric, nullable-numeric, select, multi-select, date-time, date-only, time-only, autocomplete, lookup and color-picker — each asserting default
trueand.WithShrinkLabel(false)→false. Use theMudPopoverProviderrender helper for the picker-backed ones. - Step 2: Run the filtered suite → FAIL on every component not yet converted.
- Step 3: Replace
ShrinkLabel="true"withShrinkLabel="@EffectiveShrinkLabel"in all 10 files. - Step 4: Verify none were missed:
grep -rn 'ShrinkLabel="true"' FormCraft.ForMudBlazor/returns nothing. - Step 5: Re-run the filtered suite → PASS, then the full suite → PASS.
- Step 6: Commit:
feat(mudblazor): honor configurable ShrinkLabel in all input components.
Task 4: Collection item fields (RenderTreeBuilder path)
The collection renderer builds its inputs imperatively and resolves Variant through its own helper; ShrinkLabel needs the parallel treatment.
Files: modify FormCraft.ForMudBlazor/Features/CollectionField/CollectionFieldComponent.razor.cs (AddCommonFieldAttributes line 271; add helper next to GetItemFieldVariant line 278); modify ShrinkLabelConfigurationTests.cs.
Interfaces: private bool GetItemFieldShrinkLabel(IFieldConfiguration<TItem, object> field) — reads field.AdditionalAttributes["ShrinkLabel"] as bool, else FormDefaultShrinkLabel ?? true; plus a [CascadingParameter(Name = FormCraftCascadingValues.DefaultShrinkLabel)] public bool? FormDefaultShrinkLabel alongside the existing FormDefaultVariant (line 40).
- Step 1: Write failing tests for a collection field: item inputs default to
ShrinkLabel == true, honor a per-item-field.WithShrinkLabel(false), and honor the form-levelDefaultShrinkLabel="false". - Step 2: Run the filtered suite → FAIL.
- Step 3: Add the
FormDefaultShrinkLabelcascading parameter andGetItemFieldShrinkLabel, mirroringGetItemFieldVariant's structure exactly; change line 271 to pass the resolved value. - Step 4: Re-run the filtered suite → PASS, then the full suite → PASS.
- Step 5: Commit:
feat(mudblazor): honor ShrinkLabel for collection item fields.
Task 5: Decide the LOV field's ShrinkLabel (flagged — behavior change)
Fields/LovField/MudBlazorLovFieldComponent.razor honors EffectiveVariant (line 17) but is the only variant-aware component that never sets ShrinkLabel, so it renders with MudBlazor's false while its 12 siblings pin the label. Adding ShrinkLabel="@EffectiveShrinkLabel" aligns it — and changes how LOV fields look today (label starts pinned instead of floating).
- Step 1: Confirm the asymmetry:
grep -n 'ShrinkLabel\|EffectiveVariant' FormCraft.ForMudBlazor/Fields/LovField/MudBlazorLovFieldComponent.razor. - Step 2: Take the call and record it in the PR description — recommended: align it (the input is
ReadOnly="true"with a value-or-placeholder always shown, so a pinned label is the right rendering, and consistency across the field family is the point of this issue). If instead LOV is left alone, say so explicitly and add a code comment so the next reader doesn't "fix" it silently. - Step 3: If aligning: write a failing test (
LovField_Should_Honor_ShrinkLabel) asserting defaulttrueand.WithShrinkLabel(false)→false; run → FAIL. - Step 4: If aligning: add
ShrinkLabel="@EffectiveShrinkLabel"to theMudTextFieldat line 9-23; re-run → PASS; full suite → PASS. - Step 5: Commit:
fix(mudblazor): align LOV field ShrinkLabel with the other input components(or, if not aligning,docs(mudblazor): note why the LOV field leaves ShrinkLabel unset).
Task 6: Documentation
Files: modify README.md (the v3.1.0 feature bullet at line 65).
- Step 1: Add a feature bullet next to the existing
Configurable MudBlazor Variantone, documenting.WithShrinkLabel(false)andDefaultShrinkLabel, and stating plainly thatVariant.Textusually wantsShrinkLabel="false"so the label floats — with the two-line snippet. - Step 2: Re-read the XML docs added in Tasks 1-2 and confirm each
<example>compiles as written (correct namespaces, real member names). - Step 3: Run the full solution build and test suite one final time:
dotnet buildthendotnet test→ both green. - Step 4: Commit:
docs: document configurable ShrinkLabel and the Variant.Text pairing.
Activity
feat(mudblazor): make ShrinkLabel configurable per field and per form (…