UI Components

Layouts

linkki provides some standard layout annotations which are described here. If you need another layout it is quite easy to create custom layout annotations.

Section

A section is a layout that provides a header.

linkki offers two annotations to create a section:

Both annotations share the attribute to control the content of the section header:

  • caption: short description of the section

  • closable: whether the section can be collapsed

Differences between @UISection and @UIFormSection
  • @UISection can be used to create a GridSection if the PMO class is derived from class ContainerPmo. @UIFormSection does not have this functionality.

  • @UISection has multiple layout options. @UIFormSection only offers the form layout, with extended functionalities such as the multi-column option.

Layout options in @UISection

@UISection(caption = "Common Data", closeable = true, layout = SectionLayout.FORM)
public class CommonDataSectionPmo {

    // ...

}

The layout for all the components within a UISection can be defined with the attribute layout. linkki defines the possible layouts in the enum SectionLayout: HORIZONTAL, VERTICAL or FORM.

Horizontal Section Layout

With the horizontal layout all input fields are displayed on a line, side by side in the order of their position. Labels are displayed on top of the component. UITextField and UITextArea take up all available space by default. This can be changed by setting width="". UITextField and UITextArea then will take up the same space as all other components. In addition, components are wrapped and moved into a new line if screen width is decreased.

Vertical Section Layout

With the vertical layout all input fields are displayed in a column. Labels are displayed on top of the component.

Form Section Layout

With the form layout fields are displayed one below the other. Labels are displayed on the left of the component. This Layout is used as default if no option is set.

Label width in sections

The width of labels in a section have a fixed default width. Labels that exceed the defined width are broken into multiple lines. The line breaks at white spaces whenever possible. This may cause unexpected line breaks which may impair readability.

To mitigate this issue, the utility class ComponentStyles offers the method setFormItemLabelWidth(Component, String) that can be used to apply a custom label width. This method applies the given width to all labels inside the given component.

public class MyPage extends AbstractPage {

    @Override
    public final void createContent() {
        Component myFormSection = VaadinUiCreator
                .createComponent(new MyFormSectionPmo(), new BindingContext());
        add(myFormSection);

        ComponentStyles.setFormItemLabelWidth(this, "15em");
    }

    ...
}

Typically, the custom fixed width should be applied to a layout containing all visible sections instead of a single section. A consistent label width improves readability by makes the layout appear more structured and clean. For setting label alignment see Label alignment in sections.

Label alignment in sections

By default, the labels are right aligned in a section. A right alignment has the advantage that the label and the corresponding input control are always visually close. In case the length of the labels vary strongly in a section, left alignment can make a label appear far away from the input control itself. This can make the form look less ordered as the affiliation between the label and the input control is broken visually.

To change this behavior, set --linkki-form-item-label-alignment to left on the corresponding component.

Example
Component component = VaadinUiCreator.createComponent(new ExampleSectionPmo(), new BindingContext());
component.getElement().getStyle().set("--linkki-form-item-label-alignment", "left");

Header of a section

A section has a section header that may contain a descriptive title which summarizes the content of the input group. Without a section header, a section is not directly recognizable as such.

A section may be closable with a button in the section header. When closed, its content is collapsed to give a better overview about the whole page.

Adding components to the section header

To add more elements, for example an edit button, to the section’s header than just the caption, you can annotate regular UI elements in the section’s PMO with the @SectionHeader annotation. They will then be placed in the header instead of in the section’s content area.

    @SectionHeader
    @UIButton(position = -10, icon = VaadinIcon.AMBULANCE, showIcon = true, captionType = CaptionType.NONE)
    public void callAnAmbulance() {
The position is validated by linkki to be unique in the PMO independent of where the element will be placed in a section, so it is recommended to use negative numbers for the elements marked with @SectionHeader to avoid conflicts with the regular elements.
The same effect could previously be achieved by implementing the interface PresentationModelObject with the method getEditButtonPmo() where the returned ButtonPmo defines the button and its behavior. As this allows only limited control over the button and no other elements, using a @SectionHeader annotated @UIButton like shown above is to be preferred.

Theme variants of sections

Theme variants on linkki sections can be either set with @BindVariantNames(…​) on a PMO or programmatically with getElement().getThemeList().add(…​).

Table 1. Theme Variants

card

LinkkiSection.THEME_VARIANT_CARD

Card like style

form

LinkkiSection.THEME_VARIANT_FORM

Form style layout, with labels on the left

horizontal

LinkkiSection.THEME_VARIANT_HORIZONTAL

Horizontal layout, with labels on the top and components flowing horizontally

If LinkkiTheme#VARIANT_CARD_SECTIONS is applied to a layout containing sections, all sections in that layout will be card like.

Section Styling Properties

The web component of a section defines several CSS custom properties that can be used to customize the styling of sections.

Table 2. Section Styling Properties
Function Property Default Value

Background of sections

--linkki-section-background

linear-gradient(var(--lumo-contrast-5pct), var(--lumo-contrast-5pct))

Color of the section caption

--linkki-section-caption-header-color

--lumo-contrast-80pct

Spacing below the header components

--linkki-section-header-margin-bottom

--lumo-space-xs

Border radius of the section when card variant is applied

--linkki-section-border-radius

--lumo-border-radius-m

Padding of the section, relevant when using card variant

--linkki-section-padding

--lumo-space-m

ID of a section

Each HTML element of a layout may define an ID. This can be used, for instance, to identify a section for UI testing. By default, the simple name of the class is used as the ID. Alternatively the annotation '@SectionID' can be used to specify a method that returns the ID for the section.

A method annotated with '@SectionID' is called by linkki when the section is created. The ID remains the same for the duration of the session and is not updated dynamically.

To access the section ID, the helper method Sections.getSectionId(Object) may be used.

Although the concept is named SectionID it is also applied to all kinds of layouts.

@UIFormSection

@UIFormSection offers multi-column layout with the attribute columns. Note that if elements have a fixed width, the fixed width will still be respected. This may result in unexpected layout behaviors.

Other layouts

Beside the section there are some simple Vaadin layouts that can be created with the corresponding annotations:

  • @UIHorizontalLayout

  • @UIVerticalLayout

  • @UIFormLayout

  • @UICssLayout

@UIVerticalLayout and @UIHorizontalLayout have options to configure the alignment/spacing/padding. The alignment and spacing affects the inner elements of the layout, while padding effects the layout itself.

To create the UI from a PMO with these layouts you should use VaadinUiCreator. The PmoBasedSectionFactory is only usable for @UISection whereas the VaadinUiCreator can be used for all kinds of layouts.