Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ You may be wondering where the name Blits comes from?

Firstly, it's short, memorable and just has a nice ring to it.

"Blits" is a Dutch word (a significant portion of the Lightning Open Source teams is based in the Netherlands). It means _flashy_ and it's often used to for things that are _great_ or _cool_.
"Blits" is a Dutch word (a significant portion of the Lightning Open Source team is based in the Netherlands). It means _flashy_ and it's often used for things that are _great_ or _cool_.

Finally it's a nerdy reference to the computer term "Bit Blits" commonly used in graphics processing, for rapidly moving a block of data into memory - quite similar to what Lightning is doing 🙂

Expand Down
3 changes: 1 addition & 2 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ You may be wondering where the name Blits comes from?

Firstly, it's short, memorable and just has a nice ring to it.

"Blits" is a Dutch word (a significant portion of the Lightning Open Source teams is based in the Netherlands). It means _flashy_ and it's often used to for things that are _great_ or _cool_.
"Blits" is a Dutch word (a significant portion of the Lightning Open Source team is based in the Netherlands). It means _flashy_ and it's often used for things that are _great_ or _cool_.

Finally it's a nerdy reference to the computer term "Bit Blits" commonly used in graphics processing, for rapidly moving a block of data into memory - quite similar to what Lightning is doing 🙂

2 changes: 1 addition & 1 deletion docs/built-in/directives.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ At the moment it's not possible to use the `is`-attribute as a _reactive_ attrib

The declarative coding style that is promoted in Blits components, should generally remove the need to directly interact with individual Elements or Components in your template. However, in some cases you may need to reference them directly. For example, in order to delegate the focus.

For this use case, you can specify a `ref`-attribute on Elements (or Components). And by using the helper function `this.select()`, which is vailable on every Blits component, you can gain access to the child Element or Component inside your business logic.
For this use case, you can specify a `ref`-attribute on Elements (or Components). And by using the helper function `this.select()`, which is available on every Blits component, you can gain access to the child Element or Component inside your business logic.

The `select()`-function accepts the `ref`-value that you are looking for as a single argument, and returns the Element or Component if found.

Expand Down
16 changes: 8 additions & 8 deletions docs/built-in/for-loop.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
# For loop

The for loop is technically also a [directive](../directives.md), but such an important one that it deserves it's own section.
The for loop is technically also a [directive](../directives.md), but such an important one that it deserves its own section.

The for loop directive can be used when you want to repeat multiple instances of an Element or a Component, without having to specify them hardcoded one by one in your template.

The for loop take an `Array` of data, loops over it and for each Array-item an Element or Component is created. The `Array` can be a fixed one, but it' can also dynamically be filled or modified and have it's changes reflect in the rendered result.
The for loop takes an `Array` of data, loops over it and for each Array-item an Element or Component is created. The `Array` can be a fixed one, but it can also dynamically be filled or modified and have it's changes reflect in the rendered result.

> Important: the for loop is a powerful and often used directive. Within Blits it's optimized to be as performant as possible. But if used incorrectly, it can be the cause of slow performance. So please read carefully through this entire section.

Expand Down Expand Up @@ -33,9 +33,9 @@ The example above will generate 3 _lime green_ elements, based on the array of `

## Using the index

In order to fix the example above and make all 3 elements visible, we can use the `index` of the Array, to position each item correctly.
In order to fix the example above and make all 3 elements visible, we can use the `index` of the Array to position each item correctly.

All we need to do is declare the `index` in the `for`-directive and subsequently use it in the the `x`-attribute, with a simple calculation.
All we need to do is declare the `index` in the `for`-directive and subsequently use it in the `x`-attribute, with a simple calculation.

You may choose any name for the `index` variable (like `i` or `forIndex`). This may be useful when you already have the `index`-key specified as a `state` or `prop` variable on your component, causing a conflict.

Expand Down Expand Up @@ -95,21 +95,21 @@ export default Blits.Component('ForLoop', {
})
```

This will generate 3 squares aligned next to each other, each with a differrent color and they will use the _alpha_ specific in the Component state.
This will generate 3 squares aligned next to each other, each with a different color and they will use the _alpha_ specific in the Component state.

## The importance of using the key attribute

The examples above have demonstrated the basic usage of the for-loop. But they are all missing one _very important_ ingredient to make sure that for-loops that are subject to change, continue to perform well. Meet the `key`-attribute.

For perfomance reasons, it is essential to be able track the _identity_ of an Element or Component, whenever changes are made to the Array in the for loop.
For performance reasons, it is essential to be able track the _identity_ of an Element or Component, whenever changes are made to the Array in the for loop.

Think of _identity_ as the field that makes an item in the Array unique, such as an `id` or a `hash`. It's basically the thing that allows you to distinguish between the poster of _The Matrix_ and the poster of _Frozen 2_, for example.

Providing this information, allows the for-loop to decide whether it should _update_ an existing Component or Element instance. Or whether we're dealing with a new Array item, and a new instance should be _created_.

Correctly using the `key`-attribute enables Blits to _reuse_ existing instances whenever possible - which obviously is good for performance.

It's important that the `key`-attribute is _unique_ for each Array item. Also beware that we can't rely on the `index` parameter provided in for loop, because that only indentifies the position in the Array, and not the actual item itself.
It's important that the `key`-attribute is _unique_ for each Array item. Also beware that we can't rely on the `index` parameter provided in for loop, because that only identifies the position in the Array, and not the actual item itself.


```js
Expand Down Expand Up @@ -156,7 +156,7 @@ export default Blits.Component('ForLoop', {

In the example above we have added the `key`-attribute in the template. Now whenever we push a new item to the `items`-array, the for-loop will reuse the Elements previously created and only instantiate a new Element for the newly added item.

If we would ommit the `key`-attribute, then whenever we push a new item to the Array, the for-loop would dispose all the old Elements and create new instances for _each_ item in the array.
If we would omit the `key`-attribute, then whenever we push a new item to the Array, the for-loop would dispose all the old Elements and create new instances for _each_ item in the array.

## Referencing elements in the for loop

Expand Down
46 changes: 23 additions & 23 deletions docs/built-in/layout.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
# Layout

A big portion of building a pixel perfect App is all about correctly positioning Elements and Components on screen. In Lightning and Blits _absolute_ positions are used. This fits the whole concept of building a TV app where the viewport dimensions are known and fixed. Absolute positioning (versus spacing Elements relative to each other) is also more performant.
A big portion of building a pixel-perfect App is all about correctly positioning Elements and Components on the screen. In Lightning and Blits, _absolute_ positions are used. This fits the whole concept of building a TV app where the viewport dimensions are known and fixed. Absolute positioning (versus spacing Elements relative to each other) is also more performant.

Imagine a complex design with several nested layers. Relying solely on _relative_ positioning and elements automatically floating as space is available, may lead to heavy and recursive calculations. Then throw some dynamically changing dimensions and animations in the mix as well, and your App may be starting to noticeably drop frames due to expensive re-calculations.
Imagine a complex design with several nested layers. Relying solely on _relative_ positioning and elements automatically floating as space is available may lead to heavy and recursive calculations. Then throw some dynamically changing dimensions and animations in the mix as well, and your App may be starting to noticeably drop frames due to expensive re-calculations.

That being said, there are often cases where it becomes very cumbersome to calculate all the positions manually. Especially when dimensions are not known in advance and elements may load asynchronously.

If you come from a CSS background, you may be tempted to say: "_this is why we have Flexbox!_". And while Flexbox is great and versatile in CSS and running on a powerful device, a full flexbox implementation does come at a cost and the risk of slowing down your App, when applied extensively or incorrectly.

In order to address the core problem "_how do I easily position a bunch of Elements and Components, without writing a lot of code with `@loaded` event handlers_", Blits offers the built-in `<Layout>`-component - a basic and performant solution that automatically puts your Elements in the right place.
In order to address the core problem of "_how do I easily position a bunch of Elements and Components without writing a lot of code with `@loaded` event handlers_", Blits offers the built-in `<Layout>` component - a basic and performant solution that automatically puts your Elements in the right place.

## How to use

Since the Layout-component is a built-in component, there is no need to register it separately. You can use the `<Layout>`-tag anywhere in your templates, just as you would use `<Element>` and `<Text>`.
Since the Layout component is a built-in component, there is no need to register it separately. You can use the `<Layout>` tag anywhere in your templates, just as you would use `<Element>` and `<Text>`.

The Layout component is a wrapper component, that encloses a number of children. All the direct children that are wrapped in a `<Layout>`-tag are automatically positioned in order, one next to the other.
The Layout component is a wrapper component that encloses a number of children. All direct children wrapped in a `<Layout>` tag are automatically positioned in order, one next to the other.

Whenever the dimensions of a child change, the positioning of the next children is automatically recalculated and re-applied.
Whenever dimensions of a child change, the positioning of the next children is automatically recalculated and reapplied.

```xml
<Layout>
Expand All @@ -29,31 +29,31 @@ Whenever the dimensions of a child change, the positioning of the next children

### Horizontal and vertical layout

By default the Layout component lays out it's contents _horizontally_. The Layout component accepts a `direction` attribute which allows you to control the direction.
By default, the Layout component lays out its contents _horizontally_. The Layout component accepts a `direction` attribute that allows you to control the direction.

In order to align vertically use `<Layout direction="vertical"></Layout>`. And use `<Layout direction="horizontal"></Layout>` to explicitly apply the default horizontal layout.
In order to align vertically, use `<Layout direction="vertical"></Layout>`. And use `<Layout direction="horizontal"></Layout>` to explicitly apply the default horizontal layout.

### Spacing between children

By default the Layout-component places each Element directly besides (or below) the previous one. By adding the `gap`-attribute you can control how much space will be added between each Element or Component. The `gap`-attribute accepts a number in pixels.
By default, the Layout-component places each Element directly besides (or below) the previous one. By adding the `gap`-attribute, you can control how much space will be added between each Element or Component. The `gap`-attribute accepts a number in pixels.

### Aligning items

The layout component positions its children based on the provided direction (`horizontal` or `vertical`). With the `align-items`-attribute you can specify how to align the children on the opposite axis:
The layout component positions its children based on the provided direction (`horizontal` or `vertical`). With the `align-items`-attribute, you can specify how to align the children on the opposite axis:

- `start` (the default value) - aligns the children in the _top_ for horizontal layouts, and on the _left_ for vertical layouts
- `start` (the default value) - aligns the children at the _top_ for horizontal layouts and on the _left_ for vertical layouts
- `center` - align the children in the center
- `end` - aligns the children in the _bottom_ for horizontal layouts, and on the _right_ for vertical layouts

### Dynamic dimensions

For the Layout component to work properly, the direct children all need to have dimensions (i.e `w` and `h` attributes). The exception here being Text elements.
For the Layout component to work properly, all direct children need to have dimensions (i.e., `w` and `h` attributes). The exception here being Text elements.

Due to the asynchronous nature of rendering text, the final text dimensions are not known beforehand. The width and height of Text elements are automatically set when the text has been loaded. This fires a `@loaded` event, that you can tap into as described [here](../essentials/displaying_text#text-dimensions).
Due to the asynchronous nature of rendering text, the final text dimensions are not known beforehand. The width and height of Text elements are automatically set when the text has been loaded. This fires a `@loaded` event that you can tap into as described [here](../essentials/displaying_text#text-dimensions).

The Layout component also uses this event, to execute its calculation and position the text and other elements around it properly.
The Layout component also uses this event to execute its calculation and properly position the text and other elements around it.

When the children of the Layout-component have _reactive_ dimensions (i.e. `<Element :w="$mywidth" :h="$myheight" />), the Layout component ensures that all child elements are properly re-positioned whenever a dimension changes.
When the children of the Layout-component have _reactive_ dimensions (i.e., `<Element :w="$mywidth" :h="$myheight" />`), the Layout component ensures that all child elements are properly repositioned whenever a dimension changes.

### Components inside a Layout

Expand Down Expand Up @@ -85,11 +85,11 @@ export default Blits.Component('MyButton', {
}
})
```
At this moment Blits does not have support for automatically growing the dimensions of a Component based on it's contents, because of the performance impact that this functionality has.
At this moment, Blits does not support automatically growing a Component's dimensions based on its contents due to the performance impact of this functionality.

### Nesting Layouts

It's also possible to nest layouts. Simply place a new `<Layout>`-tag, with it's own children in between the children of another Layout-component. The Layout-component itself will grow automatically with the dimensions of it's children. In other words, it's not required to specify a width (`w`) or height (`h`) on the `<Layout>`-tag itself.
It's also possible to nest layouts. Simply place a new `<Layout>`-tag, with it's own children in between the children of another Layout-component. The Layout component itself will grow automatically with the dimensions of its children. In other words, it's not required to specify a width (`w`) or height (`h`) on the `<Layout>` tag itself.

And of course you can nest _vertical_ Layouts inside a _horizontal_ one - and vice versa.

Expand Down Expand Up @@ -123,7 +123,7 @@ The `<Layout>`-component can also take into account when dimensions of children

### Updated event

The `<Layout>`-tag automatically updates its dimensions based on the dimensions of its children. After each update in the children, the an `updated`-event is emitted on the `<Layout>`-tag. It will receive the current dimensions of the layout.
The `<Layout>`-tag automatically updates its dimensions based on the dimensions of its children. After each update in the children, an `updated`-event is emitted on the `<Layout>`-tag. It will receive the current dimensions of the layout.

You can tap into this event by adding an `@updated`-attribute to the `<Layout />`-tag and refer to a method in your Component logic.

Expand Down Expand Up @@ -151,18 +151,18 @@ export default Blits.Component('LayoutUpdate', {

## Performance

The Layout-component is a very useful utility, that will make it a lot easier to put together complex layouts. It will reduce the code required, it means less hardcoding of values and removes the need to manually wire up `@loaded` events when working with dynamic / asynchronous elements.
The Layout component is a very useful utility that will make it a lot easier to put together complex layouts. It will reduce the code required, it means less hardcoding of values and removes the need to manually wire up `@loaded` events when working with dynamic / asynchronous elements.

We've done our best to make the Component as performant as possible, by deliberately keeping it simple and straight forward. But it's important to understand that the Layout component does come at a cost. Depending on the use case these costs may be negligible, but there are cases where the Layout component might prove to be a bottle-neck.
We have done our best to make the Component as performant as possible by deliberately keeping it simple and straightforward. However, it is important to understand that the Layout component does come at a cost. Depending on the use case these costs may be negligible, but there are cases where the Layout component might prove to be a bottleneck.

The performance costs may always be there to some degree. Whether it's the Layout component that does the complex calculations, or you do it in your custom code. So please feel encouraged to use the `<Layout>`-tag!
The performance costs may always be there to some degree. Whether it's the Layout component that does the complex calculations, or you do it in your custom code. So, please feel encouraged to use the `<Layout>` tag!

Some pointers to keep in mind, though:

- Every change in the dimensions of a child, triggers the Layout component to recalculate and reposition. If your child elements change frequently, the Layout component may have a performance impact.

- The Layout component support transitions, but beware that when transitioning child dimensions a recalculation happens every frame-tick. If you see frame-drops in your App, you may want to see if the `<Layout>`-tag has an impact on this.
- The Layout component support transitions, but beware that when transitioning child dimensions a recalculation happens every frame tick. If you see frame-drops in your App, you may want to see if the `<Layout>`-tag has an impact on this.

- Be mindful to not apply unnecessary deep nesting of Layout tags. Each change in a deep child, will trigger recalculations up the tree of Layout tags.

- When using the `<Layout>`-tag with a for-loop, it may be more performant to use the `$index` of the for-loop and manually position the elements yourself (i.e. `<Element :for="(item, index) in $items" :$x="$item * 200" w="150" h="150" />`). Especially if the dimensions are know before hand and possibly are the same for each child.
- When using the `<Layout>`-tag with a for-loop, it may be more performant to use the `$index` of the for-loop and manually position the elements yourself (i.e. `<Element :for="(item, index) in $items" :$x="$item * 200" w="150" h="150" />`). Especially if the dimensions are known beforehand and possibly are the same for each child.
Loading