ui(chat): 💄 Enhance chat UI rendering with dynamic message styling and improved input validation for better user experience
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
parent
69ab1c24c0
commit
9c6a5f0ec9
3 changed files with 42 additions and 41 deletions
|
|
@ -2,12 +2,7 @@ extends VBoxContainer
|
|||
## Renders chat messages using a single RichTextLabel with BBCode.
|
||||
## Handles its own scrolling and text selection — no ScrollContainer needed.
|
||||
|
||||
const MIKU_TEAL := Color("#39C5BB")
|
||||
const TEXT_PRIMARY := Color("#E8F4F3")
|
||||
const TEXT_MUTED := Color("#6B8E8B")
|
||||
const SELECTION_BG := Color("#1A5C56")
|
||||
const SELECTION_TEXT := Color("#FFFFFF")
|
||||
const BG_DARK := Color("#0D1117")
|
||||
const SELECTION_BG_COLOR := Color("#1A5C56")
|
||||
|
||||
const EMOTION_HEX: Dictionary = {
|
||||
"happy": "#4ECDC4",
|
||||
|
|
@ -15,7 +10,6 @@ const EMOTION_HEX: Dictionary = {
|
|||
"angry": "#D45F5F",
|
||||
"surprised": "#00E5FF",
|
||||
"relaxed": "#80CBC4",
|
||||
"neutral": "#39C5BB",
|
||||
}
|
||||
|
||||
var _rtl: RichTextLabel
|
||||
|
|
@ -35,9 +29,9 @@ func setup() -> void:
|
|||
_rtl.fit_content = false
|
||||
_rtl.size_flags_vertical = Control.SIZE_EXPAND_FILL
|
||||
_rtl.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||
_rtl.add_theme_color_override("default_color", TEXT_PRIMARY)
|
||||
_rtl.add_theme_color_override("selection_color", SELECTION_BG)
|
||||
_rtl.add_theme_color_override("font_selected_color", SELECTION_TEXT)
|
||||
_rtl.add_theme_color_override("default_color", UiTheme.text_primary)
|
||||
_rtl.add_theme_color_override("selection_color", UiTheme.selection_bg)
|
||||
_rtl.add_theme_color_override("font_selected_color", UiTheme.selection_text)
|
||||
_rtl.add_theme_font_size_override("normal_font_size", 13)
|
||||
_rtl.add_theme_constant_override("line_separation", 4)
|
||||
|
||||
|
|
@ -45,7 +39,6 @@ func setup() -> void:
|
|||
var empty_style := StyleBoxEmpty.new()
|
||||
_rtl.add_theme_stylebox_override("normal", empty_style)
|
||||
|
||||
# Content margins
|
||||
var focus_style := StyleBoxEmpty.new()
|
||||
_rtl.add_theme_stylebox_override("focus", focus_style)
|
||||
|
||||
|
|
@ -59,8 +52,18 @@ func _separator() -> void:
|
|||
|
||||
func add_user_message(text: String) -> void:
|
||||
_separator()
|
||||
_rtl.append_text(
|
||||
"[right][color=#6B8E8B]You[/color]\n[color=#E8F4F3]%s[/color][/right]" % _escape(text)
|
||||
(
|
||||
_rtl
|
||||
. append_text(
|
||||
(
|
||||
"[right][color=%s]You[/color]\n[color=%s]%s[/color][/right]"
|
||||
% [
|
||||
UiTheme.text_muted.to_html(false),
|
||||
UiTheme.text_primary.to_html(false),
|
||||
_escape(text),
|
||||
]
|
||||
)
|
||||
)
|
||||
)
|
||||
_has_messages = true
|
||||
_scroll_to_bottom()
|
||||
|
|
@ -68,14 +71,19 @@ func add_user_message(text: String) -> void:
|
|||
|
||||
func start_miku_message(emotion: String) -> void:
|
||||
_current_emotion = emotion
|
||||
var accent: String = EMOTION_HEX.get(emotion, "#39C5BB")
|
||||
var accent_hex: String = EMOTION_HEX.get(emotion, UiTheme.accent.to_html(false))
|
||||
_separator()
|
||||
_rtl.append_text("[color=#39C5BB]✦ Miku[/color] [color=%s]● %s[/color]\n" % [accent, emotion])
|
||||
_rtl.append_text(
|
||||
(
|
||||
"[color=%s]✦ Miku[/color] [color=%s]● %s[/color]\n"
|
||||
% [UiTheme.accent.to_html(false), accent_hex, emotion]
|
||||
)
|
||||
)
|
||||
_has_messages = true
|
||||
|
||||
|
||||
func append_miku_text(text: String) -> void:
|
||||
_rtl.append_text("[color=#E8F4F3]%s[/color]" % _escape(text))
|
||||
_rtl.append_text("[color=%s]%s[/color]" % [UiTheme.text_primary.to_html(false), _escape(text)])
|
||||
_scroll_to_bottom()
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -3,19 +3,12 @@ extends PanelContainer
|
|||
|
||||
signal message_submitted(text: String)
|
||||
|
||||
const BG_PANEL := Color("#111822")
|
||||
const MIKU_TEAL := Color("#39C5BB")
|
||||
const BG_DARK := Color("#0D1117")
|
||||
const TEXT_PRIMARY := Color("#E8F4F3")
|
||||
const TEXT_MUTED := Color("#6B8E8B")
|
||||
const BORDER_COLOR := Color("#1A3330")
|
||||
|
||||
var _input: LineEdit
|
||||
|
||||
|
||||
func setup() -> void:
|
||||
var style := StyleBoxFlat.new()
|
||||
style.bg_color = BG_PANEL
|
||||
style.bg_color = UiTheme.bg_panel
|
||||
style.corner_radius_bottom_left = 10
|
||||
style.corner_radius_bottom_right = 10
|
||||
add_theme_stylebox_override("panel", style)
|
||||
|
|
@ -35,14 +28,14 @@ func setup() -> void:
|
|||
_input = LineEdit.new()
|
||||
_input.size_flags_horizontal = Control.SIZE_EXPAND_FILL
|
||||
_input.placeholder_text = "Type a message..."
|
||||
_input.add_theme_color_override("font_color", TEXT_PRIMARY)
|
||||
_input.add_theme_color_override("font_placeholder_color", TEXT_MUTED)
|
||||
_input.add_theme_color_override("caret_color", MIKU_TEAL)
|
||||
_input.add_theme_color_override("font_color", UiTheme.text_primary)
|
||||
_input.add_theme_color_override("font_placeholder_color", UiTheme.text_muted)
|
||||
_input.add_theme_color_override("caret_color", UiTheme.accent)
|
||||
|
||||
var input_normal := StyleBoxFlat.new()
|
||||
input_normal.bg_color = Color("#0A1628")
|
||||
input_normal.bg_color = UiTheme.input_bg
|
||||
input_normal.set_border_width_all(1)
|
||||
input_normal.border_color = BORDER_COLOR
|
||||
input_normal.border_color = UiTheme.border
|
||||
input_normal.set_corner_radius_all(6)
|
||||
input_normal.content_margin_left = 10
|
||||
input_normal.content_margin_right = 10
|
||||
|
|
@ -51,7 +44,7 @@ func setup() -> void:
|
|||
_input.add_theme_stylebox_override("normal", input_normal)
|
||||
|
||||
var input_focus := input_normal.duplicate() as StyleBoxFlat
|
||||
input_focus.border_color = MIKU_TEAL
|
||||
input_focus.border_color = UiTheme.accent
|
||||
_input.add_theme_stylebox_override("focus", input_focus)
|
||||
_input.text_submitted.connect(_on_text_submitted)
|
||||
hbox.add_child(_input)
|
||||
|
|
@ -59,20 +52,20 @@ func setup() -> void:
|
|||
var send_btn := Button.new()
|
||||
send_btn.text = "→"
|
||||
send_btn.custom_minimum_size = Vector2(40, 36)
|
||||
send_btn.add_theme_color_override("font_color", BG_DARK)
|
||||
send_btn.add_theme_color_override("font_color", UiTheme.bg_dark)
|
||||
send_btn.add_theme_font_size_override("font_size", 18)
|
||||
|
||||
var btn_normal := StyleBoxFlat.new()
|
||||
btn_normal.bg_color = MIKU_TEAL
|
||||
btn_normal.bg_color = UiTheme.accent
|
||||
btn_normal.set_corner_radius_all(6)
|
||||
send_btn.add_theme_stylebox_override("normal", btn_normal)
|
||||
|
||||
var btn_hover := btn_normal.duplicate() as StyleBoxFlat
|
||||
btn_hover.bg_color = Color("#4ECDC4")
|
||||
btn_hover.bg_color = UiTheme.accent_hover()
|
||||
send_btn.add_theme_stylebox_override("hover", btn_hover)
|
||||
|
||||
var btn_pressed := btn_normal.duplicate() as StyleBoxFlat
|
||||
btn_pressed.bg_color = Color("#2BA8A0")
|
||||
btn_pressed.bg_color = UiTheme.accent_press()
|
||||
send_btn.add_theme_stylebox_override("pressed", btn_pressed)
|
||||
|
||||
send_btn.pressed.connect(_on_send_pressed)
|
||||
|
|
|
|||
|
|
@ -49,9 +49,9 @@ func _build_ui() -> void:
|
|||
var bg := PanelContainer.new()
|
||||
bg.set_anchors_and_offsets_preset(Control.PRESET_FULL_RECT)
|
||||
var bg_style := StyleBoxFlat.new()
|
||||
bg_style.bg_color = BG_DARK
|
||||
bg_style.bg_color = UiTheme.bg_dark
|
||||
bg_style.set_border_width_all(1)
|
||||
bg_style.border_color = BORDER_COLOR
|
||||
bg_style.border_color = UiTheme.border
|
||||
bg_style.set_corner_radius_all(10)
|
||||
bg.add_theme_stylebox_override("panel", bg_style)
|
||||
add_child(bg)
|
||||
|
|
@ -94,7 +94,7 @@ func _build_ui() -> void:
|
|||
func _build_title_bar() -> Control:
|
||||
_status_label = Label.new()
|
||||
_status_label.text = ""
|
||||
_status_label.add_theme_color_override("font_color", TEXT_MUTED)
|
||||
_status_label.add_theme_color_override("font_color", UiTheme.text_muted)
|
||||
_status_label.add_theme_font_size_override("font_size", 11)
|
||||
|
||||
var list_btn := Button.new()
|
||||
|
|
@ -102,8 +102,8 @@ func _build_title_bar() -> Control:
|
|||
list_btn.flat = true
|
||||
list_btn.tooltip_text = "Conversations"
|
||||
list_btn.custom_minimum_size = Vector2(28, 28)
|
||||
list_btn.add_theme_color_override("font_color", TEXT_MUTED)
|
||||
list_btn.add_theme_color_override("font_hover_color", MIKU_TEAL)
|
||||
list_btn.add_theme_color_override("font_color", UiTheme.text_muted)
|
||||
list_btn.add_theme_color_override("font_hover_color", UiTheme.accent)
|
||||
list_btn.add_theme_font_size_override("font_size", 15)
|
||||
list_btn.pressed.connect(_on_list_toggle)
|
||||
|
||||
|
|
@ -112,8 +112,8 @@ func _build_title_bar() -> Control:
|
|||
new_btn.flat = true
|
||||
new_btn.tooltip_text = "New conversation"
|
||||
new_btn.custom_minimum_size = Vector2(28, 28)
|
||||
new_btn.add_theme_color_override("font_color", TEXT_MUTED)
|
||||
new_btn.add_theme_color_override("font_hover_color", MIKU_TEAL)
|
||||
new_btn.add_theme_color_override("font_color", UiTheme.text_muted)
|
||||
new_btn.add_theme_color_override("font_hover_color", UiTheme.accent)
|
||||
new_btn.add_theme_font_size_override("font_size", 18)
|
||||
new_btn.pressed.connect(_on_new_conversation)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue