class_name ABGSharedButton extends Button const Tokens = preload("res://foundation/ui_tokens.gd") ## Generic semantic button. It emits the built-in `pressed` intent and owns no ## game state, save behavior or page lookup. var semantic_variant := "secondary" var selected_state := false var busy_state := false var _refreshing := false func _ready() -> void: focus_mode = Control.FOCUS_ALL custom_minimum_size = Tokens.touch_size(custom_minimum_size) _refresh_style() func configure(next_text: String, next_variant := "secondary"): text = next_text semantic_variant = next_variant if Tokens.is_supported_variant(next_variant) else "secondary" _refresh_style() return self func set_view_state(enabled := true, selected := false, busy := false) -> void: disabled = not enabled selected_state = selected busy_state = busy _refresh_style() func _refresh_style() -> void: if _refreshing: return if not is_inside_tree() and get_parent() == null: return _refreshing = true var normal_fill := Tokens.COLOR_NAVY var hover_fill := Tokens.COLOR_NAVY_LIFT var pressed_fill := Tokens.COLOR_NAVY_LIFT var border := Tokens.COLOR_GOLD if semantic_variant == "primary": normal_fill = Color("#e8d9b7") hover_fill = Color("#fff1c9") pressed_fill = Color("#d7c39a") border = Color("#806536") elif semantic_variant == "danger": normal_fill = Color("#4d2830") hover_fill = Color("#68343d") pressed_fill = Color("#3b2027") border = Tokens.COLOR_DANGER elif semantic_variant == "icon": normal_fill = Color(Tokens.COLOR_NAVY, 0.72) hover_fill = Tokens.COLOR_NAVY_LIFT pressed_fill = Tokens.COLOR_NAVY border = Tokens.COLOR_SKY if selected_state: hover_fill = Color("#34506a") border = Tokens.COLOR_SKY if disabled: normal_fill = Tokens.COLOR_NAVY_DISABLED hover_fill = normal_fill pressed_fill = normal_fill border = Tokens.COLOR_MUTED var text_color := Tokens.COLOR_IVORY if semantic_variant == "primary": text_color = Tokens.COLOR_INK if disabled: text_color = Color("#a1a8aa") add_theme_color_override("font_color", text_color) add_theme_color_override("font_hover_color", text_color) add_theme_color_override("font_pressed_color", text_color) add_theme_color_override("font_focus_color", text_color) add_theme_font_size_override("font_size", Tokens.font_size("label")) add_theme_stylebox_override("normal", _style_box(normal_fill, border)) add_theme_stylebox_override("hover", _style_box(hover_fill, border)) add_theme_stylebox_override("pressed", _style_box(pressed_fill, border)) add_theme_stylebox_override("disabled", _style_box(normal_fill, border)) add_theme_stylebox_override("focus", _focus_box(border)) _refreshing = false func _style_box(fill: Color, border: Color) -> StyleBoxFlat: var box := StyleBoxFlat.new() box.bg_color = fill box.border_color = border box.set_border_width_all(1) box.corner_radius_top_left = 6 box.corner_radius_top_right = 6 box.corner_radius_bottom_left = 6 box.corner_radius_bottom_right = 6 box.content_margin_left = 12.0 box.content_margin_right = 12.0 box.content_margin_top = 8.0 box.content_margin_bottom = 8.0 return box func _focus_box(border: Color) -> StyleBoxFlat: var box := _style_box(Color(0, 0, 0, 0), Tokens.COLOR_SKY) box.set_border_width_all(2) box.shadow_color = Color(border, 0.32) box.shadow_size = 3 return box