DEV Community

jaimin patel
jaimin patel

Posted on

πŸš€ Integrating a Custom Charting Library into a Textual Custom Widget – Elevate Your TUI Charts! πŸ“Š

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

Enter fullscreen mode Exit fullscreen mode

πŸš€ 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

Python #Textual #TUI #Charting #Async #DataVisualization #Developers

Hostinger image

Get n8n VPS hosting 3x cheaper than a cloud solution

Get fast, easy, secure n8n VPS hosting from $4.99/mo at Hostinger. Automate any workflow using a pre-installed n8n application and no-code customization.

Start now

Top comments (0)

Qodo Takeover

Introducing Qodo Gen 1.0: Transform Your Workflow with Agentic AI

Rather than just generating snippets, our agents understand your entire project context, can make decisions, use tools, and carry out tasks autonomously.

Read full post