Skip to content

Commit 35f28a9

Browse files
refactor(ui): improve theming system and add cursor support (#596)
- Simplify Tokens.cs with base Palette class reducing color duplication - Add shared input styling methods to JTheme for consistent form controls - Make JDropdown generic with ForEnum<T>() factory method for enum support - Add JIconButton component for small transparent icon buttons - Add USS-based cursor styles (pointer for clickables, text for inputs) - Fix hover effects using PointerOverEvent/PointerOutEvent for PopupField - Add dynamic toggle thumb colors using Primary/Secondary tokens - Update BootstrapEditorUI and PanelUI to use generic components - Remove unused JFormSection.cs and PopupFieldStyleHelper.cs Signed-off-by: JasonXuDeveloper - 傑 <jason@xgamedev.net> Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
1 parent e8f5cd2 commit 35f28a9

File tree

20 files changed

+691
-880
lines changed

20 files changed

+691
-880
lines changed

UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Editor/Components/Button/JButton.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ private void ApplyBaseStyles()
109109

110110
// Font styling
111111
style.fontSize = Tokens.FontSize.Base;
112-
style.unityFontStyleAndWeight = FontStyle.Bold;
112+
style.unityFontStyleAndWeight = FontStyle.Normal;
113113

114114
// No border for glassmorphic look
115115
style.borderTopWidth = 0;
@@ -124,6 +124,9 @@ private void ApplyBaseStyles()
124124

125125
// Smooth glassmorphic transitions
126126
JTheme.ApplyTransition(this);
127+
128+
// Pointer cursor for clickable element
129+
JTheme.ApplyPointerCursor(this);
127130
}
128131

129132
/// <summary>
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
// JIconButton.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.UI.Editor.Theming;
28+
using UnityEngine;
29+
using UnityEngine.UIElements;
30+
31+
namespace JEngine.UI.Editor.Components.Button
32+
{
33+
/// <summary>
34+
/// A small icon button with transparent background, suitable for toolbars and inline actions.
35+
/// </summary>
36+
public class JIconButton : UnityEngine.UIElements.Button
37+
{
38+
/// <summary>
39+
/// Creates a new icon button.
40+
/// </summary>
41+
/// <param name="text">The button text (typically an icon character or short text).</param>
42+
/// <param name="onClick">Click handler.</param>
43+
/// <param name="tooltip">Optional tooltip.</param>
44+
public JIconButton(string text, Action onClick = null, string tooltip = null)
45+
{
46+
this.text = text;
47+
this.tooltip = tooltip;
48+
49+
AddToClassList("j-icon-button");
50+
ApplyStyles();
51+
52+
if (onClick != null)
53+
{
54+
clicked += onClick;
55+
}
56+
57+
// Hover events
58+
RegisterCallback<MouseEnterEvent>(OnMouseEnter);
59+
RegisterCallback<MouseLeaveEvent>(OnMouseLeave);
60+
}
61+
62+
private void ApplyStyles()
63+
{
64+
// Small size
65+
style.width = 22;
66+
style.height = 18;
67+
style.minWidth = 18;
68+
style.minHeight = 18;
69+
70+
// No padding/margin
71+
style.marginLeft = 2;
72+
style.marginRight = 0;
73+
style.marginTop = 0;
74+
style.marginBottom = 0;
75+
style.paddingLeft = 0;
76+
style.paddingRight = 0;
77+
style.paddingTop = 0;
78+
style.paddingBottom = 0;
79+
80+
// Transparent background
81+
style.backgroundColor = Color.clear;
82+
83+
// No border
84+
style.borderTopWidth = 0;
85+
style.borderRightWidth = 0;
86+
style.borderBottomWidth = 0;
87+
style.borderLeftWidth = 0;
88+
style.borderTopLeftRadius = Tokens.BorderRadius.Sm;
89+
style.borderTopRightRadius = Tokens.BorderRadius.Sm;
90+
style.borderBottomLeftRadius = Tokens.BorderRadius.Sm;
91+
style.borderBottomRightRadius = Tokens.BorderRadius.Sm;
92+
93+
// Text styling
94+
style.fontSize = Tokens.FontSize.Xs;
95+
style.color = Tokens.Colors.TextMuted;
96+
style.unityTextAlign = TextAnchor.MiddleCenter;
97+
98+
// Pointer cursor
99+
JTheme.ApplyPointerCursor(this);
100+
101+
// Smooth transitions
102+
JTheme.ApplyTransition(this);
103+
}
104+
105+
private void OnMouseEnter(MouseEnterEvent evt)
106+
{
107+
style.color = Tokens.Colors.TextPrimary;
108+
style.backgroundColor = Tokens.Colors.BgElevated;
109+
}
110+
111+
private void OnMouseLeave(MouseLeaveEvent evt)
112+
{
113+
style.color = Tokens.Colors.TextMuted;
114+
style.backgroundColor = Color.clear;
115+
}
116+
117+
/// <summary>
118+
/// Sets the button tooltip.
119+
/// </summary>
120+
public JIconButton WithTooltip(string tooltip)
121+
{
122+
this.tooltip = tooltip;
123+
return this;
124+
}
125+
126+
/// <summary>
127+
/// Sets custom size for the button.
128+
/// </summary>
129+
public JIconButton WithSize(float width, float height)
130+
{
131+
style.width = width;
132+
style.height = height;
133+
return this;
134+
}
135+
}
136+
}

UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Editor/Components/Form/JFormSection.cs.meta renamed to UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Editor/Components/Button/JIconButton.cs.meta

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Editor/Components/Button/JToggleButton.cs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -103,18 +103,18 @@ private void ApplyBaseStyles()
103103
style.borderTopRightRadius = Tokens.BorderRadius.Sm;
104104
style.borderBottomLeftRadius = Tokens.BorderRadius.Sm;
105105
style.borderBottomRightRadius = Tokens.BorderRadius.Sm;
106-
style.paddingTop = 4;
107-
style.paddingRight = 10;
108-
style.paddingBottom = 4;
109-
style.paddingLeft = 10;
106+
style.paddingTop = Tokens.Spacing.Sm;
107+
style.paddingRight = Tokens.Spacing.MD;
108+
style.paddingBottom = Tokens.Spacing.Sm;
109+
style.paddingLeft = Tokens.Spacing.MD;
110110
// Remove all margins (like JDropdown does)
111111
style.marginLeft = 0;
112112
style.marginRight = 0;
113113
style.marginTop = 0;
114114
style.marginBottom = 0;
115115
style.minHeight = 22;
116116
style.maxHeight = 24;
117-
style.fontSize = 11;
117+
style.fontSize = Tokens.FontSize.Sm;
118118
style.unityFontStyleAndWeight = FontStyle.Normal;
119119
// No border for cleaner look
120120
style.borderTopWidth = 0;
@@ -126,6 +126,9 @@ private void ApplyBaseStyles()
126126
style.overflow = Overflow.Hidden;
127127
style.textOverflow = TextOverflow.Ellipsis;
128128
style.whiteSpace = WhiteSpace.NoWrap;
129+
130+
// Pointer cursor for clickable element
131+
JTheme.ApplyPointerCursor(this);
129132
}
130133

131134
private void OnClicked()

UnityProject/Packages/com.jasonxudeveloper.jengine.ui/Editor/Components/Feedback/JLogView.cs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
// THE SOFTWARE.
2525

2626
using JEngine.UI.Editor.Theming;
27-
using UnityEngine;
2827
using UnityEngine.UIElements;
2928

3029
namespace JEngine.UI.Editor.Components.Feedback
@@ -48,11 +47,8 @@ public JLogView(int maxLines = 100) : base("j-log-view")
4847
_currentLineCount = 0;
4948

5049
// Apply theme-aware background
51-
// Dark mode: subtle layer (not too dark)
52-
// Light mode: surface layer (grey)
53-
style.backgroundColor = Tokens.IsDarkTheme
54-
? Tokens.Colors.BgSubtle
55-
: Tokens.Colors.BgSurface;
50+
// Use input background for consistent control styling
51+
style.backgroundColor = Tokens.Colors.BgInput;
5652

5753
// Standard borders
5854
style.borderTopColor = Tokens.Colors.Border;
@@ -135,7 +131,7 @@ public JLogView Log(string message, bool isError = false)
135131
entry.style.fontSize = Tokens.FontSize.Sm;
136132
entry.style.paddingTop = Tokens.Spacing.Xs;
137133
entry.style.paddingBottom = Tokens.Spacing.Xs;
138-
entry.style.borderBottomColor = new Color(1, 1, 1, 0.05f);
134+
entry.style.borderBottomColor = Tokens.Colors.BorderSubtle;
139135
entry.style.borderBottomWidth = 1;
140136
entry.style.color = isError ? Tokens.Colors.StatusError : Tokens.Colors.TextSecondary;
141137
entry.style.whiteSpace = WhiteSpace.Normal;

0 commit comments

Comments
 (0)