experimental web port of the Union style engine + adapters
styling theming css solidjs react union kde
0

Configure Feed

Select the types of activity you want to include in your feed.

union-web / docs / upstream-architecture.md
5.5 kB

Union Upstream Architecture#

Union is a theming engine (not a UI framework). It provides a CSS-based styling system for Qt Quick Controls 2 and Kirigami. This document describes the native C++ architecture to clarify what Union Web must replicate.

Processing Pipeline#

CSS files (.css)
      ↓
  StyleRule[] + Variables
      ↓
  QuickStyle (attached QML property) — queries StylePropertyGroup for a QQuickItem
      ↓
  Output Plugin (QtQuick):
      ├── PositionerLayout  — reads layout/icon/text alignment, positions children
      └── StyledRectangle   — reads background/border/outline/shadow, renders visuals

The CSS-to-property pipeline is shared; two independent output systems consume different subsets of each StylePropertyGroup.

PositionerLayout#

A micro-layout engine that positions a control's internal children (icon, text, indicator). Not a page-level layout system.

  • Scope: Every control's Union.Positioner.positionItems — always internal children like [contentItem, indicator], never sibling controls.
  • Control-to-control layout is done by Qt Quick Layouts (RowLayout, ColumnLayout) or anchoring, never by Positioner.
  • Computes: x/y positions within the control's bounds, then calls item->setX()/setY()/setSize() on child QQuickItems.
  • Alignment source: Each positioned item reads from one of three CSS property groups based on its PositionedItem.source:
Source CSS property group
Layout layout.alignment
Icon icon.alignment
Text text.alignment

Three containers (coordinate reference frames)#

Layout {
    itemContainer:           // full parent box
        ├── start bucket
        ├── center bucket
        ├── end bucket
        └── fill bucket
    backgroundContainer:     // parent minus start/end, offset by inset
    contentContainer:        // parent minus start/end, offset by padding
}

These are math rectangles, not visual elements. They exist only during Layout::layout() computation and are discarded after item positions are computed.

StyledRectangle#

A C++ QQuickItem that renders visual chrome via QSG (Qt Scene Graph) nodes.

  • Scope: Used as background: on every control (64 QML files in the theme).
  • Consumes: background.*, border.*, outline.*, shadow.*, corner_radius.*, width, height, min-width, min-height.
  • Positioning: Automatically sized to fill the control by QQuickControl's base class.
  • Never in Positioner: StyledRectangle is never in any positionItems.

StyledRectangle-only controls (e.g., ApplicationWindow, Page) have no Positioner — they render visual chrome only, with child layout delegated to Qt Quick Layouts.

Three-Layer Control Architecture#

Every visual control has the same internal structure (Button example):

Button (QQuickAbstractButton)
│
├── background: StyledRectangle     ← visual chrome (border, fill, shadow)
│   [NOT in Positioner]
│
├── contentItem: DefaultContentItem ← semantic content container
│   [IN Positioner.positionItems[0]; positionChildren: true]
│   │
│   ├── Icon (source: Icon)         ← positioned via icon.alignment
│   └── Text (source: Text)         ← positioned via text.alignment
│
└── indicator: Union.Icon           ← optional visual indicator
    [IN Positioner.positionItems[1]; source: Layout]
    [positioned via layout.alignment]
Layer QML property Managed by CSS group
Background background: QQuickControl (fills control) background.*, border.*, outline.*, shadow.*
Content container contentItem: Positioner (via positionChildren: true) N/A (pass-through)
Icon child of contentItem Positioner (source: Icon) icon.alignment
Text child of contentItem Positioner (source: Text) text.alignment
Indicator indicator: Positioner (source: Layout) layout.alignment

Background Naming Collision#

Two unrelated concepts share the name "background":

  • Layout::backgroundContainer — a math rectangle in Positioner's layout computation. Child items with layout-alignment-container: background are positioned relative to this inset-offset frame. Nothing renders here.
  • control.background — a visual StyledRectangle QQuickItem that renders the control's background, border, outline, and shadow. It is never in any positionItems.

Key Takeaways for Web Ports#

  • Positioner is irrelevant for page-level layouts. Union Web positions controls using CSS flexbox/grid. The Positioner engine is only needed for internal control child layout (icon + text + indicator).
  • layout-alignment on standalone controls like buttons is effectively dead code — controls are positioned by Qt Quick Layouts, not a parent Positioner.
  • StyledRectangle is the visual heart of every control. Without it, controls have no background, border, shadow, or outline.
  • Positioner's three-container model can collapse to a single content container for web ports, since itemContainer and backgroundContainer are math frames that don't correspond to visual layers.
  • The element YAML files at tools/elementdocgenerator/*.yml define every Union element's states, hints, attributes, and sub-elements — they are the definitive reference.