Hey Devs! π
Ever wished your terminal-based applications could have interactive, dynamic charts? Well, we just made it happen by integrating a custom charting library into a Textual custom widget! π¨β¨
Why This Matters?
Textual is an incredible framework for building rich, interactive terminal applications, but charting support is limited out of the box. So, we built a custom widget that seamlessly integrates with an external charting library to bring smooth, interactive financial & technical charts directly inside a TUI.
π How We Did It
β
 Built a Custom ChartWidget inside Textual
β
 Integrated Plotly (or any other charting library) for rendering dynamic charts
β
 Used asyncio for smooth updates without UI freezing
β
 Enabled multiple chart types (Line, Bar, Candlestick, etc.)
β
 Created a Switch & Collapsible UI to toggle charts on demand
from textual.widget import Widget
from textual.containers import Horizontal, Container
from textual.widgets import Button, Static, Switch
import asyncio
import plotly.graph_objects as go
class ChartWidget(Widget):
    """A custom Textual widget to display dynamic charts."""
    def __init__(self, chart_type="line", title="Chart", widget_id="chart_widget", **kwargs):
        super().__init__(id=widget_id, **kwargs)
        self.chart_type = chart_type
        self.title = title
        self.chart_path = None  # Stores chart file path
    def compose(self):
        with Container():
            yield Static(f"π {self.title}", classes="chart-title")
            yield Switch(value=True, id=f"{self.id}_toggle", label="Show Chart", classes="toggle-switch")
            with Horizontal():
                yield Button("Open", id=f"{self.id}_open_chart")
                yield Button("Close", id=f"{self.id}_close_chart")
    async def generate_chart(self, data):
        """Generates an interactive chart asynchronously."""
        self.chart_path = await asyncio.to_thread(self._render_chart, data)
    def _render_chart(self, data):
        """Handles chart rendering using Plotly."""
        fig = go.Figure()
        fig.add_trace(go.Scatter(x=data["x"], y=data["y"], mode="lines", name="Line Chart"))
        chart_path = f"{self.title}.html"
        fig.write_html(chart_path)
        return chart_path
π What's Next?
We are expanding this to support real-time streaming charts inside Textual! Drop a π₯ in the comments if you're excited! Would love to hear your thoughts! π¬π
π Check out the full implementation & contribute to the repo:Fincept Terminal
    
Top comments (0)