from textual.app import App from textual.containers import Container, Horizontal, ScrollableContainer, Vertical from textual.screen import Screen from textual.widgets import Header, Label from textual_fastdatatable import ArrowBackend, DataTable class LabeledBox(Container): DEFAULT_CSS = """ LabeledBox { layers: base_ top_; width: 100%; height: 100%; } LabeledBox > Container { layer: base_; border: round $primary; width: 100%; height: 100%; layout: vertical; } LabeledBox > Label { layer: top_; offset-x: 2; } """ def __init__(self, title, *args, **kwargs): self.__label = Label(title) super().__init__(self.__label, Container(*args, **kwargs)) @property def label(self): return self.__label class StatusTable(DataTable): def __init__(self) -> None: backend = ArrowBackend.from_pydict( { "Foo": ["ABCDEFGH"] * 50, "Bar": ["0123456789"] * 50, "Baz": ["IJKLMNOPQRSTUVWXYZ"] * 50, } ) super().__init__(backend=backend) self.cursor_type = "row" self.show_cursor = False class Status(LabeledBox): DEFAULT_CSS = """ Status { width: auto; } Status Container { width: auto; } Status StatusTable { width: auto; height: 100%; margin-top: 1; scrollbar-gutter: stable; overflow-x: hidden; } """ def __init__(self, name: str): self.__name = name self.__table = StatusTable() super().__init__(f" {self.__name} ", self.__table) @property def name(self) -> str: return self.__name @property def table(self) -> StatusTable: return self.__table class Rendering(LabeledBox): DEFAULT_CSS = """ #issue-info { height: auto; border-bottom: dashed #632CA6; } #statuses-box { height: 1fr; width: auto; } """ def __init__(self): self.__info = Label("test") super().__init__( "", ScrollableContainer( Horizontal(self.__info, id="issue-info"), Horizontal(*[Status(str(i)) for i in range(4)], id="statuses-box"), id="issues-box", ), ) @property def info(self) -> Label: return self.__info class Sidebar(LabeledBox): DEFAULT_CSS = """ #sidebar-status { height: auto; border-bottom: dashed #632CA6; } #sidebar-options { height: 1fr; } """ def __init__(self): self.__status = Label("ok") self.__options = Vertical() super().__init__( "", Container(self.__status, id="sidebar-status"), Container(self.__options, id="sidebar-options"), ) @property def status(self) -> Label: return self.__status @property def options(self) -> Vertical: return self.__options class MyScreen(Screen): DEFAULT_CSS = """ #main-content { layout: grid; grid-size: 2; grid-columns: 1fr 5fr; grid-rows: 1fr; } #main-content-sidebar { height: 100%; } #main-content-rendering { height: 100%; } """ def compose(self): yield Header() yield Container( Container(Sidebar(), id="main-content-sidebar"), Container(Rendering(), id="main-content-rendering"), id="main-content", ) class MyApp(App): async def on_mount(self): self.install_screen(MyScreen(), "myscreen") await self.push_screen("myscreen") if __name__ == "__main__": app = MyApp() app.run()