From 125208f9ef1e3aa7ae0b18b4376cb741f30c93b0 Mon Sep 17 00:00:00 2001 From: Matt Van Horn Date: Mon, 20 Apr 2026 02:17:28 -0700 Subject: [PATCH] feat(tui/login): add ctrl+v password visibility toggle (#685) Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com> --- tui/login.go | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/tui/login.go b/tui/login.go index 4f3cd0a2fd4b06aad75560a3395955e941152532..1721ce9d54f75ba43bb059226addaffaf4f980f1 100644 --- a/tui/login.go +++ b/tui/login.go @@ -176,6 +176,18 @@ func (m *Login) Update(msg tea.Msg) (tea.Model, tea.Cmd) { case "esc": return m, func() tea.Msg { return GoToChoiceMenuMsg{} } + case "ctrl+v": + // Toggle password visibility while focused on the password field, + // so typos in app-passwords are catchable without retyping. + if m.focusIndex == inputPassword { + if m.inputs[inputPassword].EchoMode == textinput.EchoPassword { + m.inputs[inputPassword].EchoMode = textinput.EchoNormal + } else { + m.inputs[inputPassword].EchoMode = textinput.EchoPassword + } + return m, nil + } + case "enter": m.updateFlags() visible := m.visibleFields() @@ -417,7 +429,11 @@ func (m *Login) View() tea.View { if !m.hideTips && tip != "" { views = append(views, TipStyle.Render("Tip: "+tip)) } - views = append(views, helpStyle.Render("\nenter: save • tab: next field • esc: back to menu")) + helpLine := "enter: save • tab: next field • esc: back to menu" + if m.focusIndex == inputPassword { + helpLine += " • ctrl+v: toggle password visibility" + } + views = append(views, helpStyle.Render("\n"+helpLine)) return tea.NewView(lipgloss.JoinVertical(lipgloss.Left, views...)) }