{"id":24475793,"url":"https://github.com/haykh/tuigo","last_synced_at":"2025-05-07T07:33:48.295Z","repository":{"id":213220362,"uuid":"733361868","full_name":"haykh/tuigo","owner":"haykh","description":"a terminal UI framework written in Go using the `bubbletea` library","archived":false,"fork":false,"pushed_at":"2024-05-20T08:36:25.000Z","size":10011,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-31T07:41:32.420Z","etag":null,"topics":["bubbletea","cli","framework","go","tui"],"latest_commit_sha":null,"homepage":"https://pkg.go.dev/github.com/haykh/tuigo","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"unlicense","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/haykh.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}},"created_at":"2023-12-19T06:44:58.000Z","updated_at":"2024-06-10T07:01:22.000Z","dependencies_parsed_at":"2024-05-20T09:27:15.271Z","dependency_job_id":"b1060f80-4f0b-4dae-849b-9c8976e4d5f2","html_url":"https://github.com/haykh/tuigo","commit_stats":null,"previous_names":["haykh/tuigo"],"tags_count":14,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/haykh%2Ftuigo","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/haykh%2Ftuigo/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/haykh%2Ftuigo/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/haykh%2Ftuigo/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/haykh","download_url":"https://codeload.github.com/haykh/tuigo/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252833995,"owners_count":21811290,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["bubbletea","cli","framework","go","tui"],"created_at":"2025-01-21T09:27:28.608Z","updated_at":"2025-05-07T07:33:48.267Z","avatar_url":"https://github.com/haykh.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# `tuigo` \n\na terminal UI framework written in Go using the `bubbletea` library.\n\n![order](examples/order.gif)\n\n### building an application\n\nthe backbone of any application is the `tuigo.Backend` object, which contains all the states of the app, and describes the workflow of changing the states and finalizing the app. the backend object contains the constructors for each \"state\" of the application (returning an `Element`), and can optionally depend on the previous state (passed as an argument). most of the functions for making new elements are exposed through `tuigo.%Element%`, which return an `Element`. `Container` elements can be nested, while each display element (buttons, selectors, texts, etc) is contained within a parent container. the backend also contains a finalizer function, which is called when the app finishes successfully.\n\nthe `tuigo.NewApp` function takes a `Backend` and a boolean value, which determines whether the app should be run in debug mode. the backend is then used to create an app, which is the passed to the `tea.NewProgram`.\n\nsee [`examples/`](examples/) for usage examples of `tuigo` for building applications. the scheme below shows roughly the structure of the API. \n\n```mermaid\n%%{\n  init: {\n    'theme': 'base',\n    'themeVariables': {\n        'fontFamily': 'JetBrainsMono Nerd Font, BlexMono Nerd Font, Roboto Mono, Source Code Pro, monospace',\n        'primaryColor': '#4C2FAD',\n        'primaryTextColor': '#FFFFFF',\n        'lineColor': '#E840E0',\n        'primaryBorderColor': '#E840E0'\n      }\n    }\n}%%\n\nclassDiagram\n  class tuigo {\n    \u003c\u003cpackage\u003e\u003e\n    Container :: Func[bool, ContainerType, ...Element] -\u003e ComplexContainer\n    Button :: Func[string, ButtonType, Msg] -\u003e SimpleContainer\n    Selector :: Func[List~string~] -\u003e SimpleContainer\n    Input :: Func[string, string, string, InputType] -\u003e SimpleContainer\n    Radio :: Func[string] -\u003e SimpleContainer\n  }\n\n  class Backend[\"tuigo.Backend\"]{\n    States :: List~AppState~\n    Constructors :: Map[AppState]:Func[Window]-\u003eWindow\n    Updaters :: Map[AppState]:Func[Window,tea.Msg]-\u003eWindow,tea.Cmd\n    Finalizer :: Func[Map[AppState]:Window]-\u003eWindow\n  }\n\n  class NewApp[\"tuigo\"] {\n    \u003c\u003cpackage\u003e\u003e\n    App :: Func[Backend, bool] -\u003e app.App\n  }\n  note for Backend \"AppState = string\"\n  note for Backend \"Window = Collection\"\n\n  class tea[\"tea 'github.com/charmbracelet/bubbletea'\"] {\n    \u003c\u003cpackage\u003e\u003e\n    NewProgram :: Func[Model, ...ProgramOption] -\u003e *Program\n  }\n\n  tuigo --o Backend\n  NewApp --o tea\n  Backend --o NewApp\n```\n### containers\n\n```mermaid\n%%{\n  init: {\n    'theme': 'base',\n    'themeVariables': {\n        'fontFamily': 'JetBrainsMono Nerd Font, BlexMono Nerd Font, Roboto Mono, Source Code Pro, monospace',\n        'primaryColor': '#4C2FAD',\n        'primaryTextColor': '#FFFFFF',\n        'lineColor': '#E840E0',\n        'primaryBorderColor': '#E840E0'\n      }\n    }\n}%%\nclassDiagram\n  class Accessor {\n    \u003c\u003cinterface\u003e\u003e\n    ID() int\n    Data() interface\u003c\u003e\n  }\n\n  class Element {\n    \u003c\u003cinterface\u003e\u003e\n    View(bool) string\n    Update(tea.Msg) (Element, tea.Cmd)\n  }\n\n  class AbstractComponent {\n    \u003c\u003cinterface\u003e\u003e\n    Hidden() bool\n    Focusable() bool\n    Focused() bool\n\t  Disabled() bool\n  }\n\n  class Component {\n    \u003c\u003cinterface\u003e\u003e\n    Hide() Component\n    Unhide() Component\n\t  Enable() Component\n\t  Disable() Component\n    Focus() Component\n    FocusFromStart() Component\n    FocusFromEnd() Component\n    Blur() Component\n    FocusNext() (Component, tea.Cmd)\n    FocusPrev() (Component, tea.Cmd)\n    GetContainerByID(int) Component\n    GetElementByID(int) Accessor\n  }\n  Element \u003c|-- Component\n  AbstractComponent \u003c|-- Component\n\n  class Collection {\n    \u003c\u003cinterface\u003e\u003e\n    Type() utils.ContainerType\n    Components() List~Component~\n    AddComponents(...Component) Collection\n  }\n  Component \u003c|-- Collection\n\n  class Wrapper {\n    \u003c\u003cinterface\u003e\u003e\n    Element() Element\n  }\n  Component \u003c|-- Wrapper\n\n  class Container {\n    -bool hidden\n    -bool focusable\n    -bool focused\n    -Func[Container] -\u003e string render\n  }\n  AbstractComponent \u003c|.. Container\n\n  class SimpleContainer {\n    -Element element\n  }\n\n  class ComplexContainer {\n    -ContainerType containerType\n    -List~Component~ components\n  }\n\n  Wrapper \u003c|.. SimpleContainer\n  Container \u003c|-- SimpleContainer\n  Collection \u003c|.. ComplexContainer\n  Container \u003c|-- ComplexContainer\n```\n\n### elements\n\n```mermaid\n%%{\n  init: {\n    'theme': 'base',\n    'themeVariables': {\n        'fontFamily': 'JetBrainsMono Nerd Font, BlexMono Nerd Font, Roboto Mono, Source Code Pro, monospace',\n        'primaryColor': '#4C2FAD',\n        'primaryTextColor': '#FFFFFF',\n        'lineColor': '#E840E0',\n        'primaryBorderColor': '#E840E0'\n      }\n    }\n}%%\nclassDiagram\n  class Accessor {\n    \u003c\u003cinterface\u003e\u003e\n    ID() int\n    Data() interface\u003c\u003e\n  }\n\n  class Actor {\n    \u003c\u003cinterface\u003e\u003e\n    Callback()\n  }\n\n  class Element {\n    \u003c\u003cinterface\u003e\u003e\n    View(bool) string\n    Update(tea.Msg) (Element, tea.Cmd)\n  }\n\n  class ElementWithID {\n    -int id\n  }\n\n  class ElementWithCallback {\n    -tea.Msg callback\n  }\n  ElementWithID ..|\u003e Accessor\n  ElementWithCallback ..|\u003e Actor\n\n  class Button {\n    -string label\n    -npresses int\n    -ButtonType btntype\n    -tea.Msg action\n    +Data() -\u003e Button::npresses\n  }\n  ElementWithID \u003c|-- Button\n  ElementWithCallback \u003c|-- Button\n  Element \u003c|.. Button\n\n  class TextInput {\n    -InputType inputtype\n    -textinput.Model model    \n    +Data() -\u003e TextInput::model.Value -\u003e string\n  }\n  ElementWithID \u003c|-- TextInput\n  ElementWithCallback \u003c|-- TextInput\n  Element \u003c|.. TextInput\n\n  class Radio {\n\t  -string label\n\t  -bool state\n    +Toggle() -\u003e Radio\n    +Data() -\u003e Radio::state\n  }\n  ElementWithID \u003c|-- Radio\n  ElementWithCallback \u003c|-- Radio\n  Element \u003c|.. Radio\n\n  class Selector {\n    -bool multiselect\n    -int cursor\n    -List~string~ options\n    -Map~string~ selected\n    -Map~string~ disabled\n    -int view_limit\n    +Enable(string) -\u003e Selector\n    +Disable(string) -\u003e Selector\n    +Disabled(string) -\u003e bool\n    +Toggle(string) -\u003e Selector\n    +SetViewLimit(int) -\u003e Selector\n    +Next() -\u003e Selector\n    +Prev() -\u003e Selector\n    +Selected() -\u003e List~string~\n    +Cursor() -\u003e int\n    +Data() -\u003e Selector::Selected -\u003e List~string~\n  }\n  Element \u003c|.. Selector\n  ElementWithID \u003c|-- Selector\n  ElementWithCallback \u003c|-- Selector\n\n  class Text {\n    -string text\n    -TextType texttype\n    +Data() -\u003e Text::text\n    +Set(string) -\u003e Text\n  }\n  ElementWithID \u003c|-- Text\n  ElementWithCallback \u003c|-- Text\n  Element \u003c|.. Text\n```\n\n## TODO\n\n- [x] app backend\n- [x] grid structure\n- [x] easily accessible components\n- [x] update components based on others\n- [ ] unit tests\n  - [x] elements\n  - [x] containers\n  - [ ] callbacks\n  - [ ] backend\n  - [ ] app\n- [ ] customizable theme\n- [ ] more components\n- [ ] key help menu\n- [ ] validators\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhaykh%2Ftuigo","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhaykh%2Ftuigo","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhaykh%2Ftuigo/lists"}