button.go 1.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869
  1. package common
  2. import (
  3. "strings"
  4. "charm.land/lipgloss/v2"
  5. "github.com/charmbracelet/crush/internal/ui/styles"
  6. )
  7. // ButtonOpts defines the configuration for a single button
  8. type ButtonOpts struct {
  9. // Text is the button label
  10. Text string
  11. // UnderlineIndex is the 0-based index of the character to underline (-1 for none)
  12. UnderlineIndex int
  13. // Selected indicates whether this button is currently selected
  14. Selected bool
  15. // Padding inner horizontal padding defaults to 2 if this is 0
  16. Padding int
  17. }
  18. // Button creates a button with an underlined character and selection state
  19. func Button(t *styles.Styles, opts ButtonOpts) string {
  20. // Select style based on selection state
  21. style := t.ButtonBlur
  22. if opts.Selected {
  23. style = t.ButtonFocus
  24. }
  25. text := opts.Text
  26. if opts.Padding == 0 {
  27. opts.Padding = 2
  28. }
  29. // the index is out of bound
  30. if opts.UnderlineIndex > -1 && opts.UnderlineIndex > len(text)-1 {
  31. opts.UnderlineIndex = -1
  32. }
  33. text = style.Padding(0, opts.Padding).Render(text)
  34. if opts.UnderlineIndex != -1 {
  35. text = lipgloss.StyleRanges(text, lipgloss.NewRange(opts.Padding+opts.UnderlineIndex, opts.Padding+opts.UnderlineIndex+1, style.Underline(true)))
  36. }
  37. return text
  38. }
  39. // ButtonGroup creates a row of selectable buttons
  40. // Spacing is the separator between buttons
  41. // Use " " or similar for horizontal layout
  42. // Use "\n" for vertical layout
  43. // Defaults to " " (horizontal)
  44. func ButtonGroup(t *styles.Styles, buttons []ButtonOpts, spacing string) string {
  45. if len(buttons) == 0 {
  46. return ""
  47. }
  48. if spacing == "" {
  49. spacing = " "
  50. }
  51. parts := make([]string, len(buttons))
  52. for i, button := range buttons {
  53. parts[i] = Button(t, button)
  54. }
  55. return strings.Join(parts, spacing)
  56. }