| 790 | } |
| 791 | |
| 792 | func (m *agentPickerModel) renderCard(choice agentChoice, cardWidth int, selected bool) string { |
| 793 | marker := " " |
| 794 | nameStyle := styles.BoldStyle |
| 795 | borderColor := styles.BorderMuted |
| 796 | if selected { |
| 797 | marker = styles.SuccessStyle.Render("❯ ") |
| 798 | nameStyle = styles.HighlightWhiteStyle |
| 799 | borderColor = styles.BorderPrimary |
| 800 | } |
| 801 | |
| 802 | // The marker occupies 2 columns and the card chrome (border + padding) |
| 803 | // 4, so the title and detail text get cardWidth-6. Titles and details can |
| 804 | // come from arbitrary (including remote) configs, so collapse them to a |
| 805 | // single line and truncate to fit the card. |
| 806 | detailWidth := cardWidth - 6 |
| 807 | title := displayRef(choice.ref) |
| 808 | var detail string |
| 809 | switch { |
| 810 | case choice.err != nil: |
| 811 | detail = styles.ErrorStyle.Render(truncateDetail("failed to load: "+choice.err.Error(), detailWidth)) |
| 812 | case isLocalConfigRef(choice.ref) && truncateDetail(choice.description, detailWidth) != "": |
| 813 | // Local config files show their description as the title; the path is |
| 814 | // demoted to the detail line. Descriptions that sanitize to nothing |
| 815 | // (whitespace or control characters only) keep the path as title. |
| 816 | title = choice.description |
| 817 | detail = styles.MutedStyle.Render(truncateDetail(displayRef(choice.ref), detailWidth)) |
| 818 | case choice.description != "": |
| 819 | detail = styles.SecondaryStyle.Render(truncateDetail(choice.description, detailWidth)) |
| 820 | default: |
| 821 | detail = styles.MutedStyle.Render("No description available") |
| 822 | } |
| 823 | header := marker + nameStyle.Render(truncateDetail(title, detailWidth)) |
| 824 | |
| 825 | card := lipgloss.JoinVertical(lipgloss.Left, header, " "+detail, " "+renderTags(choice.tags, detailWidth)) |
| 826 | |
| 827 | return styles.BaseStyle. |
| 828 | Border(lipgloss.RoundedBorder()). |
| 829 | BorderForeground(borderColor). |
| 830 | Width(cardWidth). |
| 831 | Padding(1, 1). |
| 832 | Render(card) |
| 833 | } |
| 834 | |
| 835 | // tagChipStyles are the rotating colour palette used to render tag chips so |
| 836 | // adjacent tags are visually distinct. |