Files
dotfiles/dotfiles/config/taffybar/taffybar.css
Ivan Malison 24fe3fbb6b taffybar: add comments explaining recent CSS additions
Document the @import url() requirement, per-widget color variables,
workspace label positioning via padding (not margin, which GTK
overlays ignore), asymmetric workspace padding, active workspace
outline targeting, and bar border-radius.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-07 20:49:32 -08:00

460 lines
12 KiB
CSS

/* Widget/layout styling for taffybar.
*
* Colors live in `theme.css` (loaded via `palette.css`).
* IMPORTANT: use `@import url("...")` — bare `import` is silently ignored
* by GTK's CSS parser.
*/
@import url("theme.css");
.taffy-window * {
/* Most text should come from Iosevka Aile; icon glyphs (Font Awesome / Nerd
Font PUA) should come from a Nerd Font family to avoid tiny fallback glyphs. */
font-family: "Iosevka Aile", "Iosevka Nerd Font", "Iosevka NF", "Noto Sans", sans-serif;
font-size: 9pt;
font-weight: 600;
color: @font-color;
/* Bar background is painted on `.taffy-box`; most widget nodes stay
transparent so pills (outer-pad) read as "solid". */
background-color: transparent;
text-shadow: none;
}
/* The main bar container. border-radius matches the widget squircles (6px)
so the bar itself has softly rounded corners. */
.taffy-box {
border-width: 0px;
padding: 0px;
margin: 0px;
border-radius: 6px;
box-shadow: none;
background-color: @bar-background;
background-image: none;
}
/* Each widget is wrapped in outer-pad > inner-pad > contents by
buildContentsBox (Haskell). The outer-pad draws the squircle
background pill. border-radius kept low (6px) for a more squared
"squircle" shape rather than a fully rounded pill. */
.outer-pad {
background-color: @pill-background;
border: 0px;
border-radius: 6px;
margin: 4px 6px;
/* No white outline; define shape with subtle inner highlight + dark stroke. */
box-shadow:
inset 0 1px 0 @pill-highlight,
inset 0 0 0 1px @pill-border,
0 10px 24px @pill-shadow;
}
.inner-pad {
padding: 2px 10px;
border-radius: 4px;
}
.contents {
padding: 0px;
transition: background-color .2s;
opacity: 1;
}
/* Make each widget's squircle background feel "solid": avoid GTK nodes and
labels painting their own backgrounds on top of `.outer-pad`. */
.outer-pad *,
.inner-pad,
.inner-pad *,
.contents,
.contents * {
background-color: transparent;
}
/* Per-widget colored squircle overrides.
decorateWithClassAndBox "name" (in taffybar.hs) adds the widget class to
the same element that has .outer-pad, so `.outer-pad.audio` etc. target
each widget's pill. Colors come from @widget-*-bg/fg/border in theme.css. */
.outer-pad.audio {
background-color: @widget-audio-bg;
border-color: @widget-audio-border;
box-shadow: 0 1px 0 rgba(255, 255, 255, 0.06), 0 10px 24px rgba(0, 0, 0, 0.30);
}
.outer-pad.audio * {
color: @widget-audio-fg;
}
.outer-pad.network {
background-color: @widget-network-bg;
border-color: @widget-network-border;
box-shadow: 0 1px 0 rgba(255, 255, 255, 0.06), 0 10px 24px rgba(0, 0, 0, 0.30);
}
.outer-pad.network * {
color: @widget-network-fg;
}
.outer-pad.mpris {
background-color: @widget-mpris-bg;
border-color: @widget-mpris-border;
box-shadow: 0 1px 0 rgba(255, 255, 255, 0.06), 0 10px 24px rgba(0, 0, 0, 0.30);
}
.outer-pad.mpris * {
color: @widget-mpris-fg;
}
.outer-pad.clock {
background-color: @widget-clock-bg;
border-color: @widget-clock-border;
box-shadow: 0 1px 0 rgba(255, 255, 255, 0.06), 0 10px 24px rgba(0, 0, 0, 0.30);
}
.outer-pad.clock * {
color: @widget-clock-fg;
}
.outer-pad.disk-usage {
background-color: @widget-disk-bg;
border-color: @widget-disk-border;
box-shadow: 0 1px 0 rgba(255, 255, 255, 0.06), 0 10px 24px rgba(0, 0, 0, 0.30);
}
.outer-pad.disk-usage * {
color: @widget-disk-fg;
}
.outer-pad.sni-tray {
background-color: @widget-tray-bg;
border-color: @widget-tray-border;
box-shadow: 0 1px 0 rgba(255, 255, 255, 0.06), 0 10px 24px rgba(0, 0, 0, 0.30);
}
.outer-pad.sni-tray * {
color: @widget-tray-fg;
}
.outer-pad.battery-icon,
.outer-pad.battery-text {
background-color: @widget-battery-bg;
border-color: @widget-battery-border;
box-shadow: 0 1px 0 rgba(255, 255, 255, 0.06), 0 10px 24px rgba(0, 0, 0, 0.30);
}
.outer-pad.battery-icon *,
.outer-pad.battery-text * {
color: @widget-battery-fg;
}
.outer-pad.backlight {
background-color: @widget-backlight-bg;
border-color: @widget-backlight-border;
box-shadow: 0 1px 0 rgba(255, 255, 255, 0.06), 0 10px 24px rgba(0, 0, 0, 0.30);
}
.outer-pad.backlight * {
color: @widget-backlight-fg;
}
/* Workspaces styling */
/* Asymmetric padding: 10px left leaves room for the overlaid workspace number
label; 3px right keeps the pill tight against the trailing icon edge. */
.workspaces .inner-pad {
box-shadow: none;
border-width: 0;
padding: 2px 3px 2px 10px;
}
.workspaces .contents {
box-shadow: none;
border-radius: 5px;
border-width: 0px;
border-style: solid;
border-color: @transparent;
padding: 0px 4px;
}
.workspace-label {
/* Overlay label (workspace number) that sits inside the icon "squircle". */
padding: 1px 3px;
margin: 0px;
font-size: 10pt;
opacity: 0.92;
font-weight: 700;
transition: color .2s;
background-color: @transparent;
}
/* The workspace label is overlaid bottom-left over the workspace icon strip.
Positioning: halign=start (left), valign=end (bottom) set in Haskell code.
Margins offset from that anchor point. */
.workspaces .overlay-box {
transition: background-color .2s, border-color .2s;
background-color: transparent;
border: none;
margin: 0px;
padding: 0px;
}
/* Position the workspace number inside the squircle pill. GTK overlays ignore
CSS margin for child positioning, so we use padding on the label itself:
padding-bottom pushes the text up from the bottom edge, padding-left pushes
it inward from the left corner to clear the border-radius. */
.workspaces .overlay-box .workspace-label {
background-color: transparent;
border: none;
padding: 2px 5px 5px 12px;
color: rgba(255, 255, 255, 0.92);
}
/* White inset outline on the active workspace's squircle pill.
.active is set on the GtkOverlay (by setWorkspaceWidgetStatusClass in
Haskell), and .outer-pad is a child of that overlay, so
`.workspaces .active .outer-pad` correctly targets the pill. */
.workspaces .active .outer-pad {
box-shadow:
inset 0 0 0 2px rgba(255, 255, 255, 0.75),
inset 0 1px 0 @pill-highlight,
0 10px 24px @pill-shadow;
}
.workspaces .active .overlay-box {
background-color: transparent;
border-color: transparent;
}
.contents .window-icon {
border-width: 3px;
}
.active .contents .window-icon {
opacity: 1;
}
.active .contents {
background-color: rgba(255, 255, 255, 0.10);
opacity: 1;
}
/* (Handled above for workspaces.) */
.visible .contents {
background-color: rgba(255, 255, 255, 0.06);
}
.workspaces .window-icon-container,
.workspaces .window-icon-container.active {
/* Don't give each window icon its own background/border; the workspace
squircle is the background. */
background-color: transparent;
border: 0px;
box-shadow: none;
padding: 0px 2px;
}
.workspaces .active .contents,
.workspaces .visible .contents {
background-color: transparent;
}
.workspaces .window-icon {
border-width: 0px;
}
.window-icon-container {
transition: opacity .2s, box-shadow .2s;
opacity: 1;
border-radius: 5px;
transition: background-color .2s;
background-color: rgba(255, 255, 255, 0.04);
padding: 1px 4px;
border: 1px solid rgba(255, 255, 255, 0.08);
}
/* This gives space for the box-shadow (they look like underlines) that follow.
This will actually affect all widgets, (not just the workspace icons), but
that is what we want since we want the icons to look the same. */
.auto-size-image, .sni-tray {
padding: 1px 4px;
}
/* If the SNI tray is wrapped in our standard widget box, avoid double-padding. */
.sni-tray .sni-tray {
padding: 0px;
}
.window-icon-container.active {
background-color: rgba(255, 255, 255, 0.13);
border-color: rgba(255, 255, 255, 0.16);
}
.window-icon-container.urgent {
}
.window-icon-container.minimized .window-icon {
opacity: .3;
}
.window-icon {
opacity: 1;
transition: opacity .5s;
}
/* Button styling */
.taffy-window button {
all: initial;
background-color: @transparent;
border-width: 0px;
border-radius: 0px;
}
.taffy-window button:checked, .taffy-window button:hover .Contents:hover {
box-shadow: inset 0 -2px @accent;
background-color: rgba(255, 255, 255, 0.06);
}
/* Menu styling */
/* The ".taffy-window" prefixed selectors are needed because if they aren't present,
the top level .Taffybar selector takes precedence */
.taffy-window menuitem *, menuitem * {
color: @menu-font-color;
text-shadow: none;
}
/* Force an opaque background for menus, regardless of the system GTK theme. */
.taffy-window menu, menu,
.taffy-window menu.background, menu.background,
.taffy-window .menu, .menu,
.taffy-window .menu.background, .menu.background,
GtkMenu, GtkMenu.background {
background-color: @menu-background-color;
background-image: none;
border: 1px solid rgba(0, 0, 0, 0.20);
padding: 4px 0px;
}
/* GTK menus often have a dedicated background node under the menu. */
menu > background,
menu > .background,
GtkMenu > background,
GtkMenu > .background,
.menu > background,
.menu > .background {
background-color: @menu-background-color;
background-image: none;
}
.taffy-window menu, menu {
background-color: @menu-background-color;
background-image: none;
}
/* Some themes apply transparency to the menu's toplevel popup window. */
window.popup, window.popup.background,
window.menu, window.menu.background,
.menu, .menu.background {
background-color: @menu-background-color;
background-image: none;
}
window.popup > background,
window.popup > .background,
window.menu > background,
window.menu > .background {
background-color: @menu-background-color;
background-image: none;
}
window.popup *, window.menu * {
background-color: @menu-background-color;
background-image: none;
}
window.popup decoration, window.menu decoration {
background-color: @menu-background-color;
background-image: none;
}
.taffy-window menuitem, menuitem {
background-color: @menu-background-color;
}
/* Higher-specificity rules to beat theme defaults like `menu menuitem { background: transparent; }`. */
menu menuitem, GtkMenu menuitem, .menu menuitem {
background-color: @menu-background-color;
}
.taffy-window menuitem:hover, menuitem:hover {
background-color: @menu-highlight;
}
menu menuitem:hover, GtkMenu menuitem:hover, .menu menuitem:hover {
background-color: @menu-highlight;
}
window.popup menuitem:hover *, window.menu menuitem:hover * {
background-color: @menu-highlight;
}
/* Last-resort: some menu implementations keep child nodes transparent, so paint
the whole subtree. This is scoped to menu/popover widgets to avoid affecting
the bar itself. */
menu *, GtkMenu *, .menu * {
background-color: @menu-background-color;
background-image: none;
}
menu menuitem:hover *, GtkMenu menuitem:hover *, .menu menuitem:hover * {
background-color: @menu-highlight;
}
.taffy-window menuitem:hover > label, menuitem:hover > label {
color: @menu-font-color;
}
/* Some menus (notably a few StatusNotifierItem menus) are rendered as popovers
containing modelbuttons instead of menuitems. */
popover, popover.background, popover > contents {
background-color: @menu-background-color;
background-image: none;
border: 1px solid rgba(0, 0, 0, 0.20);
}
popover > background,
popover > .background,
popover > box,
popover > contents > box,
popover > contents > * {
background-color: @menu-background-color;
background-image: none;
}
popover modelbutton, popover modelbutton * {
background-color: @menu-background-color;
color: @menu-font-color;
text-shadow: none;
}
popover modelbutton:hover {
background-color: @menu-highlight;
}
popover modelbutton:hover > label {
color: @menu-font-color;
}
popover * {
background-color: @menu-background-color;
background-image: none;
}
popover modelbutton:hover * {
background-color: @menu-highlight;
}
.clock label,
.mpris label,
.battery-text label {
letter-spacing: 0.2px;
}
r.mpris label {
color: @font-muted;
}