Un-collapse the question toolbar - show every action directly

The 6-item + "More" overflow popup made the toolbar feel sparse and
hid frequently-used actions (flag, report, flashcard, theme) behind
an extra click. Reverting to a flat toolbar where every action is
directly visible and labeled, including text size (grouped A-/A+
under one "Text size" caption instead of behind a popup).
This commit is contained in:
hz
2026-07-24 03:03:40 -05:00
parent 974de67032
commit 0902cc238a
+31 -112
View File
@@ -99,10 +99,6 @@ var flashcard_prefill_dialog: Control
var bookmark_button: Button
var app_feedback_button: Button
var theme_button: Button
var more_button: Button
var more_menu_popup: PopupPanel
var text_size_button: Button
var text_size_popup: PopupPanel
var question_toolbar: HFlowContainer
var header_stack: VBoxContainer
var header_row: HBoxContainer
@@ -284,8 +280,8 @@ func _ready() -> void:
timer_label.horizontal_alignment = HORIZONTAL_ALIGNMENT_RIGHT
question_toolbar = HFlowContainer.new()
question_toolbar.add_theme_constant_override("h_separation", 14)
question_toolbar.add_theme_constant_override("v_separation", 8)
question_toolbar.add_theme_constant_override("h_separation", 10)
question_toolbar.add_theme_constant_override("v_separation", 10)
question_toolbar.alignment = FlowContainer.ALIGNMENT_END
# All the underlying buttons are constructed up front (same as before) so every
@@ -406,68 +402,25 @@ func _ready() -> void:
Style.style_chip(app_feedback_button, Style.CYAN)
app_feedback_button.pressed.connect(func(): main.open_feedback_dialog())
# Text size: single entry point opening a small popup with the existing A-/A+
# controls untouched, instead of two always-visible buttons.
text_size_button = Button.new()
text_size_button.text = "Aa"
text_size_button.tooltip_text = "Text size"
text_size_button.custom_minimum_size = Vector2(44, 44)
text_size_button.focus_mode = Control.FOCUS_NONE
text_size_button.pressed.connect(_toggle_text_size_popup)
question_toolbar.add_child(_toolbar_labeled_button(text_size_button, "Text size"))
# Every action is directly visible and labeled - no "More" overflow or popups
# hiding controls behind an extra click.
question_toolbar.add_child(_toolbar_labeled_group([text_smaller_button, text_larger_button], "Text size"))
question_toolbar.add_child(_toolbar_labeled_button(calculator_button, "Calculator"))
question_toolbar.add_child(_toolbar_labeled_button(labs_button, "Labs"))
question_toolbar.add_child(_toolbar_labeled_button(clear_highlight_button, "Clear highlight"))
question_toolbar.add_child(_toolbar_labeled_button(notes_button, "Notes"))
question_toolbar.add_child(_toolbar_labeled_button(flag_button, "Flag"))
question_toolbar.add_child(_toolbar_labeled_button(flashcard_button, "Flashcard"))
question_toolbar.add_child(_toolbar_labeled_button(bookmark_button, "Bookmark"))
more_button = Button.new()
more_button.text = "..."
more_button.tooltip_text = "More actions"
more_button.custom_minimum_size = Vector2(44, 44)
more_button.focus_mode = Control.FOCUS_NONE
more_button.pressed.connect(_toggle_more_menu)
question_toolbar.add_child(_toolbar_labeled_button(more_button, "More"))
question_toolbar.add_child(_toolbar_labeled_button(report_button, "Report"))
question_toolbar.add_child(_toolbar_labeled_button(notes_button, "Notes"))
question_toolbar.add_child(_toolbar_labeled_button(theme_button, "Theme"))
question_toolbar.add_child(_toolbar_labeled_button(app_feedback_button, "Feedback"))
header_toolbar_host = HBoxContainer.new()
header_toolbar_host.alignment = BoxContainer.ALIGNMENT_END
header_toolbar_host.add_child(question_toolbar)
header_row.add_child(header_toolbar_host)
text_size_popup = PopupPanel.new()
text_size_popup.name = "TextSizePopup"
add_child(text_size_popup)
var text_size_margin := MarginContainer.new()
for side in ["left", "right", "top", "bottom"]:
text_size_margin.add_theme_constant_override("margin_%s" % side, 12)
text_size_popup.add_child(text_size_margin)
var text_size_row := HBoxContainer.new()
text_size_row.add_theme_constant_override("separation", 8)
text_size_margin.add_child(text_size_row)
text_size_row.add_child(text_smaller_button)
text_size_row.add_child(text_larger_button)
more_menu_popup = PopupPanel.new()
more_menu_popup.name = "MoreMenu"
more_menu_popup.min_size = Vector2i(260, 0)
add_child(more_menu_popup)
var more_menu_margin := MarginContainer.new()
for side in ["left", "right", "top", "bottom"]:
more_menu_margin.add_theme_constant_override("margin_%s" % side, 10)
more_menu_popup.add_child(more_menu_margin)
var more_menu_content := VBoxContainer.new()
more_menu_content.add_theme_constant_override("separation", 4)
more_menu_margin.add_child(more_menu_content)
for entry in [
[labs_button, "Labs"],
[flag_button, "Flag question"],
[report_button, "Report question"],
[flashcard_button, "Save as flashcard"],
[theme_button, "Switch theme"],
[app_feedback_button, "Feedback"],
]:
more_menu_content.add_child(_more_menu_row(entry[0], entry[1]))
navigator_popup = PopupPanel.new()
navigator_popup.name = "QuestionNavigator"
navigator_popup.min_size = Vector2i(340, 180)
@@ -829,10 +782,7 @@ func _fit_modal_panels() -> void:
func _refresh_responsive_layout() -> void:
if header_toolbar_host == null or header_row == null or header_stack == null:
return
# The toolbar is now 6 labeled items (with "More" absorbing the rest) instead of
# 12 icon-only buttons, so it's meaningfully narrower - the compact-mode breakpoint
# is tuned down to match rather than reusing the old wider-toolbar threshold.
var compact := size.x < 860.0
var compact := size.x < 1120.0
var target_parent: Control = header_row
if compact:
target_parent = header_stack
@@ -840,7 +790,7 @@ func _refresh_responsive_layout() -> void:
header_toolbar_host.reparent(target_parent)
header_toolbar_host.size_flags_horizontal = Control.SIZE_EXPAND_FILL if compact else Control.SIZE_SHRINK_END
question_toolbar.size_flags_horizontal = Control.SIZE_EXPAND_FILL
header_toolbar_host.custom_minimum_size.x = 0.0 if compact else 380.0
header_toolbar_host.custom_minimum_size.x = 0.0 if compact else 520.0
if size.x < 560.0:
nav_palette.columns = 5
else:
@@ -1069,12 +1019,6 @@ func _apply_question_theme() -> void:
question_panel.add_theme_stylebox_override("panel", _question_content_box(dark))
if navigator_popup != null:
navigator_popup.add_theme_stylebox_override("panel", Brand.content_card_box(dark, false))
if text_size_popup != null:
text_size_popup.add_theme_stylebox_override("panel", Brand.content_card_box(dark, false))
if more_menu_popup != null:
more_menu_popup.add_theme_stylebox_override("panel", Brand.content_card_box(dark, false))
for label in more_menu_popup.find_children("MoreMenuLabel", "Label", true, false):
(label as Label).add_theme_color_override("font_color", Brand.text_color(dark))
if question_toolbar != null:
for label in question_toolbar.find_children("ToolbarLabel", "Label", true, false):
(label as Label).add_theme_color_override("font_color", Brand.muted_color(dark))
@@ -1115,7 +1059,7 @@ func _apply_question_theme() -> void:
var navigator_heading := navigator_popup.find_child("NavigatorHeading", true, false) as Label
if navigator_heading != null:
navigator_heading.add_theme_color_override("font_color", Brand.text_color(dark))
for control in [text_smaller_button, text_larger_button, calculator_button, bookmark_button, notes_button, flashcard_button, app_feedback_button, text_size_button, more_button]:
for control in [text_smaller_button, text_larger_button, calculator_button, bookmark_button, notes_button, flashcard_button, app_feedback_button]:
if control == null:
continue
var active: bool = control == bookmark_button and BookmarkService.is_bookmarked(str(BlockSessionService.get_current_question().get("id", "")))
@@ -1468,8 +1412,6 @@ func _should_clear_selection_from_click(mouse_event: InputEventMouseButton) -> b
return false
if report_button != null and report_button.visible and report_button.get_global_rect().has_point(pointer_position):
return false
if more_menu_popup != null and more_menu_popup.visible and Rect2(more_menu_popup.position, more_menu_popup.size).has_point(pointer_position):
return false
for button in choice_buttons:
if button.visible and button.get_global_rect().has_point(pointer_position):
return false
@@ -2206,48 +2148,25 @@ func _toolbar_labeled_button(button: Button, label_text: String) -> Control:
return wrap
func _more_menu_row(button: Button, label_text: String) -> Control:
# Reparents the *actual* button (not a duplicate/proxy) so its existing icon,
# tooltip, toggle state, and pressed connection keep working unmodified wherever
# it's mutated by reference elsewhere in this file.
func _toolbar_labeled_group(buttons: Array, label_text: String) -> Control:
var wrap := VBoxContainer.new()
wrap.add_theme_constant_override("separation", 2)
wrap.alignment = BoxContainer.ALIGNMENT_CENTER
wrap.size_flags_horizontal = Control.SIZE_SHRINK_CENTER
var row := HBoxContainer.new()
row.name = "MoreMenuRow"
row.add_theme_constant_override("separation", 10)
row.add_child(button)
row.add_theme_constant_override("separation", 4)
row.alignment = BoxContainer.ALIGNMENT_CENTER
for button in buttons:
row.add_child(button)
wrap.add_child(row)
var label := Label.new()
label.name = "MoreMenuLabel"
label.name = "ToolbarLabel"
label.text = label_text
_set_scaled_label(label, 14, Brand.SLATE)
row.add_child(label)
return row
func _toggle_text_size_popup() -> void:
if text_size_popup == null:
return
if text_size_popup.visible:
text_size_popup.hide()
return
var popup_size := Vector2i(140, 76)
var anchor := text_size_button.get_global_rect()
var viewport_size := get_viewport_rect().size
var popup_x := int(clampf(anchor.position.x, 8.0, maxf(8.0, viewport_size.x - popup_size.x - 8.0)))
var popup_y := int(minf(anchor.end.y + 6.0, viewport_size.y - popup_size.y - 8.0))
text_size_popup.popup(Rect2i(Vector2i(popup_x, popup_y), popup_size))
func _toggle_more_menu() -> void:
if more_menu_popup == null:
return
if more_menu_popup.visible:
more_menu_popup.hide()
return
var popup_size := Vector2i(260, 300)
var anchor := more_button.get_global_rect()
var viewport_size := get_viewport_rect().size
var popup_x := int(clampf(anchor.position.x - popup_size.x + anchor.size.x, 8.0, maxf(8.0, viewport_size.x - popup_size.x - 8.0)))
var popup_y := int(minf(anchor.end.y + 6.0, viewport_size.y - popup_size.y - 8.0))
more_menu_popup.popup(Rect2i(Vector2i(popup_x, popup_y), popup_size))
label.horizontal_alignment = HORIZONTAL_ALIGNMENT_CENTER
label.size_flags_horizontal = Control.SIZE_SHRINK_CENTER
_set_scaled_label(label, 11, Brand.SLATE)
wrap.add_child(label)
return wrap
func _navigate_to_question(target_index: int) -> void: