Creating and editing view components

You can create new, reusable view components by turning a container into a composite component.

Simply select a container, and at the bottom of the properties panel, click the Turn into a new view component button. After a confirmation dialog, the isolation mode is opened for your newly-created composite component.

To edit an existing composite component, simply double-click it on the view canvas to open the isolation mode.

Using the isolation mode

The isolation mode essentially lets you edit the structure and properties of a composite component in isolation from the rest of the page. To signify this, the rest of the UI is faded out with a translucent stripe pattern.

For any composite component, there's three things to consider:

  • Structure, i.e. how the composite component's child components are laid out

  • Properties, i.e. what properties are available for the user to configure after they've dragged it onto the canvas

  • Internal logic, i.e. what logic is run inside the composite instance, either automatically as part of the component's lifecycle or in reaction to user interaction

  • Events, i.e. what events the composite component can trigger via its internal logic

Structure

Creating the structure for your composite works the same way in isolation mode as outside it: you drag components to the canvas and define their properties and styles. Nested containers can be used to do more complex layouting.

The only difference is the root container for the layout. Outside Isolation mode, the root of your component structure is the page itself, while in isolation mode, it's the root of the composite component.

Styling composite components

A composite component can be thought of as a "card" that can be added to any part of your page layout. As such, the style properties available for composite component instance, when selected on the main canvas, include only properties like margin and width, i.e. things that affect the "boundaries" of the composite component.

Conversely, when editing the composite component root inside isolation mode, you can set style properties like padding and background color that affect things inside the composite component boundaries.

Best practices

You can decide yourself if you prefer to build your components first as containers outside Isolation mode, and then turn them into composites later on, or craft a set of composites as a kind of style guide beforehand.

For clarity, try to avoid unnecessary nested containers. For example, there's might not be a need to add a Row component if you can just set a regular Container to have a horizontal layout direction.

Properties

Every composite component has a set of root-level properties that define how it functions – you can read more in the Component properties panel guide.

The only property inherent to a composite component is Visibility, i.e. is the component shown in the UI or not.

All other properties are either linked to child component properties (i.e. Input value that is bound to an Input primitive's Value property), or otherwise contain data required by the composite component (i.e. Options that is used by a Pick value flow function in the inner logic canvas).

Example

For example, it makes sense for a card component with a title and body content to expose Title and Content properties: when you drag the card onto the view canvas and select it, you can configure both relevant text contents.

Internally, the card composite has two Text primitives, each with a Content property. The composite component's Title and Content properties are linked to the respective child component properties.

Thus, setting the Title text on the composite triggers the Content property of the title Text primitive inside it to be set.

The bindings are two-way. Let's say we have an Input value root level property in our composite. Inside the composite, we have an Input primitive whose Value property is bound to the root level Input value.

Now, when the user types into the input field, the Input primitive's Value field is changed. The binding then causes the composite's Input value to change. Then, if the Input value on the composite instance was further bound to e.g. a page variable, the changes would propagate further still.

Best practices

When you are building a composite component, try to prioritize ease-of-use and clarity over configurability.

It doesn't make sense to make every child component's Visibility property available as a composite property, unless your composite specifically requires that. Rather, strive for the least number of properties, and if things start to get complex, consider just making a separate component.

Note on style properties

Currently, you cannot define what child component styles are exposed to the composite top level. Instead, you should use theme variables to provide that configurability. This means that instead of black, your component header should be bound to $colorContentPrimary and so on. This will make your component compatible with the various themes available on the Marketplace.

Internal logic

In isolation mode, you are editing the composite's internal logic – the "engine under the hood". The internal logic exists isolated from the rest of the app logic and is the same for every component instance (unless you edit it). It doesn't and shouldn't know anything that's happening in the rest of the app, as a composite component should work out of the box in any app it's added to.

Thus, you can't use page variables via formulas or use Set page/data/app variable in the inner canvas, as they would be different between apps. (The only exception is theme variables, which are thought to be universal for all apps.)

One way to affect the "outside world" is to change the composite's root level properties via the Set component property flow function – which could then trigger changes via any bound variables.

Of course, directly bound properties described above also affect the outward-facing composite properties.

Another one is via events, described below.

Events

Component primitives expose various kinds of native events: Component tapped, Input value changed, Input field focused and so on. In some cases, you want to expose these events from your child components onto the composite's top level logic canvas, so they can be utilized by whoever's using your component.

For example, a list item might have both a generic tap event on the whole component, as well as a specific tap event on the info icon.

Defining custom events

All view components have the tap event by default. This is a special system event – if there's logic attached to the tap event, clicking/tapping the component shows a tap animation (changing the opacity to 50% translucent) and triggers the event. You can remove the tap event if you're sure it never makes sense for the user to tap the component as a whole, but there's no harm in keeping it there.

To define a custom event, you need to first add it under the Events section in the component properties (accessible via the Edit properties button in the isolation mode toolbar).

Component with the default tap event plus a new customEvent defined.

When a new composite component instance is dragged from the component library onto the canvas, it initializes with the default events defined in its properties. If the user removes a default-generated event node, they can re-add it by dragging in a Receive event node and selecting the desired event from the dropdown.

Triggering events from inside the composite component

To trigger an outward-facing event registered for the composite component, you simply add a Trigger event node in the right place.

For example, if you want a button inside my composite component to trigger customEvent when it's tapped, your logic would look like this:

Logic flow inside the composite component

Now, when the button inside your composite is tapped, the customEvent event is triggered on the component instance's logic canvas.

Logic flow in the composite component instance's canvas

Since composite components are meant to be isolated from the rest of the app logic, you can only trigger events registered for your composite component.