bubble-table
repository·main·Indexed 20 days ago
https://github.com/evertras/bubble-tableA customizable, interactive table component for the Bubble Tea framework. It supports complex terminal UI requirements including pagination, sorting, filtering, scrolling, and advanced styling. Key features include flexible-width columns, multiline content, OSC 8 hyperlinks, and the ability to attach hidden metadata to rows for data retrieval.
What's inside bubble-table
- Bubble-table is a customizable, interactive table component designed for use with the Bubble Tea framework. It provides a rich set of features for building terminal-based tables, including support for headers, footers, pagination, sorting, filtering, and advanced styling.
Define table columns and rows
mainA table is constructed using a slice of
table.Columnvalues and a slice oftable.Rowvalues.- Columns: Each column is defined with a unique string key, a display name, and an optional width.
- Rows: Each row contains
RowData, which is amap[string]anymapping column keys to data values. - Rendering: The table renders data using
fmt.Sprintf("%v"). If a key exists inRowDatabut has no correspondingColumn, it is ignored (useful for attaching hidden metadata). If a key exists in aColumnbut is missing from theRowData, the table can display a missing data indicator. - Styling: You can apply styles to entire rows or to individual cells using
table.NewStyledCell.
const ( columnKeyID = "id" columnKeyName = "Name" ) columns := []table.Column{ table.NewColumn(columnKeyID, "ID", 5), table.NewColumn(columnKeyName, "Name", 10), } rows := []table.Row{ table.NewRow(table.RowData{ columnKeyID: "abc", columnKeyName: "Hello", }), // Row with individual cell styling table.NewRow(table.RowData{ columnKeyID: "alert", columnKeyName: table.NewStyledCell("Alert", lipgloss.NewStyle().Foreground(lipgloss.Color("#f88")), }).WithStyle(lipgloss.NewStyle().Bold(true)), }Attach hidden metadata to rows
mainYou can attach arbitrary data to a row by including keys in the
RowDatamap that do not have a correspondingtable.Columndefinition. This data remains attached to the row and can be retrieved when the row is selected, even though it is not rendered in the table UI. This is useful for mapping table rows back to complex domain objects.const ( columnKeyID = "id" columnKeyName = "Name" columnKeyUserData = "userstuff" // This key has no Column, so it stays hidden ) columns := []table.Column{ table.NewColumn(columnKeyID, "ID", 5), table.NewColumn(columnKeyName, "Name", 10), } user := &SomeUser{ID: 3, Name: "Evertras"} rows := []table.Row{ table.NewRow(table.RowData{ columnKeyID: user.ID, columnKeyName: user.Name, columnKeyUserData: user, // Hidden metadata attached to the row }), }Use row metadata for data retrieval in bubble-table
mainInstead of retrieving data directly from the row values, you can attachmetadatato rows. This allows you to use the metadata as a lookup key or a reference to retrieve the actual data you want to display. This technique is useful for performing more natural or complex data transformations where the row itself might only contain identifiers rather than the full displayable content.Use scrolling to navigate large tables
mainFor tables that are too large to fit on a single screen,bubble-tableprovides scrolling capabilities. This allows users to navigate through extensive datasets within a constrained viewport. You can find implementation details for scrolling in theexamples/scrollingdirectory of the repository.Run bubble-table examples
mainTo explore the features of bubble-table, you can run the provided examples. After cloning the repository, use the following commands:
# Run the pokemon demo for a general feel of common useful features make # Run dimensions example to see multiple sizes of simple tables in action make example-dimensions # Or run any of them directly go run ./examples/pagination/main.gomake make example-dimensions go run ./examples/pagination/main.goUse events to trigger data retrieval in bubble-table
mainInbubble-table, events can be used to handle triggers for data retrieval or other custom behaviors. This pattern allows the table to react to user interactions or state changes by initiating new data fetching logic.Use external text controls for filtering in bubble-table
mainWhilebubble-tableprovides built-in filtering, you can implement more flexible UIs by using external text box controls to drive the filtering logic. This is achieved by manually interacting with the table's Filter API rather than relying on the default internal filter widgets. This pattern allows you to integrate the table into custom layouts where the search input is located outside the table component itself.Get started with the simplest bubble-table implementation
mainTo implement a bare-bones table usingbubble-table, you can use the default configuration to simply present data. This approach requires minimal setup and serves as a baseline for more complex use cases involving custom styling or advanced features.Implement multiline content in bubble-table rows
mainThe multiline feature inbubble-tableallows users to input and display content that spans multiple lines within a single row. This is useful for displaying long descriptions, notes, or any data that cannot be contained in a single line without breaking the table layout. You can integrate this by following the patterns demonstrated in the multiline example code.Implement pagination and multi-table navigation
mainThe pagination example demonstrates how to handle datasets that exceed a single screen's capacity by implementing pagination. It also showcases how to manage multiple tables and provide navigation between them within a Bubble Tea application.Use OSC 8 hyperlinks in bubble-table
mainYou can include clickable hyperlinks within abubble-tableby using OSC 8 escape sequences. In terminals that support OSC 8 (such as iTerm2, Ghostty, WezTerm, and kitty), text containing these sequences will be rendered as clickable links that open the specified URL in a browser.