Skip to content

Props ​

Props configure a view's appearance and behavior. Barton supports named props in any order, with type checking at compile time. Custom components can use the same syntax as built-in views.

cpp
Text {
    "Hello",
    color = Color::WHITE,
    font_size = 18.f,
    padding = 8_px,
}

Named props ​

Named props use assignment-like syntax and can be supplied in any order, unlike positional constructor arguments.

Each prop is represented by a distinct C++ type, allowing components to identify and handle arguments through overload resolution.

This provides several useful properties:

  • Any order. Named props are matched by type, not position.
  • Optional by default. Omitted props retain their component-defined defaults.
  • Compile-time checks. Unsupported props and incompatible values produce compilation errors.
  • No runtime lookup. Props use C++ overload resolution rather than string keys or dynamic property tables.

Children can be declared alongside props, keeping layout and content together in the same expression.

Custom props ​

Custom components can define named props using Prop<T>, where T is a value type that identifies the property and holds its value.

For example, a Compact property can be declared in an application's namespace:

cpp
namespace app {

struct Compact {
    bool value;
};

inline constexpr barton::Prop<Compact> compact;

}

Assigning to app::compact produces a Compact value, which a component can handle through a corresponding set overload:

cpp
void set(Compact value) {
    m_compact = value.value;
}

The component's constructor passes its arguments to set, where the argument type determines which overload is called. Unsupported props produce a compilation error.

The resulting syntax is the same as for built-in views:

cpp
UserCard {
    app::user = me,
    app::compact = true,
}

TIP

Prop names are ordinary C++ variables and follow the usual scoping rules. Keep custom props in a namespace to avoid name collisions. If a local variable shadows a prop, qualify the prop name explicitly, such as app::user.

Forwarding props ​

Components with a render function don't have layout bounds of their own. Layout and style props apply to the views they return, so components can accept these props and forward them to an underlying view.

For example, UserCard can accept a width prop and forward it to its root Row:

cpp
void set(Width value) { m_width = value; }

View render() const {
    return Row {
        m_width,
        // ...
    };
}

Width m_width { Val::Auto() };

Callers can then configure the width of the underlying row:

cpp
UserCard { app::user = me, width = 240_px }

Props aren't forwarded automatically. A component must accept and apply each prop it wants to expose.

Components can also inherit from built-in views to reuse their existing prop handling. For example, a Card derived from Container can accept its layout and style props while introducing its own additional properties.

Members vs Named Props ​

Custom components can also use ordinary public data members as props, without defining named properties or custom constructors.

cpp
struct Badge {
    std::string label;
    Color tint = Color::GRAY;

    View render() const {
        return Text { label, color = tint };
    }
};

These components use standard C++ aggregate initialization:

cpp
Badge { "New", Color::GREEN }
Badge { .label = "New" }

Public members are often sufficient for small components with a few values. Named props are useful when a component has several optional settings or should provide an interface consistent with Barton's built-in views.

Barton is in early development.