[GH-ISSUE #1417] Add ability to rotate widgets #6048

Open
opened 2026-05-23 01:54:47 +01:00 by JakeStanger · 1 comment
Owner

Originally created by @doqfgc on GitHub (Mar 15, 2026).
Original GitHub issue: https://github.com/JakeStanger/ironbar/issues/1417

Describe the bug
Item labels on the launcher module remains horizontal regardless of orientation configuration on a vertically-aligned bar.

To reproduce
Steps to reproduce the behavior:

  1. Add module launcher to a vertically-aligned bar
  2. Enable the show_names property
  3. The text is not rotated to fit (and makes the bar abnormally large)

Expected behavior
The item labels should be rotated to better align with the vertical bar.

System information:

  • Distro: openSUSE Tumbleweed
  • Compositor: Hyprland
  • Ironbar version: 0.18.0

Configuration

Config
{
  "monitors": {
    "eDP-1": [
      {
        "position": "top",
        "height": 24,
        "start": [
          {
            "type": "workspaces",
            "name_map": {
              "1": "󰈹",
              "2": "",
              "3": "",
              "4": "󰝚",
              "5": "󰈹"
            },
            "favorites": ["1", "2", "3"]
          }
        ],
        "end": [
          {
            "type": "music"
          },
          {
            "type": "battery",
            "show_if": "ls /sys/class/power_supply/ | grep --quiet '^BAT'"
          },
          {
            "type": "sys_info",
            "format": [
              " {cpu_percent:1}%"
            ],
            "interval": {
              "cpu": 1
            }
          },
          {
            "type": "sys_info",
            "format": [
              " {memory_percent:1}% ({swap_percent:1}%)"
            ],
            "interval": {
              "cpu": 1
            }
          },
          {
            "type": "volume",
            "popup_orientation": "vertical",
            "sink_slider_orientation": "horizontal"
          },
          {
            "type": "bluetooth",
            "format": {
              "disabled": " 󰂲 ",
              "enabled": " 󰂯 ",
              "connected": " 󰂱 "
            }
          },
          {
            "type": "network_manager",
            "types_whitelist": ["wifi"],
            "icon_size": 16
          },
          {
            "type": "tray"
          },
          {
            "type": "clock",
            "format": "%a %-d %b %Y %H:%M:%S"
          },
          {
            "type": "notifications",
            "icons": {
              "closed_none": "󰍥",
              "closed_some": "󱥂",
              "closed_dnd": "󱅯",
              "open_none": "󰍡",
              "open_some": "󱥁",
              "open_dnd": "󱅮"
            }
          }
        ]
      },
      {
        "position": "right",
        "center": [
          {
            "type": "launcher",
            "orientation": "v",
            "favorites": ["firefox", "discord", "thunderbird-esr"],
            "icon_size": 16,
            "show_names": true,
            "truncate": {
              "mode": "end",
              "max_length": 48
            }
          }
        ]
      }
    ]
  }
}
Styles
:root {
    --color-dark-primary: #1c1c1c;
    --bgc-light: 255,255,255;
    --bgc-dark: 0,0,0;
    --bgc-selected: var(--bgc-dark);
    --color-dark-secondary: rgba(var(--bgc-selected),0.15);
    --color-white: #fff;
    --color-selected: rgba(var(--bgc-selected),0.5);
    --color-hovered: rgba(var(--bgc-selected),0.3);
    --color-active: #6699cc;
    --color-urgent: #8f0a0a;

    --margin-lg: 0.5em;
    --margin-sm: 0.3em;
}

.background {
    background-color: rgba(0,0,0,0.4);
}

* {
    border-radius: 0;
    border: none;
    box-shadow: none;
    background-image: none;
    font-family: "Noto Sans", "Symbols Nerd Font", monospace;

    transition: all 400ms;
}

scale > trough {
    background-color: var(--color-dark-secondary);
}

scale > trough > highlight {
    background-color: var(--color-active);
    border-style: solid;
    border-color: var(--color-active);
    border-width: 0.2em;
}

scale > trough > slider {
    background-color: var(--color-white);
}

switch > slider {
    background-color: var(--color-white);
}

switch:checked {
    background-color: var(--color-active);
}

switch:not(:checked) {
  background-color: var(--color-dark-secondary);
}

#bar {
    background-color: rgba(0,0,0,0);
}

#bar > .horizontal {
    transform: skewX(-10deg);
}

#bar > .vertical {
    /* transform: skewY(-10deg); */
}

label, picture {
    transform: skewX(10deg);
}

popover, popover contents, calendar {
    background-color: var(--color-dark-primary);
}

box, button, label {
    background-color: #0000;
    color: var(--color-white);
}

button {
    padding-left: var(--margin-sm);
    padding-right: var(--margin-sm);
}

button:hover, button:active {
    background-color: var(--color-dark-secondary);
}

#end > * + * {
    margin-left: var(--margin-lg);
}

.tray {
    background-color: var(--color-dark-secondary);
}

.sysinfo > * + * {
    margin-left: var(--margin-sm);
}

.sysinfo .item {
    margin-left: 5px;
    margin-right: 5px;
}

.sysinfo, .battery, .bluetooth, .network_manager, .volume, .music {
    background-color: var(--color-dark-secondary);
}

.network_manager .icon {
    margin-left: 5px;
    margin-right: 5px;
}

.clock {
    font-weight: bold;
    background-color: var(--color-dark-secondary);
}

.popup-clock label, .tray .menu label, .popup-volume label, .launcher label, .launcher picture {
    transform: skewX(0deg);
}

.popup-clock .calendar-clock {
    font-size: 2.0em;
}

.popup-clock .calendar .today {
    background-color: var(--color-active);
}

.workspaces .item {
    font-weight: bold;
    margin-left: 5px;
    padding-left: 7px;
    padding-right: 7px;
    background-color: var(--color-dark-secondary);
}

.workspaces .item:hover {
    background-color: var(--color-hovered);
}

.workspaces .item.focused {
    background-color: var(--color-selected);
}

.workspaces .item.urgent {
    background-color: var(--color-urgent);
}

.launcher .item label {
    padding-left: 5px;
    /*font-size: 0px;*/
}

.launcher .item.focused label {
    /*font-size: 14px;*/
}

.launcher .item {
    margin-left: 3px;
    background-color: var(--color-dark-secondary);
}

.launcher .item.focused {
    background-color: var(--color-selected);
}

.popup-launcher .popup-item {
    transform: skewX(-10deg);
}

.popup-bluetooth {
    transform: skewX(0deg);
}

.popup-bluetooth .devices .box .device {
    margin: 7px 7px 0 7px;
}

.popup-bluetooth .header, .popup-bluetooth .devices .box {
    transform: skewX(-10deg);
    margin: 7px 7px 0 7px;
}

.notifications .button { 
    padding-left: 10px;
    padding-right: 10px;
    background-color: var(--color-dark-secondary);
    margin-right: 5px;
}

.notifications .count {
    margin-right: 3px;
}

.popup-music .album-art {
   transform: skewX(0deg);
}

.popup-music .label {
    transform: skewX(0deg);
}


Additional context
Despite my best efforts, I was unable to rotate the text myself without adverse results (note to self: transform: rotate(90deg) does not also affect its bounding box)

As an aside, disabling labels leaves gaps where the labels would have been.

Screenshots
Image

Originally created by @doqfgc on GitHub (Mar 15, 2026). Original GitHub issue: https://github.com/JakeStanger/ironbar/issues/1417 **Describe the bug** Item labels on the launcher module remains horizontal regardless of orientation configuration on a vertically-aligned bar. **To reproduce** Steps to reproduce the behavior: 1. Add module `launcher` to a vertically-aligned bar 2. Enable the `show_names` property 3. The text is not rotated to fit (and makes the bar abnormally large) **Expected behavior** The item labels should be rotated to better align with the vertical bar. **System information:** - Distro: openSUSE Tumbleweed - Compositor: Hyprland - Ironbar version: 0.18.0 **Configuration** <!-- Share your bar configuration and stylesheet as applicable: --> <details><summary>Config</summary> ``` { "monitors": { "eDP-1": [ { "position": "top", "height": 24, "start": [ { "type": "workspaces", "name_map": { "1": "󰈹", "2": "", "3": "", "4": "󰝚", "5": "󰈹" }, "favorites": ["1", "2", "3"] } ], "end": [ { "type": "music" }, { "type": "battery", "show_if": "ls /sys/class/power_supply/ | grep --quiet '^BAT'" }, { "type": "sys_info", "format": [ " {cpu_percent:1}%" ], "interval": { "cpu": 1 } }, { "type": "sys_info", "format": [ " {memory_percent:1}% ({swap_percent:1}%)" ], "interval": { "cpu": 1 } }, { "type": "volume", "popup_orientation": "vertical", "sink_slider_orientation": "horizontal" }, { "type": "bluetooth", "format": { "disabled": " 󰂲 ", "enabled": " 󰂯 ", "connected": " 󰂱 " } }, { "type": "network_manager", "types_whitelist": ["wifi"], "icon_size": 16 }, { "type": "tray" }, { "type": "clock", "format": "%a %-d %b %Y %H:%M:%S" }, { "type": "notifications", "icons": { "closed_none": "󰍥", "closed_some": "󱥂", "closed_dnd": "󱅯", "open_none": "󰍡", "open_some": "󱥁", "open_dnd": "󱅮" } } ] }, { "position": "right", "center": [ { "type": "launcher", "orientation": "v", "favorites": ["firefox", "discord", "thunderbird-esr"], "icon_size": 16, "show_names": true, "truncate": { "mode": "end", "max_length": 48 } } ] } ] } } ``` </details> <details><summary>Styles</summary> ```css :root { --color-dark-primary: #1c1c1c; --bgc-light: 255,255,255; --bgc-dark: 0,0,0; --bgc-selected: var(--bgc-dark); --color-dark-secondary: rgba(var(--bgc-selected),0.15); --color-white: #fff; --color-selected: rgba(var(--bgc-selected),0.5); --color-hovered: rgba(var(--bgc-selected),0.3); --color-active: #6699cc; --color-urgent: #8f0a0a; --margin-lg: 0.5em; --margin-sm: 0.3em; } .background { background-color: rgba(0,0,0,0.4); } * { border-radius: 0; border: none; box-shadow: none; background-image: none; font-family: "Noto Sans", "Symbols Nerd Font", monospace; transition: all 400ms; } scale > trough { background-color: var(--color-dark-secondary); } scale > trough > highlight { background-color: var(--color-active); border-style: solid; border-color: var(--color-active); border-width: 0.2em; } scale > trough > slider { background-color: var(--color-white); } switch > slider { background-color: var(--color-white); } switch:checked { background-color: var(--color-active); } switch:not(:checked) { background-color: var(--color-dark-secondary); } #bar { background-color: rgba(0,0,0,0); } #bar > .horizontal { transform: skewX(-10deg); } #bar > .vertical { /* transform: skewY(-10deg); */ } label, picture { transform: skewX(10deg); } popover, popover contents, calendar { background-color: var(--color-dark-primary); } box, button, label { background-color: #0000; color: var(--color-white); } button { padding-left: var(--margin-sm); padding-right: var(--margin-sm); } button:hover, button:active { background-color: var(--color-dark-secondary); } #end > * + * { margin-left: var(--margin-lg); } .tray { background-color: var(--color-dark-secondary); } .sysinfo > * + * { margin-left: var(--margin-sm); } .sysinfo .item { margin-left: 5px; margin-right: 5px; } .sysinfo, .battery, .bluetooth, .network_manager, .volume, .music { background-color: var(--color-dark-secondary); } .network_manager .icon { margin-left: 5px; margin-right: 5px; } .clock { font-weight: bold; background-color: var(--color-dark-secondary); } .popup-clock label, .tray .menu label, .popup-volume label, .launcher label, .launcher picture { transform: skewX(0deg); } .popup-clock .calendar-clock { font-size: 2.0em; } .popup-clock .calendar .today { background-color: var(--color-active); } .workspaces .item { font-weight: bold; margin-left: 5px; padding-left: 7px; padding-right: 7px; background-color: var(--color-dark-secondary); } .workspaces .item:hover { background-color: var(--color-hovered); } .workspaces .item.focused { background-color: var(--color-selected); } .workspaces .item.urgent { background-color: var(--color-urgent); } .launcher .item label { padding-left: 5px; /*font-size: 0px;*/ } .launcher .item.focused label { /*font-size: 14px;*/ } .launcher .item { margin-left: 3px; background-color: var(--color-dark-secondary); } .launcher .item.focused { background-color: var(--color-selected); } .popup-launcher .popup-item { transform: skewX(-10deg); } .popup-bluetooth { transform: skewX(0deg); } .popup-bluetooth .devices .box .device { margin: 7px 7px 0 7px; } .popup-bluetooth .header, .popup-bluetooth .devices .box { transform: skewX(-10deg); margin: 7px 7px 0 7px; } .notifications .button { padding-left: 10px; padding-right: 10px; background-color: var(--color-dark-secondary); margin-right: 5px; } .notifications .count { margin-right: 3px; } .popup-music .album-art { transform: skewX(0deg); } .popup-music .label { transform: skewX(0deg); } ``` </details> **Additional context** Despite my best efforts, I was unable to rotate the text myself without adverse results (note to self: `transform: rotate(90deg)` does *not* also affect its bounding box) As an aside, disabling labels leaves gaps where the labels would have been. **Screenshots** <img width="1163" height="1079" alt="Image" src="https://github.com/user-attachments/assets/f9eaceac-54bf-4935-a09b-9aa48a421a46" />
Author
Owner

@JakeStanger commented on GitHub (Mar 28, 2026):

GTK4 removed angle/rotation properties, so at the moment transform: rotate(90deg) is the best option if you want text.

I'll leave this open as there's a potential route forward with custom widgets and overriding some of the bounding box behaviours, but I don't know how feasible that is currently.

<!-- gh-comment-id:4148187395 --> @JakeStanger commented on GitHub (Mar 28, 2026): GTK4 removed angle/rotation properties, so at the moment `transform: rotate(90deg)` is the best option if you want text. I'll leave this open as there's a potential route forward with custom widgets and overriding some of the bounding box behaviours, but I don't know how feasible that is currently.
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#6048
No description provided.