diff --git a/bingo.py b/bingo.py index e197259..4e40684 100644 --- a/bingo.py +++ b/bingo.py @@ -1,21 +1,79 @@ #!/usr/bin/env python3 from textual.app import App, ComposeResult -from textual.widgets import Header, Input, Static, Button -from textual.containers import Horizontal +from textual.widgets import Header, Input, Static, Button +from textual.containers import Horizontal, Container from textual.validation import Number +from textual.command import DiscoveryHit, Provider, Hits, Hit +from textual.reactive import reactive from datetime import datetime from BingoBoard import BingoBoard +MESSAGE = ''' +Be excellent to each other! + +Made with :red_heart: by Panki + +[@click="app.open_link('https://tty0.social/@panki')"]Mastodon:[/] tty0.social/@panki +[@click="app.open_link('https://git.theresno.cloud/panki/bingo-cli')"]Source:[/] git.theresno.cloud/panki/bingo-cli + +Built using [@click="app.open_link('https://textual.textualize.io/')"]Textual[/] + +''' + +class AboutCommand(Provider): + async def discover(self) -> Hits: + yield DiscoveryHit(display='About', command=self.app.action_toggle_sidebar, help='Link to repo etc.') + + def show_about(self): + pass + + async def search(self, query: str) -> Hits: + matcher = self.matcher(query) + command = "About" + score = matcher.match(command) + if score > 0: + yield Hit(score, matcher.highlight(command), self.app.action_toggle_sidebar, 'Link to repo etc.') + +class Sidebar(Container): + def compose(self) -> ComposeResult: + yield Static('CCC Bingo', classes='title') + yield Static(MESSAGE, classes='message') + self.button = Button('< Back', variant='primary', classes='btn_sidebar') + self.button.disabled = True + yield self.button + + def on_button_pressed(self, event: Button.Pressed) -> None: + print('sidebar button press') + self.app.action_toggle_sidebar() + class BingoApp(App): '''A Textual app to run a Bingo board.''' CSS_PATH = "bingo.tcss" + COMMANDS = App.COMMANDS | {AboutCommand} + AUTO_FOCUS = 'Input' + + show_sidebar = reactive(False) + + def action_toggle_sidebar(self) -> None: + print('sidebar toggle') + sidebar = self.query_one(Sidebar) + self.set_focus(None) + if sidebar.has_class("-hidden"): + sidebar.remove_class("-hidden") + sidebar.button.disabled = False + else: + if sidebar.query("*:focus"): + self.screen.set_focus(None) + sidebar.add_class("-hidden") + sidebar.button.disabled = True def compose(self) -> ComposeResult: '''Create child widgets for the app.''' - yield Header() + yield Sidebar(classes="-hidden") + yield Header(show_clock=True) yield BingoDisplay() def on_mount(self) -> None: diff --git a/bingo.tcss b/bingo.tcss index 4ab573e..ef2eab8 100644 --- a/bingo.tcss +++ b/bingo.tcss @@ -1,3 +1,7 @@ +Screen { + layers: base overlay; +} + BingoBoard { layout: grid; grid-size: 5 5; @@ -42,3 +46,39 @@ Input.-valid { Input.-valid:focus { border: tall $success; } + +Sidebar { + width: 40; + background: $panel; + transition: offset 500ms in_out_cubic; + layer: overlay; +} + +Sidebar:focus-within { + offset: 0 0 !important; +} + +Sidebar.-hidden { + offset-x: -100%; +} + +Static.title { + background: $boost; + color: $secondary; + padding: 2 4; + border-right: vkey $background; + dock: top; + text-align: center; + text-style: bold; +} +Static.message { + background: $boost; + color: $text; + height: 1fr; + border-right: vkey $background; + text-align: center; +} + +Button.btn_sidebar { + width: 100%; +}