Add reusable Button component and migrate generic button markup app-wide#602
Merged
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
Introduces a reusable ButtonBase component (plus variant wrappers) under EventLogExpert.UI.Inputs and migrates existing .button design-system usage across the UI to reduce duplicated markup and default type="button" for safer in-form usage.
Changes:
- Added
ButtonBaseplus variant components (Button,PrimaryButton,DangerButton,WarningButton) and a comprehensive bUnit test suite for rendering/click/attribute-splat behavior. - Migrated many Razor views from raw
<button class="button ...">to the new components, including updates to CSS-isolation selectors via::deep. - Moved one previously component-scoped button style (
library-saved-tab-new-button) into the global stylesheet to keep styling working after migration.
Reviewed changes
Copilot reviewed 53 out of 53 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| tests/Unit/EventLogExpert.UI.Tests/Inputs/ButtonTests.cs | Adds unit coverage for ButtonBase rendering, variants, default type, splatted attributes, and click behavior. |
| src/EventLogExpert.UI/wwwroot/app.css | Adds global styling for library-saved-tab-new-button under the .button design system. |
| src/EventLogExpert.UI/Modal/ModalChrome.razor.css | Updates isolated CSS selectors to use ::deep for button styling through the new component. |
| src/EventLogExpert.UI/Modal/ModalChrome.razor.cs | Switches focus refs from ElementReference to component refs to support ButtonBase focus API. |
| src/EventLogExpert.UI/Modal/ModalChrome.razor | Migrates modal chrome buttons to the new Button components. |
| src/EventLogExpert.UI/Inputs/WarningButton.cs | Adds warning (yellow) button variant wrapper. |
| src/EventLogExpert.UI/Inputs/PrimaryButton.cs | Adds primary (green) button variant wrapper. |
| src/EventLogExpert.UI/Inputs/DangerButton.cs | Adds danger (red) button variant wrapper. |
| src/EventLogExpert.UI/Inputs/ButtonBase.cs | Implements the reusable base button component with attribute splat, icon support, and focus API. |
| src/EventLogExpert.UI/Inputs/Button.cs | Adds the default (no variant class) button wrapper. |
| src/EventLogExpert.UI/FilterPane/FilterPane.razor.css | Adjusts isolated CSS to style nested button elements via ::deep after migration. |
| src/EventLogExpert.UI/FilterPane/FilterPane.razor | Migrates filter pane buttons (including icon-only actions) to reusable Button components. |
| src/EventLogExpert.UI/FilterLibrary/TagManagementPanel.razor | Migrates tag management action buttons to variant Button components. |
| src/EventLogExpert.UI/FilterLibrary/LibrarySavedTabHeader.razor.css | Removes component-scoped styles that were moved global to keep styling after migration. |
| src/EventLogExpert.UI/FilterLibrary/LibrarySavedTabHeader.razor | Migrates the “New saved filter” button to the reusable Button component. |
| src/EventLogExpert.UI/FilterLibrary/LibraryEntryRow.razor.css | Uses ::deep selectors to style button elements rendered by child components. |
| src/EventLogExpert.UI/FilterLibrary/LibraryEntryRow.razor.cs | Switches “more actions” focus/anchor handling to component refs and ButtonBase.Element. |
| src/EventLogExpert.UI/FilterLibrary/LibraryEntryRow.razor | Migrates library entry row buttons (expand, tags, favorite, menu) to reusable components. |
| src/EventLogExpert.UI/FilterLibrary/LibraryEntryFilterEditor.razor.css | Updates isolated selector to target nested button via ::deep. |
| src/EventLogExpert.UI/FilterLibrary/LibraryEntryFilterEditor.razor | Migrates “Add filter” button to reusable Button component. |
| src/EventLogExpert.UI/FilterLibrary/FilterLibraryModal.razor | Migrates modal retry and tag management trigger buttons to reusable components. |
| src/EventLogExpert.UI/FilterEditor/Rows/FilterRowHeader.razor.css | Updates isolated selectors with ::deep for nested button styling. |
| src/EventLogExpert.UI/FilterEditor/Rows/FilterRowHeader.razor | Migrates exclude/include toggle button to reusable Button component. |
| src/EventLogExpert.UI/FilterEditor/Rows/FilterRowActions.razor.cs | Updates focus handling to use ButtonBase.Element instead of ElementReference. |
| src/EventLogExpert.UI/FilterEditor/Rows/FilterRowActions.razor | Migrates row action icon buttons to Button/DangerButton. |
| src/EventLogExpert.UI/FilterEditor/Editing/FilterPredicateList.razor.css | Updates isolated selectors with ::deep for nested button styling. |
| src/EventLogExpert.UI/FilterEditor/Editing/FilterPredicateList.razor.cs | Updates focus handling to use a Button component ref. |
| src/EventLogExpert.UI/FilterEditor/Editing/FilterPredicateList.razor | Migrates “add predicate” icon button to reusable Button component. |
| src/EventLogExpert.UI/FilterEditor/Editing/FilterPredicateEditor.razor | Migrates predicate done/remove buttons to reusable components. |
| src/EventLogExpert.UI/FilterEditor/Editing/FilterEditPanel.razor.css | Updates isolated selectors with ::deep for nested button styling. |
| src/EventLogExpert.UI/FilterEditor/Editing/FilterEditPanel.razor | Migrates edit panel save/cancel/remove/exclude buttons to reusable components. |
| src/EventLogExpert.UI/DebugLog/DebugLogModal.razor | Migrates footer actions (export/copy/refresh/clear) to reusable Button components. |
| src/EventLogExpert.UI/DatabaseTools/Tabs/UpgradeDatabaseTab.razor | Migrates tool tab buttons (browse/run/cancel) to reusable components. |
| src/EventLogExpert.UI/DatabaseTools/Tabs/ShowProvidersTab.razor | Migrates tool tab buttons (browse/run elevated/run/cancel) to reusable components. |
| src/EventLogExpert.UI/DatabaseTools/Tabs/MergeDatabaseTab.razor | Migrates tool tab buttons (browse/run/cancel) to reusable components. |
| src/EventLogExpert.UI/DatabaseTools/Tabs/ManageDatabasesTab.razor.css | Updates isolated selector to target nested button via ::deep. |
| src/EventLogExpert.UI/DatabaseTools/Tabs/ManageDatabasesTab.razor.cs | Switches focus refs to component refs for selection/import/bulk actions. |
| src/EventLogExpert.UI/DatabaseTools/Tabs/ManageDatabasesTab.razor | Migrates manage-databases actions (select/import/bulk/remove/save/discard) to reusable components. |
| src/EventLogExpert.UI/DatabaseTools/Tabs/DiffDatabasesTab.razor | Migrates tool tab buttons (browse/run/cancel) to reusable components. |
| src/EventLogExpert.UI/DatabaseTools/Tabs/CreateDatabaseTab.razor | Migrates tool tab buttons (browse/run elevated/run/cancel) to reusable components. |
| src/EventLogExpert.UI/DatabaseTools/DatabaseToolsLogView.razor | Migrates toolbar actions (copy/export/jump) to reusable Button components. |
| src/EventLogExpert.UI/Database/DatabaseRecoveryModal.razor | Migrates batch recovery action buttons to reusable Button components. |
| src/EventLogExpert.UI/Database/DatabaseEntryRow.razor.css | Updates isolated selectors and reduced-motion rules to style nested buttons via ::deep. |
| src/EventLogExpert.UI/Database/DatabaseEntryRow.razor | Migrates database entry row action buttons to reusable Button components. |
| src/EventLogExpert.UI/Dashboard/EmptyStateDashboard.razor | Migrates empty-state “Clear filter” button to reusable Button component. |
| src/EventLogExpert.UI/Banner/UpgradeProgressBanner.razor | Migrates banner cancel action to reusable Button component. |
| src/EventLogExpert.UI/Banner/InfoBanner.razor | Migrates dismiss button to reusable Button component with icon support. |
| src/EventLogExpert.UI/Banner/ExportProgressBanner.razor | Migrates banner cancel action to reusable Button component. |
| src/EventLogExpert.UI/Banner/ErrorBanner.razor | Migrates banner action/dismiss buttons to reusable components. |
| src/EventLogExpert.UI/Banner/CriticalBanner.razor.cs | Switches focus ref to a Button component ref for post-render focusing. |
| src/EventLogExpert.UI/Banner/CriticalBanner.razor | Migrates banner action buttons (reload/relaunch/copy details) to reusable components. |
| src/EventLogExpert.UI/Banner/BannerHost.razor | Migrates cycle navigation buttons to reusable icon buttons. |
| src/EventLogExpert.UI/Banner/AttentionBanner.razor | Migrates action/dismiss buttons to reusable components. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
fd5f01e to
8dff8b5
Compare
…ainst arch mismatch
NikTilton
approved these changes
Jun 22, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Introduces a reusable Button component hierarchy and migrates the duplicated
<button class="button ...">markup across the UI to use it. This removes markup duplication, centralizes the shared button contract, and structurally defaultstype="button"so buttons inside forms no longer risk accidental submission.Component
Added under
src/EventLogExpert.UI/Inputs/(alongside the existing input components):ButtonBase: an abstract component with a single render path and all shared parameters (OnClick,Disabled,IconClass,IconOnly,Typedefaulting to"button",CssClass,ChildContent, plus an attribute splat foraria-*/data-*/title/autofocus). It exposesElementandFocusAsync(preventScroll)for focus management and JS interop.Button(default),PrimaryButton(green),DangerButton(red),WarningButton(yellow). Icon-only rendering is an orthogonalIconOnlyflag rather than a separate type.Scope
Migrated every button whose styling is the shared
.buttondesign system: the banners, the database-tools tabs, the filter editor, the filter library, the filter pane, the modal chrome, the debug log, and the empty-state dashboard's filter chip.Left native by design (bespoke styling or event semantics outside the
.buttonsystem): the filter-pane split-button compound, the sidebar tabs, the tag-chip remove controls, the master-selection checkbox, the filter predicate chips, the database-name button, and the dashboard / scenario launch tiles.Component-scoped CSS targeting these buttons was preserved through
::deepin the affected stylesheets (with one component-root button's rule moved to the global stylesheet).Testing
ButtonTests(18 cases) cover the variant classes, icon rendering, the defaulttype="button", the disabled state, the attribute splat, and click invocation.