TUI -> Kivy porting strategies #201967
Replies: 5 comments 1 reply
-
|
I ran into something similar when moving from a TUI to a GUI framework. The biggest lesson was not to "port" the UI itself. Keep your core application logic untouched and rebuild the presentation layer from scratch. Textual's CSS-like styling doesn't really have a clean equivalent in Kivy, so trying to map styles one-for-one usually becomes more work than it's worth. |
Beta Was this translation helpful? Give feedback.
-
|
If you've already separated the application logic, the next step is to stop thinking in terms of recreating the Textual layout. Kivy's widget tree and layout system ( A strategy that often works is to rebuild the interface one screen at a time:
If rendering is the main blocker, it would help to know what specifically isn't rendering correctly. Are the widgets not appearing at all, are the layouts behaving unexpectedly, or are you having trouble converting specific Textual CSS rules? A small example of the original Textual layout and your Kivy code would make it much easier to suggest an equivalent approach. |
Beta Was this translation helpful? Give feedback.
-
|
I would treat this as a rewrite of the presentation layer, but not a rewrite of the application. The migration pattern that has worked best for me is:
Before touching Kivy, define plain Python objects/dataclasses that describe what each screen needs to show: @dataclass
class JobRow:
name: str
status: str
progress: float
@dataclass
class DashboardState:
title: str
jobs: list[JobRow]
selected_job_id: str | NoneYour Textual widgets and Kivy widgets should both render from this model. That prevents the port from becoming “translate Textual widget tree into Kivy widget tree.”
If your Textual app uses messages/events heavily, introduce your own small event API: class AppController:
def select_job(self, job_id: str): ...
def refresh(self): ...
def cancel_job(self, job_id: str): ...Then wire Textual callbacks to that controller first. After that, Kivy button handlers call the same controller methods.
Textual CSS and Kivy layout/styling are different enough that a rule-by-rule conversion usually burns time. Instead, convert CSS into a small design-token file: COLORS = {
"bg": "#101418",
"panel": "#182028",
"accent": "#4aa3ff",
}
SPACING = {
"sm": 6,
"md": 12,
"lg": 20,
}Then use those tokens from
Make a table like this: Port one screen at a time. Keep the old Textual screen around until the Kivy version can render the same state model and pass the same controller actions.
The first Kivy milestone should not edit anything. It should only display one realistic state snapshot. Once layout is stable, add event handlers. This avoids debugging layout, data flow, and business logic all at once. A useful folder structure is: The main thing I would avoid is a compatibility layer that tries to emulate Textual CSS in Kivy. It sounds attractive, but it usually creates a second framework inside your app. A thin state/controller boundary gives you a much cleaner migration path. |
Beta Was this translation helpful? Give feedback.
-
|
Porting from Textual to Kivy is challenging because Textual's CSS and widget model don't translate 1:1. The key to success is separating your presentation layer from your logic instead of trying to translate widgets directly. Here is a proven strategy to get your Kivy UI rendering correctly:
Start by building a read-only Kivy prototype of your main screen using static state. Once it renders, wire up your event controller! |
Beta Was this translation helpful? Give feedback.
-
|
Hi, this is an interesting case because Textual and Kivy aren't just "two different frameworks" — they're two different UI paradigms entirely (text/cell-based terminal rendering vs. graphical OpenGL rendering), so a 1:1 port of the interface logic almost never works well. Some strategies that tend to work better than trying to translate widget-by-widget: Separate business logic from the presentation layer first (if you haven't already): Before touching Kivy, make sure all your app logic (state, validation, data calls) is fully decoupled from Textual widgets. If your current code mixes logic into on_mount, compose(), etc., the port will be much more painful. This is usually 80% of the real work. Textual-web or exporting your Textual app as a web app (Textual already supports this) gives you more visual flexibility without abandoning your current code. Practical migration approach: Instead of porting the whole app at once, start by migrating a single simple screen/view as a proof of concept. This gives you a realistic sense of how much effort the rest will take before committing to a full rewrite. How large is the app (how many screens/views), and what specifically is the terminal preventing you from doing? That would help give a more targeted recommendation on whether Kivy is really the best fit. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
🏷️ Discussion Type
Question
Body
I have a Python TUI application (using Textual) that I want to port to Kivy, since the terminal has proven to constrained for my application. I have already made several failed attempts to port the UI logic, and want to know if anyone has a good strategy for this sort of problem (the biggest issue so far has been Textual's use of a CSS subset for styling)?
Guidelines
Beta Was this translation helpful? Give feedback.
All reactions