Skip to content

Version 1.0-RC8

Compare
Choose a tag to compare
@Lysander Lysander released this 22 Aug 10:20

Improvements

PR #783 / PR #788 - New utility render-functions for RenderContext

PR #783 and PR #788 add new utility render-functions inside RenderContext. @serras initially brought up the idea and implementations to reduce boilerplate code by adding some convenience render-functions for common UI-patterns.

Motivation

Often only some specific state of the data model should be rendered, while for other states the UI artefact should disappear. Typical cases are nullable types, where only for the none null part something should be rendered. The following new functions are added to the fritz2's core to adress those cases.

Please regard: If you ever need to render some UI also for the other state-variants, then just refer to the standard render-function and use explicit case analysis like if-else or when expressions inside the render-block.

New Functions

The renderIf(predicate: (V) -> Boolean) function only renders the given content, when the given predicate returns true for the value inside the Flow<V>.

val store = storeOf<String>("foo")
render {
    store.data.renderIf(String::isNotBlank) {
        p { +it }
    }
}

The renderNotNull() function only renders the given content, when the value inside the Flow<V?> is not null.

val store = storeOf<String?>(null)
render {
    store.data.renderNotNull {
        p { +it }
    }
}

The renderIs(klass: KClass<W>) function only renders the given content, when the value inside the Flow<V> is a type of klass.

interface I
class A: I
class B: I

val store = storeOf<I>(A())
render {
    store.data.renderIs(A::class) {
        p { +"A" }
    }
}

PR #781: Migrate popper.js to Floating-UI and add Portalling

This PR adresses two closely related aspects within our headless components:

The first one is quite simple to explain: popper.js is outdated and therefor it makes sense to upgrade to the successor project. Floating-UI fits so much better than popper.js for fritz2 and our headless-components, as it is in fact by itself only a headless component. It offers functionality to calculate the position of some floating element, but it does no more render some styling by itself to the DOM. This obviously is great news for our implementations of popup-elements, as the integration removes some pain points and works much smoother together with fritz2's core mechanics!

For the user there are not much changes; the core approach to implement PopUpPanel as base for some floating brick, does not change. It is only about some properties that have different names and sometimes slightly different values. But we gain much more flexibility like the new concept of midlewares, that can be easily added by custom bricks. So in the end the user has more power to control and modify the floating element for his custom needs.

The other aspect of this PR adresses fundamental problems with overlayed elements in general (this includes the headless modals and toast on top of the PopupPanel based components): There will always be a chance for clipping errors, if the overlay is rendered close to the trigger, which often is kinda deep down inside the DOM hierarchy. Please read about in the description of the Floating-UI project.

That said, nothing will change on API level for this aspect. It is a pure implementation aspect, that has changed now: All headless-overlay components will now render their overlay-bricks inside the original target-node of the outer render-function, which acts as a portal-root. The trigger will create only some placeholder node into the DOM, whereas the real overlay content will be rendered inside the portal-root quite upside in the DOM. The placeholder acts as a portal to the final rendering place.

This is a common pattern and so we stick to the wording inside our code and name everything about it with portal prefix.

API-Breaking Remarks and Migration-Guide

Be aware that this PR might be API breaking for the headless package and the components, that implements the PopupPanel-class for some of their bricks. Also your own Implementation that relies on PopupPanel might break.

We do not consider this API breaking for the whole project, so we prefer to present this under the improvement aspect. We have no knowledge about users, using our headless-component yet, so obviously this will affect primarely ourselves.

There is one action needed to keep the headless components working: To use portalling you have to render the portalRoot manually in our your render {} Block like this:

fun main() {
    //...

    render {
        // custom content
        // ...
        
        portalRoot() // should be the last rendered element
    }
}

After this patch, the Headless-Components listBox, menu, modal, popOver, toast and tooltip should be working again.

If you should against all expectations encounter a break, please simply refer to the updated list of properties within the headless documentation. This list and the following explanations should enable you to adapt to the new properties.

Further improvements

  • PR #785: Add binary compatibility validation

Fixed Bugs

  • PR #778: Fix link to Arrow docs

Credits

Special thanks to @serras for his effords and contributions to this release!