From 19e73610dbed5bcb1a50dc77c16957567e57ed20 Mon Sep 17 00:00:00 2001 From: Valentin Chaboche Date: Mon, 23 Feb 2026 10:10:54 +0100 Subject: [PATCH] fix(widgets): table row selection shows full background color MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When selection_mode = Row, the entire row should display the selection background color. Previously, only the vertical border characters (│) showed the selection color because: 1. assemble_columns() applied themed_border to each vline separator 2. Each themed_border adds ANSI codes with \033[0m reset suffix 3. themed_selection wraps the assembled row, but reset codes inside clear the selection background 4. Result: only vlines show selection; cell content loses background Fix: Pass ~is_selected flag to assemble_columns. When true, vlines are rendered without themed_border styling, allowing them to inherit the selection background applied to the full row. This affects both wrapped and non-wrapped table rendering paths. BREAKING CHANGE: Bumps version to 0.4.1 for bug fix release. --- .github/workflows/ci.yml | 2 ++ CHANGELOG.md | 6 ++++++ example/demos/table/page.ml | 9 +-------- src/miaou_widgets_display/table_widget.ml | 19 +++++++++++++++---- 4 files changed, 24 insertions(+), 12 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a9658908..2a1bd2f2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -16,6 +16,8 @@ jobs: - uses: ocaml/setup-ocaml@v3 with: ocaml-compiler: 5.3.0 + - name: Pin external dependencies + run: opam pin add ppx_forbid git+https://github.com/atacama-dev/ppx_forbid.git --no-action - name: Install dependencies run: opam install --deps-only --with-test -y . - name: Build & test diff --git a/CHANGELOG.md b/CHANGELOG.md index 2f04d36a..7703c6e2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [0.4.1] - Unreleased +### Fixed + +- **Table row selection highlighting**: Full row background now displays correctly when `selection_mode = Row`. Previously, only border characters (vertical separators) showed the selection color due to ANSI reset codes from `themed_border` clearing the selection background. Now, border styling is skipped for selected rows, allowing the full row to inherit the selection background color. + +## [0.4.0] - Unreleased + ### Breaking Changes - **Box_widget border style**: added `None_` to `Box_widget.border_style` for borderless containers. Pattern matches on `border_style` may need a new case. diff --git a/example/demos/table/page.ml b/example/demos/table/page.ml index 2533c95e..316f16b5 100644 --- a/example/demos/table/page.ml +++ b/example/demos/table/page.ml @@ -60,14 +60,7 @@ module Inner = struct "↑/↓ to move • Enter logs the selection • t opens tutorial • Esc \ returns" in - let body = - Miaou_widgets_display.Table_widget.render_table_80 - ~cols:(Some 80) - ~header:("Name", "Score", "Status") - ~rows:s.table.rows - ~cursor:s.table.cursor - ~sel_col:0 - in + let body = Miaou_widgets_display.Table_widget.Table.render s.table in header ^ "\n\n" ^ body let log_selection table = diff --git a/src/miaou_widgets_display/table_widget.ml b/src/miaou_widgets_display/table_widget.ml index 44230624..aa849b6a 100644 --- a/src/miaou_widgets_display/table_widget.ml +++ b/src/miaou_widgets_display/table_widget.ml @@ -271,9 +271,12 @@ let render_table_generic_with_opts ?backend ?(wrap = false) ~cols ~header_list let blank_for_col = List.mapi (fun idx w -> (idx, String.make w ' ')) col_widths in - let assemble_columns cols = + let assemble_columns ~is_selected cols = let buf = Buffer.create inner_w in - let vline = W.themed_border glyphs.vline in + (* When row is selected, don't style vlines - let them inherit selection bg *) + let vline = + if is_selected then glyphs.vline else W.themed_border glyphs.vline + in Buffer.add_string buf vline ; List.iteri (fun idx col -> @@ -296,7 +299,10 @@ let render_table_generic_with_opts ?backend ?(wrap = false) ~cols ~header_list ^ String.make copts.pad_right ' ') cols_cells in - let line_core = assemble_columns cells in + let is_selected = + match opts.selection_mode with Row when i = cursor -> true | _ -> false + in + let line_core = assemble_columns ~is_selected cells in let line = match opts.selection_mode with | Row when i = cursor -> W.themed_selection line_core @@ -347,7 +353,12 @@ let render_table_generic_with_opts ?backend ?(wrap = false) ~cols ~header_list | None -> "")) padded_lines in - let line_core = assemble_columns cols_for_idx in + let is_selected = + match opts.selection_mode with + | Row when i = cursor -> true + | _ -> false + in + let line_core = assemble_columns ~is_selected cols_for_idx in let line = match opts.selection_mode with | Row when i = cursor -> W.themed_selection line_core