Skip to content

Dark mode UI#859

Open
awilliansd wants to merge 17 commits intopaolosalvatori:mainfrom
awilliansd:feature/dark-mode
Open

Dark mode UI#859
awilliansd wants to merge 17 commits intopaolosalvatori:mainfrom
awilliansd:feature/dark-mode

Conversation

@awilliansd
Copy link
Copy Markdown

@awilliansd awilliansd commented Mar 12, 2026

Add Dark/Light Theme Toggle

Summary

Adds a runtime dark/light theme toggle to Service Bus Explorer.
Default is dark, switchable via View → Theme → Dark / Light, with persistence across sessions.

Changes

New

  • Helpers/ThemeManager.cs — theming engine (recursive apply, persistence, custom control support)
  • Helpers/MainFormThemeExtension.cs — menu injection + native dark title bar

Updated

  • MainForm.cs — initializes theming
  • All Forms and UserControls — apply theme after InitializeComponent()
  • All .Designer.cs — neutralized hardcoded colors

Technical Overview

  • Recursive theming via ThemeManager.Apply(Control)
  • Runtime switching with SetTheme / Toggle
  • Reapplies theme to all open forms
  • Preference persisted via ConfigurationManager
  • Custom control support via reflection
  • Dark rendering for ToolStrip, MenuStrip, TabControl
  • Native dark title bar (Windows 10 1903+ via DWM)

Themes

Dark

  • Background: #212121
  • Surface: #2A2A2A
  • Border: #484848
  • Text: #ECECEC
  • Accent: #007ACC

Light

  • Uses SystemColors (native Windows appearance)

Notes

  • UI-only change (no impact on logic)
  • AboutForm excluded due to custom background
  • Azure logo uses fixed background for visibility

Testing

  • Verified on Windows 11 (.NET Framework 4.7.2)
  • All forms render correctly in both themes
  • Theme persists after restart

Copy link
Copy Markdown
Collaborator

@SeanFeldman SeanFeldman left a comment

Choose a reason for hiding this comment

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

@awilliansd there are a few comments that apply to multiple places.
Also, the screenshots are missing.
The AI-generated documentation has the "Build script" section, mentioning a build script build-dark-theme.ps1, but that's not in the PR. Nor should there be, as it should work with the existing build infrastructure.

Comment thread src/ServiceBusExplorer/Helpers/ThemeManager.cs Outdated
Comment thread src/ServiceBusExplorer/Helpers/ThemeManager.cs Outdated
@awilliansd
Copy link
Copy Markdown
Author

I've fixed the comments, added the script I used, and refactored several times. I've also added screenshots in the folder. Sorry for my mistake. Thanks for the feedback.

@awilliansd awilliansd requested a review from SeanFeldman March 16, 2026 00:34
Comment thread scripts/build-dark-theme.ps1 Outdated
@awilliansd awilliansd requested a review from SeanFeldman March 18, 2026 11:27
@SeanFeldman
Copy link
Copy Markdown
Collaborator

@paolosalvatori and @ErikMogensen, a nice UI update for those that crave dark mode. Thoughts?

@paolosalvatori
Copy link
Copy Markdown
Owner

If the feature works as expected, I'm more than happy to approve and merge it. Did you guys tried it @SeanFeldman / @ErikMogensen?

var color = e.Item.Selected
? ThemeManager.SurfaceLighter
: ThemeManager.SurfaceLight;
e.Graphics.FillRectangle(new SolidBrush(color), e.Item.ContentRectangle);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The SolidBrush is not being disposed of. Unlike above where you are using a using statement.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed

}

protected override void OnRenderToolStripBackground(ToolStripRenderEventArgs e)
=> e.Graphics.FillRectangle(new SolidBrush(ThemeManager.Surface), e.AffectedBounds);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Same here

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed

if (e.Item.Selected || e.Item.Pressed)
{
var color = e.Item.Pressed ? ThemeManager.Accent : ThemeManager.SurfaceLighter;
e.Graphics.FillRectangle(new SolidBrush(color), new Rectangle(Point.Empty, e.Item.Size));
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

And here

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed

{
ApplyToControl(control);
ApplyRecursive(control);
control.ControlAdded += (s, e) => ApplyRecursive(e.Control);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Each Apply() call (e.g., during Toggle()/SetTheme()) adds another handler. After toggling twice, every new control added gets themed twice. Guard against this or unsubscribe first.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

I changed duplicate event subscriptions in ThemeManager.Apply

Comment on lines +272 to +273
MainFormThemeExtension.InitTheme(this, mainMenuStrip);
ThemeManager.Apply(this);
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

InitTheme(MainForm, MenuStrip) already calls ThemeManager.Apply(form) . The second call in MainForm's constructor (line after) is a duplicate that also registers a second ControlAdded handler.

Comment thread src/ServiceBusExplorer/Forms/ContainerForm.cs Outdated
Comment thread src/ServiceBusExplorer/Helpers/ThemeManager.cs Outdated
@ErikMogensen
Copy link
Copy Markdown
Collaborator

I think it is a very cool feature. I started a build from the branch but the Themes menu item was not visible when I ran it. I haven't looked into it so it may be something on my side.
image

@awilliansd, since normally application default to the light theme I think we should stick to that.

…commit includes:\n- Translation of theme manager components to English\n- Updates to EventGrid library files\n- Improvements to ContainerForm UI layout\n- Enhancements to various controls (HandleEventGridSubscriptionControl, HandleQueueControl)\n- Dark mode implementation refinements
@awilliansd
Copy link
Copy Markdown
Author

I think it is a very cool feature. I started a build from the branch but the Themes menu item was not visible when I ran it. I haven't looked into it so it may be something on my side. image

@awilliansd, since normally application default to the light theme I think we should stick to that.

image

In my branch, this is the button to choose theme

@awilliansd awilliansd changed the title Apply dark mode in many files UI Dark mode Mar 30, 2026
@awilliansd awilliansd changed the title UI Dark mode Dark mode UI Mar 30, 2026
@awilliansd awilliansd requested a review from ErikMogensen March 30, 2026 23:26
@ErikMogensen
Copy link
Copy Markdown
Collaborator

In my branch, this is the button to choose theme

I pulled ten commits and now I see it. It is quite a different look even for the light theme:
image

The dark theme:
image

@paolosalvatori, you are the author - what do you think of it?

@awilliansd
Copy link
Copy Markdown
Author

In my branch, this is the button to choose theme

I pulled ten commits and now I see it. It is quite a different look even for the light theme: image

The dark theme: image

@paolosalvatori, you are the author - what do you think of it?

I tried to get the closest color. But if you want, I can try to get even closer; it's a bit difficult.

@awilliansd
Copy link
Copy Markdown
Author

image image

Color changed in Light Theme

Resolve conflicts by prioritizing upstream dashboard and control logic while preserving dark-mode integration in MainForm, HandleQueueControl, and HandleSubscriptionControl.
@SeanFeldman
Copy link
Copy Markdown
Collaborator

@awilliansd is the latest round of changes addressing the issue @ErikMogensen brought up?

@awilliansd
Copy link
Copy Markdown
Author

@awilliansd is the latest round of changes addressing the issue @ErikMogensen brought up?

Yes, I merged it with the main version, just check my last commits.

0998004

cd66735

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.

4 participants