Skip to content

Conversation

@arika0093
Copy link
Owner

@arika0093 arika0093 commented Dec 7, 2025

Introduce the IntroductionSection component for query-based DTO generation and enhance accessibility by adding translate attributes to relevant playground components.

Summary by CodeRabbit

  • New Features

    • Added interactive step-by-step interface for Query-Based DTO Generation with visual progress tracking, code preview, and dynamic content switching between generated DTO classes and select expressions.
  • Updates

    • Updated messaging to reflect auto-generated DTOs from query shape.
    • Removed promotional callout section.
  • UI Improvements

    • Enhanced styling and layout refinements across components.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link

coderabbitai bot commented Dec 7, 2025

Walkthrough

This pull request introduces an interactive step-driven UI component for Query-Based DTO Generation, adds minor styling adjustments to existing components (CSS height and translate attributes), updates content copy in WhyLinqraftSection, and integrates the new component into the Home page layout.

Changes

Cohort / File(s) Summary
Styling & Attribute Updates
playground/Components/Home/CodeBlock.razor, playground/Components/Home/SectionTitle.razor
Added translate="no" attribute; adjusted CSS height constraint from max-h-150 to max-h-120 in CodeBlock.
Content Updates
playground/Components/Home/WhyLinqraftSection.razor
Updated bullet text to reflect auto-generated DTOs from query shape; removed UI callout block with bouncing chevron SVG.
New Interactive Component
playground/Components/Home/IntroductionSection.razor
Implements multi-step, progress-driven UI with IAsyncDisposable lifecycle. Features include: dynamic step styling, animated progress bar, dual-pane layout (user query + generated code), typewriter animation for code insertion, tab switching (DTO Class / Select Expression), step jumping with conditional animation/consolidation, and full async cancellation/disposal support.
Component Integration
playground/Pages/Home.razor
Added IntroductionSection component immediately after HeroSection in the page composition sequence; minor formatting cleanup.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Areas requiring extra attention:

  • IntroductionSection.razor: Review typewriter animation logic, step progression and jump-to-step behavior, async state management, and cancellation token handling to ensure timing correctness and no memory leaks on disposal.
  • CodeStep nested class: Verify the code consolidation logic and tab-switching implementation (GetCodeForTab method).
  • Async lifecycle: Confirm IAsyncDisposable pattern is correctly implemented for timer/cancellation cleanup.

Poem

🐰 Step by step, the query takes shape,
Typewriter whispers code into place,
Progress bars dance, tabs gently switch,
DTO riches from prompts that pitch,
Async cleanup keeps the hutch so tidy! ✨

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main changes: adding the new IntroductionSection component and improving accessibility with translate attributes.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch docs/update-playground-pages

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.

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

🧹 Nitpick comments (2)
playground/Components/Home/IntroductionSection.razor (2)

387-397: Consider broader exception handling in timer callback.

The timer's async event handler only catches ObjectDisposedException. If other exceptions occur in TypeNextCharacter or InvokeAsync, they could go unobserved since this is an async void method.

Apply this diff to add comprehensive exception handling:

 typewriterTimer.Elapsed += async (sender, e) =>
 {
     try
     {
         await TypeNextCharacter();
     }
-    catch (ObjectDisposedException) { }
+    catch (Exception ex) when (ex is ObjectDisposedException or TaskCanceledException)
+    {
+        // Expected during disposal
+    }
+    catch (Exception)
+    {
+        // Stop timer on unexpected errors to prevent repeated failures
+        typewriterTimer?.Stop();
+    }
 };

342-354: Consider logging when insertion point is not found.

The method silently skips insertion if LastIndexOf(" })") returns -1 or 0. This could lead to incomplete code display without any indication of the problem.

Consider adding defensive logging:

 int insertPosition = displayedCode.LastIndexOf("    })");
-if (insertPosition > 0)
+if (insertPosition > 0)
 {
     displayedCode = displayedCode.Insert(insertPosition, codeToAdd + "\n");
 }
+else
+{
+    // Log or handle the case where insertion point wasn't found
+    // This indicates a mismatch between BaseCode format and expectations
+}
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a25737e and 0fb650a.

📒 Files selected for processing (5)
  • playground/Components/Home/CodeBlock.razor (1 hunks)
  • playground/Components/Home/IntroductionSection.razor (1 hunks)
  • playground/Components/Home/SectionTitle.razor (1 hunks)
  • playground/Components/Home/WhyLinqraftSection.razor (1 hunks)
  • playground/Pages/Home.razor (1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-11-25T12:08:35.849Z
Learnt from: CR
Repo: arika0093/Linqraft PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T12:08:35.849Z
Learning: Applies to src/Linqraft.Core/**/*.cs : Keep helper methods lightweight and focused; helper methods are called frequently during analysis

Applied to files:

  • playground/Components/Home/WhyLinqraftSection.razor
📚 Learning: 2025-11-25T12:08:35.849Z
Learnt from: CR
Repo: arika0093/Linqraft PR: 0
File: CLAUDE.md:0-0
Timestamp: 2025-11-25T12:08:35.849Z
Learning: Applies to src/Linqraft/DummyExpression.cs : Do not edit `DummyExpression.cs`; it serves only as a marker for the Source Generator

Applied to files:

  • playground/Components/Home/WhyLinqraftSection.razor
🔇 Additional comments (8)
playground/Components/Home/CodeBlock.razor (1)

10-10: LGTM! Accessibility and styling improvements.

The addition of translate="no" correctly prevents browser translation of code content, preserving syntax highlighting and formatting. The height adjustment aligns with the new IntroductionSection layout.

playground/Components/Home/WhyLinqraftSection.razor (1)

85-85: LGTM! More accurate description.

The updated wording "auto-generated from query shape" better describes how Linqraft generates DTOs from the query structure, aligning with the new IntroductionSection's focus on query-based generation.

playground/Pages/Home.razor (1)

7-7: LGTM! Logical component placement.

The IntroductionSection is appropriately positioned after the HeroSection to provide an interactive demonstration before the detailed "Why Linqraft?" explanations.

playground/Components/Home/SectionTitle.razor (1)

1-1: Verify that section titles should suppress translation.

Adding translate="no" to section titles prevents browser translation of content like "Why Linqraft?" and "Query-Based DTO Generation." While product names like "Linqraft" shouldn't be translated, the surrounding words typically should be.

Consider whether this aligns with your i18n/accessibility strategy. If the site is intended to be English-only, this is acceptable. Otherwise, you may want to apply translate="no" more selectively (e.g., just to the product name).

playground/Components/Home/IntroductionSection.razor (4)

1-1: LGTM! Proper async disposal implementation.

The component correctly implements IAsyncDisposable and properly cleans up resources (CancellationTokenSource and Timer) in the DisposeAsync method.

Also applies to: 478-490


356-408: LGTM! Well-structured step navigation logic.

The method correctly handles both forward (animated) and backward (instant) navigation, with proper cancellation checks and state management. The use of InvokeAsync(StateHasChanged) is appropriate for Blazor.


3-88: LGTM! Well-structured interactive UI.

The component's layout is clean and intuitive:

  • Step indicators with visual state (completed/current/pending)
  • Animated progress bars for typing steps
  • Split-pane design showing both input query and generated output
  • Tab switching for DTO vs Select Expression views

The use of translate="no" on step indicators (line 24) is appropriate for preserving the UI structure.


104-330: LGTM! Well-organized step definitions.

The CodeStep class provides a clean structure for managing step data, and the steps array comprehensively demonstrates Linqraft's features through progressive examples. The data is well-aligned with the README examples.

Also applies to: 492-504

Comment on lines +410 to +443
private async Task TypeNextCharacter()
{
if (_cts?.Token.IsCancellationRequested == true) return;

if (currentCharIndex >= currentBlockText.Length)
{
// Typing complete
typewriterTimer?.Stop();
isTyping = false;

// Update currentStep immediately (this makes tabs turn green and updates right side)
currentStep = targetStep;
await InvokeAsync(StateHasChanged);

// Wait a moment before clearing highlight
await Task.Delay(1000);
highlightedSection = "";
await InvokeAsync(StateHasChanged);
return;
}

// Add next character
char nextChar = currentBlockText[currentCharIndex];
currentCharIndex++;

// Insert the character before the closing braces
int insertPosition = displayedCode.LastIndexOf(" })");
if (insertPosition > 0)
{
displayedCode = displayedCode.Insert(insertPosition, nextChar.ToString());
}

await InvokeAsync(StateHasChanged);
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major

Pass cancellation token to Task.Delay.

Line 425 uses Task.Delay(1000) without a cancellation token. If the component is disposed during this delay, it will continue executing and may attempt operations on disposed resources.

Apply this diff:

-await Task.Delay(1000);
+await Task.Delay(1000, _cts?.Token ?? CancellationToken.None);
 highlightedSection = "";
🤖 Prompt for AI Agents
In playground/Components/Home/IntroductionSection.razor around lines 410 to 443,
the Task.Delay(1000) call should accept the component cancellation token so the
delay is canceled if the component is disposed; replace Task.Delay(1000) with
awaiting Task.Delay(1000, _cts?.Token ?? CancellationToken.None) and after the
await check _cts?.Token.IsCancellationRequested (or return immediately) before
touching highlightedSection/StateHasChanged to avoid operating on disposed
resources.

@arika0093 arika0093 merged commit 2a039c0 into main Dec 7, 2025
3 checks passed
@arika0093 arika0093 deleted the docs/update-playground-pages branch December 7, 2025 02:29
arika0093 added a commit that referenced this pull request Dec 10, 2025
* feat: add IntroductionSection component for query-based DTO generation

* fix: add translate attribute to improve accessibility in playground components

* refactor: remove custom animation definitions from tailwind.css

(cherry picked from commit 2a039c0)
@arika0093 arika0093 mentioned this pull request Dec 10, 2025
arika0093 added a commit that referenced this pull request Dec 10, 2025
* Fix: Remove parent class nesting from implicit DTOs in hash namespaces (#219)

* Initial plan

* Add test for issue: implicit DTOs should not be nested in parent class when using hash namespace

Co-authored-by: arika0093 <[email protected]>

* Fix: Implicit DTOs should not be nested in parent class when using hash namespace

Co-authored-by: arika0093 <[email protected]>

---------

Co-authored-by: copilot-swe-agent[bot] <[email protected]>
Co-authored-by: arika0093 <[email protected]>
(cherry picked from commit dd2d380)

* Fix nested SelectExpr inconsistency between playground and source generator (#221)

* Initial plan

* Add shared IsNestedInsideAnotherSelectExpr helper and use in playground and source generator

Co-authored-by: arika0093 <[email protected]>

* Add comprehensive tests for nested SelectExpr consistency fix

Co-authored-by: arika0093 <[email protected]>

* Remove tests for nested SelectExpr type verification

---------

Co-authored-by: copilot-swe-agent[bot] <[email protected]>
Co-authored-by: arika0093 <[email protected]>
Co-authored-by: Arika Ishinami <[email protected]>
(cherry picked from commit a25737e)

* docs: Add IntroductionSection component and improve accessibility (#223)

* feat: add IntroductionSection component for query-based DTO generation

* fix: add translate attribute to improve accessibility in playground components

* refactor: remove custom animation definitions from tailwind.css

(cherry picked from commit 2a039c0)

* Fix nested SelectExpr code generation: parent class qualification, array types, and comment verbosity (#222)

* Initial plan

* Initial analysis of nested SelectExpr issues

Co-authored-by: arika0093 <[email protected]>

* Fix Issues 1 and 3 for nested SelectExpr - Issue 2 still in progress

Co-authored-by: arika0093 <[email protected]>

* Fix Issue 2 - array property types now correctly include [] suffix

Co-authored-by: arika0093 <[email protected]>

* Refactor array type detection into helper method per code review

Co-authored-by: arika0093 <[email protected]>

* Address PR review comments: rename test file, remove qualifiers with partial declarations, improve comments, extract method

Co-authored-by: arika0093 <[email protected]>

* Clarify that partial class declarations are required for nested DTO generation

Co-authored-by: arika0093 <[email protected]>

---------

Co-authored-by: copilot-swe-agent[bot] <[email protected]>
Co-authored-by: arika0093 <[email protected]>
(cherry picked from commit a163791)

* docs: separate README contents to other files (#224)

(cherry picked from commit 29b0301)

* Fix: set default value of settingsExpanded to false in Sidebar component

(cherry picked from commit a34d686)

* docs: add comprehensive documentation for Nested SelectExpr feature

(cherry picked from commit 97439c9)

* Revert "docs: add comprehensive documentation for Nested SelectExpr feature"

This reverts commit 97439c9.

(cherry picked from commit 755698c)

* docs: add Nested SelectExpr documentation for reusable DTOs (#225)

* docs: add Nested SelectExpr documentation for reusable DTOs

* docs: update Nested SelectExpr documentation with important notes and usage requirements

* upd

* Fix GitHub Issue link in nested-selectexpr.md

(cherry picked from commit 64b9787)

* fix: NestedSelectExprTest and update documentation (#229)

* Fix: update Issue207_NestedSelectExprTest to support partial classes and remove .NET 9 specific warnings

* Fix: update documentation for Nested SelectExpr to clarify beta status and remove .NET 9+ recommendation

(cherry picked from commit 1aa5ec7)

* Document explicit class naming for nested DTOs

Added section on explicit class naming in nested DTOs.

(cherry picked from commit 1ddc079)

* Enhance library comparison with GitHub stars

Updated the library comparison table to include GitHub repository star counts for each library.

(cherry picked from commit d875f80)

* Update Docs link to point to library directory

(cherry picked from commit 59498e4)

* Refactor Order example to use records and facets

Updated the example to use records and facets for Order and OrderChild.

(cherry picked from commit c66f8b8)

* Add pre-built expression tree caching for IQueryable operations (#234)

* Initial plan

* Add pre-built expression tree configuration and implementation

- Added LinqraftUsePrebuildExpression configuration option (default: false)
- Created ExpressionTreeBuilder helper class for generating cached expression fields
- Updated SelectExprInfoAnonymous to use pre-built expressions when enabled
- Updated SelectExprInfoNamed to use pre-built expressions when enabled
- Updated SelectExprInfoExplicitDto to use pre-built expressions when enabled
- Pre-built expressions only apply to IQueryable (not IEnumerable)
- Pre-built expressions are disabled when captures are used

Co-authored-by: arika0093 <[email protected]>

* Refactor static field generation to class level

- Moved static field generation from method body to class level
- Added GenerateStaticFields() virtual method to SelectExprInfo
- Updated SelectExprGroups to collect and pass static fields
- Updated GenerateSourceCodeSnippets to output static fields before methods
- Fixed null reference warning in SelectExprGroups

Co-authored-by: arika0093 <[email protected]>

* Complete pre-built expression tree implementation

- Fixed CompilerVisibleProperty list to include LinqraftUsePrebuildExpression
- Anonymous types cannot use pre-built expressions (result type is compiler-generated)
- Pre-built expressions only work for named/predefined/explicit DTO types
- Added comprehensive tests for IQueryable with different DTO patterns
- All tests passing with pre-built expressions enabled

Co-authored-by: arika0093 <[email protected]>

* Add LinqraftUsePrebuildExpression to all CompilerVisibleProperty lists

- Updated examples/Directory.Build.props with new configuration property
- Fixed playground/Services/CodeGenerationService.cs to use updated API signature
- All projects now support the new LinqraftUsePrebuildExpression configuration

Co-authored-by: arika0093 <[email protected]>

* Add LinqraftUsePrebuildExpression property to project files

* Fix code generation issues per review feedback

- Use 'var' instead of explicit type in expression initialization (line 93)
- Remove unnecessary '!' null-forgiving operator when fieldName is not null
- Fix indentation of generated multi-line lambda expressions
- Use explicit Expression<> type instead of 'as' operator (lambdas cannot use 'as')

Co-authored-by: arika0093 <[email protected]>

* Refactor to use direct expression initialization per review feedback

- Updated documentation in global-properties.md for LinqraftUsePrebuildExpression
- Added note about captures not supporting pre-built expressions
- Refactored ExpressionTreeBuilder to directly initialize expression fields (no lazy init)
- Removed GenerateNamedExpressionTreeInitialization and GenerateAnonymousExpressionTreeInitialization
- Expression trees now initialized at field declaration, eliminating null checks
- Updated SelectExprInfoNamed and SelectExprInfoExplicitDto to use new approach
- Added test for multiple DTO types to verify pre-built expressions work correctly
- All 6 tests passing

Co-authored-by: arika0093 <[email protected]>

* Address final review feedback: readonly, indentation, remove test, add playground toggle

- Added 'readonly' keyword to static expression fields for immutability
- Fixed indentation: ensured proper line ending with AppendLine for multi-line expressions
- Deleted Linqraft.Tests.Configuration project as requested
- Removed project reference from Linqraft.slnx
- Added toggle for LinqraftUsePrebuildExpression in playground Settings section
- All tests passing (130/130)

Co-authored-by: arika0093 <[email protected]>

* revert: reset Linqraft.Tests.Configuration

* Fix indentation in BuildExprCodeSnippets for static fields

* Add static fields generation to expression code snippets

* formatt

---------

Co-authored-by: copilot-swe-agent[bot] <[email protected]>
Co-authored-by: arika0093 <[email protected]>
Co-authored-by: Arika Ishinami <[email protected]>
(cherry picked from commit 1761753)

* chore(deps): bump stefanzweifel/git-auto-commit-action from 4 to 7 (#236)

Bumps [stefanzweifel/git-auto-commit-action](https://github.com/stefanzweifel/git-auto-commit-action) from 4 to 7.
- [Release notes](https://github.com/stefanzweifel/git-auto-commit-action/releases)
- [Changelog](https://github.com/stefanzweifel/git-auto-commit-action/blob/master/CHANGELOG.md)
- [Commits](stefanzweifel/git-auto-commit-action@v4...v7)

---
updated-dependencies:
- dependency-name: stefanzweifel/git-auto-commit-action
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
(cherry picked from commit 107f2d2)

* Bump AutoMapper from 15.1.0 to 16.0.0 (#237)

---
updated-dependencies:
- dependency-name: AutoMapper
  dependency-version: 16.0.0
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
(cherry picked from commit 623b9fa)

* feat: optimize DTO generation and performance documentation (#235)

* Refactor GenerateDtoClasses method for improved readability and performance

* Add caching for pre-built expressions in SelectExprInfoNamed

* Refactor nullable access conversion to simplify default value handling

* Update performance documentation to clarify benchmarks and improve readability

* Update README to simplify performance and FAQ sections

* Fix nullable type handling in GetDefaultValueForType method

(cherry picked from commit 54005a1)

* formatted

(cherry picked from commit 11122cb)

* chore: update commit message format for csharpier workflow

(cherry picked from commit 735eb9f)

* playground: enable ScrollBeyondLastLine and update StickyScroll options in EditorPane and PreviewPane

(cherry picked from commit 9bc3057)

* Deduplicate DTO class definitions globally across all generated files (#240)

* Initial plan

* Fix duplicate ChildDto generation for same-shaped nested DTOs in Select expressions

Co-authored-by: arika0093 <[email protected]>

* Improve code comments based on review feedback

Co-authored-by: arika0093 <[email protected]>

* Fix duplicate DTO class definitions by deduplicating at generation point

Reverted changes to DtoProperty.cs and implemented deduplication in
GenerateSourceCodeSnippets.BuildDtoCodeSnippetsGroupedByNamespace instead.
This ensures DTOs with the same FullName (namespace + class name) are only
generated once, even when used across multiple SelectExpr calls.

Co-authored-by: arika0093 <[email protected]>

* Implement global DTO deduplication across all files

- Collect all DTOs from all SelectExpr groups
- Deduplicate globally by FullName before generation
- Generate all DTOs in a single shared GeneratedDtos.g.cs file
- Each expression group file now only contains expression methods
- This ensures DTOs are not duplicated even when used across different files

Co-authored-by: arika0093 <[email protected]>

* Refactor DTO generation based on code review feedback

- Moved global DTO deduplication logic to GenerateSourceCodeSnippets.BuildGlobalDtoCodeSnippet
- Separated SelectExprGroups.GenerateCode into two methods: GenerateCode and GenerateCodeWithoutDtos
- Made GenerateCommentHeaderPart and GenerateHeaderFlagsPart public for cross-namespace use
- Renamed test files to Issue239_* pattern for clarity
- Updated playground CodeGenerationService to use new global DTO deduplication
- Fixed null reference warning in playground service

Co-authored-by: arika0093 <[email protected]>

---------

Co-authored-by: copilot-swe-agent[bot] <[email protected]>
Co-authored-by: arika0093 <[email protected]>
(cherry picked from commit 16b287e)

* refactor: DTO handling and improve code clarity (#216)

* refactor: improve code structure and add documentation for auto-generated DTO attribute

* refactor: rename ExportAll method to ExportAllConstantSnippets for clarity

* refactor: replace hardcoded DTO attributes with a dedicated method for better maintainability

* refactor: add EditorBrowsable attribute to internal DTO attributes for better visibility control

(cherry picked from commit ae2ba5f)

* fix

---------

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: Copilot <[email protected]>
Co-authored-by: arika0093 <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
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.

2 participants