{"id":51043748,"url":"https://github.com/floatpane/bubble-overlay","last_synced_at":"2026-06-22T12:02:25.148Z","repository":{"id":361553930,"uuid":"1254296688","full_name":"floatpane/bubble-overlay","owner":"floatpane","description":"ANSI-aware overlay painter for Bubble Tea / lipgloss views","archived":false,"fork":false,"pushed_at":"2026-06-22T06:25:33.000Z","size":84,"stargazers_count":2,"open_issues_count":8,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-06-22T08:15:39.182Z","etag":null,"topics":["ansi","ansi-escape-codes","bubbletea","charmbracelet","cli","command-line","go","golang","golang-library","lipgloss","modal","overlay","popup","rendering","terminal","terminal-ui","text-ui","tooltip","tui","ui-components"],"latest_commit_sha":null,"homepage":"https://bubble.floatpane.com","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/floatpane.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null},"funding":{"github":"floatpane"}},"created_at":"2026-05-30T11:46:13.000Z","updated_at":"2026-06-16T20:29:07.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/floatpane/bubble-overlay","commit_stats":null,"previous_names":["floatpane/bubble-overlay"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/floatpane/bubble-overlay","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/floatpane%2Fbubble-overlay","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/floatpane%2Fbubble-overlay/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/floatpane%2Fbubble-overlay/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/floatpane%2Fbubble-overlay/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/floatpane","download_url":"https://codeload.github.com/floatpane/bubble-overlay/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/floatpane%2Fbubble-overlay/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34647750,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-22T02:00:06.391Z","response_time":106,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ansi","ansi-escape-codes","bubbletea","charmbracelet","cli","command-line","go","golang","golang-library","lipgloss","modal","overlay","popup","rendering","terminal","terminal-ui","text-ui","tooltip","tui","ui-components"],"created_at":"2026-06-22T12:02:24.159Z","updated_at":"2026-06-22T12:02:25.108Z","avatar_url":"https://github.com/floatpane.png","language":"Go","funding_links":["https://github.com/sponsors/floatpane"],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\n# bubble-overlay\n\n**ANSI-aware overlay painter for Bubble Tea / lipgloss views.**\n\n[![Go Version](https://img.shields.io/github/go-mod/go-version/floatpane/bubble-overlay)](https://golang.org)\n[![Go Reference](https://pkg.go.dev/badge/github.com/floatpane/bubble-overlay.svg)](https://pkg.go.dev/github.com/floatpane/bubble-overlay)\n[![GitHub release (latest by date)](https://img.shields.io/github/v/release/floatpane/bubble-overlay)](https://github.com/floatpane/bubble-overlay/releases)\n[![CI](https://github.com/floatpane/bubble-overlay/actions/workflows/ci.yml/badge.svg)](https://github.com/floatpane/bubble-overlay/actions/workflows/ci.yml)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)\n\n\u003c/div\u003e\n\n`bubble-overlay` paints rectangular blocks of styled text on top of an\nexisting ANSI-styled string at a given `(row, col)` cell position. It's the\nmissing primitive for modals, popups, tooltips, filepickers, and floating\npanels in [Bubble Tea](https://github.com/charmbracelet/bubbletea) /\n[lipgloss](https://github.com/charmbracelet/lipgloss) apps — render your\nbase view as a single string, render your popup as another, then composite.\n\n## Features\n\n- **SGR-safe.** Existing ANSI styles around the overlaid region are preserved; cells underneath are replaced. The overlay is terminated with `\\x1b[0m` so its styles don't bleed into the row's tail.\n- **Cell-accurate.** Uses `charmbracelet/x/ansi` for width — wide-character / emoji handling matches what the terminal actually renders, not byte counts.\n- **Auto-grow.** Overlays that extend past the bottom of the base string append new lines instead of truncating.\n- **Auto-pad.** Overlays past the right edge of a short row are padded with spaces, so a popup on row 3 column 40 still lands correctly when the base row is only 10 cells wide.\n- **Tiny.** Two functions. No state. Drop-in.\n\n## Install\n\n```bash\ngo get github.com/floatpane/bubble-overlay\n```\n\nRequires Go 1.26+.\n\n## Usage\n\n```go\npackage main\n\nimport (\n    \"fmt\"\n\n    \"github.com/charmbracelet/lipgloss\"\n    \"github.com/floatpane/bubble-overlay\"\n)\n\nfunc main() {\n    base := lipgloss.NewStyle().\n        Foreground(lipgloss.Color(\"240\")).\n        Render(\"a quiet inbox view\\nwith two lines\\nand a third\")\n\n    popup := lipgloss.NewStyle().\n        Background(lipgloss.Color(\"57\")).\n        Foreground(lipgloss.Color(\"231\")).\n        Padding(0, 1).\n        Render(\"are you sure?\\nyes / no\")\n\n    block := strings.Split(popup, \"\\n\")\n    fmt.Println(overlay.Block(base, block, 1, 4))\n}\n```\n\n### Center a floating popup\n\nFor the common case of a centered modal — command palette, confirmation dialog,\ntooltip — `Center` handles the positioning automatically:\n\n```go\ncomposited := overlay.Center(baseView, popupView, termWidth, termHeight)\n```\n\nIt computes the centered `(row, col)` from the popup's visual size and your\nscreen dimensions, then calls `Block`. Rows/columns clamp to zero if the popup\nis larger than the screen.\n\n### Low-level API\n\n```go\n// Center places popup as a floating layer centered over base within a screen\n// of screenW × screenH cells.\nfunc Center(base, popup string, screenW, screenH int) string\n\n// Paint a multi-line block on top of base at (row, col).\nfunc Block(base string, block []string, row, col int) string\n\n// Paint a single overlay line on top of base at col.\nfunc Line(base, overlay string, col int) string\n```\n\n## When to use this\n\nYou have a Bubble Tea `View()` returning a styled multi-line string and\nyou want to render a modal/popup over it without:\n\n- Re-rendering the base view with a \"modal-shaped hole\" cut out of it.\n- Walking the ANSI sequences yourself.\n- Truncating styles that span across the modal region.\n\n`bubble-overlay` does the composite for you. The base view stays a single\nstring; the modal stays a single string; you call `Block` and emit the\nresult.\n\n## Documentation\n\nFull API reference: [pkg.go.dev/github.com/floatpane/bubble-overlay](https://pkg.go.dev/github.com/floatpane/bubble-overlay)\n\n## Contributing\n\nPRs welcome. See [CONTRIBUTING.md](CONTRIBUTING.md).\n\n## Security\n\nReport vulnerabilities privately via [SECURITY.md](SECURITY.md).\n\n## License\n\nMIT. See [LICENSE](LICENSE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffloatpane%2Fbubble-overlay","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffloatpane%2Fbubble-overlay","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffloatpane%2Fbubble-overlay/lists"}