chrome

package
v0.6.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 24, 2026 License: MIT Imports: 12 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var ListWrapperStyle = lipgloss.NewStyle().
	Padding(1, 2, 2, 2)

ListWrapperStyle is the frame around the two body lists. Its padding is what separates the list content from the panel edges, and its frame size is subtracted from the panel box when the inner list is sized.

View Source
var WrapperStyle = lipgloss.NewStyle().
	Padding(1, 2)

Functions

func ActionDescription

func ActionDescription(action, target string, isGroup bool) string

ActionDescription returns a full description of the pending action.

func BarColumn

func BarColumn(fg color.Color, bg color.Color, content string) string

BarColumn renders the nav's ▌ indicator once per line of content, so the bar spans a multi-line row's full height instead of a sliver at its top. bg may be nil to leave the cell background unset.

func DockerActionFor

func DockerActionFor(msg tea.KeyPressMsg) (string, bool)

DockerActionFor returns the `docker compose` action a keypress asks for. Both details panels read it, which is what makes "s starts a group" and "s starts a service" the same fact rather than two switch statements that happen to agree. Remove is absent on purpose: it is destructive, so it goes through a confirmation instead of straight to a command.

func EmptyCard

func EmptyCard(width, availHeight int, bg color.Color, title, body, key, hint string) string

EmptyCard renders a dim, centered, rounded-border card used for the empty / onboarding states. `key` is shown in the accent color inside brackets, `hint` is the trailing description in a dim color. `availHeight` is the vertical space in which the card should be centered. `bg` is the panel's background tier, which the space around the card sits on; the card itself is recessed below that tier so it reads as inset into the panel.

func FitBox

func FitBox(s lipgloss.Style, w, h int) lipgloss.Style

FitBox constrains a style to an exact w x h box: Width/Height pad it out, Max* clip anything that would otherwise overflow (Width alone pads but never truncates, which is how a too-wide panel ends up wrapped by the terminal). Non-positive dimensions are left unset so a component still renders naturally before the first SetBodyLayoutMsg arrives.

func HandleSpinnerTick

func HandleSpinnerTick(spinnerModel spinner.Model, pendingAction *PendingAction, msg tea.Msg) (spinner.Model, tea.Cmd)

HandleSpinnerTick updates the spinner and returns the next tick command. Returns nil if no spinner is active.

func HealthColor

func HealthColor(health string) color.Color
func Hyperlink(text, url string) string

Hyperlink wraps already-sized text in an OSC 8 terminal hyperlink pointing at url. text must already be truncated and padded to its column - OSC 8's escape sequence is not text, and handing a not-yet-truncated string to runewidth.Truncate (chrome.Truncate) will cut through the middle of it, corrupting the rest of the screen. Terminals without OSC 8 support simply do not render the sequence, so text is what they show.

func ListRowBg

func ListRowBg(isActive bool) color.Color

ListRowBg is the background a list row renders on. The active row is lifted to the surface tier; every other row sits flush on the panel's elevated tier. Rows need an explicit background (rather than inheriting the panel's) because each row is rendered and sealed on its own - see appstyles.FillBackground.

func ModalHints

func ModalHints(hints ...KeyHint) string

ModalHints renders a modal's own help line, in the footer bar's format but with the lighter description color the modal surface needs. Every modal carries one: the footer bar is hidden behind the modal while it is open, so the keys the modal takes over are advertised here or nowhere.

func ModalListHeight

func ModalListHeight(items, termHeight int) int

ModalListHeight is the height to build a modal's list with so the modal fits a terminal termHeight rows tall.

renderWithModal (src/model/View.go) centers a modal by clamping y to 0, so a modal taller than the terminal does not scroll or shrink - it loses its hint line and bottom border off the bottom of the screen. A list sized to len(items) is therefore a latent overflow on any project big enough, and the caller pairs this with SetShowPagination(height < len(items)) so the rows that no longer fit stay reachable and say so.

The floor of 3 is deliberate: below about 12 rows there is no honest answer, and a terminal that short cannot show the modal's own chrome either.

func ModalSurface

func ModalSurface(bg color.Color, content string) string

ModalSurface wraps a modal's content in the shared modal chrome: an accent rounded border, padding, and a background sealed against `bg` so the modal reads as one opaque surface over the page it is composited onto. Modals in particular cannot afford an unpainted cell - the page shows through it.

BorderBackground is set explicitly because lipgloss leaves border cells on the default background otherwise, which outlines the modal in the terminal's color.

func ModalTitle

func ModalTitle(text string) string

ModalTitle renders a modal's heading. Every modal names itself, so a user who lands on one mid-flow can tell what it is about to do without having to infer it from the fields. It is the shared accent chip - appstyles.NormalTitle - stood off the body by its own margin, so a style or theme change to the chip lands on modals and panes alike.

The margin replaces the blank line each caller would otherwise have to add - it matches the blank row the hint line sits above: the heading and the footer are the modal's chrome, and both stand off the body.

func NewSpinner

func NewSpinner() spinner.Model

NewSpinner creates a spinner styled with the active theme's accent color.

func PanelBg

func PanelBg() color.Color

PanelBg is the background tier a body panel renders on. Both body panels are always active now that focus is gone, so they share the elevated tier (what the previously "focused" panel used to get). Focus used to lift the whole panel rather than adding a border, so the panel's box stayed the same size either way - that lift is now the steady state.

func PanelBodyHeight

func PanelBodyHeight(total int) int

func PanelBodyWidth

func PanelBodyWidth(total int) int

PanelBodyWidth and PanelBodyHeight are the space a panel body gets inside a frame of the given total size: the frame's own padding taken off, plus the title row for the vertical axis. Callers size their content with these rather than with hardcoded offsets, so a change to WrapperStyle's padding doesn't silently push content out of the panel.

func PanelBodyWithFooter

func PanelBodyWithFooter(width, avail int, bg color.Color, content, footer string) string

PanelBodyWithFooter lays out a details panel's body: `content` at the top, `footer` on the body's last rows, and blank rows between them. Both details panels build their body through here, which is what makes the pending-action spinner land on the same line of both rather than wherever each panel's content happens to end - see "The panel footer" in docs/DESIGN.md.

The content is clipped before the footer is attached, so a panel whose content outgrows its box loses its last rows rather than its footer. Doing it the other way round - joining first and clipping the result - takes the bottom off, which is exactly the row that has to survive.

An empty footer costs no rows. lipgloss.Height("") is 1, so passing "" would otherwise reserve a blank line at the foot of every panel that has nothing to pin there - which is most frames, now that the panels only use the footer for the spinner and the service panel's transient confirmations.

func PanelFrame

func PanelFrame(title string, titleRight string, width int, height int, body string) string

PanelFrame renders the title chrome shared by DetailsPanel and GroupDetailsPanel, filling exactly the width x height box the panel was given. Both body panels are always active now that focus is gone, so they share the elevated background tier.

`titleRight` is an optional accessory pinned to the right end of the title row - the group status pill uses it. A blank row separates the title row from the body, so the panel's own label doesn't read as part of whatever the body starts with; PanelBodyHeight accounts for both rows.

Callers embed their action buttons at the bottom of `body`, which pins the action row to the bottom of the panel. The chip itself is appstyles.NormalTitle; the MarginLeft(2) here is the frame's own left gutter, matching the 2 columns the bubbles list TitleBar adds inside the list wrappers - see appstyles.NormalTitle.

func PanelRule

func PanelRule(width int) string

PanelRule is the thin horizontal line both details panels separate their sections with. One helper rather than five copies of the same three-line style, so the panels cannot drift to different rules.

func PortLabel

func PortLabel(p types.ServicePortConfig) string

PortLabel is one published port in full: the form the service details panel shows, where there is room for it.

14533->4533/tcp
127.0.0.1:14533->4533/tcp   (bound to loopback: not reachable off-host)
4533/tcp                    (exposed, not published)

func PublishedPorts

func PublishedPorts(ports []types.ServicePortConfig) []string

PublishedPorts returns the host-side ports a service publishes, in file order, deduplicated, for a column too narrow for the full mapping. A service that publishes nothing returns an empty slice.

[]{14533:4533/tcp}                        -> ["14533"]
[]{8080:8080/tcp, 6881:6881/tcp+udp}      -> ["8080", "6881"]
[]{4533/tcp}                              -> []          (not published)
[]{53:53/udp}                             -> ["53/udp"]

func RenderKeyHints

func RenderKeyHints(hints []KeyHint, descColor color.Color) string

RenderKeyHints renders hints as "key desc · key desc": the key bold in the primary text color, the description in descColor. Modals render their own help lines through this so they read the same as the footer bar, passing a lighter descColor when they sit on a lighter surface than the bar does.

func ShortImage

func ShortImage(ref string, width int) string

ShortImage renders an image reference to fit width columns, giving up whole parts of the reference in a fixed order rather than truncating the tail — the name is the part a reader needs and it is the part a plain truncation destroys first.

The ladder, widest first, each rung tried in full - the first that fits wins:

  1. as written, minus a ":latest" tag
  2. drop the registry host
  3. drop the namespace
  4. drop the tag (or digest)
  5. Truncate, as a backstop

func Truncate

func Truncate(s string, w int) string

Truncate hard-truncates s to w display columns, appending an ellipsis when it is shortened. lipgloss Width wraps rather than truncates, so cells are pre-truncated to keep every row on a single line.

The ansi.StringWidth check is a fast path, not an alternate algorithm: a plain string that already fits returns unchanged either way, but a string carrying a zero-width escape sequence - an OSC 8 hyperlink built by chrome.Hyperlink, already sized to its column before being wrapped - does not, because runewidth.Truncate is not ANSI-aware and would cut through the middle of the sequence. See docs/plans/service-urls.md D5, which is why Hyperlink's own doc comment requires already-sized text rather than truncating after wrapping.

Types

type KeyHint

type KeyHint struct {
	Key  string
	Desc string
}

KeyHint represents a single keybinding for display in the bottom bar. Key is the literal key (e.g. "n", "space", "←/→"). Desc is a short verb describing what the key does.

func HintAs

func HintAs(binding key.Binding, desc string) KeyHint

func HintFor

func HintFor(binding key.Binding) KeyHint

HintFor is one binding as a hint. HintAs overrides the description for the places where a shared key does something more specific than its general help text says - Enter is "confirm" everywhere, but "create group" in the checklist that creates a group.

type PendingAction

type PendingAction struct {
	Action  string
	Target  string
	IsGroup bool
}

PendingAction tracks a docker action that is currently running.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL