diff --git a/pkg/gui/controllers/helpers/confirmation_helper.go b/pkg/gui/controllers/helpers/confirmation_helper.go
index 7a53f9243..6e45087c0 100644
--- a/pkg/gui/controllers/helpers/confirmation_helper.go
+++ b/pkg/gui/controllers/helpers/confirmation_helper.go
@@ -56,8 +56,8 @@ func (self *ConfirmationHelper) DeactivateConfirmationPrompt() {
 	self.clearConfirmationViewKeyBindings()
 }
 
-func getMessageHeight(wrap bool, editable bool, message string, width int) int {
-	wrappedLines, _, _ := utils.WrapViewLinesToWidth(wrap, editable, message, width)
+func getMessageHeight(wrap bool, editable bool, message string, width int, tabWidth int) int {
+	wrappedLines, _, _ := utils.WrapViewLinesToWidth(wrap, editable, message, width, tabWidth)
 	return len(wrappedLines)
 }
 
@@ -265,7 +265,7 @@ func (self *ConfirmationHelper) resizeMenu(parentPopupContext types.Context) {
 	if selectedItem != nil {
 		tooltip = self.TooltipForMenuItem(selectedItem)
 	}
-	tooltipHeight := getMessageHeight(true, false, tooltip, contentWidth) + 2 // plus 2 for the frame
+	tooltipHeight := getMessageHeight(true, false, tooltip, contentWidth, self.c.Views().Menu.TabWidth) + 2 // plus 2 for the frame
 	_, _ = self.c.GocuiGui().SetView(self.c.Views().Tooltip.Name(), x0, tooltipTop, x1, tooltipTop+tooltipHeight-1, 0)
 }
 
@@ -276,7 +276,7 @@ func (self *ConfirmationHelper) layoutMenuPrompt(contentWidth int) int {
 	var promptLines []string
 	prompt := self.c.Contexts().Menu.GetPrompt()
 	if len(prompt) > 0 {
-		promptLines, _, _ = utils.WrapViewLinesToWidth(true, false, prompt, contentWidth)
+		promptLines, _, _ = utils.WrapViewLinesToWidth(true, false, prompt, contentWidth, self.c.Views().Menu.TabWidth)
 		promptLines = append(promptLines, "")
 	}
 	self.c.Contexts().Menu.SetPromptLines(promptLines)
@@ -305,17 +305,18 @@ func (self *ConfirmationHelper) resizeConfirmationPanel(parentPopupContext types
 	}
 	panelWidth := self.getPopupPanelWidth()
 	contentWidth := panelWidth - 2 // minus 2 for the frame
-	prompt := self.c.Views().Confirmation.Buffer()
+	confirmationView := self.c.Views().Confirmation
+	prompt := confirmationView.Buffer()
 	wrap := true
-	editable := self.c.Views().Confirmation.Editable
+	editable := confirmationView.Editable
 	if editable {
-		prompt = self.c.Views().Confirmation.TextArea.GetContent()
+		prompt = confirmationView.TextArea.GetContent()
 		wrap = false
 	}
-	panelHeight := getMessageHeight(wrap, editable, prompt, contentWidth) + suggestionsViewHeight
+	panelHeight := getMessageHeight(wrap, editable, prompt, contentWidth, confirmationView.TabWidth) + suggestionsViewHeight
 	x0, y0, x1, y1 := self.getPopupPanelDimensionsAux(panelWidth, panelHeight, parentPopupContext)
 	confirmationViewBottom := y1 - suggestionsViewHeight
-	_, _ = self.c.GocuiGui().SetView(self.c.Views().Confirmation.Name(), x0, y0, x1, confirmationViewBottom, 0)
+	_, _ = self.c.GocuiGui().SetView(confirmationView.Name(), x0, y0, x1, confirmationViewBottom, 0)
 
 	suggestionsViewTop := confirmationViewBottom + 1
 	_, _ = self.c.GocuiGui().SetView(self.c.Views().Suggestions.Name(), x0, suggestionsViewTop, x1, suggestionsViewTop+suggestionsViewHeight, 0)
@@ -325,7 +326,7 @@ func (self *ConfirmationHelper) ResizeCommitMessagePanels(parentPopupContext typ
 	panelWidth := self.getPopupPanelWidth()
 	content := self.c.Views().CommitDescription.TextArea.GetContent()
 	summaryViewHeight := 3
-	panelHeight := getMessageHeight(false, true, content, panelWidth)
+	panelHeight := getMessageHeight(false, true, content, panelWidth, self.c.Views().CommitDescription.TabWidth)
 	minHeight := 7
 	if panelHeight < minHeight {
 		panelHeight = minHeight
diff --git a/pkg/gui/patch_exploring/state.go b/pkg/gui/patch_exploring/state.go
index 2b32d1e7f..074793f8e 100644
--- a/pkg/gui/patch_exploring/state.go
+++ b/pkg/gui/patch_exploring/state.go
@@ -323,6 +323,6 @@ func (s *State) CalculateOrigin(currentOrigin int, bufferHeight int, numLines in
 
 func wrapPatchLines(diff string, view *gocui.View) ([]int, []int) {
 	_, viewLineIndices, patchLineIndices := utils.WrapViewLinesToWidth(
-		view.Wrap, view.Editable, strings.TrimSuffix(diff, "\n"), view.InnerWidth())
+		view.Wrap, view.Editable, strings.TrimSuffix(diff, "\n"), view.InnerWidth(), view.TabWidth)
 	return viewLineIndices, patchLineIndices
 }
diff --git a/pkg/utils/lines.go b/pkg/utils/lines.go
index ebb131c1c..c601bb806 100644
--- a/pkg/utils/lines.go
+++ b/pkg/utils/lines.go
@@ -109,7 +109,7 @@ func ScanLinesAndTruncateWhenLongerThanBuffer(maxBufferSize int) func(data []byt
 // - the line indices of the original lines, indexed by the wrapped line indices
 // If wrap is false, the text is returned as is.
 // This code needs to behave the same as `gocui.lineWrap` does.
-func WrapViewLinesToWidth(wrap bool, editable bool, text string, width int) ([]string, []int, []int) {
+func WrapViewLinesToWidth(wrap bool, editable bool, text string, width int, tabWidth int) ([]string, []int, []int) {
 	if !editable {
 		text = strings.TrimSuffix(text, "\n")
 	}
@@ -126,14 +126,18 @@ func WrapViewLinesToWidth(wrap bool, editable bool, text string, width int) ([]s
 	wrappedLineIndices := make([]int, 0, len(lines))
 	originalLineIndices := make([]int, 0, len(lines))
 
+	if tabWidth < 1 {
+		tabWidth = 4
+	}
+
 	for originalLineIdx, line := range lines {
 		wrappedLineIndices = append(wrappedLineIndices, len(wrappedLines))
 
 		// convert tabs to spaces
 		for i := 0; i < len(line); i++ {
 			if line[i] == '\t' {
-				numSpaces := 4 - (i % 4)
-				line = line[:i] + "    "[:numSpaces] + line[i+1:]
+				numSpaces := tabWidth - (i % tabWidth)
+				line = line[:i] + strings.Repeat(" ", numSpaces) + line[i+1:]
 				i += numSpaces - 1
 			}
 		}
diff --git a/pkg/utils/lines_test.go b/pkg/utils/lines_test.go
index 6011cf1fd..a67d59237 100644
--- a/pkg/utils/lines_test.go
+++ b/pkg/utils/lines_test.go
@@ -173,6 +173,7 @@ func TestWrapViewLinesToWidth(t *testing.T) {
 		editable                     bool
 		text                         string
 		width                        int
+		tabWidth                     int
 		expectedWrappedLines         []string
 		expectedWrappedLinesIndices  []int
 		expectedOriginalLinesIndices []int
@@ -353,14 +354,25 @@ func TestWrapViewLinesToWidth(t *testing.T) {
 			},
 		},
 		{
-			name:  "Tabs",
-			wrap:  true,
-			text:  "\ta\tbb\tccc\tdddd\teeeee",
-			width: 50,
+			name:     "Tabs, width 4",
+			wrap:     true,
+			text:     "\ta\tbb\tccc\tdddd\teeeee",
+			width:    50,
+			tabWidth: 4,
 			expectedWrappedLines: []string{
 				"    a   bb  ccc dddd    eeeee",
 			},
 		},
+		{
+			name:     "Tabs, width 8",
+			wrap:     true,
+			text:     "\ta\tbb\tccc\tdddddddd\teeeee",
+			width:    100,
+			tabWidth: 8,
+			expectedWrappedLines: []string{
+				"        a       bb      ccc     dddddddd        eeeee",
+			},
+		},
 		{
 			name:  "Multiple lines",
 			wrap:  true,
@@ -425,7 +437,11 @@ func TestWrapViewLinesToWidth(t *testing.T) {
 	}
 	for _, tt := range tests {
 		t.Run(tt.name, func(t *testing.T) {
-			wrappedLines, wrappedLinesIndices, originalLinesIndices := WrapViewLinesToWidth(tt.wrap, tt.editable, tt.text, tt.width)
+			tabWidth := tt.tabWidth
+			if tabWidth == 0 {
+				tabWidth = 4
+			}
+			wrappedLines, wrappedLinesIndices, originalLinesIndices := WrapViewLinesToWidth(tt.wrap, tt.editable, tt.text, tt.width, tabWidth)
 			assert.Equal(t, tt.expectedWrappedLines, wrappedLines)
 			if tt.expectedWrappedLinesIndices != nil {
 				assert.Equal(t, tt.expectedWrappedLinesIndices, wrappedLinesIndices)
@@ -436,6 +452,7 @@ func TestWrapViewLinesToWidth(t *testing.T) {
 
 			// As a sanity check, also test that gocui's line wrapping behaves the same way
 			view := gocui.NewView("", 0, 0, tt.width+1, 1000, gocui.OutputNormal)
+			view.TabWidth = tabWidth
 			assert.Equal(t, tt.width, view.InnerWidth())
 			view.Wrap = tt.wrap
 			view.Editable = tt.editable