Skip to content

feat(field): add LumexField component for consistent field layout#271

Open
ogix wants to merge 12 commits intoLumexUI:mainfrom
ogix:feature/lumex-field-design
Open

feat(field): add LumexField component for consistent field layout#271
ogix wants to merge 12 commits intoLumexUI:mainfrom
ogix:feature/lumex-field-design

Conversation

@ogix
Copy link

@ogix ogix commented Feb 4, 2026

Summary

This PR introduces the LumexField component, which provides a consistent field layout with label, content, description, and error message slots. It also refactors existing components to use this new component for consistency.

Changes

  • feat(field): Add LumexField component with vertical and horizontal orientations
  • feat(field): Add FieldSlots class for customizable slot styling
  • feat(input-base): Add Label, Description, ErrorMessage properties to base class
  • refactor: Update LumexInputFieldBase to use inherited properties
  • refactor: Update RadioGroup and Select to use inherited properties
  • refactor: Update RadioGroup and CheckboxGroup to use LumexField for layout
  • fix(field): Use LumexComponent for polymorphic rendering

New Component Usage

<LumexField Label="Email" Description="We'll never share your email">
    <input type="email" @bind="email" />
</LumexField>

<LumexField Label="Remember me" Orientation="Orientation.Horizontal">
    <input type="checkbox" @bind="remember" />
</LumexField>

Test plan

  • Added unit tests for LumexField component
  • Added FindAllBySlot test extension method
  • All existing tests pass (346 tests)

🤖 Generated with Claude Code

Summary by CodeRabbit

Release Notes

  • New Features

    • Introduced a standardized field component for consistent label, description, and error message rendering across input components.
    • Added vertical and horizontal layout orientation options for enhanced layout flexibility.
    • Enhanced input components with standardized label, description, and error message properties.
    • Boolean inputs now support horizontal orientation and descriptions with backwards-compatible fallback behavior.
    • Added customizable CSS slots for field styling.
  • Tests

    • Added comprehensive field component tests covering layout orientations, state attributes, and custom styling.

ogix and others added 11 commits February 4, 2026 09:16
Design document for a reusable field layout component that will
provide consistent label, description, and error message rendering
across all input components.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add the LumexField component that provides a consistent field layout
with label, content, description, and error message support. The
component supports both vertical and horizontal orientations.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add Label, Description, and ErrorMessage parameters to LumexInputBase
so that all input components have these properties available. This is
part of the LumexField design to ensure consistency across all inputs.

Note: This change introduces CS0108 warnings about hiding inherited
members in LumexInputFieldBase, which will be addressed in a follow-up
change.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…ssage

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…in RadioGroup and Select

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Use LumexComponent wrapper to support the As parameter for rendering
as any HTML element, and properly pass through Class, Style, and
AdditionalAttributes.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Refactor LumexRadioGroup to use LumexField internally, which:
- Adds ErrorMessage support (previously missing)
- Provides consistent label/description rendering
- Reduces code duplication

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add ErrorMessage, Invalid, and Required parameters to LumexCheckboxGroup
and refactor to use LumexField internally for consistent rendering.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@ogix ogix requested a review from desmondinho as a code owner February 4, 2026 10:21
@coderabbitai
Copy link

coderabbitai bot commented Feb 4, 2026

📝 Walkthrough

Walkthrough

This pull request introduces a new LumexField component and supporting infrastructure to standardize label, description, and error message rendering across input components. It refactors the component hierarchy by moving Label, Description, and ErrorMessage properties from LumexInputFieldBase to LumexInputBase, adds a new Orientation enum and FieldSlots class, and updates multiple components (Checkbox, Radio, Select, Datebox) to use LumexField internally. Comprehensive tests and styling logic are included.

Changes

Cohort / File(s) Summary
Field Component Foundation
src/LumexUI/Components/Field/LumexField.razor, src/LumexUI/Components/Field/LumexField.razor.cs, src/LumexUI/Components/Field/FieldSlots.cs
Introduces new LumexField component with parameters for Label, Description, ErrorMessage, Invalid, Required, Disabled, Orientation, and ChildContent; adds FieldSlots class for slot CSS customization; implements vertical/horizontal layout rendering logic.
Input Base Classes
src/LumexUI/Components/Bases/LumexInputBase.cs, src/LumexUI/Components/Bases/LumexInputFieldBase.razor.cs
Moves Label, Description, and ErrorMessage parameters from LumexInputFieldBase to LumexInputBase, consolidating common field metadata properties.
Boolean Input Components
src/LumexUI/Components/Checkbox/LumexCheckboxGroup.razor, src/LumexUI/Components/Checkbox/LumexCheckboxGroup.razor.cs, src/LumexUI/Components/Radio/LumexRadioGroup.razor, src/LumexUI/Components/Radio/LumexRadioGroup.razor.cs
Refactors CheckboxGroup and RadioGroup to use LumexField wrapper; removes duplicate Label/Description properties from RadioGroup; adds ErrorMessage, Invalid, and Required parameters to CheckboxGroup; replaces style helpers with FieldSlots structure.
Select Component
src/LumexUI/Components/Select/LumexSelect.razor.cs
Removes duplicated Label, Description, and ErrorMessage parameters (now managed by LumexField internally).
Field Styling
src/LumexUI/Styles/Field.cs
Adds static styling methods (GetStyles, GetLabelStyles, GetContentStyles, etc.) to compute class strings for Field components based on orientation, validation state, and custom slot classes.
Tests & Extensions
tests/LumexUI.Tests/Components/Field/FieldTests.cs, tests/LumexUI.Tests/Extensions/AngleSharpExtensions.cs
Adds comprehensive unit tests for LumexField covering orientation, data attributes, description/error rendering precedence, and slot class application; adds FindAllBySlot extension method for test queries.
Design Documentation
docs/plans/2026-02-04-lumex-field-design.md
Documents new LumexField design, migration strategy, rendering structures, backwards-compatibility approach, and future enhancements.

Sequence Diagram(s)

sequenceDiagram
    participant App as Consumer
    participant LF as LumexField
    participant Render as Render Methods
    participant Helper as Helper Logic
    
    App->>LF: Pass Label, Description, Orientation
    LF->>LF: Determine layout (Vertical/Horizontal)
    
    alt Vertical Orientation
        LF->>Render: RenderVerticalLayout()
        Render->>Render: Render Label slot
        Render->>Render: Render Content slot
        Render->>Helper: RenderHelper()
    else Horizontal Orientation
        LF->>Render: RenderHorizontalLayout()
        Render->>Render: Render Content slot
        Render->>Render: Render LabelWrapper with Label
        Render->>Helper: RenderHelper()
    end
    
    Helper->>Helper: Check Invalid state
    alt Invalid && ErrorMessage
        Helper->>Render: Render ErrorMessage slot
    else Description exists
        Helper->>Render: Render Description slot
    end
    
    Render-->>LF: Composed HTML
    LF-->>App: Rendered field with labels/errors
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~30 minutes

Possibly related PRs

  • PR #250: Modifies LumexDatebox component which is updated to use the new LumexField for consistent field rendering.

Suggested labels

💥 Type: Breaking Change, 📦 Scope: Components, 🚀 Type: Feature

Suggested reviewers

  • desmondinho

Poem

🐰 A field takes shape with grace and care,
Labels dance where they belong,
Vertical, horizontal—layouts fair,
Errors and descriptions sing along,
The UI components grow more strong! ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 4.76% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The pull request title clearly and concisely describes the main change: introducing the LumexField component for consistent field layout across components.
Description check ✅ Passed The PR description includes a summary, organized changes list, new component usage examples, and a completed test plan; however, it lacks the issue number reference and formal checklist from the template.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Important

Action Needed: IP Allowlist Update

If your organization protects your Git platform with IP whitelisting, please add the new CodeRabbit IP address to your allowlist:

  • 136.113.208.247/32 (new)
  • 34.170.211.100/32
  • 35.222.179.152/32

Reviews will stop working after February 8, 2026 if the new IP is not added to your allowlist.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@src/LumexUI/Components/Field/LumexField.razor.cs`:
- Around line 74-80: HasHelper currently returns true if ErrorMessage is
non-empty even when Invalid is false, causing RenderHelper to emit an empty
wrapper; update the logic so error text is only considered when the field is
invalid — e.g., change HasHelper to check !string.IsNullOrEmpty(Description) ||
(!string.IsNullOrEmpty(ErrorMessage) && Invalid) (or alternatively gate the
error rendering inside RenderHelper by only rendering ErrorMessage when Invalid
is true), referencing the HasHelper, ErrorMessage, Invalid, Description and
RenderHelper members.

Comment on lines +74 to +80
private bool HasHelper =>
!string.IsNullOrEmpty( Description ) ||
!string.IsNullOrEmpty( ErrorMessage );

private bool HasLabelOrHelper =>
!string.IsNullOrEmpty( Label ) ||
HasHelper;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Avoid rendering an empty helper container when error text is inactive.

If ErrorMessage is set but Invalid is false and Description is empty, HasHelper becomes true and RenderHelper produces an empty wrapper (extra spacing). Consider gating error text on Invalid.

🔧 Suggested adjustment
-	private bool HasHelper =>
-		!string.IsNullOrEmpty( Description ) ||
-		!string.IsNullOrEmpty( ErrorMessage );
+	private bool HasHelper =>
+		!string.IsNullOrEmpty( Description ) ||
+		( Invalid && !string.IsNullOrEmpty( ErrorMessage ) );
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
private bool HasHelper =>
!string.IsNullOrEmpty( Description ) ||
!string.IsNullOrEmpty( ErrorMessage );
private bool HasLabelOrHelper =>
!string.IsNullOrEmpty( Label ) ||
HasHelper;
private bool HasHelper =>
!string.IsNullOrEmpty( Description ) ||
( Invalid && !string.IsNullOrEmpty( ErrorMessage ) );
private bool HasLabelOrHelper =>
!string.IsNullOrEmpty( Label ) ||
HasHelper;
🤖 Prompt for AI Agents
In `@src/LumexUI/Components/Field/LumexField.razor.cs` around lines 74 - 80,
HasHelper currently returns true if ErrorMessage is non-empty even when Invalid
is false, causing RenderHelper to emit an empty wrapper; update the logic so
error text is only considered when the field is invalid — e.g., change HasHelper
to check !string.IsNullOrEmpty(Description) ||
(!string.IsNullOrEmpty(ErrorMessage) && Invalid) (or alternatively gate the
error rendering inside RenderHelper by only rendering ErrorMessage when Invalid
is true), referencing the HasHelper, ErrorMessage, Invalid, Description and
RenderHelper members.

@ogix ogix mentioned this pull request Feb 4, 2026
1 task
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant