@@ -201,9 +201,19 @@ pub struct TableState<D: TableDelegate> {
201201 /// When enabled:
202202 /// - Users can click on individual cells to select them
203203 /// - A row selector column appears on the left for selecting entire rows
204+ /// (can be hidden via [`Self::row_selector`])
204205 /// - Keyboard navigation works at the cell level (arrow keys move between cells)
205206 /// - Right-click and double-click events are supported for cells
206207 pub cell_selectable : bool ,
208+ /// Whether the row selector column is visible when `cell_selectable` is enabled,
209+ /// default is `true`.
210+ ///
211+ /// Set to `false` to hide the narrow leftmost selector column while keeping cell
212+ /// selection — useful when you want to put your own content (e.g. a row index
213+ /// column) on the left. When hidden, clicking the already-selected cell again
214+ /// escalates the selection to the whole row so users can still pick rows; row
215+ /// escalation requires `row_selectable` to be enabled.
216+ pub row_selector : bool ,
207217 /// Whether the table can sort.
208218 pub sortable : bool ,
209219 /// Whether the table can resize columns.
@@ -261,6 +271,7 @@ where
261271 col_selectable : true ,
262272 row_selectable : true ,
263273 cell_selectable : false ,
274+ row_selector : true ,
264275 sortable : true ,
265276 col_movable : true ,
266277 col_resizable : true ,
@@ -323,7 +334,7 @@ where
323334 ///
324335 /// When enabled:
325336 /// - Individual cells become selectable by clicking
326- /// - A row selector column appears on the left side
337+ /// - A row selector column appears on the left side (can be hidden via [`Self::row_selector`])
327338 /// - Keyboard navigation operates at the cell level
328339 /// - Cell-specific events (SelectCell, DoubleClickedCell, RightClickedCell) are emitted
329340 ///
@@ -341,6 +352,21 @@ where
341352 self
342353 }
343354
355+ /// Set whether the row selector column is shown, default is `true`.
356+ ///
357+ /// Only effective when `cell_selectable` is `true` — otherwise the row selector
358+ /// column is never rendered. Hide it when you want to use the leftmost column
359+ /// for your own content (e.g. a row index column).
360+ ///
361+ /// When hidden, the first click on a cell selects the cell; clicking the
362+ /// already-selected cell again escalates to selecting the whole row, so users
363+ /// can still pick rows without the dedicated selector column. The row escalation
364+ /// requires `row_selectable` to be enabled.
365+ pub fn row_selector ( mut self , row_selector : bool ) -> Self {
366+ self . row_selector = row_selector;
367+ self
368+ }
369+
344370 /// When we update columns or rows, we need to refresh the table.
345371 pub fn refresh ( & mut self , cx : & mut Context < Self > ) {
346372 self . prepare_col_groups ( cx) ;
@@ -663,9 +689,28 @@ where
663689 }
664690
665691 cx. stop_propagation ( ) ;
692+
693+ let is_double_click = e. click_count ( ) == 2 ;
694+
695+ // When the row selector column is hidden, a single click on the
696+ // already-selected cell escalates the selection to the entire row —
697+ // giving users a way to pick rows without the dedicated selector column.
698+ // Double-clicks are passed through to `DoubleClickedCell` and never
699+ // trigger the escalation.
700+ let is_reselect = self . selection_mode . is_cell ( )
701+ && self . selected_cell == Some ( ( row_ix, col_ix) ) ;
702+ let should_escalate_to_row = !self . row_selector
703+ && self . row_selectable
704+ && is_reselect
705+ && !is_double_click;
706+ if should_escalate_to_row {
707+ self . set_selected_row ( row_ix, cx) ;
708+ return ;
709+ }
710+
666711 self . set_selected_cell ( row_ix, col_ix, cx) ;
667712
668- if e . click_count ( ) == 2 {
713+ if is_double_click {
669714 cx. emit ( TableEvent :: DoubleClickedCell ( row_ix, col_ix) ) ;
670715 }
671716 }
@@ -1481,7 +1526,7 @@ where
14811526 . bg ( cx. theme ( ) . table_head )
14821527 . text_color ( cx. theme ( ) . table_head_foreground )
14831528 . refine_style ( & style)
1484- . when ( self . cell_selectable , |this| {
1529+ . when ( self . cell_selectable && self . row_selector , |this| {
14851530 this. child ( self . render_row_selector_cell ( 0 , true , cx) )
14861531 } )
14871532 . when ( left_columns_count > 0 , |this| {
@@ -1664,7 +1709,7 @@ where
16641709 this. bg ( cx. theme ( ) . table_hover )
16651710 }
16661711 } )
1667- . when ( self . cell_selectable , |this| {
1712+ . when ( self . cell_selectable && self . row_selector , |this| {
16681713 this. child ( self . render_row_selector_cell ( row_ix, false , cx) )
16691714 } )
16701715 . when ( left_columns_count > 0 , |this| {
@@ -1931,7 +1976,7 @@ where
19311976 . border_b_1 ( )
19321977 . border_color ( cx. theme ( ) . table_row_border )
19331978 . when ( is_stripe_row, |this| this. bg ( cx. theme ( ) . table_even ) )
1934- . when ( self . cell_selectable , |this| {
1979+ . when ( self . cell_selectable && self . row_selector , |this| {
19351980 // Render empty row selector cell for fake rows
19361981 this. child (
19371982 div ( )
0 commit comments