Module: TuiTui::Widget::Tabs

Defined in:
lib/tui_tui/widget/tabs.rb

Overview

A one-row tab bar: labels rendered as label segments separated by a single space. The active tab uses theme.selection, the rest theme.muted. Stateless like StatusBar / Scrollbar — the active index lives in the app; index_at maps a mouse event back to the tab under it.

Labels that overflow rect.cols are clipped at the right edge; there is no scrolling. Advanced handling for bars with more tabs than fit (scrolling, collapsing, overflow menus) is out of scope.

Constant Summary collapse

PAD =

Horizontal padding inside a tab, on each side of the label.

1
GAP =

Columns between adjacent tabs.

1

Class Method Summary collapse

Class Method Details

.draw(canvas, rect, labels, active:, theme: Theme::DEFAULT) ⇒ Object



24
25
26
27
28
29
30
31
32
33
34
35
# File 'lib/tui_tui/widget/tabs.rb', line 24

def draw(canvas, rect, labels, active:, theme: Theme::DEFAULT)
  canvas.fill(rect, nil)
  segments(labels).each_with_index do |(offset, _width, padded), index|
    remaining = rect.cols - offset
    break if remaining <= 0

    style = index == active ? theme.selection : theme.muted
    canvas.text(rect.row, rect.col + offset, padded.truncate(remaining, marker: ""), style)
  end

  canvas
end

.index_at(rect, event, labels) ⇒ Object

The tab index under a MouseEvent, or nil: outside the rect, past the visible (clipped) columns, or beyond the last tab. The single separator space between tabs belongs to no tab and also yields nil. Shares the segment layout with draw, so hits always match what was rendered.



41
42
43
44
45
46
47
48
49
50
# File 'lib/tui_tui/widget/tabs.rb', line 41

def index_at(rect, event, labels)
  return nil unless rect.hit?(event)

  offset = event.col - rect.col
  segments(labels).each_with_index do |(start, width, _padded), index|
    return index if offset >= start && offset < start + width
  end

  nil
end

.segments(labels) ⇒ Object

The layout both draw and index_at share: for each label, its starting column offset (0-based, relative to rect.col), its rendered width, and the padded label DisplayText.



55
56
57
58
59
60
61
62
63
64
# File 'lib/tui_tui/widget/tabs.rb', line 55

def segments(labels)
  offset = 0
  labels.map do |label|
    padded = DisplayText.new(" " * PAD + label.to_s + " " * PAD)
    width = padded.width
    segment = [offset, width, padded]
    offset += width + GAP
    segment
  end
end