[GH-ISSUE #415] Dynamic class names #5764

Open
opened 2026-05-23 01:52:53 +01:00 by JakeStanger · 7 comments
Owner

Originally created by @izelnakri on GitHub (Jan 24, 2024).
Original GitHub issue: https://github.com/JakeStanger/ironbar/issues/415

Problem statement: As a user I'd like style my battery module when it's charging(or not) and the battery levels. Same dynamic styling is needed for disk usage, cpu, memory etc.

In waybar I could create a module with different states for different css class name styling.

For example in config.json:

  "disk": {
    "format": "🗄️ {percentage_used}% [{used}]",
    "states": {
      "very-high": 80,
      "high": 60
    },
    "on-click": "tmux kill-session -t disk || alacritty -e tmux new-session -s disk \"zsh -c 'df -h'; zsh\""
  },

This allows me in waybar to style different states via:

#disk.very-high {
  color: @waybar_red_color;
}
#disk.high {
  color: @waybar_orange_color;
}

How can I go about implementing this in ironbar?

One not-so-ideal solution I found is to create different modules with type: custom and has different show_ifs and class attributes. However this solution is very verbose and requires me to create bash scripts(I think?). I'm not even sure how to accomplish this with Pango markup, could you provide an example for this scenario in the documentation?

Basically I think we need:

  • a custom states option object & assignments for type: custom and have it documented, or make the class value Dynamic String, even then I'm not sure how to add these classes dynamically on same bash(?) script check?. I'm also not sure how I can create conditionals in Pango markup. I found Pango markup documentation to be insufficient to say the least 😅
  • If we'd like to keep things as is, with no changes in ironbar. That means the not-so-ideal show_if solution is the only way to go(?). It would be great if we can put a basic example in the documentation for a battery level + charging states custom css classes assignment/change.
  • A documented way to declare internal Modules for ironbar.
Originally created by @izelnakri on GitHub (Jan 24, 2024). Original GitHub issue: https://github.com/JakeStanger/ironbar/issues/415 Problem statement: As a user I'd like style my battery module when it's charging(or not) and the battery levels. Same dynamic styling is needed for disk usage, cpu, memory etc. In waybar I could create a module with different states for different css class name styling. For example in config.json: ``` "disk": { "format": "🗄️ {percentage_used}% [{used}]", "states": { "very-high": 80, "high": 60 }, "on-click": "tmux kill-session -t disk || alacritty -e tmux new-session -s disk \"zsh -c 'df -h'; zsh\"" }, ``` This allows me in waybar to style different states via: ``` #disk.very-high { color: @waybar_red_color; } #disk.high { color: @waybar_orange_color; } ``` **How can I go about implementing this in ironbar?** One not-so-ideal solution I found is to create different modules with `type: custom` and has different `show_if`s and `class` attributes. However this solution is very verbose and requires me to create bash scripts(I think?). I'm not even sure how to accomplish this with Pango markup, could you provide an example for this scenario in the documentation? Basically I think we need: - a custom `states` option object & assignments for `type: custom` and have it documented, or make the `class` value `Dynamic String`, even then I'm not sure how to add these classes dynamically on same bash(?) script check?. I'm also not sure how I can create conditionals in Pango markup. I found Pango markup documentation to be insufficient to say the least :sweat_smile: - If we'd like to keep things as is, with no changes in ironbar. That means the not-so-ideal `show_if` solution is the only way to go(?). It would be great if we can put a basic example in the documentation for a battery level + charging states custom css classes assignment/change. - A documented way to declare internal `Module`s for ironbar.
Author
Owner

@JakeStanger commented on GitHub (Jan 24, 2024):

Thanks for the detailed issue. It sounds like there's a few things nested into one here.

As it stands:

This is not currently achievable natively, and does require some external scripting, but there are ways of doing it with a single script or label module.

Pango markup is akin to HTML, and lets you set some basic attributes on a span. This means it does give you some styling control. For example, <span color="red">hello</span> will work. The entire spec can be found here.

You could output the entire markup from an external script directly (doesn't have to be bash, just needs to write to stdout), or use a label along with the ironvar feature.

For example with ironvars:

{
  "end": [
    {
      "type": "label",
      "label": "<span color'#battery-color'>#battery-percent</span>"
    }
  ]
}

And then you'd have a script call ironbar set battery-color and ironbar set battery-percent.

Alternatively you can use <span color='{{my_script.sh}}'> to call a script directly.


The future:

I think there is a clear need for improvement to this, so I'm open to implementing additional functionality. I have never been a big fan of the state model in waybar as it never felt very intuitive to me. It may be that this ends up being the best way to go, but I think this is a long-term goal that requires some planning.

Making the class option a dynamic string feels like a no-brainer to get a quick win. This would still require some external scripting as it stands, but would allow for this to be achieved via the native modules at least.

The documentation requests I'd consider separate to this issue, and there's two there. I'd ask that separate issues are opened for each so they can be individually tracked:

  1. More examples for scripting, ironvars and consuming external content in general.
  2. Improved code documentation (assuming you're referring to docs around writing your own native modules?). This I've held off intentionally as the internals are far from stable. Once the code-base matures, this will definitely get covered.
<!-- gh-comment-id:1908651337 --> @JakeStanger commented on GitHub (Jan 24, 2024): Thanks for the detailed issue. It sounds like there's a few things nested into one here. **As it stands:** This is not currently achievable natively, and does require some external scripting, but there are ways of doing it with a single `script` or `label` module. Pango markup is akin to HTML, and lets you set some basic attributes on a span. This means it does give you some styling control. For example, `<span color="red">hello</span>` will work. The entire spec can be found [here](https://docs.gtk.org/Pango/pango_markup.html). You could output the entire markup from an external script directly (doesn't have to be bash, just needs to write to stdout), or use a l`abel` along with the `ironvar` feature. For example with ironvars: ```json { "end": [ { "type": "label", "label": "<span color'#battery-color'>#battery-percent</span>" } ] } ``` And then you'd have a script call `ironbar set battery-color` and `ironbar set battery-percent`. Alternatively you can use `<span color='{{my_script.sh}}'>` to call a script directly. --- **The future:** I think there is a clear need for improvement to this, so I'm open to implementing additional functionality. I have never been a big fan of the `state` model in waybar as it never felt very intuitive to me. It may be that this ends up being the best way to go, but I think this is a long-term goal that requires some planning. Making the `class` option a dynamic string feels like a no-brainer to get a quick win. This would still require some external scripting as it stands, but would allow for this to be achieved via the native modules at least. The documentation requests I'd consider separate to this issue, and there's two there. I'd ask that separate issues are opened for each so they can be individually tracked: 1. More examples for scripting, ironvars and consuming external content in general. 2. Improved code documentation (assuming you're referring to docs around writing your own native modules?). This I've held off intentionally as the internals are far from stable. Once the code-base matures, this will definitely get covered.
Author
Owner

@izelnakri commented on GitHub (Jan 25, 2024):

Hi again @JakeStanger

I tried your two suggestions and there is a pango parser bug with "<span color='#battery-color'>#battery-percent</span>" the parser tries to output the markup before reading the variable inside the color attribute, even when ironvar_defaults declared on the top level, the .textContent area with ironvars work correctly.

Alternatively you can use to call a script directly.

This solution works, and its fantastic, because it allows me to run even deno scripts via #!/usr/bin/env -S deno run --allow-env so sky is the limit ;)

<!-- gh-comment-id:1910300157 --> @izelnakri commented on GitHub (Jan 25, 2024): Hi again @JakeStanger I tried your two suggestions and there is a pango parser bug with `"<span color='#battery-color'>#battery-percent</span>"` the parser tries to output the markup before reading the variable inside the `color` attribute, even when `ironvar_defaults` declared on the top level, the .textContent area with ironvars work correctly. > Alternatively you can use <span color='{{my_script.sh}}'> to call a script directly. This solution works, and its fantastic, because it allows me to run even deno scripts via `#!/usr/bin/env -S deno run --allow-env` so sky is the limit ;)
Author
Owner

@JakeStanger commented on GitHub (Jan 25, 2024):

Glad to hear you found a working solution! If you get a chance, could you log the pango bug separately please and I'll investigate that as part of the next release?

<!-- gh-comment-id:1910305195 --> @JakeStanger commented on GitHub (Jan 25, 2024): Glad to hear you found a working solution! If you get a chance, could you log the pango bug separately please and I'll investigate that as part of the next release?
Author
Owner

@izelnakri commented on GitHub (Jan 25, 2024):

Added the issue here: https://github.com/JakeStanger/ironbar/issues/418

<!-- gh-comment-id:1910457046 --> @izelnakri commented on GitHub (Jan 25, 2024): Added the issue here: https://github.com/JakeStanger/ironbar/issues/418
Author
Owner

@azertyfun commented on GitHub (Sep 11, 2025):

Hi! I might be interested in helping out with this. I'm not entirely satisfied by the work-around of <span color="{{ script }}"> because it does not allow me to re-use my CSS variables (e.g. @blue), so I unfortunately have to make my script aware of my ironbar theme.

@JakeStanger I haven't yet looked into the code base but what do you reckon would be easiest to get working?

  • Turning end.bar.class into a Dynamic String:
    [[end]]
    type = "custom"
    class = "{{ my_script get_class }}"
    [[end.bar]]
    label = "{{ my_script get_label }}"
    
  • Allowing class as an attribute for <span> (currently I get Attribute 'class' is not allowed on the <span> tag)
    [[end]]
    type = "custom"
    [[end.bar]]
    label = "<span class=\"{{ my_script get_class }}\">{{ my_script get_label }}</span>"
    

EDIT: Oh, I just realized that background-color is not supported as an attribute for <span> either. That leads me to believe the first solution would probably be best.

<!-- gh-comment-id:3279232626 --> @azertyfun commented on GitHub (Sep 11, 2025): Hi! I might be interested in helping out with this. I'm not entirely satisfied by the work-around of `<span color="{{ script }}">` because it does not allow me to re-use my CSS variables (e.g. `@blue`), so I unfortunately have to make my script aware of my ironbar theme. @JakeStanger I haven't yet looked into the code base but what do you reckon would be easiest to get working? * Turning `end.bar.class` into a Dynamic String: ```toml [[end]] type = "custom" class = "{{ my_script get_class }}" [[end.bar]] label = "{{ my_script get_label }}" ``` * Allowing `class` as an attribute for `<span>` (currently I get `Attribute 'class' is not allowed on the <span> tag`) ```toml [[end]] type = "custom" [[end.bar]] label = "<span class=\"{{ my_script get_class }}\">{{ my_script get_label }}</span>" ``` EDIT: Oh, I just realized that `background-color` is not supported as an attribute for `<span>` either. That leads me to believe the first solution would probably be best.
Author
Owner

@JakeStanger commented on GitHub (Sep 11, 2025):

The <span> element is provided by Pango, which is baked into GTK, so there's no changing that.

Dynamic strings would be possible to implement without too much work (you'd just need a bit of logic to split the string and add/remove class names on update). They'd also provide Ironvar support.

In case you missed it, it's also now possible to add/remove classes using the ironbar style IPC/CLI commands.

<!-- gh-comment-id:3279299844 --> @JakeStanger commented on GitHub (Sep 11, 2025): The `<span>` element is provided by Pango, which is baked into GTK, so there's no changing that. Dynamic strings would be possible to implement without too much work (you'd just need a bit of logic to split the string and add/remove class names on update). They'd also provide Ironvar support. In case you missed it, it's also now possible to add/remove classes using the `ironbar style` IPC/CLI commands.
Author
Owner

@azertyfun commented on GitHub (Sep 11, 2025):

Indeed I noticed that after making my comment. It's already a bit more elegant, though it is a bit weird that I have to set my-class for all custom modules, then discriminate with .my-custom.my-class. Oh well, it works well enough for my use-case.

Thanks!

<!-- gh-comment-id:3279367579 --> @azertyfun commented on GitHub (Sep 11, 2025): Indeed I noticed that after making my comment. It's already a bit more elegant, though it is a bit weird that I have to set `my-class` for all custom modules, then discriminate with `.my-custom.my-class`. Oh well, it works well enough for my use-case. Thanks!
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
JakeStanger/ironbar#5764
No description provided.