Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to style a ProgressBar's bar in a widget #5349

Closed
ktmeaton opened this issue Dec 5, 2024 · 3 comments
Closed

How to style a ProgressBar's bar in a widget #5349

ktmeaton opened this issue Dec 5, 2024 · 3 comments

Comments

@ktmeaton
Copy link

ktmeaton commented Dec 5, 2024

I was wondering if I could get some tips on styling the bar component of a ProgressBar that is inside a widget? For testing purposes, I'm aiming for a small bar that is red:

image

I've consulted the Progress Bar docs, and can achieve the desired style by declaring the CSS globally inside the app's main CSS attribute:

from textual.app import App, ComposeResult
from textual.containers import Center, Middle
from textual.timer import Timer
from textual.widgets import Footer, ProgressBar

class StyledProgressBar(ProgressBar):
    def compose(self) -> ComposeResult:
        yield ProgressBar()

class StyledProgressBarApp(App[None]):
    BINDINGS = [("s", "start", "Start")]
    CSS = """
    Bar {
        width: 10;
    }
    Bar > .bar--bar {
        color: red;
        background: yellow 50%;
    }
    """
    progress_timer: Timer
    """Timer to simulate progress happening."""

    def compose(self) -> ComposeResult:
        with Center():
            with Middle():
                yield StyledProgressBar()
        yield Footer()

    def on_mount(self) -> None:
        """Set up a timer to simulate progress happening."""
        self.progress_timer = self.set_interval(1 / 10, self.make_progress, pause=True)

    def make_progress(self) -> None:
        """Called automatically to advance the progress bar."""
        self.query_one(StyledProgressBar).query_one(ProgressBar).advance(1)

    def action_start(self) -> None:
        """Start the progress tracking."""
        self.query_one(StyledProgressBar).query_one(ProgressBar).update(total=100)
        self.progress_timer.resume()


if __name__ == "__main__":
    StyledProgressBarApp().run()

But I can't figure out how to achieve this customization locally in the widget, without setting a global style. This is what I was hoping would work, but I just get whatever the default/global style is instead:

image

class StyledProgressBar(ProgressBar):
    DEFAULT_CSS = """
    Bar {
        width: 10;
    }
    Bar > .bar--bar {
        color: red;
        background: yellow 50%;
    }
    """
    def compose(self) -> ComposeResult:
        yield ProgressBar()

Any help would be greatly appreciated!

Copy link

github-actions bot commented Dec 5, 2024

We found the following entry in the FAQ which you may find helpful:

Feel free to close this issue if you found an answer in the FAQ. Otherwise, please give us a little time to review.

This is an automated reply, generated by FAQtory

@ktmeaton
Copy link
Author

ktmeaton commented Dec 5, 2024

Hah, I figured it out. Sometimes you just need to say something "out loud" 😆. This is how the widget DEFAULT_CSS needs to be defined. I don't yet understand why this CSS works, but it does!

class StyledProgressBar(ProgressBar):
    DEFAULT_CSS = """
    .custom-bar Bar {
        width: 10;
    }
    .custom-bar Bar > .bar--bar {
        color: red;
        background: yellow 50%;
    }
    """
    def compose(self) -> ComposeResult:
        yield ProgressBar(classes="custom-bar")

image

@ktmeaton ktmeaton closed this as completed Dec 5, 2024
Copy link

github-actions bot commented Dec 5, 2024

Don't forget to star the repository!

Follow @textualizeio for Textual updates.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant