[GH-ISSUE #793] frames: tab navigation and unpredictable mouse focusing #581

Closed
opened 2026-03-04 01:06:13 +03:00 by kerem · 2 comments
Owner

Originally created by @carpii on GitHub (Jan 16, 2023).
Original GitHub issue: https://github.com/rivo/tview/issues/793

I have a UI with this hierarchy..

Flex
    Frame 
        Form
    Frame 
        Table

Tab cycling..

When I tab through the form inputs, focus cycles back to the top of the form.
So there appears to be no way to tab to the next frame, it's only possible by using the mouse.
There's an argument to be made that TAB should propagate up the hierarchy, and focus the next frame (and so the table)

Mouse focusing

Even when resorting to the mouse, clicking within a frame is a bit unpredictable as to whether the frame gets focused or not

Below is a screenshot of my test app...

And again, showing the mouse regions which do not focus the frame..

RED: clicking here will never focus the frame

AMBER: clicking here will focus the frame maybe 60% of the time. It's hard to identify why sometimes it works, and other times does nothing

Sample code:

package ui

import (
	"strings"

	"github.com/gdamore/tcell/v2"
	"github.com/rivo/tview"
)

func UI_test_tableselect() {
	app := tview.NewApplication().EnableMouse(true)

	form := tview.NewForm().
		AddInputField("Payee", "PAYEE", 0, nil, nil).
		AddInputField("Amount", "1358.01", 20, nil, nil).
		AddInputField("Memo", "MEMO", 0, nil, nil)

	frame_form := tview.NewFrame(form)
	frame_form.SetBorder(true).SetTitleAlign(tview.AlignLeft).SetTitle(" Edit Transaction ")

	// -----------
	table := tview.NewTable().SetBorders(true)
	hc := 0
	headers := strings.Split("Category Split Amount", " ")
	for ih := range headers {
		table.SetCell(0, hc, tview.NewTableCell(headers[ih]).SetTextColor(tcell.ColorYellow).SetAlign(tview.AlignLeft))
		hc++
	}

	var rowdata []string
	rowdata = append(rowdata, "Expenses: Computer Equipment,80%,1234.56")
	rowdata = append(rowdata, "Taxes:VAT,20%,123.45")

	for r := 0; r < len(rowdata); r++ {
		row := rowdata[r]
		cols := 3
		for c := 0; c < cols; c++ {
			cols := strings.Split(row, ",")
			table.SetCell(r+1, c,
				tview.NewTableCell(cols[c]))
		}
	}

	table.Select(1, 0).SetFixed(1, 0).SetDoneFunc(func(key tcell.Key) {
		if key == tcell.KeyEnter {
			table.SetSelectable(true, false)
		}
	})

	form.AddButton("Save", func() {}).
		AddButton("Cancel", func() {})

	frame_table := tview.NewFrame(table)
	frame_table.SetBorder(true).SetTitleAlign(tview.AlignLeft).SetTitle(" Category Splits ")

	flex := tview.NewFlex().SetDirection(tview.FlexRow)
	flex.AddItem(frame_form, 0, 3, true)
	flex.AddItem(frame_table, 0, 1, false)

	if err := app.SetRoot(flex, true).SetFocus(form).Run(); err != nil {
		panic(err)
	}
}
Originally created by @carpii on GitHub (Jan 16, 2023). Original GitHub issue: https://github.com/rivo/tview/issues/793 I have a UI with this hierarchy.. Flex Frame Form Frame Table **Tab cycling..** When I tab through the form inputs, focus cycles back to the top of the form. So there appears to be no way to tab to the next frame, it's only possible by using the mouse. There's an argument to be made that TAB should propagate up the hierarchy, and focus the next frame (and so the table) **Mouse focusing** Even when resorting to the mouse, clicking within a frame is a bit unpredictable as to whether the frame gets focused or not Below is a screenshot of my test app... ![](https://i.imgur.com/xp9D1RG.png) And again, showing the mouse regions which do not focus the frame.. RED: clicking here will never focus the frame AMBER: clicking here will focus the frame maybe 60% of the time. It's hard to identify why sometimes it works, and other times does nothing ![](https://i.imgur.com/0lZ8qLi.png) Sample code: package ui import ( "strings" "github.com/gdamore/tcell/v2" "github.com/rivo/tview" ) func UI_test_tableselect() { app := tview.NewApplication().EnableMouse(true) form := tview.NewForm(). AddInputField("Payee", "PAYEE", 0, nil, nil). AddInputField("Amount", "1358.01", 20, nil, nil). AddInputField("Memo", "MEMO", 0, nil, nil) frame_form := tview.NewFrame(form) frame_form.SetBorder(true).SetTitleAlign(tview.AlignLeft).SetTitle(" Edit Transaction ") // ----------- table := tview.NewTable().SetBorders(true) hc := 0 headers := strings.Split("Category Split Amount", " ") for ih := range headers { table.SetCell(0, hc, tview.NewTableCell(headers[ih]).SetTextColor(tcell.ColorYellow).SetAlign(tview.AlignLeft)) hc++ } var rowdata []string rowdata = append(rowdata, "Expenses: Computer Equipment,80%,1234.56") rowdata = append(rowdata, "Taxes:VAT,20%,123.45") for r := 0; r < len(rowdata); r++ { row := rowdata[r] cols := 3 for c := 0; c < cols; c++ { cols := strings.Split(row, ",") table.SetCell(r+1, c, tview.NewTableCell(cols[c])) } } table.Select(1, 0).SetFixed(1, 0).SetDoneFunc(func(key tcell.Key) { if key == tcell.KeyEnter { table.SetSelectable(true, false) } }) form.AddButton("Save", func() {}). AddButton("Cancel", func() {}) frame_table := tview.NewFrame(table) frame_table.SetBorder(true).SetTitleAlign(tview.AlignLeft).SetTitle(" Category Splits ") flex := tview.NewFlex().SetDirection(tview.FlexRow) flex.AddItem(frame_form, 0, 3, true) flex.AddItem(frame_table, 0, 1, false) if err := app.SetRoot(flex, true).SetFocus(form).Run(); err != nil { panic(err) } }
kerem closed this issue 2026-03-04 01:06:13 +03:00
Author
Owner

@rivo commented on GitHub (Mar 20, 2023):

Thanks for the report. I fixed the issue where a mouse click on a form outside any form item didn't focus it.

Regarding tab cycling, I understand that examples can be created where the expectation for pressing tab at the end of a form would be to focus on the next flex item. At the same time, counter-examples can be provided where this would be unintuitive. That is because people use the Flex component for much more complex layouts where flex items are again other Flex components or where flex items are read-only elements (e.g. TextView) which should not be focused. Or look at Grid (or even Pages) where there is no clear "order" of elements.

For this reason, I decided to keep the focus within one component and leave it up to the user to manage switching between components themselves. There are lots of ways to do this and every user of tview will use what's appropriate for their application.

I will keep this open so I can read your comments if you still have any. Otherwise, feel free to close this issue.

<!-- gh-comment-id:1475940809 --> @rivo commented on GitHub (Mar 20, 2023): Thanks for the report. I fixed the issue where a mouse click on a form outside any form item didn't focus it. Regarding tab cycling, I understand that examples can be created where the expectation for pressing tab at the end of a form would be to focus on the next flex item. At the same time, counter-examples can be provided where this would be unintuitive. That is because people use the `Flex` component for much more complex layouts where flex items are again other `Flex` components or where flex items are read-only elements (e.g. `TextView`) which should not be focused. Or look at `Grid` (or even `Pages`) where there is no clear "order" of elements. For this reason, I decided to keep the focus within one component and leave it up to the user to manage switching between components themselves. There are lots of ways to do this and every user of `tview` will use what's appropriate for their application. I will keep this open so I can read your comments if you still have any. Otherwise, feel free to close this issue.
Author
Owner

@carpii commented on GitHub (Mar 23, 2023):

Thanks for the mouse-focus fix.

I understand your reasoning about tab propagation. I need to spend a bit of time understanding how I can tackle this at app level, so will close this issue for now.

<!-- gh-comment-id:1481854140 --> @carpii commented on GitHub (Mar 23, 2023): Thanks for the mouse-focus fix. I understand your reasoning about tab propagation. I need to spend a bit of time understanding how I can tackle this at app level, so will close this issue for now.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/tview#581
No description provided.