tabris-js
tabris-js copied to clipboard
Support FlexBox Layout
Original discussion: https://github.com/eclipsesource/tabris-js/issues/2101
API draft:
Adjusting the CSS API to our Tabris API and the yoga feature set.
Parent/Container
Things are pretty straight-forward for the container. For the property names we convert kebab-case to camelCase. We could omit the "flex" prefix, though that makes it potentially inconsistent with the layoutData properties, as discussed below. The values stay as-is, but enums can be provided as well. Only oddity are the values which contain a space, here some error tolerance may be needed in the JS code.
new FlexBox({
direction: 'row', // | 'row-reverse' | 'column' | 'column-reverse'
wrap: 'nowrap', // | 'wrap' | 'wrap-reverse'
flow: 'row nowrap', // | 'column-reverse' | 'column-wrap' | 'row-reverse wrap-reverse'
justifyContent: 'flex-start', // | 'flex-end' | 'center' | 'space-between' | 'space-around' | 'space-evenly'
alignItems: 'stretch', // | 'flex-start' | 'flex-end' | 'center' | 'baseline'
alignContent: 'flex-start' // | 'flex-end' | 'center' | 'stretch' | 'space-between' | 'space-arond'
})
All optional and read-only of course, first value is the default.
The above is JS-only shorthand for:
new Composite({
layout: new FlexBoxLayout(...) // same props as above
})
This is closer to what the native client will get, a Composte
, Page
, TabItem
, etc with a layout
property set either not at all (let's say it's equivalent to {display: 'constraint'}
), or to {display: 'flex', direction: 'row', ...}
. It's always the complete set of properties, fallback to default. The padding
property will continue to be set separately and not as part of layout
.
Item/Child
Flexbox respects various item layout (for us: layoutData) properties that aren't exclusive to it, and we already established that some layoutData properties work differently or not at all depending on the parent layout. Also, having a completely different set of layoutData properties for flexbox would cause sever backwards compatibility issues in TypeScript. I therefore propose to just extend the existing set of layoutData properties.
The existing properties are used as follows:
Property | Type | Usage |
---|---|---|
left | constraint or number | flex only respects 'auto', number and percent. |
top | constraint or number | " |
right | constraint or number | " |
bottom | constraint or number | " |
width | number or percent or 'auto' | percent is only respected by flex |
heigh | number or percent or 'auto' | " |
centerX | number | not respected by flex, but could be re-directed in JS to set alignSelf |
centerY | number | " |
baseline | sibling | " |
For the new properties we will use a flex
prefix to minimize the risk of clashing with existing properties of custom components (since the inherit from Composite
and therefore Widget
, which will get the new flex properties). They are ignored (with warning) if the parent doesn't use flexbox. The native client won't receive them either.
The following new properties would match 1:1 with their CSS counterpart:
{
flexBasis: 'auto', // | number | percent
flexGrow: 0, // number,
flexShrink: 1, // number
}
The following new properties do not have the "flex" prefix in CSS, but would have for us to avoid collision. (We can invent a shorthand syntax for the JS side to make it shorter to express.)
{
flexAlignSelf: 'auto', // | 'stretch' | 'flex-start' | 'flex-end' | 'center' | 'baseline',
flexPositionType: 'relative', // | ' absolute'
flexMaxWidth: null, // | number | percent
flexMinWidth: null, // | number | percent
flexMaxHeight: null, // | number | percent
flexMinHeight: null, // | number | percent
flexMarginLeft: 0, // | number | percent
flexMarginTop: 0, // | number | percent
flexMarginRight: 0, // | number | percent
flexMarginBottom: 0, // | number | percent
}
The positionType
property is acually just position
in CSS, but in yoga it's positionType
. I find that more precise.
Yoga supports a border
property, but as far as I can tell it's no use to us.
Finally there is a order
property is in the flexbox standard, but it don't seem to be supported by yoga. We could possibly support it on a JS level, by re-ordering them when sending the client the children ids.
Since we now have mixed types which can be number or percent (width
, height
, flexBasis
) we need to render them differently for the percent value. I suggest [fraction, 0]
to be aligned with left
/top
/width
/height
.
References used
https://yogalayout.com/docs (note https://github.com/facebook/yoga/issues/993) https://www.w3.org/TR/css-flexbox-1 https://yoksel.github.io/flex-cheatsheet/#section-display https://css-tricks.com/snippets/css/a-guide-to-flexbox/
We will not remove the flex
prefixes for the container properties after all.
width
, height
and flexBasis
will be rendered as tuple [percent, 0]
only if it's percent in layoutData
, otherwise still number
or 'auto'
.