Skip to content

feat: add ResponseExt trait to enforce tooltip cursor policy#738

Merged
lklimek merged 6 commits into
v1.0-devfrom
chore/tooltip-cursors
Mar 13, 2026
Merged

feat: add ResponseExt trait to enforce tooltip cursor policy#738
lklimek merged 6 commits into
v1.0-devfrom
chore/tooltip-cursors

Conversation

@lklimek
Copy link
Copy Markdown
Contributor

@lklimek lklimek commented Mar 12, 2026

Summary

Introduces a ResponseExt trait for egui::Response that enforces a consistent tooltip cursor policy across the UI. Three semantic methods replace raw .on_hover_text() calls:

Method Cursor Use case
.info_tooltip() Help (❓) Informational labels, non-interactive elements
.clickable_tooltip() PointingHand (👆) Clickable/actionable elements
.disabled_tooltip() NotAllowed (🚫) Disabled elements explaining why unavailable
  • Migrates ~56 callsites across 30 files to use the new trait methods
  • Adds documentation section to docs/ux-design-patterns.md
  • disabled_tooltip() uses on_disabled_hover_text() so tooltips appear correctly on disabled widgets
  • Buttons using add_enabled() split tooltip path: clickable_tooltip when enabled, disabled_tooltip when disabled
  • info_tooltip() on editable TextEdit fields moved to their labels to preserve the I-beam cursor
  • Connection indicator uses contextual tooltip (clickable only when Dash-Qt can be launched)

Test plan

  • Hover over clickable buttons → PointingHand cursor + tooltip
  • Hover over disabled buttons → NotAllowed cursor + tooltip visible
  • Hover over info labels → Help cursor + tooltip
  • Hover over "Public note" text inputs → normal I-beam cursor (tooltip on label only)
  • Hover over connection indicator when disconnected in RPC mode → PointingHand cursor
  • Hover over connection indicator when connected → Help cursor
  • Verify no regressions in existing tooltip text content

🤖 Generated with Claude Code

🤖 Co-authored by Claudius the Magnificent AI Agent

Summary by CodeRabbit

  • New Features

    • Added three standardized tooltip types: info, clickable, and disabled — with matching cursor feedback and click-aware behavior.
  • Refactor

    • Replaced many hover-only helper texts across the UI with the new tooltip helpers for consistent, accessible interactions and proper enabled/disabled affordances.
  • Documentation

    • UX guidance added recommending the new tooltip helpers; the new subsection was unintentionally duplicated.

Introduce `ResponseExt` extension trait on `egui::Response` with three
methods — `info_tooltip` (Help cursor), `clickable_tooltip` (PointingHand),
and `disabled_tooltip` (NotAllowed) — that combine tooltip text with the
correct cursor icon in a single call.

Migrate all 56 `.on_hover_text()` callsites across 31 files to use the
new helpers, ensuring consistent cursor behavior project-wide. Update
UX design patterns doc to reference the new API.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Mar 12, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: ada9aa9c-b99b-4907-a0ae-23f400d3c918

📥 Commits

Reviewing files that changed from the base of the PR and between f608edd and dc030fc.

📒 Files selected for processing (5)
  • docs/ux-design-patterns.md
  • src/ui/identities/withdraw_screen.rs
  • src/ui/network_chooser_screen.rs
  • src/ui/tokens/set_token_price_screen.rs
  • src/ui/tokens/transfer_tokens_screen.rs
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/ui/network_chooser_screen.rs
  • docs/ux-design-patterns.md

📝 Walkthrough

Walkthrough

Adds a public ResponseExt trait with three tooltip helpers (info_tooltip, clickable_tooltip, disabled_tooltip) and updates many UI modules to use these methods instead of raw on_hover_text / on_disabled_hover_text; docs updated and the trait was inserted twice in src/ui/theme.rs.

Changes

Cohort / File(s) Summary
Core Extension Trait
src/ui/theme.rs
Adds pub trait ResponseExt and impl ResponseExt for egui::Response with info_tooltip, clickable_tooltip, disabled_tooltip. Implementation/docs inserted twice (duplicate).
Documentation
docs/ux-design-patterns.md
Adds "Cursor Icons and Tooltips" guidance recommending ResponseExt and helper methods; guidance duplicated in the document.
Core UI Components & Helpers
src/ui/components/..., src/ui/helpers.rs
src/ui/components/left_panel.rs, src/ui/components/password_input.rs, src/ui/components/top_panel.rs
Import ResponseExt; replace .on_hover_text() / cursor chains with clickable_tooltip/info_tooltip/disabled_tooltip. top_panel adds gating so clicks on a tooltip-driven response only start Dash-Qt when allowed.
Dashpay & DPNS
src/ui/dashpay/profile_screen.rs, src/ui/dpns/dpns_contested_names_screen.rs
Swap avatar/label/save hover usages to clickable_tooltip / disabled_tooltip / info_tooltip.
Identities UIs
src/ui/identities/...
src/ui/identities/identities_screen.rs, .../keys/add_key_screen.rs, .../register_dpns_name_screen.rs, .../transfer_screen.rs, .../withdraw_screen.rs
Add ResponseExt; convert many on_hover_text usages to info_tooltip, clickable_tooltip, or disabled_tooltip. Some actions now capture a response and check response.clicked().
Tokens screens (collection)
src/ui/tokens/...
Import ResponseExt; move public-note/help hover text to info_tooltip on labels and replace disabled hover messages with disabled_tooltip where applicable across token screens.
Tokens (nested screens)
src/ui/tokens/tokens_screen/{mod.rs,my_tokens.rs}
Replace on_hover_text calls with info_tooltip, clickable_tooltip, or disabled_tooltip for owner labels and purchase/remove/transfer actions.
Tools screens
src/ui/tools/{masternode_list_diff_screen.rs,proof_log_screen.rs,transition_visualizer_screen.rs}
Import ResponseExt; replace header/button/contract link hover text with clickable_tooltip; change error/help hover text to info_tooltip.
Wallets screens
src/ui/wallets/wallets_screen/{asset_locks.rs,mod.rs}
Add ResponseExt; switch TXID/help hover to info_tooltip and copy/action buttons to clickable_tooltip.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐇 I fiddled with cursors, nudged tooltips to play,

Clickable, info, disabled — each finds its way,
I hopped through the code with a tiny delight,
Now hover and click feel just right.

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 35.56% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title clearly and concisely summarizes the main change: introducing a ResponseExt trait to enforce tooltip cursor policy across the codebase.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch chore/tooltip-cursors
📝 Coding Plan
  • Generate coding plan for human review comments

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@lklimek lklimek marked this pull request as ready for review March 12, 2026 13:19
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (10)
src/ui/tokens/set_token_price_screen.rs (1)

1043-1051: ⚠️ Potential issue | 🟡 Minor

Avoid using the Help-cursor tooltip on an editable input.

This TextEdit is interactive, so info_tooltip() gives it the wrong affordance. Moving the tooltip to the label would keep the cursor policy consistent without making the input look passive.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/ui/tokens/set_token_price_screen.rs` around lines 1043 - 1051, The
TextEdit for public_note is using info_tooltip(), which gives an incorrect
Help-cursor affordance on an editable input; move the tooltip from the TextEdit
to the label instead: update the ui.horizontal block that constructs the label
and TextEdit (the ui.label("Public note (optional):") and the subsequent
ui.text_edit_singleline(&mut txt) using self.public_note) so the label receives
the info_tooltip(...) call and the TextEdit is rendered without info_tooltip(),
preserving an editable cursor on the input while still exposing the explanatory
tooltip on the label.
src/ui/identities/keys/add_key_screen.rs (1)

559-569: ⚠️ Potential issue | 🟡 Minor

Use the disabled-tooltip variant on this locked selector.

This hover target represents an unavailable control, so info_tooltip() gives it the wrong cursor. disabled_tooltip() would preserve the not-allowed affordance the new policy expects.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/ui/identities/keys/add_key_screen.rs` around lines 559 - 569, The hover
target for the locked security-level selector currently calls
hover_response.info_tooltip(...), which gives the wrong cursor; change it to use
hover_response.disabled_tooltip(...) so the control preserves the "not-allowed"
affordance. Locate the block that checks has_multiple_security_levels and
creates hover_response via ui.interact (using inner_response.response.rect and
egui::Id::new("security_level_tooltip")), and replace the call to
info_tooltip(format!("{:?} purpose requires {:?} security level", self.purpose,
self.security_level)) with a disabled_tooltip call that passes the same
formatted message.
src/ui/tokens/mint_tokens_screen.rs (1)

615-623: ⚠️ Potential issue | 🟡 Minor

This tooltip should not live on the text input itself.

info_tooltip() makes the public-note TextEdit advertise the Help cursor instead of a text-entry cursor. Prefer attaching the tooltip to the label, so the field still reads as editable.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/ui/tokens/mint_tokens_screen.rs` around lines 615 - 623, The public-note
tooltip is currently applied to the TextEdit (via
text_edit_singleline(...).info_tooltip(...)) which forces a Help cursor and
prevents normal text-entry cursor; move the tooltip to the label instead so the
field remains editable: remove the info_tooltip call from the TextEdit for
self.public_note and attach the explanatory tooltip to the label created by
ui.label("Public note (optional):") (e.g., use the label's tooltip/hover API),
keeping the rest of the ui.horizontal block and the mutable txt handling
unchanged.
src/ui/tokens/claim_tokens_screen.rs (1)

458-466: ⚠️ Potential issue | 🟡 Minor

Keep the tooltip off the editable text box.

info_tooltip() puts the Help cursor on a TextEdit, which makes an editable control look non-editable. Attach the tooltip to the label instead, or use a helper that preserves the text-entry cursor for input fields.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/ui/tokens/claim_tokens_screen.rs` around lines 458 - 466, The tooltip is
being attached to the editable TextEdit via text_edit_singleline(&mut
txt).info_tooltip(...), which makes the input show a Help cursor; move the
tooltip to the label instead so the editable field retains the text-entry
cursor: remove the .info_tooltip(...) call on text_edit_singleline and attach
the same tooltip string to the label created by ui.label("Public note
(optional):") (e.g., use label.info_tooltip(...) or equivalent), leaving the
TextEdit call as-is so public_note editing behaves normally.
src/ui/tokens/destroy_frozen_funds_screen.rs (1)

550-558: ⚠️ Potential issue | 🟡 Minor

Don’t turn the note editor into a Help-cursor target.

info_tooltip() is fine for passive labels, but on TextEdit it hides the normal text-entry affordance. This field should keep the I-beam cursor; move the tooltip to the label.

💡 Proposed fix
                     ui.horizontal(|ui| {
-                        ui.label("Public note (optional):");
+                        ui.label("Public note (optional):").info_tooltip(
+                            "A note about the transaction that can be seen by the public.",
+                        );
                         ui.add_space(10.0);
                         let mut txt = self.public_note.clone().unwrap_or_default();
                         if ui
-                            .text_edit_singleline(&mut txt)
-                            .info_tooltip(
-                                "A note about the transaction that can be seen by the public.",
-                            )
+                            .text_edit_singleline(&mut txt)
                             .changed()
                         {
                             self.public_note = if !txt.is_empty() { Some(txt) } else { None };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/ui/tokens/destroy_frozen_funds_screen.rs` around lines 550 - 558, The
TextEdit is currently wrapped with info_tooltip which forces a Help cursor and
hides the I-beam; change the tooltip to the label instead: in the ui.horizontal
block locate the label creation and move the .info_tooltip(...) call from the
TextEdit invocation (text_edit_singleline on the local variable txt) to the
label call that displays "Public note (optional):", leaving
text_edit_singleline(&mut txt) without info_tooltip so the I-beam/text-entry
affordance is preserved for the public_note field.
src/ui/tokens/unfreeze_tokens_screen.rs (1)

537-545: ⚠️ Potential issue | 🟡 Minor

Keep the I-beam cursor on the note input.

Using info_tooltip() on the TextEdit swaps its hover affordance from “editable text” to Help. That is a UX regression for a field the user is supposed to type into. Put the tooltip on the label instead.

💡 Proposed fix
                     ui.horizontal(|ui| {
-                        ui.label("Public note (optional):");
+                        ui.label("Public note (optional):").info_tooltip(
+                            "A note about the transaction that can be seen by the public.",
+                        );
                         ui.add_space(10.0);
                         let mut txt = self.public_note.clone().unwrap_or_default();
                         if ui
-                            .text_edit_singleline(&mut txt)
-                            .info_tooltip(
-                                "A note about the transaction that can be seen by the public.",
-                            )
+                            .text_edit_singleline(&mut txt)
                             .changed()
                         {
                             self.public_note = if !txt.is_empty() { Some(txt) } else { None };
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/ui/tokens/unfreeze_tokens_screen.rs` around lines 537 - 545, The
TextEdit's info_tooltip is causing the I-beam hover to be lost; remove the
.info_tooltip(...) call from the text_edit_singleline(&mut txt) invocation and
instead attach the tooltip to the label widget (e.g. the ui.label("Public note
(optional):") call) using the label's tooltip API (on_hover_text / info_tooltip
equivalent) so the label shows help while the text input retains its editable
cursor; keep the rest of the logic around self.public_note, mutable txt, and
ui.horizontal unchanged.
src/ui/tokens/transfer_tokens_screen.rs (1)

555-563: ⚠️ Potential issue | 🟡 Minor

Keep the text cursor on this editable field.

info_tooltip() is the Help-cursor helper, so putting it on TextEdit makes this input look non-editable while hovered. That regresses the cursor semantics this PR is standardizing. Attach the tooltip to the adjacent label instead, or keep a plain hover tooltip on the editor.

💡 Proposed fix
                 ui.horizontal(|ui| {
-                    ui.label("Public note (optional):");
+                    ui.label("Public note (optional):").info_tooltip(
+                        "A note about the transaction that can be seen by the public.",
+                    );
                     ui.add_space(10.0);
                     let mut txt = self.public_note.clone().unwrap_or_default();
                     if ui
-                        .text_edit_singleline(&mut txt)
-                        .info_tooltip(
-                            "A note about the transaction that can be seen by the public.",
-                        )
+                        .text_edit_singleline(&mut txt)
                         .changed()
                     {
                         self.public_note = Some(txt);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/ui/tokens/transfer_tokens_screen.rs` around lines 555 - 563, The text
edit's info_tooltip is making the field appear non-editable; remove the
.info_tooltip call from the ui.text_edit_singleline(&mut txt) and instead attach
the explanatory tooltip to the label widget (the ui.label("Public note
(optional):") call) using a label hover tooltip (e.g., label.on_hover_text(...))
or keep a plain hover tooltip on the editor; update references around
self.public_note, txt, and ui.text_edit_singleline accordingly so the tooltip
sits on the label and not the TextEdit.
src/ui/components/top_panel.rs (1)

170-177: ⚠️ Potential issue | 🟡 Minor

Match the indicator cursor to its clickable state.

This response can launch Dash-Qt in the disconnected RPC case, but info_tooltip() always forces Help semantics. That means the one actionable state advertises the wrong cursor. Use clickable_tooltip() only when the click path is live, and fall back to info_tooltip() otherwise.

💡 Proposed fix
-                    let tip = status.tooltip_text(app_context);
-                    let resp = resp.info_tooltip(tip);
+                    let can_start_dash_qt = overall == OverallConnectionState::Disconnected
+                        && backend_mode == CoreBackendMode::Rpc
+                        && !status.rpc_online();
+                    let tip = status.tooltip_text(app_context);
+                    let resp = if can_start_dash_qt {
+                        resp.clickable_tooltip(tip)
+                    } else {
+                        resp.info_tooltip(tip)
+                    };

-                    if resp.clicked()
-                        && overall == OverallConnectionState::Disconnected
-                        && backend_mode == CoreBackendMode::Rpc
-                        && !status.rpc_online()
-                    {
+                    if resp.clicked() && can_start_dash_qt {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/ui/components/top_panel.rs` around lines 170 - 177, The tooltip currently
always uses info_tooltip(), which forces help semantics/cursor even when the
widget is actionable; change the tooltip selection to use clickable_tooltip()
when the widget is actually clickable and keep info_tooltip() otherwise: compute
the same clickable condition used for the click-path (overall ==
OverallConnectionState::Disconnected && backend_mode == CoreBackendMode::Rpc &&
!status.rpc_online()) and call resp = resp.clickable_tooltip(tip) in that
branch, otherwise call resp = resp.info_tooltip(tip); keep the existing click
handling logic unchanged.
src/ui/dashpay/profile_screen.rs (1)

982-997: ⚠️ Potential issue | 🟡 Minor

Use the disabled helper for the non-saveable state.

Line 995 applies clickable_tooltip() even when can_save is false, so the disabled Save button can still get the clickable cursor policy. That undercuts the new tooltip contract for unavailable actions. Split the response handling so enabled uses clickable_tooltip() and disabled uses disabled_tooltip().

Suggested fix
-                                        if ui
-                                            .add_enabled(can_save, save_button)
-                                            .clickable_tooltip(&hover_text)
-                                            .on_disabled_hover_text(&hover_text)
-                                            .clicked()
-                                        {
-                                            action |= self.save_profile();
-                                        }
+                                        let save_response =
+                                            ui.add_enabled(can_save, save_button);
+
+                                        let save_response = if can_save {
+                                            save_response.clickable_tooltip(&hover_text)
+                                        } else {
+                                            save_response.disabled_tooltip(&hover_text)
+                                        };
+
+                                        if save_response.clicked() {
+                                            action |= self.save_profile();
+                                        }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/ui/dashpay/profile_screen.rs` around lines 982 - 997, The Save button
currently always applies clickable_tooltip() even when can_save is false so the
disabled button gets a clickable cursor; fix by splitting the widget
creation/response handling: build the button widget with
ui.add_enabled(can_save, save_button) but if can_save is true call
.clickable_tooltip(&hover_text).on_disabled_hover_text(&hover_text).clicked() to
handle clicks, otherwise call .disabled_tooltip(&hover_text) (and do not treat
it as clickable). Refer to hover_text, can_save, save_button,
ui.add_enabled(...) and self.is_valid() to keep the same hover text/conditions
when switching the branches.
src/ui/identities/identities_screen.rs (1)

611-671: ⚠️ Potential issue | 🟡 Minor

Use disabled_tooltip() on the controls that can be disabled.

Line 611 is inside ui.add_enabled_ui(is_active, ...), and Lines 635 and 671 are inside branches that call ui.disable(), but all three still use clickable_tooltip(). That gives disabled controls a pointing-hand affordance and breaks the cursor policy this PR is introducing. Split the enabled/disabled branches and use disabled_tooltip() whenever the button cannot be activated.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/ui/identities/identities_screen.rs` around lines 611 - 671, The popup
currently uses clickable_tooltip() for buttons that may be disabled (the
Withdraw and Transfer buttons inside the actions_popup created from
actions_response), which leaves a pointing-hand cursor and breaks the new cursor
policy; split the code paths so enabled and disabled UI are added separately (or
use ui.add_enabled_ui/is_active) and call clickable_tooltip(...) only in the
enabled branch while calling disabled_tooltip(...) in the branches where
ui.disable() is currently used (affecting the Withdraw button that pushes
Screen::WithdrawalScreen via WithdrawalScreen::new and the Transfer button), and
similarly replace clickable_tooltip on the Top up / other disabled controls with
disabled_tooltip when their can_* checks are false.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/ux-design-patterns.md`:
- Around line 184-185: The docs currently point readers to StyledButton for
helpers like add_primary_button and related tooltip policy, but those helpers
live on ComponentStyles; update the text to reference ComponentStyles (and
change the import suggestion from ResponseExt/StyledButton to ComponentStyles)
and clarify that tooltip policy should be applied via the ComponentStyles helper
methods (e.g., add_primary_button), not on StyledButton.

In `@src/ui/identities/register_dpns_name_screen.rs`:
- Around line 549-552: The tooltip is using clickable_tooltip() even when the
control is disabled; change the branch that builds the UI for
add_enabled(button_enabled, button) so that when button_enabled is false you
call disabled_tooltip(...) instead of clickable_tooltip(...). Update the code
path around add_enabled, clickable_tooltip, and on_disabled_hover_text to use
disabled_tooltip on the disabled branch (using the same hover_text) so the
disabled button does not present a click affordance.

In `@src/ui/identities/transfer_screen.rs`:
- Around line 801-804: The UI currently always calls clickable_tooltip(...) on
the result of ui.add_enabled(ready, button), which causes a clickable cursor to
be shown even when the widget is disabled; change the flow to inspect the
Response from ui.add_enabled(ready, button) and branch: if the Response is
enabled use .clickable_tooltip(hover_text).clicked() as before, otherwise call
the disabled-tooltip path (e.g. use the disabled tooltip method or attach the
hover_text via the disabled response) so the disabled state does not advertise
clickability; look for add_enabled, clickable_tooltip, clicked, ready, button
and hover_text to update the handling accordingly.

In `@src/ui/theme.rs`:
- Around line 950-963: The disabled_tooltip implementation in the ResponseExt
impl should use egui's disabled-hover API so tooltips show for disabled widgets;
update the disabled_tooltip(self, text: impl Into<egui::WidgetText>) method to
call on_disabled_hover_text(text) (and still chain
.on_hover_cursor(CursorIcon::NotAllowed)) instead of on_hover_text(text) so
disabled responses created via ui.add_enabled(false, ...) display the tooltip
correctly.

In `@src/ui/tokens/burn_tokens_screen.rs`:
- Around line 575-578: Remove the .info_tooltip(...) call from the text input
chain so the text field created by .text_edit_singleline(&mut txt) keeps its
normal text-edit cursor; instead attach the tooltip to the label or surrounding
widget (e.g., call .info_tooltip(...) on the label or a separate ui.label(...)
before/above the .text_edit_singleline) in burn_tokens_screen.rs so the help
cursor appears on the label, not the editable field.

In `@src/ui/tokens/freeze_tokens_screen.rs`:
- Around line 539-542: The tooltip is currently attached to the editable widget
via .text_edit_singleline(&mut txt).info_tooltip(...), which gives the input an
unintended Help hover; move the .info_tooltip(...) off the text_edit_singleline
call and attach it to the field label or an adjacent info/icon widget instead
(e.g., place the info_tooltip on the label rendering code for the public-note
field or the label/icon widget that wraps this input). Ensure
.text_edit_singleline(&mut txt) remains a plain editable field and the tooltip
is only present on the non-editable label/info affordance.

---

Outside diff comments:
In `@src/ui/components/top_panel.rs`:
- Around line 170-177: The tooltip currently always uses info_tooltip(), which
forces help semantics/cursor even when the widget is actionable; change the
tooltip selection to use clickable_tooltip() when the widget is actually
clickable and keep info_tooltip() otherwise: compute the same clickable
condition used for the click-path (overall ==
OverallConnectionState::Disconnected && backend_mode == CoreBackendMode::Rpc &&
!status.rpc_online()) and call resp = resp.clickable_tooltip(tip) in that
branch, otherwise call resp = resp.info_tooltip(tip); keep the existing click
handling logic unchanged.

In `@src/ui/dashpay/profile_screen.rs`:
- Around line 982-997: The Save button currently always applies
clickable_tooltip() even when can_save is false so the disabled button gets a
clickable cursor; fix by splitting the widget creation/response handling: build
the button widget with ui.add_enabled(can_save, save_button) but if can_save is
true call
.clickable_tooltip(&hover_text).on_disabled_hover_text(&hover_text).clicked() to
handle clicks, otherwise call .disabled_tooltip(&hover_text) (and do not treat
it as clickable). Refer to hover_text, can_save, save_button,
ui.add_enabled(...) and self.is_valid() to keep the same hover text/conditions
when switching the branches.

In `@src/ui/identities/identities_screen.rs`:
- Around line 611-671: The popup currently uses clickable_tooltip() for buttons
that may be disabled (the Withdraw and Transfer buttons inside the actions_popup
created from actions_response), which leaves a pointing-hand cursor and breaks
the new cursor policy; split the code paths so enabled and disabled UI are added
separately (or use ui.add_enabled_ui/is_active) and call clickable_tooltip(...)
only in the enabled branch while calling disabled_tooltip(...) in the branches
where ui.disable() is currently used (affecting the Withdraw button that pushes
Screen::WithdrawalScreen via WithdrawalScreen::new and the Transfer button), and
similarly replace clickable_tooltip on the Top up / other disabled controls with
disabled_tooltip when their can_* checks are false.

In `@src/ui/identities/keys/add_key_screen.rs`:
- Around line 559-569: The hover target for the locked security-level selector
currently calls hover_response.info_tooltip(...), which gives the wrong cursor;
change it to use hover_response.disabled_tooltip(...) so the control preserves
the "not-allowed" affordance. Locate the block that checks
has_multiple_security_levels and creates hover_response via ui.interact (using
inner_response.response.rect and egui::Id::new("security_level_tooltip")), and
replace the call to info_tooltip(format!("{:?} purpose requires {:?} security
level", self.purpose, self.security_level)) with a disabled_tooltip call that
passes the same formatted message.

In `@src/ui/tokens/claim_tokens_screen.rs`:
- Around line 458-466: The tooltip is being attached to the editable TextEdit
via text_edit_singleline(&mut txt).info_tooltip(...), which makes the input show
a Help cursor; move the tooltip to the label instead so the editable field
retains the text-entry cursor: remove the .info_tooltip(...) call on
text_edit_singleline and attach the same tooltip string to the label created by
ui.label("Public note (optional):") (e.g., use label.info_tooltip(...) or
equivalent), leaving the TextEdit call as-is so public_note editing behaves
normally.

In `@src/ui/tokens/destroy_frozen_funds_screen.rs`:
- Around line 550-558: The TextEdit is currently wrapped with info_tooltip which
forces a Help cursor and hides the I-beam; change the tooltip to the label
instead: in the ui.horizontal block locate the label creation and move the
.info_tooltip(...) call from the TextEdit invocation (text_edit_singleline on
the local variable txt) to the label call that displays "Public note
(optional):", leaving text_edit_singleline(&mut txt) without info_tooltip so the
I-beam/text-entry affordance is preserved for the public_note field.

In `@src/ui/tokens/mint_tokens_screen.rs`:
- Around line 615-623: The public-note tooltip is currently applied to the
TextEdit (via text_edit_singleline(...).info_tooltip(...)) which forces a Help
cursor and prevents normal text-entry cursor; move the tooltip to the label
instead so the field remains editable: remove the info_tooltip call from the
TextEdit for self.public_note and attach the explanatory tooltip to the label
created by ui.label("Public note (optional):") (e.g., use the label's
tooltip/hover API), keeping the rest of the ui.horizontal block and the mutable
txt handling unchanged.

In `@src/ui/tokens/set_token_price_screen.rs`:
- Around line 1043-1051: The TextEdit for public_note is using info_tooltip(),
which gives an incorrect Help-cursor affordance on an editable input; move the
tooltip from the TextEdit to the label instead: update the ui.horizontal block
that constructs the label and TextEdit (the ui.label("Public note (optional):")
and the subsequent ui.text_edit_singleline(&mut txt) using self.public_note) so
the label receives the info_tooltip(...) call and the TextEdit is rendered
without info_tooltip(), preserving an editable cursor on the input while still
exposing the explanatory tooltip on the label.

In `@src/ui/tokens/transfer_tokens_screen.rs`:
- Around line 555-563: The text edit's info_tooltip is making the field appear
non-editable; remove the .info_tooltip call from the
ui.text_edit_singleline(&mut txt) and instead attach the explanatory tooltip to
the label widget (the ui.label("Public note (optional):") call) using a label
hover tooltip (e.g., label.on_hover_text(...)) or keep a plain hover tooltip on
the editor; update references around self.public_note, txt, and
ui.text_edit_singleline accordingly so the tooltip sits on the label and not the
TextEdit.

In `@src/ui/tokens/unfreeze_tokens_screen.rs`:
- Around line 537-545: The TextEdit's info_tooltip is causing the I-beam hover
to be lost; remove the .info_tooltip(...) call from the
text_edit_singleline(&mut txt) invocation and instead attach the tooltip to the
label widget (e.g. the ui.label("Public note (optional):") call) using the
label's tooltip API (on_hover_text / info_tooltip equivalent) so the label shows
help while the text input retains its editable cursor; keep the rest of the
logic around self.public_note, mutable txt, and ui.horizontal unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 62860992-a1fb-43df-a2f1-23555f552997

📥 Commits

Reviewing files that changed from the base of the PR and between 8598ca8 and 9cd4624.

📒 Files selected for processing (32)
  • docs/ux-design-patterns.md
  • src/ui/components/left_panel.rs
  • src/ui/components/password_input.rs
  • src/ui/components/top_panel.rs
  • src/ui/dashpay/profile_screen.rs
  • src/ui/dpns/dpns_contested_names_screen.rs
  • src/ui/helpers.rs
  • src/ui/identities/identities_screen.rs
  • src/ui/identities/keys/add_key_screen.rs
  • src/ui/identities/register_dpns_name_screen.rs
  • src/ui/identities/transfer_screen.rs
  • src/ui/network_chooser_screen.rs
  • src/ui/theme.rs
  • src/ui/tokens/burn_tokens_screen.rs
  • src/ui/tokens/claim_tokens_screen.rs
  • src/ui/tokens/destroy_frozen_funds_screen.rs
  • src/ui/tokens/direct_token_purchase_screen.rs
  • src/ui/tokens/freeze_tokens_screen.rs
  • src/ui/tokens/mint_tokens_screen.rs
  • src/ui/tokens/pause_tokens_screen.rs
  • src/ui/tokens/resume_tokens_screen.rs
  • src/ui/tokens/set_token_price_screen.rs
  • src/ui/tokens/tokens_screen/mod.rs
  • src/ui/tokens/tokens_screen/my_tokens.rs
  • src/ui/tokens/transfer_tokens_screen.rs
  • src/ui/tokens/unfreeze_tokens_screen.rs
  • src/ui/tokens/update_token_config.rs
  • src/ui/tools/masternode_list_diff_screen.rs
  • src/ui/tools/proof_log_screen.rs
  • src/ui/tools/transition_visualizer_screen.rs
  • src/ui/wallets/wallets_screen/asset_locks.rs
  • src/ui/wallets/wallets_screen/mod.rs

Comment thread docs/ux-design-patterns.md Outdated
Comment thread src/ui/identities/register_dpns_name_screen.rs Outdated
Comment thread src/ui/identities/transfer_screen.rs
Comment thread src/ui/theme.rs
Comment thread src/ui/tokens/burn_tokens_screen.rs Outdated
Comment thread src/ui/tokens/freeze_tokens_screen.rs Outdated
Copy link
Copy Markdown

@claude claude Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review Summary — PR #738

Ah, a tooltip cursor policy trait. Claudius approves of the concept — enforcing consistency through the type system rather than trusting developers to remember cursor conventions. How delightfully pessimistic about human reliability.

Overall: Clean, well-structured mechanical refactoring. The ResponseExt trait is well-designed, the 56-callsite migration is mechanically correct (no tooltip text accidentally altered), and the documentation is clear. Import organization across 30 files is pristine.

Findings

ID Severity Title
RUST-001 🟡 MEDIUM disabled_tooltip uses on_hover_text instead of on_disabled_hover_text

One inline comment posted. Two LOW-severity observations (not posted): text input fields showing Help cursor instead of IBeam, and clickable_tooltip on add_enabled buttons showing PointingHand when disabled. These are edge cases worth considering but not blocking.

Verdict: Fix RUST-001 (the disabled_tooltip implementation), then this is ready to merge. The remaining on_disabled_hover_text migration can be done in this PR or a follow-up.

Full report available as a workflow artifact.

🤖 Claudius the Magnificent · review report

Comment thread src/ui/theme.rs
- Fix disabled_tooltip() to use on_disabled_hover_text() so tooltips
  actually appear on disabled widgets
- Split add_enabled() callsites to use clickable_tooltip when enabled
  and disabled_tooltip when disabled (4 files)
- Move info_tooltip from editable TextEdit fields to their labels to
  preserve the I-beam cursor on inputs (8 token screens)
- Use contextual tooltip on connection indicator (clickable only when
  Dash-Qt can be launched)
- Change locked security level selector from info_tooltip to
  disabled_tooltip
- Fix docs referencing StyledButton instead of ComponentStyles

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/ui/components/top_panel.rs (1)

171-194: ⚠️ Potential issue | 🟡 Minor

Don't advertise Dash-Qt startup when no executable path is configured.

can_start_dash_qt only checks connection state, but Lines 181-194 still no-op when settings.dash_qt_path is None. That leaves the new clickable cursor/tooltip active for a path that cannot actually start Dash-Qt. Fold the path check into can_start_dash_qt, or switch to a non-clickable/disabled tooltip that explains the missing path.

Suggested adjustment
-                    let tip = status.tooltip_text(app_context);
-                    let can_start_dash_qt = overall == OverallConnectionState::Disconnected
-                        && backend_mode == CoreBackendMode::Rpc
-                        && !status.rpc_online();
+                    let tip = status.tooltip_text(app_context);
+                    let settings = app_context.get_settings().ok().flatten();
+                    let can_start_dash_qt = overall == OverallConnectionState::Disconnected
+                        && backend_mode == CoreBackendMode::Rpc
+                        && !status.rpc_online()
+                        && settings
+                            .as_ref()
+                            .and_then(|s| s.dash_qt_path.as_ref())
+                            .is_some();
                     let resp = if can_start_dash_qt {
                         resp.clickable_tooltip(tip)
                     } else {
                         resp.info_tooltip(tip)
                     };
 
                     if resp.clicked() && can_start_dash_qt {
-                        let settings = app_context.get_settings().ok().flatten();
-
                         let (custom_path, overwrite) = settings
                             .map(|s| (s.dash_qt_path, s.overwrite_dash_conf))
                             .unwrap_or((None, true));
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/ui/components/top_panel.rs` around lines 171 - 194, can_start_dash_qt
currently only checks connection/backend state but not whether a Dash-Qt
executable is configured, causing a clickable tooltip that no-ops; change the
logic so the UI is only clickable when a path exists: fetch settings via
app_context.get_settings(), compute has_dash_qt_path = settings.map(|s|
s.dash_qt_path.is_some()).unwrap_or(false), and include that in the
can_start_dash_qt boolean (or use it to choose resp.clickable_tooltip vs
resp.info_tooltip), leaving the existing StartDashQT call and the tracing::debug
branch unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/ui/identities/identities_screen.rs`:
- Line 611: The Actions button uses clickable_tooltip() inside the
add_enabled_ui(is_active, ...) block so when the identity is inactive the
response is disabled but still gets an interactive tooltip; change the tooltip
call to disabled_tooltip() for the disabled state so inactive identities show
the non-interactive explanation. Locate where actions_response is created from
ui.add(actions_button) inside add_enabled_ui and replace clickable_tooltip(...)
with disabled_tooltip(...) (or conditionally call clickable_tooltip when
is_active is true and disabled_tooltip when false) so the tooltip behavior
matches the enabled/disabled state.

---

Outside diff comments:
In `@src/ui/components/top_panel.rs`:
- Around line 171-194: can_start_dash_qt currently only checks
connection/backend state but not whether a Dash-Qt executable is configured,
causing a clickable tooltip that no-ops; change the logic so the UI is only
clickable when a path exists: fetch settings via app_context.get_settings(),
compute has_dash_qt_path = settings.map(|s|
s.dash_qt_path.is_some()).unwrap_or(false), and include that in the
can_start_dash_qt boolean (or use it to choose resp.clickable_tooltip vs
resp.info_tooltip), leaving the existing StartDashQT call and the tracing::debug
branch unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 10fb2a88-7033-4aa2-9b67-ee99646c91ab

📥 Commits

Reviewing files that changed from the base of the PR and between 9cd4624 and 79641b4.

📒 Files selected for processing (16)
  • docs/ux-design-patterns.md
  • src/ui/components/top_panel.rs
  • src/ui/dashpay/profile_screen.rs
  • src/ui/identities/identities_screen.rs
  • src/ui/identities/keys/add_key_screen.rs
  • src/ui/identities/register_dpns_name_screen.rs
  • src/ui/identities/transfer_screen.rs
  • src/ui/theme.rs
  • src/ui/tokens/burn_tokens_screen.rs
  • src/ui/tokens/claim_tokens_screen.rs
  • src/ui/tokens/destroy_frozen_funds_screen.rs
  • src/ui/tokens/freeze_tokens_screen.rs
  • src/ui/tokens/mint_tokens_screen.rs
  • src/ui/tokens/set_token_price_screen.rs
  • src/ui/tokens/transfer_tokens_screen.rs
  • src/ui/tokens/unfreeze_tokens_screen.rs
🚧 Files skipped from review as they are similar to previous changes (8)
  • src/ui/tokens/unfreeze_tokens_screen.rs
  • src/ui/tokens/mint_tokens_screen.rs
  • src/ui/tokens/transfer_tokens_screen.rs
  • src/ui/tokens/destroy_frozen_funds_screen.rs
  • src/ui/identities/transfer_screen.rs
  • src/ui/tokens/burn_tokens_screen.rs
  • src/ui/tokens/freeze_tokens_screen.rs
  • src/ui/tokens/claim_tokens_screen.rs

Comment thread src/ui/identities/identities_screen.rs Outdated
clickable_tooltip now only applies when widget is enabled,
disabled_tooltip only when disabled. This enables clean chaining:

    ui.add_enabled(ready, button)
        .clickable_tooltip("Transfer")
        .disabled_tooltip("Fill fields first")
        .clicked()

Simplifies 4 callsites that previously needed if/else branching.
Adds comprehensive rustdocs with chaining contract for future
implementors.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
src/ui/identities/identities_screen.rs (1)

611-611: ⚠️ Potential issue | 🟡 Minor

Add the disabled-tooltip path for inactive identities’ Actions button.

This button is still created inside add_enabled_ui(is_active, ...), so when is_active is false clickable_tooltip() becomes a no-op and the user loses the “why is this unavailable?” hover text. Chain disabled_tooltip(...) here as well.

Suggested fix
-                                                    let actions_response = ui.add(actions_button).clickable_tooltip("Manage identity credits");
+                                                    let actions_response = ui
+                                                        .add(actions_button)
+                                                        .clickable_tooltip("Manage identity credits")
+                                                        .disabled_tooltip(
+                                                            "Identity actions are unavailable until this identity becomes active",
+                                                        );
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/ui/identities/identities_screen.rs` at line 611, The Actions button
created inside add_enabled_ui currently only chains clickable_tooltip("Manage
identity credits") so inactive identities lose hover feedback; update the chain
on the actions_response (the value from ui.add(actions_button) in
add_enabled_ui) to also call disabled_tooltip("Manage identity credits") so the
tooltip appears when is_active is false while keeping clickable_tooltip for the
active path; modify the code that creates actions_response in add_enabled_ui to
append .disabled_tooltip("Manage identity credits") alongside the existing
.clickable_tooltip(...) call.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/ui/theme.rs`:
- Around line 949-951: The doc comment for info_tooltip() promises
state-agnostic tooltips but the implementation currently uses on_hover_text(),
which doesn't show for disabled widgets; update the info_tooltip()
implementation to use on_disabled_hover_text() (or call both on_hover_text() and
on_disabled_hover_text() appropriately) so informational tooltips appear for
disabled widgets as well, ensuring the function name info_tooltip() and the
helper calls on_hover_text() / on_disabled_hover_text() are adjusted
accordingly.

---

Duplicate comments:
In `@src/ui/identities/identities_screen.rs`:
- Line 611: The Actions button created inside add_enabled_ui currently only
chains clickable_tooltip("Manage identity credits") so inactive identities lose
hover feedback; update the chain on the actions_response (the value from
ui.add(actions_button) in add_enabled_ui) to also call disabled_tooltip("Manage
identity credits") so the tooltip appears when is_active is false while keeping
clickable_tooltip for the active path; modify the code that creates
actions_response in add_enabled_ui to append .disabled_tooltip("Manage identity
credits") alongside the existing .clickable_tooltip(...) call.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 7b9e3599-6d74-4c22-8344-3b737cbeefef

📥 Commits

Reviewing files that changed from the base of the PR and between 79641b4 and 8befbe7.

📒 Files selected for processing (5)
  • src/ui/dashpay/profile_screen.rs
  • src/ui/identities/identities_screen.rs
  • src/ui/identities/register_dpns_name_screen.rs
  • src/ui/identities/transfer_screen.rs
  • src/ui/theme.rs
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/ui/dashpay/profile_screen.rs
  • src/ui/identities/register_dpns_name_screen.rs

Comment thread src/ui/theme.rs
Copy link
Copy Markdown

@claude claude Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claudius Review — PR #738

Well-designed PR. The ResponseExt trait with state-aware chaining is elegant — it eliminates a whole class of cursor/state mismatch bugs in one stroke. The migration across 30+ files is consistently correct and the ux-design-patterns docs are clean.

2 findings posted (MEDIUM):

ID Severity File Issue
RUST-001 🟡 MEDIUM add_key_screen.rs:566-569 disabled_tooltip on always-enabled hover_response — tooltip silently lost (regression)
RUST-002 🟡 MEDIUM theme.rs:985-987 info_tooltip doc promises state-agnostic but on_hover_text ignores disabled widgets

Additional LOW findings (not posted inline):

  • 4 unmigrated on_disabled_hover_text callsites remain (withdraw_screen.rs, transfer_tokens_screen.rs, set_token_price_screen.rs, network_chooser_screen.rs)
  • Redundant manual set_cursor_icon in password_input.rs:201-203 (now handled by clickable_tooltip)
  • add_primary_button_enabled sets PointingHand unconditionally even when disabled
  • ux-design-patterns.md "no tooltip helper needed" phrasing could be clearer

2 unresolved CodeRabbit threads also remain on this PR (identities_screen.rs Actions button, info_tooltip disabled behavior).

Full report: report.json + report.html in CI artifacts.

🤖 Claudius the Magnificent · Full report

Comment thread src/ui/identities/keys/add_key_screen.rs Outdated
Comment thread src/ui/theme.rs
lklimek and others added 2 commits March 12, 2026 16:52
- Make info_tooltip truly state-agnostic by calling both on_hover_text
  and on_disabled_hover_text (fixes doc/impl mismatch)
- Change add_key_screen locked selector back to info_tooltip — the
  hover overlay from ui.interact() is always enabled, so state-aware
  disabled_tooltip was a silent no-op
- Chain disabled_tooltip on Actions button in identities_screen so
  inactive identities show explanation instead of click affordance

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown

@claude claude Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved ✅ — Excellent trait design, thorough migration, well-documented policy.

The ResponseExt trait's state-aware chaining pattern (where clickable_tooltip silently skips on disabled widgets and vice versa) is genuinely clever — it makes the enabled/disabled tooltip pattern composable and eliminates a whole class of cursor-policy bugs. The migration across ~56 callsites in 30+ files is consistent and the method choices are correct throughout.

One MEDIUM finding: 4 bare on_disabled_hover_text() calls survive in files that already import ResponseExt — a quick cleanup to fully deliver on the "never use bare" policy this PR establishes. See inline comment.

Minor suggestions (LOW):

  • 3 token screens (pause, resume, update_token_config) kept info_tooltip on the text_edit instead of the label — inconsistent with the 7 screens that moved it
  • password_input.rs:201-203 has a now-redundant manual set_cursor_icon(PointingHand) alongside clickable_tooltip()
  • network_chooser_screen.rs:418-421 discards the disabled_tooltip return value — assign to _ for clarity

None of these are merge-blocking. Ship it! 🚀

🤖 Claudius the Magnificent · Full report · 2 agents, 7 findings (1 MEDIUM, 4 LOW, 2 INFO), redundancy ratio 43%

Comment thread docs/ux-design-patterns.md Outdated
| `.disabled_tooltip("text")` | `NotAllowed` | Disabled elements explaining why the action is unavailable |

- Import: `use crate::ui::theme::ResponseExt;`
- `ComponentStyles` button constructors (`add_primary_button`, etc.) set `PointingHand` automatically -- no tooltip helper needed
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[MEDIUM] The policy is sound, but it's contradicted by 4 remaining bare on_disabled_hover_text() calls in files this PR already touches:

  • src/ui/tokens/set_token_price_screen.rs:1132
  • src/ui/tokens/transfer_tokens_screen.rs:613
  • src/ui/network_chooser_screen.rs:1640
  • src/ui/identities/withdraw_screen.rs:627 (not in this PR's changeset)

The first three files were modified by this PR and already import ResponseExt — migrating them is a one-line change each. These callsites also miss the NotAllowed cursor that disabled_tooltip() provides.

Separately, the phrasing "no tooltip helper needed" on line 185 could be read as "no ResponseExt call ever needed on ComponentStyles buttons." Consider: "ComponentStyles button constructors set PointingHand automatically — no clickable_tooltip needed for the cursor. You still need disabled_tooltip when the button can be disabled."

🤖 Claudius the Magnificent · RUST-001

Addresses the last unresolved PR review comment: 4 callsites still
used bare on_disabled_hover_text() instead of the ResponseExt policy,
and the docs understated when disabled_tooltip is still needed.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@lklimek lklimek enabled auto-merge (squash) March 13, 2026 12:24
@lklimek lklimek merged commit c938b67 into v1.0-dev Mar 13, 2026
5 checks passed
@lklimek lklimek deleted the chore/tooltip-cursors branch March 13, 2026 12:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant