Skip to content

Conversation

@ArgoZhang
Copy link
Member

@ArgoZhang ArgoZhang commented Oct 24, 2025

Link issues

fixes #6998

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

Introduce an IsButton mode for DateTimePicker that renders as a configurable button, refactor its JS interop to support dynamic resets, update the demo page and localization, and add a corresponding unit test

New Features:

  • Add IsButton, PickerButtonText, and ButtonColor parameters to DateTimePicker to render it as a styled button
  • Provide a demo toggle in the sample page to switch DateTimePicker between input and button modes

Enhancements:

  • Refactor DateTimePicker JavaScript interop by extracting createPopover and handlerInput functions and adding a reset method to respond to parameter changes
  • Trigger a JS reset when the IsButton parameter changes to reinitialize the popover and input handlers

Documentation:

  • Update localization files with new PickerButtonText resource entries

Tests:

  • Add a unit test verifying button mode rendering, CSS classes, and toggling back to input mode

Copilot AI review requested due to automatic review settings October 24, 2025 13:02
@bb-auto bb-auto bot added the enhancement New feature or request label Oct 24, 2025
@bb-auto bb-auto bot added this to the 9.11.0 milestone Oct 24, 2025
@sourcery-ai
Copy link
Contributor

sourcery-ai bot commented Oct 24, 2025

Reviewer's Guide

This PR introduces a new IsButton mode for DateTimePicker, allowing it to render as a styled button instead of the default input, and implements the necessary JS reset logic, unit tests, and sample updates to support and demonstrate this feature.

Sequence diagram for DateTimePicker IsButton parameter change and JS reset

sequenceDiagram
    participant Blazor as "DateTimePicker (Blazor)"
    participant JS as "DateTimePicker.razor.js"
    Blazor->>Blazor: IsButton parameter changes
    Blazor->>JS: InvokeVoidAsync("reset", Id)
    JS->>JS: reset(id)
    JS->>JS: disposeInput(input)
    JS->>JS: Popover.dispose(popover)
    JS->>JS: picker.popover = createPopover(...)
    JS->>JS: picker.input = handlerInput(...)
    JS->>Blazor: JS reset complete
Loading

Class diagram for updated DateTimePicker component

classDiagram
    class DateTimePicker {
        +bool IsButton
        +string? PickerButtonText
        +Color ButtonColor
        -string? ButtonClassString
        -bool _isButton
        +OnAfterRenderAsync(bool firstRender)
    }
    DateTimePicker --> DatePickerBody
Loading

File-Level Changes

Change Details Files
Add IsButton display mode to DateTimePicker component
  • Introduce IsButton, PickerButtonText, and ButtonColor parameters with defaults
  • Implement ButtonClassString builder for styled button mode
  • Add OnAfterRenderAsync logic to detect IsButton changes and invoke JS reset
  • Update Razor markup to conditionally render a button or input with icon
src/BootstrapBlazor/Components/DateTimePicker/DateTimePicker.razor.cs
src/BootstrapBlazor/Components/DateTimePicker/DateTimePicker.razor
Refactor DateTimePicker JS interop to support reset and event cleanup
  • Extract createPopover and handlerInput helper functions
  • Implement disposeInput to detach key event handlers
  • Add reset(id) to recreate popover and rebind events on parameter change
  • Simplify init and dispose functions to use the new helpers
src/BootstrapBlazor/Components/DateTimePicker/DateTimePicker.razor.js
Add unit tests for IsButton behavior
  • Create IsButton_Ok test verifying button CSS classes and fallback to input
  • Test dynamic toggling of the IsButton parameter and its effect on rendering
test/UnitTest/Components/DateTimePickerTest.cs
Update sample demos to showcase the new IsButton feature
  • Add a Switch control bound to a _isButton field in the sample UI
  • Bind the IsButton parameter on DateTimePicker instances in samples
  • Extend sample code-behind with the _isButton state field
src/BootstrapBlazor.Server/Components/Samples/DateTimePickers.razor
src/BootstrapBlazor.Server/Components/Samples/DateTimePickers.razor.cs

Assessment against linked issues

Issue Objective Addressed Explanation
#6998 Add an IsButton parameter to the DateTimePicker component that allows it to be rendered as a button instead of an input.
#6998 Ensure the IsButton parameter is documented and demonstrated in the sample/demo code.
#6998 Add unit tests to verify the IsButton parameter functionality in the DateTimePicker component.

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

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull Request Overview

This PR adds an IsButton parameter to the DateTimePicker component, allowing it to be rendered as a button instead of the default input field. When enabled, the picker displays as a button with configurable text and color.

Key Changes

  • Added IsButton, PickerButtonText, and ButtonColor parameters to DateTimePicker
  • Implemented JavaScript reset function to handle dynamic switching between button and input modes
  • Added localization support for the picker button text across all supported languages

Reviewed Changes

Copilot reviewed 16 out of 16 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
DateTimePicker.razor Added conditional rendering for button vs input display modes
DateTimePicker.razor.cs Added new parameters and lifecycle logic to handle IsButton state changes
DateTimePicker.razor.js Refactored to support dynamic mode switching with new reset function
DateTimePickerTest.cs Added test coverage for IsButton parameter functionality
Localization files Added PickerButtonText translations for all supported languages
DateTimePickers.razor Updated demo page to showcase the new IsButton feature
Comments suppressed due to low confidence (1)

src/BootstrapBlazor/Components/DateTimePicker/DateTimePicker.razor:1

  • The 'IsButton' parameter binding is incorrect. It should use '@_isButton' instead of '_isButton' to properly bind the boolean value.
@namespace BootstrapBlazor.Components

Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.

sourcery-ai[bot]
sourcery-ai bot previously approved these changes Oct 24, 2025
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 there - I've reviewed your changes and they look great!

Prompt for AI Agents
Please address the comments from this code review:

## Individual Comments

### Comment 1
<location> `src/BootstrapBlazor/Components/DateTimePicker/DateTimePicker.razor:13-15` </location>
<code_context>
-           disabled="@Disabled" data-bs-toggle="@Constants.DropdownToggleString" data-bs-placement="@PlacementString"
-           data-bs-custom-class="@CustomClassString" @onblur="OnBlur" />
-    @if (ShowIcon)
+    @if(IsButton)
     {
-        <i class="@DateTimePickerIconClassString"></i>
+        <button type="button" class="@ButtonClassString" disabled="@Disabled"
+                data-bs-toggle="@Constants.DropdownToggleString" data-bs-placement="@PlacementString"
+                data-bs-custom-class="@CustomClassString">@PickerButtonText</button>
</code_context>

<issue_to_address>
**suggestion:** Button element lacks accessibility attributes.

Add aria-label or aria-labelledby to ensure screen readers can identify the button's purpose, especially if the button text is missing or localized.

```suggestion
        <button type="button" class="@ButtonClassString" disabled="@Disabled"
                data-bs-toggle="@Constants.DropdownToggleString" data-bs-placement="@PlacementString"
                data-bs-custom-class="@CustomClassString"
                aria-label="@(!string.IsNullOrEmpty(PickerButtonText) ? PickerButtonText : "Open date time picker")">@PickerButtonText</button>
```
</issue_to_address>

### Comment 2
<location> `src/BootstrapBlazor/Components/DateTimePicker/DateTimePicker.razor.js:16` </location>
<code_context>
+    Data.set(id, { el, input, invoke, options, popover });
+}
+
+const createPopover = (el, invoke, options) => {
     const popover = Popover.init(el, {
         dropdownSelector: el.getAttribute('data-bb-dropdown'),
</code_context>

<issue_to_address>
**issue (complexity):** Consider inlining helper functions into lifecycle methods to make the code flow more direct and readable.

Consider inlining the small helpers back into `init`/`reset`/`dispose` to remove a layer of indirection. For example:

```js
export function init(id, invoke, options) {
  const el = document.getElementById(id);
  if (!el) return;

  const popover = Popover.init(el, {
    dropdownSelector: el.getAttribute('data-bb-dropdown'),
    isDisabled: () => el.classList.contains('disabled'),
    hideCallback: () => {
      if (invoke) invoke.invokeMethodAsync(options.triggerHideCallback);
    }
  });

  const input = el.querySelector('.datetime-picker-input');
  if (input) {
    EventHandler.on(input, 'keydown', e => {
      if (e.key === 'Tab' && popover.isShown()) popover.hide();
    });
    EventHandler.on(input, 'keyup', e => {
      if (e.key === 'Escape') {
        popover.hide();
        input.blur();
      } else if (e.key === 'Tab') {
        popover.show();
      }
    });
  }

  Data.set(id, { el, popover, input, invoke, options });
}
```

Then in `reset` and `dispose` you can similarly inline off-calls:

```js
export function dispose(id) {
  const data = Data.get(id);
  Data.remove(id);
  if (!data) return;

  const { input, popover } = data;
  if (input) {
    EventHandler.off(input, 'keydown');
    EventHandler.off(input, 'keyup');
  }
  Popover.dispose(popover);
}
```

This removes `createPopover`, `handlerInput`, `disposeInput` and makes the flow directly visible in each lifecycle method.
</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.

@codecov
Copy link

codecov bot commented Oct 24, 2025

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 100.00%. Comparing base (7239ed0) to head (66f817a).
⚠️ Report is 1 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff            @@
##              main     #6999   +/-   ##
=========================================
  Coverage   100.00%   100.00%           
=========================================
  Files          741       741           
  Lines        32371     32397   +26     
  Branches      4481      4485    +4     
=========================================
+ Hits         32371     32397   +26     
Flag Coverage Δ
BB 100.00% <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.

@ArgoZhang ArgoZhang merged commit 37ab016 into main Oct 24, 2025
2 of 4 checks passed
@ArgoZhang ArgoZhang deleted the feat-dtm-button branch October 24, 2025 13:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(DateTimePicker): add IsButton parameter

2 participants