Skip to content

Commit 3b89208

Browse files
feat(ui): modernize editor UI with monochrome design system (#592)
* feat(ui): modernize editor UI with shadcn-style design system Major UI overhaul implementing shadcn-inspired design with glassmorphic elements in dark mode and clean monochromatic styling in light mode. ## New UI Package (com.jasonxudeveloper.jengine.ui) ### Components - **Button**: JButton, JToggleButton, JButtonGroup with 5 variants - **Form**: JFormField, JTextField, JDropdown, JToggle, JObjectField - **Layout**: JCard, JSection, JStack, JRow for composition - **Feedback**: JStatusBar, JLogView, JProgressBar - **Navigation**: JBreadcrumb with clean hierarchical display ### Theme System - Design tokens (Tokens.cs) with dark/light theme support - Glassmorphic palette for dark mode (translucent layers, vibrant accents) - shadcn-style monochromatic palette for light mode (black/white/grey only) - 8px spacing grid, typography scale, border radius system - Smooth transitions (150-300ms) ### Enhanced Editor UIs - BootstrapEditorUI: Redesigned Bootstrap inspector with modern components - PanelUI: Redesigned Panel window with enhanced scene management ## Core Package Improvements ### Code Deduplication - **EditorUtils.cs**: Extracted 6 shared helper methods from BootstrapEditor and BootstrapEditorUI (GetAvailableAsmdefFiles, GetAvailableHotScenes, GetAvailableHotClasses, GetAvailableHotMethods, GetAvailableDynamicSecretKeys, GetAvailableAOTDataFiles) - **BuildHelper.cs**: New shared build execution logic with UI callbacks, eliminating ~200 lines of duplication between Panel.cs and PanelUI.cs ### Bug Fixes - Panel.cs: Added null checks in LogMessage to prevent crashes when using enhanced PanelUI - PanelUI: Creates its own BuildManager with proper log routing to JLogView ## Design Decisions ### Light Theme Philosophy - Monochromatic black/white/grey only (no colors except semantic highlights) - Buttons use grey shades (Primary: gray-700, Secondary: gray-300) - Clean, minimal aesthetic inspired by shadcn/ui ### Dark Theme Philosophy - Glassmorphic translucent layers (40-80% opacity) - Vibrant cyan accents (#06B6D4) with subtle glow effects - 5-level glass system (Base → Subtle → Surface → Elevated → Overlay) ### Component Patterns - Fluent API for chaining (.WithText().FullWidth()) - Consistent spacing and sizing across all components - Theme-aware colors (automatically adapt to Unity editor theme) - Proper keyboard navigation with visible focus states Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> Signed-off-by: JasonXuDeveloper - 傑 <jason@xgamedev.net> * refactor(ui): eliminate closure allocations in event callbacks Replace lambda closures with static lambdas and state parameters to avoid heap allocations in RegisterCallback calls. Updated 6 component files: - JBreadcrumb: static methods with state parameters - JCard: instance methods - JStack: static lambda with tuple state - JToggle: static lambdas with state parameters - JObjectField: instance methods + static lambdas with state - JTextField: static lambdas with state parameters This improves performance by eliminating 14 closure allocations across the UI toolkit components using C#9 static lambda support. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> Signed-off-by: JasonXuDeveloper - 傑 <jason@xgamedev.net> * refactor(ui): simplify dark theme to monochrome grayscale Replace vibrant glassmorphic design with clean monochrome palette where dark theme is the grayscale inversion of light theme. Changes: - Remove all vibrant accent colors (cyan, emerald, rose, amber) - Dark theme now uses black/white/greys inverted from light theme - Light theme colors remain unchanged - Remove opacity-based glass layers, use solid greys - Update JToggle to use Primary/Secondary instead of Accent - Simplify comments to reflect new monochrome approach Color mapping (dark theme inverted from light): - BgBase: #0F1419 (near-black) ← #FFFFFF (white) - BgSurface: #374151 (gray-700) ← #E5E7EB (gray-200) - TextPrimary: #FFFFFF (white) ← #111827 (gray-900) - Primary: #D1D5DB (gray-300) ← #374151 (gray-700) - Borders: #4B5563 (gray-600) ← #D1D5DB (gray-300) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> Signed-off-by: JasonXuDeveloper - 傑 <jason@xgamedev.net> * refactor(ui): fix dark theme colors to pure neutral greys Improved dark theme to use truly neutral RGB greys (R=G=B) instead of blue-tinted colors. Fixed three visual issues from user feedback: 1. Primary button color too dark - changed dark theme to use lighter #C8C8C8 grey for better contrast with white text 2. Status bar showing blue - removed colored backgrounds in dark mode, now uses neutral grey like light mode (monochrome design) 3. Log view too black - changed from BgBase (#0A0A0A) to BgSubtle (#1A1A1A) for slightly lighter background Color changes (dark theme only, light theme unchanged): - BgBase: #0F1419 → #0A0A0A (pure neutral black) - BgSubtle: #1F2937 → #1A1A1A (pure neutral dark grey) - BgSurface: #374151 → #2A2A2A (pure neutral grey) - BgElevated: #4B5563 → #3A3A3A (pure neutral medium-dark grey) - BgOverlay: #6B7280 → #4A4A4A (pure neutral medium grey) - Primary: #D1D5DB → #C8C8C8 (lighter for better button contrast) - All text/borders now use neutral greys (#FFFFFF, #D0D0D0, etc.) JStatusBar now uses monochrome design in both themes (no colored backgrounds in dark mode). Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> Signed-off-by: JasonXuDeveloper - 傑 <jason@xgamedev.net> * refactor(ui): improve dark theme with proper color inversions and contrast Fixed multiple visual issues in dark theme based on user feedback: 1. Button colors now properly inverted: - Dark Primary (#D0D0D0) = Light Secondary - Dark Secondary (#374151) = Light Primary - True grayscale inversion between themes 2. Input field backgrounds differentiated: - New BgInput color (#353535) lighter than BgSurface in dark mode - Applies to JTextField, JObjectField, and JDropdown - Better visual separation from surrounding surface 3. Toggle styling fixed: - Track colors match Primary/Secondary button colors - Thumb stays white in both themes (no inversion) 4. Separator/divisor visibility improved: - BorderSubtle lightened to #454545 in dark mode - Now visible against darker backgrounds 5. Button text colors use theme tokens: - JButton and JToggleButton use PrimaryText/SecondaryText - No more hardcoded Color.white - Dark Primary buttons now have black text (#111111) 6. Log view lightened: - Uses BgSubtle (#252525) instead of BgBase - More readable background Color mapping (dark theme): - Primary: #D0D0D0 (light grey, black text) - Secondary: #374151 (dark grey, white text) - BgInput: #353535 (for inputs) - BgSubtle: #252525 (for log view) - BorderSubtle: #454545 (for separators) Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> Signed-off-by: JasonXuDeveloper - 傑 <jason@xgamedev.net> * fix(ui): correct Primary button hover/active colors for true inversion Fixed Primary button hover and active states to properly invert with light theme's Secondary colors: Dark mode Primary (was wrong): - Hover: #E0E0E0 → #9A9A9A (now matches light's SecondaryHover) - Active: #C0C0C0 → #6A6A6A (now matches light's SecondaryActive) Now the inversion is complete and consistent across all button states. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com> Signed-off-by: JasonXuDeveloper - 傑 <jason@xgamedev.net> --------- Signed-off-by: JasonXuDeveloper - 傑 <jason@xgamedev.net> Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
1 parent 4c635ad commit 3b89208

File tree

79 files changed

+6805
-220
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

79 files changed

+6805
-220
lines changed

.github/instructions/code-review.instructions.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,13 @@ For state accessed across Unity callbacks:
3636
- Hot update: `HotUpdate.Code`
3737
- **Exception**: `Assets/Scripts/` may contain user-level code without namespace (intentional for user customization)
3838

39+
### 6. Performance Patterns
40+
Avoid LINQ in hot paths and UI code for performance:
41+
- Use `for`/`foreach` loops with inline null checks instead of `.Where()`
42+
- Use `Count > 0` or `Length > 0` instead of `.Any()`
43+
- Use array/list indexing instead of `.First()` / `.Last()`
44+
- LINQ allocates iterators and delegates - avoid in frequently called code
45+
3946
## Common Issues to Flag
4047

4148
- Missing XML documentation on public APIs
Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
// BuildHelper.cs
2+
//
3+
// Author:
4+
// JasonXuDeveloper <jason@xgamedev.net>
5+
//
6+
// Copyright (c) 2025 JEngine
7+
//
8+
// Permission is hereby granted, free of charge, to any person obtaining a copy
9+
// of this software and associated documentation files (the "Software"), to deal
10+
// in the Software without restriction, including without limitation the rights
11+
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12+
// copies of the Software, and to permit persons to whom the Software is
13+
// furnished to do so, subject to the following conditions:
14+
//
15+
// The above copyright notice and this permission notice shall be included in
16+
// all copies or substantial portions of the Software.
17+
//
18+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23+
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24+
// THE SOFTWARE.
25+
26+
using System;
27+
using JEngine.Core.Editor.CustomEditor;
28+
using UnityEditor;
29+
30+
namespace JEngine.Core.Editor
31+
{
32+
/// <summary>
33+
/// Helper class for build operations with UI update callbacks.
34+
/// </summary>
35+
public static class BuildHelper
36+
{
37+
/// <summary>
38+
/// Callbacks for build UI updates.
39+
/// </summary>
40+
public class BuildCallbacks
41+
{
42+
/// <summary>
43+
/// Called to enable/disable build buttons.
44+
/// </summary>
45+
public Action<bool> SetButtonsEnabled { get; set; }
46+
47+
/// <summary>
48+
/// Called to clear the log view.
49+
/// </summary>
50+
public Action ClearLog { get; set; }
51+
52+
/// <summary>
53+
/// Called to update status text.
54+
/// </summary>
55+
public Action<string> UpdateStatus { get; set; }
56+
57+
/// <summary>
58+
/// Called when build completes successfully.
59+
/// </summary>
60+
public Action OnSuccess { get; set; }
61+
62+
/// <summary>
63+
/// Called when build fails.
64+
/// </summary>
65+
public Action OnError { get; set; }
66+
}
67+
68+
/// <summary>
69+
/// Executes BuildAll with standard UI callbacks.
70+
/// </summary>
71+
public static void ExecuteBuildAll(BuildManager buildManager, BuildCallbacks callbacks)
72+
{
73+
if (buildManager.IsBuilding) return;
74+
75+
callbacks.SetButtonsEnabled?.Invoke(false);
76+
callbacks.ClearLog?.Invoke();
77+
78+
buildManager.StartBuildAll(
79+
onComplete: () =>
80+
{
81+
callbacks.SetButtonsEnabled?.Invoke(true);
82+
callbacks.UpdateStatus?.Invoke("Build completed");
83+
callbacks.OnSuccess?.Invoke();
84+
EditorUtility.DisplayDialog("Build Successful", "Build completed successfully!", "OK");
85+
},
86+
onError: e =>
87+
{
88+
callbacks.SetButtonsEnabled?.Invoke(true);
89+
callbacks.UpdateStatus?.Invoke("Build failed");
90+
callbacks.OnError?.Invoke();
91+
EditorUtility.DisplayDialog("Build Failed", $"Build failed with error:\n{e.Message}", "OK");
92+
}
93+
);
94+
}
95+
96+
/// <summary>
97+
/// Executes BuildCodeOnly with standard UI callbacks.
98+
/// </summary>
99+
public static void ExecuteBuildCodeOnly(BuildManager buildManager, BuildCallbacks callbacks)
100+
{
101+
if (buildManager.IsBuilding) return;
102+
103+
callbacks.SetButtonsEnabled?.Invoke(false);
104+
callbacks.ClearLog?.Invoke();
105+
106+
buildManager.StartBuildCodeOnly(
107+
onComplete: () =>
108+
{
109+
callbacks.SetButtonsEnabled?.Invoke(true);
110+
callbacks.UpdateStatus?.Invoke("Code build completed");
111+
callbacks.OnSuccess?.Invoke();
112+
EditorUtility.DisplayDialog("Code Build Successful", "Code build completed successfully!", "OK");
113+
},
114+
onError: e =>
115+
{
116+
callbacks.SetButtonsEnabled?.Invoke(true);
117+
callbacks.UpdateStatus?.Invoke("Code build failed");
118+
callbacks.OnError?.Invoke();
119+
EditorUtility.DisplayDialog("Code Build Failed", $"Code build failed with error:\n{e.Message}", "OK");
120+
}
121+
);
122+
}
123+
124+
/// <summary>
125+
/// Executes BuildAssetsOnly with standard UI callbacks.
126+
/// </summary>
127+
public static void ExecuteBuildAssetsOnly(BuildManager buildManager, BuildCallbacks callbacks)
128+
{
129+
if (buildManager.IsBuilding) return;
130+
131+
callbacks.SetButtonsEnabled?.Invoke(false);
132+
callbacks.ClearLog?.Invoke();
133+
134+
buildManager.StartBuildAssetsOnly(
135+
onComplete: () =>
136+
{
137+
callbacks.SetButtonsEnabled?.Invoke(true);
138+
callbacks.UpdateStatus?.Invoke("Assets build completed");
139+
callbacks.OnSuccess?.Invoke();
140+
EditorUtility.DisplayDialog("Assets Build Successful", "Assets build completed successfully!", "OK");
141+
},
142+
onError: e =>
143+
{
144+
callbacks.SetButtonsEnabled?.Invoke(true);
145+
callbacks.UpdateStatus?.Invoke("Assets build failed");
146+
callbacks.OnError?.Invoke();
147+
EditorUtility.DisplayDialog("Assets Build Failed", $"Assets build failed with error:\n{e.Message}", "OK");
148+
}
149+
);
150+
}
151+
}
152+
}

UnityProject/Packages/com.jasonxudeveloper.jengine.core/Editor/BuildHelper.cs.meta

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)