The IComponent Interface

Every Tesserae component implements one interface, IComponent:

namespace Tesserae
{
    public interface IComponent
    {
        HTMLElement Render();
    }
}

Render() returns the component's root DOM element. A parent container calls it to splice the component into the page, and the mount helpers (MountToBody, MountCenteredToBody) call it for the top-level component.

Most of the fluent API you call on components — .WS(), .Margin(8), .Tooltip(...), .Class(...), .Bind(...) — is not defined on each individual component. These are generic extension methods on IComponent:

public static T Width<T>(this T component, UnitSize unitSize) where T : IComponent

Because they are generic over T, they return the concrete component type, so calls chain without losing type information. Bring them into scope with:

using static Tesserae.UI;

A handful of helpers (.Validation, .Error, .SetText…) are constrained to narrower interfaces such as ICanValidate or ITextFormating, so they only appear on components that support them.

When the styles are applied

Sizing, spacing, and placement helpers tag the element with marker attributes. When the component is added to a container, the container wraps it in an item <div> and transfers those styles onto the wrapper — the wrap-and-transfer protocol. Call the helpers before adding the component to its parent. If a sizing helper "doesn't work", inspect the DOM: the style usually landed on the tss-stack-item wrapper rather than the element you called it on. See Layout & Alignment for the details.

Sizing

Method Effect
.Width(UnitSize) / .W(...) fixed width
.Height(UnitSize) / .H(...) fixed height
.MinWidth / .MaxWidth / .MinHeight / .MaxHeight bounds
.WidthAuto() / .HeightAuto() width / height: auto
.WidthStretch() / .WS() width: 100%
.HeightStretch() / .HS() height: 100%
.MinHeightStretch() min-height: 100%
.Stretch() / .S() both width and height to 100%
.Grow(int = 1) flex-grow (inside a Stack)
.Shrink() / .NoShrink() flex-shrink 1 / 0

UnitSize values come from numeric helpers — 100.px(), 50.percent(), 1.em(), 2.fr(). See Styling.

Spacing

.Margin(UnitSize), .MarginLeft, .MarginRight, .MarginTop, .MarginBottom — with shorthands .M(), .ML(), .MR(), .MT(), .MB(). The same set exists for padding: .Padding(...), .PaddingLeft…, and .P(), .PL(), .PR(), .PT(), .PB().

Alignment and grid placement

  • Cross-axis self-alignment: .AlignAuto(), .AlignStretch(), .AlignBaseline(), .AlignStart(), .AlignCenter(), .AlignEnd().
  • Main-axis self-alignment: .JustifyStart(), .JustifyCenter(), .JustifyEnd().
  • Grid placement: .GridColumn(start, end), .GridColumnStretch(), .GridRow(start, end), .GridRowStretch() — call before .Add.

Visibility and animation

.Show(), .Collapse(), .Fade() (also .Fade(Action) and .Fade(Func<Task>)), .LightFade(), .FadeThenCollapse().

Text formatting

For text-bearing components (TextBlock, Button, Label, …):

  • Size: .Tiny(), .XSmall(), .Small(), .SmallPlus(), .Medium(), .MediumPlus(), .Large(), .XLarge(), .XXLarge(), .Mega().
  • Weight: .Regular(), .SemiBold(), .Bold().
  • Alignment: .TextLeft(), .TextCenter(), .TextRight().
  • Explicit: .SetTextSize(...), .SetTextWeight(...), .SetTextAlign(...), .SetCanWrap(bool).

Styling

  • .Class(string) / .RemoveClass(string) — add or remove a CSS class.
  • .Style(Action<CSSStyleDeclaration>) — set inline CSS, e.g. .Style(s => s.color = "red").
  • .Background(...), .Foreground(...), .Rounded(...).
  • .Id(string) — set the element id.

See Styling and Custom Styles.

Tooltips

.Tooltip("Plain or <b>HTML</b> text", placement: TooltipPlacement.Top)
.Tooltip(componentTooltip, interactive: true)   // rich IComponent tooltip
.RemoveTooltip()

Accessibility

.AriaLabel, .AriaLabelledBy, .AriaDescribedBy, .AriaRole, .AriaHidden, .AriaExpanded, .AriaSelected, .AriaChecked, .AriaDisabled, .AriaBusy, .AriaCurrent, .AriaLive, .AriaAtomic, .AriaControls, .AriaHasPopup. Focus order: .TabIndex(int), .SkipTab(). See Accessibility.

Gestures

.OnTapped(...), .OnDoubleTapped(...), .OnLongPress(...), .OnPan(...), .OnPinch(...), .OnRotate(...). See Gestures.

Reactive binding and validation

  • .Bind(SettableObservable<T> source) keeps a component in sync with an observable (overloads exist for IReadOnlyList<T> and an explicit SubscriptionScope).
  • .Validation(c => error-or-null), .Error("message"), .IsInvalid() on validatable inputs. See Validator.

Lifecycle and utility

  • .WhenMounted(Action), .WhenMountedDelayed(TimeSpan, Action, bool), .WhenRemoved(Action) — run code when the element enters or leaves the DOM.
  • .ScrollIntoView().
  • .Do(Action<T>) — run an arbitrary action on the component mid-chain.
  • .Var(out T var) — capture the component into a variable mid-chain.
  • .ToToggle() — wrap a Button as a ToggleButton.

Example

using static Tesserae.UI;

var name = TextBox().SetPlaceholder("Name");

var row = HStack().Children(
    TextBlock("Profile").Bold().Large(),
    name.WS().Validation(t => string.IsNullOrEmpty(t.Text) ? "Required" : null),
    Button("Save")
        .Primary()
        .Margin(8.px())
        .Tooltip("Save changes")
        .AriaLabel("Save profile")
).Grow().AlignCenter();

See also

© 2026 Curiosity. All rights reserved.