6 "charm.land/lipgloss/v2"
7 "github.com/charmbracelet/crush/internal/ui/styles"
10// ButtonOpts defines the configuration for a single button
11type ButtonOpts struct {
12 // Text is the button label
14 // UnderlineIndex is the 0-based index of the character to underline (-1 for none)
16 // Selected indicates whether this button is currently selected
18 // Padding inner horizontal padding defaults to 2 if this is 0
22// Button creates a button with an underlined character and selection state
23func Button(t *styles.Styles, opts ButtonOpts) string {
24 // Select style based on selection state
31 if opts.Padding == 0 {
35 // the index is out of bound
36 if opts.UnderlineIndex > -1 && opts.UnderlineIndex > len(text)-1 {
37 opts.UnderlineIndex = -1
40 text = style.Padding(0, opts.Padding).Render(text)
42 if opts.UnderlineIndex != -1 {
43 text = lipgloss.StyleRanges(text, lipgloss.NewRange(opts.Padding+opts.UnderlineIndex, opts.Padding+opts.UnderlineIndex+1, style.Underline(true)))
49// ButtonGroup creates a row of selectable buttons
50// Spacing is the separator between buttons
51// Use " " or similar for horizontal layout
52// Use "\n" for vertical layout
53// Defaults to " " (horizontal)
54func ButtonGroup(t *styles.Styles, buttons []ButtonOpts, spacing string) string {
55 if len(buttons) == 0 {
63 parts := make([]string, len(buttons))
64 for i, button := range buttons {
65 parts[i] = Button(t, button)
68 return strings.Join(parts, spacing)
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list