feat(ui): modernize editor UI with monochrome shadcn-style design system#591
feat(ui): modernize editor UI with monochrome shadcn-style design system#591JasonXuDeveloper wants to merge 15 commits intomasterfrom
Conversation
Make core lightweight by extracting MessageBox with an abstraction layer: - Add Prompt abstraction in core for user dialogs (delegate-based) - Create new jengine.ui package for UI utilities - Move MessageBox from core to ui package (namespace: JEngine.UI) - Update Bootstrap to use Prompt.ShowDialogAsync instead of MessageBox - Add PromptInitializer.cs for easy UI integration Package structure after changes: - jengine.core: Independent hot update only, with Prompt abstraction - jengine.ui: Optional UI utilities (MessageBox) Users can customize prompt behavior by: 1. Using the default MessageBox via PromptInitializer 2. Implementing custom dialog providers This keeps core non-invasive (无侵入式) for hot updates while allowing UI customization through the optional ui package. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> Signed-off-by: JasonXuDeveloper - 傑 <jason@xgamedev.net>
- Make ShowDialogAsync thread-safe with volatile backing field and Interlocked.Exchange - Improve XML documentation for Prompt class with usage examples - Change default behavior to log error and return false (safer default) - Add namespace to PromptInitializer (JEngine) - Add TextMeshPro dependency to jengine.ui package.json - Remove JEngine.UI dependency from HotUpdate.Code (use Prompt abstraction instead) - Update EntryPoint.cs to use Prompt.ShowDialogAsync instead of MessageBox.Show Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> Signed-off-by: JasonXuDeveloper - 傑 <jason@xgamedev.net>
- Use null-coalescing in getter instead of field initializer - Remove namespace from PromptInitializer (user-level code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> Signed-off-by: JasonXuDeveloper - 傑 <jason@xgamedev.net>
HotUpdate code should not directly depend on utility packages. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> Signed-off-by: JasonXuDeveloper - 傑 <jason@xgamedev.net>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> Signed-off-by: JasonXuDeveloper - 傑 <jason@xgamedev.net>
New package should start at 0.0.0. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> Signed-off-by: JasonXuDeveloper - 傑 <jason@xgamedev.net>
- New packages should start at version 0.0.0 - Document naming convention and required files - Add ui scope to commit message conventions Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> Signed-off-by: JasonXuDeveloper - 傑 <jason@xgamedev.net>
Split verbose CLAUDE.md (295 lines) into focused files: - .claude/rules/commit-conventions.md - .claude/rules/package-creation.md - .claude/rules/coding-patterns.md Main CLAUDE.md now 84 lines with essential info only. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> Signed-off-by: JasonXuDeveloper - 傑 <jason@xgamedev.net>
- Add @imports to CLAUDE.md for .claude/rules/ files - Update copilot instructions to allow no-namespace code in Assets/Scripts/ - Add JEngine.UI namespace to instruction files Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com> Signed-off-by: JasonXuDeveloper - 傑 <jason@xgamedev.net>
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>
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>
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>
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>
…trast 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>
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>
58faf0e to
3859505
Compare
Unity Test Results✅ EditMode: All tests passed Unity Version: 2022.3.55f1 ✅ All tests passed! The PR is ready for review. View workflow run |
There was a problem hiding this comment.
Pull request overview
This PR modernizes JEngine's Unity Editor UI by introducing a new com.jasonxudeveloper.jengine.ui package with a clean, professional monochrome design system. The changes extract MessageBox from the core package, create a new Prompt abstraction layer, add comprehensive UI components with performance optimizations, and enhance editor integration with extensible handler registration.
Changes:
- New UI package with monochrome design system (Tokens, JTheme, 15+ components)
- MessageBox extraction from core with test infrastructure (TestHandler, SimulateNoPrefab)
- Prompt abstraction layer for dialog provider decoupling with thread-safe registration
- Performance optimizations using static lambdas to eliminate closure allocations
- Enhanced editor integration with handler registration pattern for PanelUI and BootstrapEditorUI
Reviewed changes
Copilot reviewed 109 out of 109 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| com.jasonxudeveloper.jengine.ui/* | New package with UI components, theming system, and MessageBox |
| MessageBox.cs | Moved to UI package with testability features (InternalsVisibleTo, TestHandler) |
| Prompt.cs | New abstraction layer for dialogs with thread-safe registration |
| Bootstrap.cs | Updated to use Prompt.ShowDialogAsync instead of MessageBox.Show |
| Panel.cs | Added CreatePanelContentHandler for UI package integration |
| BootstrapEditor.cs | Added CreateInspectorHandler, moved helper methods to EditorUtils |
| EditorUtils.cs | New helper methods for package/assembly/scene discovery |
| BuildHelper.cs | Extracted build execution logic with callback pattern |
| PromptInitializer.cs | Runtime initializer to register MessageBox as dialog provider |
| .github/workflows/* | Updated release and test workflows for UI package |
| CLAUDE.md | Restructured into modular rules files |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| foreach (var button in buttons) | ||
| { | ||
| if (button != null) | ||
| { | ||
| // Apply group styling to buttons - compact | ||
| button.style.marginRight = Tokens.Spacing.Sm; | ||
| button.style.marginBottom = Tokens.Spacing.Xs; | ||
| button.style.flexGrow = 1; | ||
| button.style.flexShrink = 0; | ||
| button.style.minWidth = 100; | ||
| base.Add(button); | ||
| } | ||
| } |
There was a problem hiding this comment.
This foreach loop implicitly filters its target sequence - consider filtering the sequence explicitly using '.Where(...)'.
| foreach (var child in children) | ||
| { | ||
| if (child != null) | ||
| { | ||
| base.Add(child); | ||
| } | ||
| } |
There was a problem hiding this comment.
This foreach loop implicitly filters its target sequence - consider filtering the sequence explicitly using '.Where(...)'.
| foreach (var button in buttons) | ||
| { | ||
| if (button != null) | ||
| { | ||
| button.style.marginRight = Tokens.Spacing.Sm; | ||
| button.style.marginBottom = Tokens.Spacing.Xs; | ||
| button.style.flexGrow = 1; | ||
| button.style.flexShrink = 0; | ||
| button.style.minWidth = 100; | ||
| base.Add(button); | ||
| } | ||
| } |
There was a problem hiding this comment.
This foreach loop implicitly filters its target sequence - consider filtering the sequence explicitly using '.Where(...)'.
| foreach (var child in children) | ||
| { | ||
| if (child != null) | ||
| { | ||
| _fields.Add(child); | ||
| } | ||
| } |
There was a problem hiding this comment.
This foreach loop implicitly filters its target sequence - consider filtering the sequence explicitly using '.Where(...)'.
| foreach (var child in children) | ||
| { | ||
| if (child != null) | ||
| { | ||
| _controlContainer.Add(child); | ||
| } | ||
| } |
There was a problem hiding this comment.
This foreach loop implicitly filters its target sequence - consider filtering the sequence explicitly using '.Where(...)'.
| foreach (var child in children) | ||
| { | ||
| if (child != null) | ||
| { | ||
| _content.Add(child); | ||
| } | ||
| } |
There was a problem hiding this comment.
This foreach loop implicitly filters its target sequence - consider filtering the sequence explicitly using '.Where(...)'.
|
Closing to recreate PR from correct base (master already has MessageBox extraction from #590) |
Summary
Modernizes JEngine's Unity Editor UI with a clean, professional monochrome design system inspired by shadcn/ui. The new design features true grayscale inversion between light and dark themes, improved visual hierarchy, and performance optimizations.
Key Changes
🎨 Design System
📦 New Package Structure
com.jasonxudeveloper.jengine.uipackageTokens.cs🧩 Components
Layout:
Forms:
Buttons:
Feedback:
All components feature:
⚡ Performance Improvements
🎯 Visual Improvements
Dark Theme:
Light Theme:
Both Themes:
📝 Documentation
Testing
Breaking Changes
None. All changes are internal to the new UI package. Existing code is unaffected.
Screenshots
Before
Original dark theme with blue-tinted colors and less contrast
After
Clean monochrome design with true grayscale inversion:
Design Philosophy: Shadcn-style monochrome with professional, clean aesthetics. Dark theme is a perfect grayscale inversion of light theme for consistency.
Co-Authored-By: Claude Sonnet 4.5 noreply@anthropic.com