diff --git a/examples/sidebar.py b/examples/sidebar.py new file mode 100644 index 000000000..cc104e3ed --- /dev/null +++ b/examples/sidebar.py @@ -0,0 +1,95 @@ +""" +A simple animated sidebar. + +See comments for details. + +""" + +from textual.app import App, ComposeResult +from textual.containers import Vertical +from textual.reactive import reactive +from textual.widget import Widget +from textual.widgets import Footer, Label + +TEXT = """I must not fear. +Fear is the mind-killer. +Fear is the little-death that brings total obliteration. +I will face my fear. +I will permit it to pass over me and through me. +And when it has gone past, I will turn the inner eye to see its path. +Where the fear has gone there will be nothing. Only I will remain.""" + + +class Sidebar(Widget): + """ + Our sidebar widget. + + Add desired content to compose() + + """ + + DEFAULT_CSS = """ + Sidebar { + width: 30; + /* Needs to go in its own layer to sit above content */ + layer: sidebar; + /* Dock the sidebar to the appropriate side */ + dock: left; + /* Offset x to be -100% to move it out of view by default */ + offset-x: -100%; + + background: $boost; + border-right: vkey $background; + + /* Enable animation */ + transition: offset 200ms; + + &.-visible { + /* Set offset.x to 0 to make it visible when class is applied */ + offset-x: 0; + } + + & > Vertical { + margin: 1 2; + } + } + """ + + def compose(self) -> ComposeResult: + with Vertical(): + yield Label("Your scrollbar here!") + + +class SidebarApp(App): + """ + Test app to show our sidebar. + """ + + DEFAULT_CSS = """ + Screen { + layers: sidebar; + } + + """ + + BINDINGS = [("s", "toggle_sidebar", "Toggle Sidebar")] + + show_sidebar = reactive(False) + + def compose(self) -> ComposeResult: + yield Sidebar() + yield Label(TEXT) + yield Footer() + + def action_toggle_sidebar(self) -> None: + """Toggle the sidebar visibility.""" + self.show_sidebar = not self.show_sidebar + + def watch_show_sidebar(self, show_sidebar: bool) -> None: + """Set or unset visible class when reactive changes.""" + self.query_one(Sidebar).set_class(show_sidebar, "-visible") + + +if __name__ == "__main__": + app = SidebarApp() + app.run()