Skip to content

doc(Template5): add transition animation #6469

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jul 23, 2025
Merged

doc(Template5): add transition animation #6469

merged 3 commits into from
Jul 23, 2025

Conversation

ArgoZhang
Copy link
Member

@ArgoZhang ArgoZhang commented Jul 23, 2025

Link issues

fixes #6468

Summary By Copilot

Regression?

  • Yes
  • No

Risk

  • High
  • Medium
  • Low

Verification

  • Manual (required)
  • Automated

Packaging changes reviewed?

  • Yes
  • No
  • N/A

☑️ Self Check before Merge

⚠️ Please check all items below before review. ⚠️

  • Doc is updated/provided or not needed
  • Demo is updated/provided or not needed
  • Merge the latest code from the main branch

Summary by Sourcery

Implement animated transitions for the Template5 login tutorial by refactoring the component into a code-behind structure, adding a JS module for fade-in/out effects, updating CSS rules, and adjusting layout navigation to load the new files.

New Features:

  • Add transition animations (fade-in/out) between email and password steps in Template5
  • Integrate a JS module for handling form step animations and auto-load it via JSModuleAutoLoader attribute
  • Refactor Template5 component by moving its logic into a code-behind file

Enhancements:

  • Revise CSS to support absolute positioning of login steps and adjust animation timing
  • Update TutorialsNavMenu to include the new .razor.cs and .razor.js files
  • Remove the Wwads component from the TutorialsLayout sidebar

@bb-auto bb-auto bot added the documentation Improvements or additions to documentation label Jul 23, 2025
Copy link
Contributor

sourcery-ai bot commented Jul 23, 2025

Reviewer's Guide

This PR adds a transition animation to the Template5 login sample by modularizing component logic into a partial class, loading a JavaScript module for step-by-step animations, restructuring the Razor markup and CSS for animated transitions, and updating the tutorial navigation and layout to register the new files.

Sequence diagram for login step transition animation

sequenceDiagram
    actor User
    participant BlazorComponent as Template5 (Blazor)
    participant JSModule as Template5.razor.js
    User->>BlazorComponent: Submit email
    BlazorComponent->>JSModule: go(id) (transition to password)
    JSModule-->>BlazorComponent: Animation complete
    User->>BlazorComponent: Submit password
    BlazorComponent->>BlazorComponent: Set isAuth = true
    User->>BlazorComponent: Click reset
    BlazorComponent->>BlazorComponent: Reset state
Loading

Class diagram for Template5 component structure

classDiagram
    class Template5 {
        - bool isAuth
        - bool showEmailError
        - bool isEmailEntered
        - LoginModel _loginModel
        + Task OnEmailSubmit(EditContext)
        + Task OnPasswordSubmit(EditContext)
        + Task GoBack()
        + void OnReset()
        + Task OnAfterRenderAsync(bool)
    }
    class LoginModel {
        string? Email
        string? Password
    }
    Template5 o-- LoginModel
Loading

File-Level Changes

Change Details Files
Modularize component logic and integrate JavaScript interop
  • Added JSModuleAutoLoader attribute and @inherits directive to Template5.razor
  • Removed inline @code block and migrated state logic to Template5.razor.cs
  • Implemented InvokeVoidAsync calls for init, go, and back in the partial class
  • Created Template5.razor.js with init, go, and back animation functions
src/BootstrapBlazor.Server/Components/Samples/Tutorials/LoginAndRegister/Template5.razor
src/BootstrapBlazor.Server/Components/Samples/Tutorials/LoginAndRegister/Template5.razor.cs
src/BootstrapBlazor.Server/Components/Samples/Tutorials/LoginAndRegister/Template5.razor.js
Restructure Razor markup to support animated steps
  • Wrapped email and password forms in .login-body and .login-item containers
  • Reordered @if blocks for auth, email, and password steps
  • Added id attribute on login-box for JS targeting
  • Renamed .header-row to .login-header
src/BootstrapBlazor.Server/Components/Samples/Tutorials/LoginAndRegister/Template5.razor
Enhance CSS with animation and layout styles
  • Adjusted .animate-fade-out duration from 0.5s to 0.2s
  • Added .login-body and .login-item classes with show/hide behavior
  • Updated .login-header styles to replace .header-row rules
src/BootstrapBlazor.Server/Components/Samples/Tutorials/LoginAndRegister/Template5.razor.css
Update tutorial navigation and layout
  • Added Template5.razor.cs and Template5.razor.js to _template5 array in TutorialsNavMenu
  • Removed Wwads component from TutorialsLayout.razor
src/BootstrapBlazor.Server/Components/Layout/TutorialsNavMenu.razor.cs
src/BootstrapBlazor.Server/Components/Layout/TutorialsLayout.razor

Assessment against linked issues

Issue Objective Addressed Explanation
#6468 Add documentation and/or code to Template5 that implements a transition animation between login steps.

Possibly linked issues


Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@bb-auto bb-auto bot added this to the 9.8.0 milestone Jul 23, 2025
@ArgoZhang ArgoZhang merged commit e0f10c0 into main Jul 23, 2025
4 checks passed
@ArgoZhang ArgoZhang deleted the doc-login branch July 23, 2025 01:59
Copy link
Contributor

@sourcery-ai sourcery-ai bot left a comment

Choose a reason for hiding this comment

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

Hey @ArgoZhang - I've reviewed your changes - here's some feedback:

  • Use OnAfterRenderAsync to invoke the JS init function (e.g. InvokeVoidAsync("init", Id)) so the initial animation is properly triggered, or remove the empty override if it’s unused.
  • Double-check whether Template5.razor.cs should be exposed in the TutorialsNavMenu file list—code-behind files are usually hidden from end-user samples.
  • Confirm the removal of the Wwads component from TutorialsLayout was intentional, as it will change the ad placement in the tutorials sidebar.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- Use OnAfterRenderAsync to invoke the JS init function (e.g. InvokeVoidAsync("init", Id)) so the initial animation is properly triggered, or remove the empty override if it’s unused.
- Double-check whether Template5.razor.cs should be exposed in the TutorialsNavMenu file list—code-behind files are usually hidden from end-user samples.
- Confirm the removal of the Wwads component from TutorialsLayout was intentional, as it will change the ad placement in the tutorials sidebar.

## Individual Comments

### Comment 1
<location> `src/BootstrapBlazor.Server/Components/Samples/Tutorials/LoginAndRegister/Template5.razor.js:1` </location>
<code_context>
+export function init(id) {
+    const el = document.getElementById(id);
+    if (el) {
+        const email = el.querySelector('.login-item-email');
+        if (email) {
+            email.classList.add('show');
+        }
+    }
+}
</code_context>

<issue_to_address>
The 'init' function is defined but not invoked from C#.

Call 'init' from the C# side (e.g., in OnAfterRenderAsync) to ensure the login form displays the email step correctly on first render.
</issue_to_address>

### Comment 2
<location> `src/BootstrapBlazor.Server/Components/Samples/Tutorials/LoginAndRegister/Template5.razor.js:36` </location>
<code_context>
+        const email = el.querySelector('.login-item-email');
+        if (email) {
+            email.classList.add('show');
+            email.classList.remove('animate-fade-out');
+            email.classList.add('animate-fade-in');
+        }
</code_context>

<issue_to_address>
Consider removing all animation classes before adding new ones to prevent animation conflicts.

Residual animation classes can cause unintended effects. Remove both 'animate-fade-in' and 'animate-fade-out' before adding the new class.
</issue_to_address>

<suggested_fix>
<<<<<<< SEARCH
        const email = el.querySelector('.login-item-email');
        if (email) {
            email.classList.add('show');
            email.classList.remove('animate-fade-out');
            email.classList.add('animate-fade-in');
        }
=======
        const email = el.querySelector('.login-item-email');
        if (email) {
            // Remove all animation classes before adding new ones to prevent animation conflicts
            email.classList.remove('animate-fade-in', 'animate-fade-out');
            email.classList.add('show');
            email.classList.add('animate-fade-in');
        }
>>>>>>> REPLACE

</suggested_fix>

### Comment 3
<location> `src/BootstrapBlazor.Server/Components/Samples/Tutorials/LoginAndRegister/Template5.razor.cs:15` </location>
<code_context>
-
-@code {
-    private bool isEmailEntered = false;
-    private bool isAuth = false;
-    private bool showEmailError = false;
-    private LoginModel _loginModel = new LoginModel()
</code_context>

<issue_to_address>
Consider replacing multiple boolean flags with a single state enum, removing the unused lifecycle method, and extracting the model class to its own file for clarity.

Here are a few focused tweaks that preserve all functionality while collapsing the three bool flags into a single state enum, removing the no-op lifecycle hook, and pulling your model out of the component:

1. Introduce an enum and single `Stage` field:  
```csharp
private enum Stage { EnterEmail, EnterPassword, Authenticated }
private Stage _stage = Stage.EnterEmail;
```

2. Update your handlers to drive that one state and drop all manual `StateHasChanged()` calls (Blazor auto-re-renders on events):  
```csharp
private async Task OnEmailSubmit(EditContext ctx)
{
    if (string.IsNullOrWhiteSpace(_loginModel.Email))
    {
        // e.g. set validation message via EditContext
        return;
    }

    _stage = Stage.EnterPassword;
    await InvokeVoidAsync("go", Id);
}

private Task OnPasswordSubmit(EditContext ctx)
{
    _stage = Stage.Authenticated;
    return Task.CompletedTask;
}

private async Task GoBack()
{
    _stage = Stage.EnterEmail;
    await InvokeVoidAsync("back", Id);
}

private void OnReset() => _stage = Stage.EnterEmail;
```

3. Remove the empty `OnAfterRenderAsync` override completely.

4. Extract `LoginModel` into its own file (e.g. `LoginModel.cs`) under the same namespace:
```csharp
namespace BootstrapBlazor.Server.Components.Samples.Tutorials.LoginAndRegister
{
    public class LoginModel
    {
        public string? Email { get; set; }
        public string? Password { get; set; }
    }
}
```

5. In your Razor markup, branch on `_stage` instead of multiple booleans:
```razor
@if (_stage == Stage.EnterEmail)
{
  <!-- email form -->
}
else if (_stage == Stage.EnterPassword)
{
  <!-- password form -->
}
else
{
  <!-- authenticated view -->
}
```

This collapses your three flags (`isAuth`, `showEmailError`, `isEmailEntered`) into one, removes redundant lifecycle overrides, and pulls the model to its own file.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

Comment on lines +1 to +7
export function init(id) {
const el = document.getElementById(id);
if (el) {
const email = el.querySelector('.login-item-email');
if (email) {
email.classList.add('show');
}
Copy link
Contributor

Choose a reason for hiding this comment

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

issue (bug_risk): The 'init' function is defined but not invoked from C#.

Call 'init' from the C# side (e.g., in OnAfterRenderAsync) to ensure the login form displays the email step correctly on first render.

Comment on lines +33 to +38
const email = el.querySelector('.login-item-email');
if (email) {
email.classList.add('show');
email.classList.remove('animate-fade-out');
email.classList.add('animate-fade-in');
}
Copy link
Contributor

Choose a reason for hiding this comment

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

suggestion: Consider removing all animation classes before adding new ones to prevent animation conflicts.

Residual animation classes can cause unintended effects. Remove both 'animate-fade-in' and 'animate-fade-out' before adding the new class.

Suggested change
const email = el.querySelector('.login-item-email');
if (email) {
email.classList.add('show');
email.classList.remove('animate-fade-out');
email.classList.add('animate-fade-in');
}
const email = el.querySelector('.login-item-email');
if (email) {
// Remove all animation classes before adding new ones to prevent animation conflicts
email.classList.remove('animate-fade-in', 'animate-fade-out');
email.classList.add('show');
email.classList.add('animate-fade-in');
}

/// </summary>
public partial class Template5
{
private bool isAuth = false;
Copy link
Contributor

Choose a reason for hiding this comment

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

issue (complexity): Consider replacing multiple boolean flags with a single state enum, removing the unused lifecycle method, and extracting the model class to its own file for clarity.

Here are a few focused tweaks that preserve all functionality while collapsing the three bool flags into a single state enum, removing the no-op lifecycle hook, and pulling your model out of the component:

  1. Introduce an enum and single Stage field:
private enum Stage { EnterEmail, EnterPassword, Authenticated }
private Stage _stage = Stage.EnterEmail;
  1. Update your handlers to drive that one state and drop all manual StateHasChanged() calls (Blazor auto-re-renders on events):
private async Task OnEmailSubmit(EditContext ctx)
{
    if (string.IsNullOrWhiteSpace(_loginModel.Email))
    {
        // e.g. set validation message via EditContext
        return;
    }

    _stage = Stage.EnterPassword;
    await InvokeVoidAsync("go", Id);
}

private Task OnPasswordSubmit(EditContext ctx)
{
    _stage = Stage.Authenticated;
    return Task.CompletedTask;
}

private async Task GoBack()
{
    _stage = Stage.EnterEmail;
    await InvokeVoidAsync("back", Id);
}

private void OnReset() => _stage = Stage.EnterEmail;
  1. Remove the empty OnAfterRenderAsync override completely.

  2. Extract LoginModel into its own file (e.g. LoginModel.cs) under the same namespace:

namespace BootstrapBlazor.Server.Components.Samples.Tutorials.LoginAndRegister
{
    public class LoginModel
    {
        public string? Email { get; set; }
        public string? Password { get; set; }
    }
}
  1. In your Razor markup, branch on _stage instead of multiple booleans:
@if (_stage == Stage.EnterEmail)
{
  <!-- email form -->
}
else if (_stage == Stage.EnterPassword)
{
  <!-- password form -->
}
else
{
  <!-- authenticated view -->
}

This collapses your three flags (isAuth, showEmailError, isEmailEntered) into one, removes redundant lifecycle overrides, and pulls the model to its own file.

Copy link

codecov bot commented Jul 23, 2025

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 100.00%. Comparing base (ddc61cd) to head (3582f62).
Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff            @@
##              main     #6469   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files          749       749           
  Lines        32364     32364           
  Branches      4572      4572           
=========================================
  Hits         32364     32364           
Flag Coverage Δ
BB 100.00% <ø> (?)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation
Projects
None yet
Development

Successfully merging this pull request may close these issues.

doc(Template5): add transition animation
1 participant