Version 1.0-RC8
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:
- migrate outdated popper.js to the newer Floating-UI (see https://floating-ui.com/docs/migration)
- introduce a portalling mechanism to prevent overlays beeing clipped (see https://floating-ui.com/docs/misc#clipping)
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!