Define the component's purpose. Narrow down the scope as much as possible.
Avoid assumptions about its parent/owner
- See [broken behavior example](./code-examples.md#Dont-assume-parents-context-bad-example)
- See [well-behaved behavior example](./code-examples.md#Give-user-choice)
Define and make clear the interface/contract that defines requirements.
To simplify maintenance consider the following options for implementing custom controls, generic containers or views:
- Use QML2's customization mechanics in place if the change is simple: [Check docs for examples](https://doc.qt.io/qt-6/qtquickcontrols2-customize.html)
- If the control should be generic or the changes are extensive and the design maps to a QML control, use QML2's customization mechanisms in a generic QML control: [Check docs for examples](https://doc.qt.io/qt-6/qtquickcontrols2-customize.html) instead of starting from scratch.
- Use Qt controls instead of defining our own. Defining and implementing a complex control from scratch should be the last resort and there should be an excellent reason to do that.
- For keyboard input item, ensure focus properties are set; see [Qt docs](https://doc.qt.io/qt-6/qtquick-input-focus.html)
When unsure, check Qt's excellent documentation.
- For main components/controls, there is a good overview that is worth revisiting from time to time
- Functions/Properties usually have a short on-point description
- In `QtCreator` you can quickly open the doc panel using `F1` key while having a cursor on component or function/property and recheck its invariants, pre and post conditions
Consider that design follows user-friendlier principles.
- Have commonly used items at hand
- Have transition if possible
- Use Qt's property animation for states
- Avoid often and radical size changes to items in views/layouts. Radical size change confuses users.
- They are used to break polishing binding loops for adaptive control
- All the containers use the implicit size for deriving the initial size (Layouts, Popups, Delegates, GridView, ListView ...). Size hints combined with resize adaptability are the appropriate way to have reactive controls.
- For complex controls, look if layouts are the choice as the main position driver. [Layouts](###Layouts)
```qml
Item {
id: root
implicitWidth: mainLayout.implicitWidth
implicitHeight: mainLayout.implicitHeight
RowLayout { // Column, Grid
id: mainLayout
// ...
}
```
- Adapt to the requested size if control can scale or it make sense to be extensible. For sizes bigger than content follow QML way for similar controls. e.g. Text leaves empty space around content
- If the control is not adaptable and makes sense only in its full size, define default sizes and make it work by default with positioners (`Row`, `Column`, `Grid`).
- [Item Positioners in QML](https://doc.qt.io/qt-5/qtquick-positioning-layouts.html)
- Don't mix hints with sizes, it will create binding loops
Pixel miss-alignment for sensitive elements like icons and images with straight and thin lines can degrade the quality perceptibly.
Dividing sizes and coordinates are the usual root cause of pixel miss-alignment. Correct subpixel division by rounding the result of the operation to a fixed value, e.g. `x: (width/2).toFixed()`
- Example of pixel miss-alignment. The right control has a position offset of `Qt.pos(0.7, 0.4)` therefore, the image interpolation generates a blurred rendering.
Hierarchically sources hints from children. Implicit properties will have the recommended aggregated size.
Layouts as children of other layouts have `fillWidth` and `fillHeight` enabled; controls don't.
Use `Layout.preferredWidth` and `Layout.preferredHeight` attached properties to overwrite item's `implicitWidth` if they are not appropriate to the design.
### Scope
Follow [Qt's recommendations](https://doc.qt.io/qt-5/qtqml-documents-scope.html) if appropriate
// Probably won't work as intended. If another `testComp` instance is defined in QML's document hierarchy model and has a `testProp` property, that will be sourced instead
property bool booleanProp: testComp.testProp
// Same behavior if the TestComponent is defined in a file TestComponent.qml
- Component `id`s are not accessible outside the component's scope. If required, the component can expose the instance through properties binding. E.g. `readonly property ComponentType exposedComponent: privateInstanceId`
As stated in Qt documentation on Popup content sizing:
1.`Popup` size is as calculated internally as `contentItem.implicitSize + paddings`
2. The size of `contentItem` is managed by the popup to fit the Popup and paddings
It's important to understand that `Popup.contentItem` is an internal invisible Item. Any user items will be parented to the `contentItem`, not the `Popup` itself.
Knowing this, we make a simple rule to choose one of 2 ways for popup content sizing:
1. Replace the `contentItem` with your item, but don't explicitly anchor or bind it's sizes, because the size of `contentItem` is managed by the popup.
```qml
Popup {
contentItem: ColumnLayout {
// no anchoring or binding
}
}
```
2. Don't touch the `contentItem` property, but create a single child to the popup and **anchor it to `parent`**.
```qml
Popup {
ColumnLayout {
anchors.fill: parent // parent is contentItem, not Popup