Close Menu
  • AI
  • Content Creation
  • Tech
  • Robotics
AI-trends.todayAI-trends.today
  • AI
  • Content Creation
  • Tech
  • Robotics
Trending
  • Prego Has a Dinner-Conversation-Recording Device, Capisce?
  • AI CEOs think they can be everywhere at once
  • OpenAI’s GPT-5.4 Cyber: A Finely Tuned Model for Verified Security Defenders
  • Code Implementation for an AI-Powered Pipeline to Detect File Types and Perform Security Analysis with OpenAI and Magika
  • TabPFN’s superior accuracy on tabular data sets is achieved by leveraging in-context learning compared to Random Forest or CatBoost
  • Moonshot AI Researchers and Tsinghua Researchers propose PrfaaS, a cross-datacenter KVCache architecture that rethinks how LLMs can be served at scale.
  • OpenMythos – A PyTorch Open Source Reconstruction of Claude Mythos, where 770M Parameters match a 1.3B Transformator
  • This tutorial will show you how to run PrismML Bonsai 1Bit LLM using CUDA, Benchmarking and Chat with JSON, RAG, GGUF.All 128 weights have the same FP16 scaling factor. 1 bit (sign) + 16/128 bits (shared scale) = 1.125 bpw Compare Memory for Bonsai 1.7B:?It is 14.2 times smaller than Q1_0_g128!
AI-trends.todayAI-trends.today
Home»Tech»How can I create a fully interactive, reactive, and dynamic terminal-based data dashboard using textual?

How can I create a fully interactive, reactive, and dynamic terminal-based data dashboard using textual?

Tech By Gavin Wallace15/11/20256 Mins Read
Facebook Twitter LinkedIn Email
Researchers at UT Austin Introduce Panda: A Foundation Model for
Researchers at UT Austin Introduce Panda: A Foundation Model for
Share
Facebook Twitter LinkedIn Email

We will build an advanced dashboard with Dashboard. TextualIn this article, we will explore how terminal first UI frameworks feel just as expressive and as dynamic as modern dashboards. We actively build the interface as we run and write each snippet. This includes widgets, responsive state, event flows and layouts. At the end of this tutorial, you will see how easily we were able to combine tables, tree forms and progress indicator into one cohesive app that felt fast, responsive and clean. Click here to see the FULL CODES here.

!pip install textual textual-web nest-asyncio


Import App from Textual.app, ComposeResult
Textual.containers.import Container, Horizontal.
Import textual.widgets (
   Header, Footer, Button, DataTable, Static, Input,
 Label Tree ProgressBar
)
Textual import of reactive
From textual import
Datetime can be imported from another datetime
Random Import


Class StatsCard (Static),
 Value = reactive(0)
  
   def __init__(self, title: str, *args, **kwargs):
 Supermarkets are a great way to buy goods and services.().__init__(*args, **kwargs)
 Title = self-title
      
   def compose(self) -> ComposeResult:
 "self-title" Label
       yield Label(str(self.value), id="stat-value")
  
   def watch_value(self, new_value: int) -> None:
 If self.is_mounted
           try:
               self.query_one("#stat-value", Label).update(str(new_value))
 Except Exception
               pass

Set up your environment, and then import the components you need to create our Textual app. We create a component that is reusable and automatically updates when the value of a widget changes. Textual’s reactive system allows us to quickly create dynamic UI with little effort. Look at the FULL CODES here.

class DataDashboard(App):
 The CSS code is: """
   Screen { background: $surface; }
   #main-container { height: 100%; padding: 1; }
   #stats-row { height: auto; margin-bottom: 1; }
   StatsCard { border: solid $primary; height: 5; padding: 1; margin-right: 1; width: 1fr; }
   #stat-value { text-style: bold; color: $accent; content-align: center middle; }
   #control-panel { height: 12; border: solid $secondary; padding: 1; margin-bottom: 1; }
   #data-section { height: 1fr; }
   #left-panel { width: 30; border: solid $secondary; padding: 1; margin-right: 1; }
   DataTable { height: 100%; border: solid $primary; }
   Input { margin: 1 0; }
   Button { margin: 1 1 1 0; }
   ProgressBar { margin: 1 0; }
   """
  
 BINDINGS [
       ("d", "toggle_dark", "Toggle Dark Mode"),
       ("q", "quit", "Quit"),
       ("a", "add_row", "Add Row"),
       ("c", "clear_table", "Clear Table"),
   ]
  
   total_rows = reactive(0)
   total_sales = reactive(0)
   avg_rating = reactive(0.0)

DataDashboard can be configured by configuring global styles, keys bindings, reactive attributes, etc. The app’s appearance and behavior are decided from the beginning. We have full control of themes and interaction. We can create a dashboard using this structure without needing to know HTML or JS. Click here to see the FULL CODES here.

  def compose(self) -> ComposeResult:
       yield Header(show_clock=True)
      
 With Container(id="main-container"):
 With Horizontal(id="stats-row"):
 StatsCard"Total Rows", id="card-rows")
 StatsCard"Total Sales", id="card-sales")
 StatsCard"Avg Rating", id="card-rating")
          
 With Vertical(id="control-panel"):
 It is a placeholder for the input (placeholder="Product Name", id="input-name")
 Choose ()
                   [("Electronics", "electronics"),
                    ("Books", "books"),
                    ("Clothing", "clothing")],
                   prompt="Select Category",
                   id="select-category"
               )
 Horizontal():
 Give Button"Add Row", variant="primary", id="btn-add")
 Give Button"Clear Table", variant="warning", id="btn-clear")
 Give Button"Generate Data", variant="success", id="btn-generate")
               yield ProgressBar(total=100, id="progress")
          
 With Horizontal(id="data-section"):
 Container(id="left-panel"):
 ?????????????????????????????????????????????????????????????????????????????????????????????????????"Navigation")
 Tree = Tree"Dashboard")
                   tree.root.expand()
 Product = root.add ("Products", expand=True)
                   products.add_leaf("Electronics")
                   products.add_leaf("Books")
                   products.add_leaf("Clothing")
                   tree.root.add_leaf("Reports")
                   tree.root.add_leaf("Settings")
 Yield tree
              
 Yield DataTable (id=)"data-table")
      
 The Footer()

The entire UI is composed by arranging the containers, forms, buttons, navigation trees, data tables, form inputs and cards. We can watch as the interface takes shape in the exact way that we want it to. It allows you to create the dashboard visual structure in an elegant, declarative way. See the FULL CODES here.

 def on_mount(self) -> None:
       table = self.query_one(DataTable)
       table.add_columns("ID", "Product", "Category", "Price", "Sales", "Rating")
       table.cursor_type = "row"
       self.generate_sample_data(5)
       self.set_interval(0.1, self.update_progress)
  
   def generate_sample_data(self, count: int = 5) -> None:
       table = self.query_one(DataTable)
 Categories =Products = ["Electronics", "Books", "Clothing"]
       products = {
           "Electronics": ["Laptop", "Phone", "Tablet", "Headphones"],
           "Books": ["Novel", "Textbook", "Magazine", "Comic"],
           "Clothing": ["Shirt", "Pants", "Jacket", "Shoes"]
       }
      
 The range of _ is:
           category = random.choice(categories)
           product = random.choice(productsArtificial Intelligence)
           row_id = self.total_rows + 1
           price = round(random.uniform(10, 500), 2)
           sales = random.randint(1, 100)
           rating = round(random.uniform(1, 5), 1)
          
           table.add_row(
               str(row_id),
               product,
               category,
 The f"${price}",
               str(sales),
               str(rating)
           )
          
           self.total_rows += 1
           self.total_sales += sales
      
       self.update_stats()
  
   def update_stats(self) -> None:
       self.query_one("#card-rows", StatsCard).value = self.total_rows
       self.query_one("#card-sales", StatsCard).value = self.total_sales
      
       if self.total_rows > 0:
           table = self.query_one(DataTable)
           total_rating = sum(float(row[5]Rows in table)
           self.avg_rating = round(total_rating / self.total_rows, 2)
           self.query_one("#card-rating", StatsCard).value = self.avg_rating
  
   def update_progress(self) -> None:
       progress = self.query_one(ProgressBar)
       progress.advance(1)
       if progress.progress >= 100:
           progress.progress = 0

We then implement the entire logic to generate data, compute statistics, animate progress and update cards. Textual’s Reactive Model allows us to quickly bind the backend logic with frontend components. It is now possible to make the dashboard look alive by updating numbers instantly, and letting progress bars move smoothly. Look at the FULL CODES here.

 @on(Button.Pressed, "#btn-add")
   def handle_add_button(self) -> None:
       name_input = self.query_one("#input-name", Input)
 "category = self.query_one""#select-category", Select).value
      
 If name_input.value is equal to category
           table = self.query_one(DataTable)
           row_id = self.total_rows + 1
           price = round(random.uniform(10, 500), 2)
           sales = random.randint(1, 100)
           rating = round(random.uniform(1, 5), 1)
          
           table.add_row(
               str(row_id),
               name_input.value,
               str(category),
 The f"${price}",
               str(sales),
               str(rating)
           )
          
           self.total_rows += 1
           self.total_sales += sales
           self.update_stats()
           name_input.value = ""
  
   @on(Button.Pressed, "#btn-clear")
   def handle_clear_button(self) -> None:
       table = self.query_one(DataTable)
       table.clear()
       self.total_rows = 0
       self.total_sales = 0
       self.avg_rating = 0
       self.update_stats()
  
   @on(Button.Pressed, "#btn-generate")
   def handle_generate_button(self) -> None:
       self.generate_sample_data(10)
  
   def action_toggle_dark(self) -> None:
 Not self.
  
   def action_add_row(self) -> None:
       self.handle_add_button()
  
   def action_clear_table(self) -> None:
       self.handle_clear_button()




If the __name__ equals "__main__":
   import nest_asyncio
   nest_asyncio.apply()
   app = DataDashboard()
   app.run()

We link UI events with backend actions by using keyboard shortcuts and functions at the app level. While running the application, we are interacting with a dashboard that is fully functional and responds to clicks and commands instantly. The snippet shows how Textual allows us to create dynamic and state-driven interfaces.

We see that the dashboard is now fully interactive and functional. It runs from within a notebook. Textual allows us to create terminal UIs that have the look and feel of web applications, all while remaining in Python. The tutorial gives us the confidence to continue experimenting with Textual’s reactive UI, adding more charts, feeds from APIs and multi-pages navigation.


Take a look at the FULL CODES here. Check out our GitHub Page for Tutorials, Codes and Notebooks. Also, feel free to follow us on Twitter Join our Facebook group! 100k+ ML SubReddit Subscribe now our Newsletter. Wait! Are you using Telegram? now you can join us on telegram as well.


Asif Razzaq, CEO of Marktechpost Media Inc. is a visionary engineer and entrepreneur who is dedicated to harnessing Artificial Intelligence’s potential for the social good. Marktechpost was his most recent venture. This platform, which specializes in covering machine learning and deep-learning news, is both technically solid and understandable to a broad audience. Over 2 million views per month are a testament to the platform’s popularity.

🙌 Follow MARKTECHPOST: Add us as a preferred source on Google.

ar dat data x
Share. Facebook Twitter LinkedIn Email
Avatar
Gavin Wallace

Related Posts

OpenAI’s GPT-5.4 Cyber: A Finely Tuned Model for Verified Security Defenders

20/04/2026

Code Implementation for an AI-Powered Pipeline to Detect File Types and Perform Security Analysis with OpenAI and Magika

20/04/2026

TabPFN’s superior accuracy on tabular data sets is achieved by leveraging in-context learning compared to Random Forest or CatBoost

20/04/2026

Moonshot AI Researchers and Tsinghua Researchers propose PrfaaS, a cross-datacenter KVCache architecture that rethinks how LLMs can be served at scale.

20/04/2026
Top News

IBM and NASA create a digital twin of the sun to predict future solar storms

Siri Must Die

OpenAI Ramps Robotics in the Race for AGI

OpenAI Leadership’s Response to Meta Offers, ‘Someone is Breaking into Our House’

The Way forward for AI Filmmaking Is a Parody of the Apocalypse, Made by a Man Named Josh

Load More
AI-Trends.Today

Your daily source of AI news and trends. Stay up to date with everything AI and automation!

X (Twitter) Instagram
Top Insights

Create a powerful tool for advanced portfolio analysis and market intelligence with OpenBB

11/08/2025

Youtube affected by European power cuts

26/05/2025
Latest News

Prego Has a Dinner-Conversation-Recording Device, Capisce?

20/04/2026

AI CEOs think they can be everywhere at once

20/04/2026
X (Twitter) Instagram
  • Privacy Policy
  • Contact Us
  • Terms and Conditions
© 2026 AI-Trends.Today

Type above and press Enter to search. Press Esc to cancel.