experimental web port of the Union style engine + adapters
styling theming css solidjs react union kde
union-web docs core.md
6.2 kB · 134 lines
Markdown
at main

@union-web/core #

Core package providing CSS parsing, selector matching, property resolution, and color scheme resolution. This is the TypeScript port of Union's C++ core.

Native Union Parity #

See the official Union documentation at https://api.kde.org/union-index.html for detailed descriptions of Union's C++ API.

Native Union (C++) Union Web (TypeScript) Status
Union::StyleRule StyleRule interface (selectors + declarations) Full
Union::Element Element interface + createElement(role, opts) Full
Union::Selector Selector interface + AST atoms (SelectorAtom) Full
Union::ElementQuery matchRules() / resolveElement() functions Full
Union::Properties::Layout LayoutPropertyGroup Full
Union::Properties::Text TextPropertyGroup Full
Union::Properties::Icon IconPropertyGroup Full
Union::Properties::Background BackgroundPropertyGroup Full
Union::Properties::Border BorderPropertyGroup Full
Union::Properties::Outline OutlinePropertyGroup Full
Union::Properties::Shadow ShadowPropertyGroup Full
CSS input plugin parseCss() / parseStylesheet() Full
Input plugin system Single CSS input — no plugin architecture Partial
Output plugin system styleGroupToUnionStyleProps() → UnionStyleProps (typed semantic model). styleGroupToCss() moved to @union-web/react-plugin. Partial
KColorScheme KColorSchemeResolver (JS port of KDE's KColorScheme) Full
KColorUtils Color class + mix, shade, lighten, darken, tint functions Full
Variable resolution VariableResolver (resolves var(), custom-color(), modify-color(), mix()) Full
INI parsing for .colors parseIni() Full
Platform plugin system Not implemented — .colors + CSS is the only input path None
@property syntax in CSS Not implemented None

Key Differences from Native Union #

  • No class hierarchy. Union's C++ property classes are replaced by plain TypeScript interfaces (StylePropertyGroup with optional group keys).
  • No C++ input plugin system. The only input format is the custom CSS DSL — there is no Plasma SVG input equivalent.
  • No @property syntax. Native Union supports @property for declaring custom properties with type syntax; Union Web does not.
  • Selector matching uses the same semantics (type, id, state, hint, attribute, child/descendant combinators with specificity), implemented as pure functions rather than a query class.
  • Pseudo-element selectors (::name) are parsed and accepted by the matching engine (treated as no-ops — they always match), but are not used in any Union theme. This is a slight divergence by union-web, that is not present in native Union's CSS input.
  • Combinator limitation — only child (>) and descendant ( ) combinators are supported. Adjacent sibling (+) and general sibling (~) are treated as descendant combinators (potentially bad).

API Reference #

CSS Parsing #

parseCss(css: string, sourceName?: string): ParseResult
parseStylesheet(filePath: string, fileLoader?): ParseResult
parseStylesheetFromString(css: string, baseDir, sourceName?, fileLoader?): ParseResult

ParseResult contains rules: StyleRule[], variables: Record<string, string>, and errors: string[].

Elements #

interface Element {
  type: string;
  ids: string[];
  states: string[];
  hints: string[];
  attributes: Record<string, string>;
  children: Element[];
}

function createElement(type: string, opts?): Element

Rule Matching #

function matchRules(rules: StyleRule[], element: Element, ancestors?: Element[]): MatchResult[]
function resolveElement(rules: StyleRule[], element: Element, ancestors?: Element[]): StylePropertyGroup

Color #

class Color { ... }
function mix(a: Color, b: Color, bias: number): Color
function shade(color: Color, amount: number, chromaPreservation: number): Color
function tint(color: Color, amount: number): Color
function lighten(color: Color, amount: number, chromaPreservation?: number): Color
function darken(color: Color, amount: number, chromaPreservation?: number): Color
function luma(color: Color): number

KColorSchemeResolver #

class KColorSchemeResolver { ... }

Port of KDE's KColorScheme. Resolves color roles from .colors INI data across all color sets (Window, Button, View, Header, Tooltip, Selection, Complementary), groups (Active, Inactive, Disabled), and role types (Background, Foreground, Decoration).

VariableResolver #

class VariableResolver { ... }

Resolves CSS value expressions. Supports:

  • var(--name) with fallback
  • custom-color("kcolorscheme", "<group>", "<colorSet>", "<roleType>", "<role>")
  • modify-color(<colorExpr>, <operation> <value>) where operations are set-alpha, shade, lighten, darken, tint
  • mix(<colorA>, <colorB>, <weight>)

Style Output #

UnionStyleProps + styleGroupToUnionStyleProps() (typed, preserves Union's semantic property model) is the current approach. Lives in this package.

styleGroupToCss() (flattened CSS declarations) was moved to @union-web/react-plugin. It is no longer exported from core.

function styleGroupToUnionStyleProps(sg: StylePropertyGroup): UnionStyleProps
function generateCssVariables(resolver: KColorSchemeResolver): CssDeclaration[]
function formatCss(declarations: CssDeclaration[]): string

Property Groups #

StylePropertyGroup {
  layout?:     LayoutPropertyGroup   (width, height, spacing, padding, inset, margin, alignment)
  text?:       TextPropertyGroup     (color, font-size, font-weight, font-family, alignment, wrap, elide)
  icon?:       IconPropertyGroup     (name, source, width, height, color, alignment)
  background?: BackgroundPropertyGroup (color, image)
  border?:     BorderPropertyGroup   (per-side width/color/style, radius)
  outline?:    OutlinePropertyGroup  (per-side size/color/style, simulated via box-shadow)
  shadow?:     ShadowPropertyGroup   (offset, blur, spread, color)
}