{"id":51654978,"url":"https://github.com/allisonhere/tideui","last_synced_at":"2026-07-14T08:30:58.931Z","repository":{"id":360305241,"uuid":"1249544570","full_name":"allisonhere/tideui","owner":"allisonhere","description":"Themeable multi-pane terminal UI toolkit for Bubble Tea and Lipgloss applications.","archived":false,"fork":false,"pushed_at":"2026-06-15T19:42:24.000Z","size":303,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-26T20:05:38.927Z","etag":null,"topics":["accessibility","bubble-tea","bubbletea","charmbracelet","component-library","golang","golang-library","layout-engine","lipgloss","terminal-ui","themeable","themes","tui","tui-framework","ui-toolkit","wcag"],"latest_commit_sha":null,"homepage":"","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/allisonhere.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"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}},"created_at":"2026-05-25T20:17:33.000Z","updated_at":"2026-06-15T19:42:28.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/allisonhere/tideui","commit_stats":null,"previous_names":["allisonhere/tideui"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/allisonhere/tideui","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/allisonhere%2Ftideui","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/allisonhere%2Ftideui/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/allisonhere%2Ftideui/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/allisonhere%2Ftideui/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/allisonhere","download_url":"https://codeload.github.com/allisonhere/tideui/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/allisonhere%2Ftideui/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":35453842,"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-07-14T02:00:06.603Z","response_time":114,"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":["accessibility","bubble-tea","bubbletea","charmbracelet","component-library","golang","golang-library","layout-engine","lipgloss","terminal-ui","themeable","themes","tui","tui-framework","ui-toolkit","wcag"],"created_at":"2026-07-14T08:30:58.821Z","updated_at":"2026-07-14T08:30:58.921Z","avatar_url":"https://github.com/allisonhere.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# tideui\n\n**A themeable, multi-pane terminal UI toolkit for [Bubble Tea](https://github.com/charmbracelet/bubbletea) and [Lipgloss](https://github.com/charmbracelet/lipgloss).**\n\n`tideui` renders application-provided content inside themed pane shells, status\nbars, and overlays. It is deliberately *view-oriented*: your application keeps\nits own Bubble Tea model, key routing, persistence, and viewport state — you\nhand `tideui` strings and dimensions, and it returns a framed, themed view.\n\n![tideui three-pane layout and theme picker](./screen.png)\n\n## Lineage\n\nThe three-pane layout, theme-preview workflow, and themed modal language began\nin [Tide](https://github.com/allisonhere/tide), a terminal RSS reader, and were\nrefined in [TideMail](https://github.com/allisonhere/tidemail), a keyboard-first\nemail client. `tideui` packages those reusable primitives for any Bubble Tea\napplication.\n\n## Install\n\n```bash\ngo get github.com/allisonhere/tideui\n```\n\n## Features\n\n- **Five layout modes** — `StackedRight`, `ThreeColumn`, `SidebarOnly`, `Tabbed`, and `Floating`, each with tunable ratios.\n- **Nineteen built-in palettes** (Catppuccin, Nord, Dracula, Gruvbox, and more) with per-field background/foreground/accent overrides.\n- **Themed chrome** — pane headers, status bars, centered modal overlays, and a ready-made theme picker.\n- **List primitives** — single-line `Row` and multi-line `Block` with selected/muted states.\n- **Per-pane scrolling** via `Pane.ScrollOffset` and the `PaneScroller` helper.\n- **Density + accessibility** — compact/comfortable spacing and a VT52 ASCII mode.\n- **Bounded output** — never exceeds the requested terminal dimensions, down to tiny windows.\n- **Terminal background control** — exposes the escape sequences so the app, not the library, writes to the terminal.\n\n## Quick start\n\n```go\nimport \"github.com/allisonhere/tideui\"\n\ntheme, _ := tideui.ThemeByName(\"catppuccin-mocha\")\nrenderer := tideui.NewRenderer(theme, tideui.StyleOptions{Density: tideui.Compact})\n\nview := renderer.Render(tideui.Layout{\n    Width: 80, Height: 24, Mode: tideui.StackedRight,\n    Panes: [3]tideui.Pane{\n        {Title: \"Mailboxes\", Content: \"Inbox\\nArchive\", Focused: true},\n        {Title: \"Messages\",  Content: \"Welcome to tideui\"},\n        {Title: \"Preview\",   Content: \"Application-owned content.\"},\n    },\n    Status: \u0026tideui.StatusBar{Left: \"ready\", Right: \"? help\"},\n})\n```\n\n## Bubble Tea integration\n\n`tideui` owns no model state. Track dimensions and theme in your own model and\nbuild a renderer in `View`:\n\n```go\nfunc (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {\n    if size, ok := msg.(tea.WindowSizeMsg); ok {\n        m.width, m.height = size.Width, size.Height\n    }\n    return m, nil\n}\n\nfunc (m model) View() string {\n    r := tideui.NewRenderer(m.theme, tideui.StyleOptions{Density: m.density})\n    return r.Render(tideui.Layout{\n        Width: m.width, Height: m.height, Mode: tideui.ThreeColumn,\n        Panes: m.panes(),\n    })\n}\n```\n\n## Layout modes\n\n| Mode | Description | Ratio fields |\n|---|---|---|\n| `StackedRight` | Pane 0 sidebar; panes 1 \u0026 2 stacked on the right | `SidebarRatio`, `UpperRightRatio` |\n| `ThreeColumn` | All three panes side by side | `ColumnRatios` |\n| `SidebarOnly` | Pane 0 sidebar; pane 1 full-height main (pane 2 unused) | `SidebarRatio` |\n| `Tabbed` | Tab bar on top; the focused pane fills the area below | — |\n| `Floating` | Pane 0 as background; panes 1 \u0026 2 as floating panels | `FloatWidthRatio`, `FloatHeightRatio` |\n\n```go\nlayout.Mode = tideui.StackedRight\nlayout.SidebarRatio, layout.UpperRightRatio = 0.30, 0.45\n\nlayout.Mode, layout.ColumnRatios = tideui.ThreeColumn, [3]float64{2, 3, 5}\n```\n\nIn `Tabbed` mode the first `Focused` pane selects the active tab (falling back to\npane 0). All ratio fields default to sensible values when left zero.\n\n## Theming\n\n```go\ntheme, ok := tideui.ThemeByName(\"nord\")   // false if unknown\nfor _, t := range tideui.BuiltinThemes { /* ... */ }\n```\n\nOverride individual colors without forking a palette:\n\n```go\ntheme = tideui.ThemeOverrides{\n    Accent: \"#f5c2e7\",\n}.Apply(tideui.CatppuccinMocha)\n```\n\n`Theme.UsesASCII()` reports VT52 mode (ASCII-only glyphs) so callers can adapt.\n`StyleOptions{Density: tideui.Comfortable}` adds spacing; `Compact` removes it.\n\n## Rows and blocks\n\n`RenderRow` draws a single-line list item; `RenderBlock` adds an optional\nmulti-line body (a `Block` with no `Body` is byte-identical to the matching\n`Row`). Both support `Selected` and `Muted`:\n\n```go\nrenderer.RenderRow(tideui.Row{Prefix: \"* \", Text: \"Inbox\", Suffix: \"12\", Selected: true}, width)\n\nrenderer.RenderBlock(tideui.Block{\n    Prefix: \"● \", Header: \"alice\", Meta: \"10:02\",\n    Body:   \"Multi-line body, indented to the header.\",\n}, width)\n```\n\nFor fully custom pane content, use the exported `renderer.Styles` (e.g.\n`DetailTitle`, `DetailMeta`, `DetailBody`).\n\n## Scrollable panes\n\nSet `Pane.ScrollOffset`, or let `PaneScroller` manage it:\n\n```go\nm.scroll.ScrollDown(1)            // ScrollUp / ScrollToTop also available\nm.scroll.ClampTo(total, visible)  // optional; renderer clamps out-of-range anyway\n\npane.ScrollOffset = m.scroll.Offset()\n```\n\n`CanScrollDown(total, visible)` reports whether more content lies below.\n\n## Theme picker\n\nA drop-in modal for previewing and confirming themes:\n\n```go\npicker := tideui.NewThemePicker(tideui.ThemePickerOptions{InitialTheme: \"nord\"})\npicker.Open(\"nord\")\n\nswitch picker.Update(keyMsg) {\ncase tideui.ThemePickerConfirm:\n    m.theme = picker.ConfirmedTheme()\ncase tideui.ThemePickerCancel:\n    // preview reverted to the confirmed theme\n}\n\noverlay := picker.Modal(renderer, m.width, m.height) // assign to Layout.Modal\n```\n\nThe picker previews live as you navigate and restores the confirmed theme on\ncancel.\n\n## Terminal background\n\n`tideui` never writes to the terminal itself. To paint the terminal background\nto match the theme, fetch the sequences and emit them from your program:\n\n```go\nset, reset := tideui.TerminalBackgroundSequences(theme)\n```\n\n## Design\n\nApplications retain ownership of their model, commands, key routing,\npersistence, and viewport state. `tideui` is purely presentational — it turns\ncontent + dimensions + a theme into a bounded, framed string. The one exception\nis the optional `ThemePicker`, which manages its own navigation once opened.\n\n## License\n\nMIT.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fallisonhere%2Ftideui","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fallisonhere%2Ftideui","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fallisonhere%2Ftideui/lists"}