Skip to main content
Version: 0.0.6

Layout Reference

The layout.xml file defines which widgets appear in notifications and how they're arranged. This gives you complete control over notification structure without writing CSS.

File Location

Layout files can be placed in:

~/.config/histui/themes/mytheme/
├── layout.xml # Custom layout
├── theme.css # CSS styling
└── manifest.toml # Metadata

If a theme doesn't include layout.xml, the default layout is used automatically.

Basic Structure

Every layout starts with a <popup> root element:

<popup min-width="250" max-width="400" min-height="0" max-height="600">
<!-- Child elements here -->
</popup>

The <popup> element accepts sizing constraints:

AttributeTypeDefaultDescription
min-widthint300Minimum popup width in pixels
max-widthint450Maximum popup width in pixels
min-heightint0Minimum popup height in pixels
max-heightint900Maximum popup height in pixels

Values can be specified with or without px suffix:

<popup min-width="300" max-width="400px">

Sizing Behavior

  • Dynamic width: Set different min/max values for content-responsive width
  • Fixed width: Set min-width = max-width for a fixed size
  • Dynamic height: Use min-height="0" to let content determine height
  • Scrolling: Content exceeding max-height becomes scrollable

Available Elements

Content Elements

These elements display notification content:

ElementDescriptionCSS Class
<summary />Notification title.notification-summary
<body />Notification message body.notification-body
<appname />Application name.notification-appname
<timestamp />Time since notification.notification-timestamp
<icon />Application icon (with symbol font fallback).notification-icon
<image />Notification image attachment.notification-image
<progress />Progress bar (if hint provided).notification-progress
<actions />Action buttons.notification-actions
<stack-count />Badge showing stacked notification count.notification-stack-count

Stack Count Attributes

<stack-count />
<stack-count format="dots" />
<stack-count format="dots" overlay="top-right" />
AttributeTypeDefaultDescription
formatstringnumberDisplay format: number (shows count) or dots (shows one dot per stacked item)
overlaystring(none)Float over other elements at specified position (see Overlay Positioning)

Format Options:

  • number (default) - Displays "2", "3", etc. as a badge
  • dots - Displays one bullet point (•) per additional notification in the stack

The dots format is useful for minimal themes where you want a subtle visual indicator without numeric display.

Overlay Positioning

Elements inside <header> can be positioned as floating overlays using the overlay or underlay attributes. This allows elements to float over (or under) other content without affecting layout flow.

<header>
<summary />
<stack-count format="dots" overlay="top-right" />
</header>
AttributeTypeValuesDescription
overlaystringtop-right, top-left, bottom-right, bottom-leftFloat above other elements at specified corner
underlaystringtop-right, top-left, bottom-right, bottom-leftFloat below other elements at specified corner

Position Values:

  • top-right - Upper right corner (default if not specified)
  • top-left - Upper left corner
  • bottom-right - Lower right corner
  • bottom-left - Lower left corner

CSS Positioning:

Overlay elements use GTK alignment for base positioning. Use negative margins in CSS to fine-tune placement outside the header bounds:

.notification-stack-count {
/* Float outside the header boundary */
margin-top: -8px;
margin-right: -6px;
}

Use Cases:

  • Corner badges that don't push other elements
  • Floating indicators
  • Decorative elements that shouldn't affect layout

Container Elements

These elements group other elements:

ElementDescriptionCSS Class
<header>Horizontal container for header elements.notification-header
<box>Generic container with configurable orientation(none)

Element Attributes

Icon Attributes

<icon size="48" />
AttributeTypeDefaultDescription
sizeint48Icon size in pixels

The icon element displays:

  1. Application-provided icon (if available)
  2. GTK icon theme icon (if app name matches)
  3. Symbol font glyph (fallback, styled with .notification-icon-symbol)

Image Element

<image />

The <image /> element displays notification images from image-data or image-path hints. It has special sizing and cropping behavior:

Sizing Rules:

  1. Images scale down to fit the popup width (minus padding)
  2. Images never scale up beyond their original size
  3. Tall images are cropped to max 150px height, showing the top portion
  4. Cropped images display a fade gradient at the bottom to indicate truncation

Omitting Images:

To create a compact layout that never displays images, simply omit the <image /> element:

<!-- Minimal layout - no images -->
<popup min-width="150" max-width="250">
<summary />
<body />
</popup>

This is useful for text-focused themes like minimal and compact.

CSS Classes:

ClassDescription
.notification-imageThe image itself
.notification-image-containerWrapper for cropped images
.notification-image-container.croppedAdded when image is cropped
.notification-image-fadeGradient overlay on cropped images

Default Action Indicator (CSS-based)

When a notification includes a "default" action key (a D-Bus notification spec feature), clicking the notification body triggers that action instead of dismissing it. This is common for notifications from terminal emulators (kitty, alacritty) or messaging apps where clicking should focus the window or open a conversation.

CSS Classes:

The popup container automatically receives these classes when a default action exists:

  • .has-default-action - Notification has a "default" action key
  • .is-clickable - Semantic alias (same as above)

Styling the Indicator:

The default themes use a right-hand inset shadow effect from effects.css:

.notification-popup.has-default-action {
/* Customize the indicator color (optional) */
--indicator-color: alpha(@accent_bg_color, 0.35);

/* Inset shadow on right side */
box-shadow:
0 4px 12px alpha(black, 0.15),
inset -20px 0 16px -12px var(--indicator-color);
}

The --indicator-color variable defaults to alpha(@accent_bg_color, 0.35) in effects.css. Override it in your theme to use a different color (e.g., catppuccin themes use mauve).

See CSS Reference for more styling examples.

Box Attributes

<box orientation="vertical">
<summary />
<appname />
</box>
AttributeTypeDefaultDescription
orientationstringhorizontalLayout direction: vertical or horizontal

Element Order

Element order in the XML determines visual order in the notification.

For horizontal containers (like <header>), elements appear left-to-right in the order they're listed:

<!-- Icon on left, text in middle, stack-count on right -->
<header>
<icon size="48" />
<summary />
<stack-count />
</header>

<!-- Icon on right -->
<header>
<summary />
<stack-count />
<icon size="24" />
</header>

For vertical containers, elements appear top-to-bottom.

Layout Examples

Default Layout

The standard layout with icon, summary, app name, body, and actions:

<popup min-width="250" max-width="400" min-height="0" max-height="600">
<header>
<icon size="48" />
<box orientation="vertical">
<summary />
<appname />
</box>
<stack-count />
</header>
<body />
<progress />
<image />
<actions />
</popup>

Minimal Layout

Text-only notifications with floating dot indicators for stacked notifications:

<popup min-width="150" max-width="250" min-height="0" max-height="200">
<header>
<summary />
<stack-count format="dots" overlay="top-right" />
</header>
<body />
<progress />
</popup>

The overlay="top-right" attribute positions the dots as a floating overlay that doesn't affect the header layout. Use negative margins in CSS to position the dots at the popup edge.

Compact Layout

Smaller icon, right-aligned, with floating dot indicators:

<popup min-width="180" max-width="280" min-height="0" max-height="300">
<header>
<summary />
<stack-count format="dots" overlay="top-right" />
<icon size="24" />
</header>
<body />
<progress />
<actions />
</popup>

Detailed Layout

Full layout with timestamp:

<popup min-width="250" max-width="450" min-height="0" max-height="700">
<header>
<icon size="48" />
<box orientation="vertical">
<summary />
<box orientation="horizontal">
<appname />
<timestamp />
</box>
</box>
<stack-count />
</header>
<body />
<progress />
<image />
<actions />
</popup>

Media-Focused Layout

Large image area, minimal text:

<popup min-width="300" max-width="400" min-height="0" max-height="500">
<image />
<header>
<icon size="32" />
<summary />
</header>
<body />
<actions />
</popup>

Chat-Style Layout

Optimized for messaging apps:

<popup min-width="280" max-width="380" min-height="0" max-height="400">
<header>
<icon size="40" />
<box orientation="vertical">
<appname />
<summary />
</box>
<timestamp />
</header>
<body />
<image />
<actions />
</popup>

Conditional Display

Elements are automatically hidden when their content is empty:

  • <body /> - Hidden if notification has no body text
  • <progress /> - Hidden if no progress hint is set
  • <image /> - Hidden if no image is attached
  • <actions /> - Hidden if no visible action buttons (excludes "default" action and empty labels)
  • <stack-count /> - Hidden if notification isn't stacked
  • <timestamp /> - Always displays relative time ("2m ago")

You don't need to handle these cases in your layout.

Note: The default action indicator is now CSS-based. The .has-default-action class is automatically added to the popup when a notification has a default action. See Default Action Indicator for styling details.

Nesting Elements

Elements can be nested in containers for complex layouts:

<header>
<icon size="48" />
<box orientation="vertical">
<summary />
<box orientation="horizontal">
<appname />
<timestamp />
</box>
</box>
<stack-count />
</header>

This creates:

[icon] | [summary          ] | [stack-count]
| [appname] [time ] |

Layout and CSS Interaction

The layout defines structure; CSS defines appearance. They work together:

Layout (what elements exist and where):

<header>
<summary />
<icon size="24" /> <!-- Icon after summary = visually on right -->
</header>

CSS (how elements look):

/* Right-aligned icon needs left margin, not right */
.notification-icon {
margin-left: 8px;
margin-right: 0;
}

Default Fallback

If your theme doesn't include layout.xml, histuid uses this default:

<popup min-width="300" max-width="450" min-height="0" max-height="900">
<header>
<icon size="48" />
<box orientation="vertical">
<summary />
<appname />
</box>
<stack-count />
</header>
<body />
<progress />
<image />
<actions />
</popup>

Validation

histuid validates layout XML at load time. Invalid elements produce an error:

unknown element type: invalid-element

Only elements listed in Available Elements are valid.

Tips

  1. Start with a bundled layout - Copy from an embedded theme and modify
  2. Test with different content - Long titles, multi-line bodies, images, actions
  3. Consider urgency - Critical notifications may need different emphasis
  4. Icon size affects layout - Larger icons need more header height
  5. Use timestamps sparingly - They add visual noise

See Also