Skip to content

feat(bar): Add support for custom icons #5963

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

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

NSPC911
Copy link

@NSPC911 NSPC911 commented Jul 15, 2025

You can now super a textual.renderable.bar.Bar class and change HALF_BAR_LEFT, BAR, and HALF_BAR_RIGHT, before passing the class as a keyword argument in the textual.widgets.ProgressBar widget as bar_renderable. The keyword arg's name might be weird.

resolves #5350

Image:
image

Code Snippet

from textual.app import App, ComposeResult
from textual.renderables.bar import Bar as BarRenderable
from textual.widgets import ProgressBar
from textual.color import Gradient
class SignsRenderable(BarRenderable):
    HALF_BAR_LEFT = "-"
    BAR = "="
    HALF_BAR_RIGHT = "-"
class ArrowsRenderable(BarRenderable):
    HALF_BAR_LEFT = ">"
    BAR = "="
    HALF_BAR_RIGHT = ">"
class ThickBarRenderable(BarRenderable):
    HALF_BAR_LEFT = "▐"
    BAR = "█"
    HALF_BAR_RIGHT = "▌"
class SlashBarRenderable(BarRenderable):
    HALF_BAR_LEFT = "\\"
    BAR = "|"
    HALF_BAR_RIGHT = "/"
class Application(App):
    DEFAULT_CSS = """
    .bar--indeterminate { color: #bf616a !important; background: #2e3440 !important }
    """
    def compose(self) -> ComposeResult:
        gradient = Gradient.from_colors("#8fbcbb", "#88c0d0", "#81a1c1", "#5e81ac")
        for widget in [ThickBarRenderable, SignsRenderable, SlashBarRenderable, ArrowsRenderable]:
            yield ProgressBar(bar_renderable=widget, gradient=gradient)
        yield ProgressBar(gradient=gradient)
    def on_mount(self) -> None:
        self.progress_timer = self.set_interval(1 / 10, self.make_progress, pause=True)
        self.set_timer(4.0, self.start_progress)
    def start_progress(self) -> None:
        for bar in self.query(ProgressBar):
            bar.update(total=100)
        self.progress_timer.resume()
    def make_progress(self) -> None:
        for bar in self.query(ProgressBar):
            bar.advance(1)
Application().run()

Please review the following checklist.

  • Docstrings on all new or modified functions / classes
  • Updated documentation
  • Updated CHANGELOG.md (where appropriate)

You can super a textual.renderable.bar.Bar class and change `HALF_BAR_LEFT`, `BAR`, and `HALF_BAR_RIGHT`, before passing the class as an keyword argument in the textual.widgets.ProgressBar widget as `bar_renderable`.
The keyword arg's name is weird, I'm not sure what to name it
@@ -72,11 +72,13 @@ def __init__(
disabled: bool = False,
clock: Clock | None = None,
gradient: Gradient | None = None,
bar_renderable: BarRenderable = BarRenderable,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not convinced this is something that warrants being in the constructor. It feels more like an internal detail than configuration.

How about we expose the bar renderable as a classvar?

Something like this:

class FancyProgress(ProgressBar):
    BAR_RENDERABLE_CLASS = FancyBar

Then you wouldn't have to specify it everywhere you use the progress bar.

Copy link
Author

@NSPC911 NSPC911 Jul 21, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the bar renderable is passed in as a class variable into the Bar element, what about the main ProgressBar element?

I'm not sure how the ProgressBar element can receive the Bar Renderable to be passed to the Bar widget as a class variable before being rendered

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm also a tad bit confused on the comment, because your review comment is on the Bar element while your code example is for the ProgressBar element

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

Successfully merging this pull request may close these issues.

Customize progress bar with arbitrary bar text
2 participants