Views & Layout
A view is one screen. Views live in a project, are addressed by slug, and are composed from components arranged by a layout mode.
Layout modes
Choose per view. The choice is not cosmetic — it determines how the screen behaves on a display size you did not anticipate.
| Mode | Positioning | Best for |
|---|---|---|
| Coordinate | Absolute X/Y within a fixed design size, scaled to fit | P&ID mimics, plant overviews, anything where spatial relationships are the information |
| Grid | Rows and columns, items snap to cells | Dashboards, KPI walls, tabular layouts |
| Flex | Flow layout, items size and wrap | Responsive screens, forms, lists, anything viewed on varied displays |
| Breakpoint 1.0.4 | A separate authored screen per width tier | A screen whose phone version is genuinely different, not merely narrower |
Coordinate
The classic SCADA canvas. You place a pump exactly where the pump is on the line, draw pipes between equipment, and the whole view scales to the display.
Use it when position carries meaning. Do not use it for a dashboard that must look right on both a 55" wall panel and a tablet — that is what flex is for.
Grid
Components occupy grid cells and can be dragged and resized within the grid. Good for dashboards where alignment matters more than exact position, and where a maintainer will add a tile later.
Changed in 1.0.8 A widget dropped from the palette lands in the cell you aimed at; before 1.0.8 every drop queued up under the last widget however carefully it was aimed. Press Esc during a drag to abandon it — the widget stays where it was.
A grid view now scrolls when its tiles are taller than the screen (overflow defaults to
scroll on a grid view, including grid views authored before 1.0.8). Before, tiles past the bottom
edge were simply cut off. A grid nested inside another layout is unchanged: its height comes from
what contains it.
Five grid properties were removed because nothing read them: maxRows, autoSize, bounded,
dragThreshold and dropEnabled. Changing them never did anything.
Flex
Components flow, size and wrap. This is the mode that survives contact with an unexpected screen size. Use it for forms, lists, side panels and anything that will be viewed on more than one device class.
Changed in 1.0.8 A widget in a flex layout has width and height in its Position panel, beside grow, shrink, basis and align-self. A bare number means pixels; clear the field to let the layout size it. Before 1.0.8 some widgets — an Image in a flex row, for one — had no size control at all there. A flex container's align items setting also no longer stops its children from following the container's height: a logo stretched to a 70 px header now renders at 70 px, not at the photo's own size.
Breakpoint New in 1.0.4
Where flex adapts one layout, breakpoint replaces it. Each width tier — mobile, tablet,
desktop by default — gets its own panel, and the container renders exactly one of them. A tier can
also mirror another, so a fresh view costs two authored screens rather than three.
Use it when the wide and narrow versions differ in what they show, not just how it is arranged: a desktop trend, alarm table and control strip against three numbers and an acknowledge button on a phone.
The cost is that every tier you author is a screen you maintain, which is why flex remains the right default. → Breakpoint layout
Containers
| Container | Purpose |
|---|---|
| FlexContainer | A flow container inside any view — the workhorse for grouping. |
| TabContainer | Multiple panes behind tabs. |
| EmbeddedView | Renders another view inside this one. |
| FlexRepeater | Repeats a view once per item in a bound array. |
Nest deliberately. Two or three levels of container is readable; six is a layout nobody will maintain.
Embedded views
The single most valuable pattern in the Designer.
Author MotorFaceplate once, with a parameter for the tag path:
MotorFaceplate params: { tagPath }
Text → {tagPath}/Name
Gauge → {tagPath}/Speed
Indicator → {tagPath}/Running
AlarmEvent → {tagPath}
Then embed it wherever a motor appears:
EmbeddedView MotorFaceplate { tagPath: "Line1/Filler/Motor1" }
EmbeddedView MotorFaceplate { tagPath: "Line1/Filler/Motor2" }
EmbeddedView MotorFaceplate { tagPath: "Line1/Capper/Motor1" }
One change to the faceplate updates every motor on every screen. This is the visualization counterpart of a UDT, and the two are designed to be used together.
Repeaters
A FlexRepeater takes an array and renders an embedded view per item, passing the item as parameters.
FlexRepeater
bound to → query: SELECT path, name FROM active_equipment
renders → EquipmentCard { tagPath: item.path, label: item.name }
The screen then grows and shrinks with the plant instead of being rebuilt when equipment is added.
Navigation
| Mechanism | Use |
|---|---|
| HorizontalMenu / VerticalMenu | Persistent site navigation |
| Link | An inline navigation target |
| navigate event action | Navigation from any component's event, with parameters |
| TabContainer | Switching within one screen |
Navigation passes parameters, so one detail view serves every instance:
Overview → navigate("equipment-detail", { tagPath: "Line1/Filler/Motor1" })
The view tab strip New in 1.0.0
Open views sit on a strip along the bottom of the Designer. A view with unsaved changes shows a dot where its close button goes; reach for the close and the dot becomes the button, so a tab never loses its unsaved indicator to a hover.
The strip does not scroll. A horizontal scrollbar in a 40-pixel bar is a four-pixel target that is present in the DOM and undiscoverable in practice, and it leaves the view you are editing off-screen with nothing to say it exists. Instead the strip shows a window over the tabs — the run that fits — with a control on each side that appears only when something is hidden behind it, and a list button for every open view.
Tabs are sized by their title, capped and then ellipsised, rather than dealt equal shares of the row: Home and Line 3 Kiln Preheater Detail are not the same size, and forcing them to be wastes the row on the short one while truncating the long one for nothing.
Closing a tab activates its neighbour, not the last tab on the strip. Closing tab 3 of 20 and landing on tab 20 reads as a teleport, and with a windowed strip it scrolls the whole thing out from under you. Closing an inactive tab never moves focus at all.
Changed in 1.0.8 The window slides when it steps, and the next tab outside it peeks in at each edge, so the row visibly continues past the arrows. One notch of the mouse wheel moves one tab.
Editing on the canvas
Double-click to go inside. Double-click a container to select what is in it, and double-click an interactive widget — a Map, a 3D Viewer, a File Manager — to work with it rather than move it. 1.0.8 That now works in Flex and Grid views too, not only in Coordinate views, and a click inside an entered widget no longer drops you back out.
Edit text in place New in 1.0.8. Double-click a Text widget to type into it on the
canvas. Enter or a click elsewhere keeps the edit, Esc cancels it, and the edit is one undo
step. You edit the text as written, so a template such as Speed {{tag}} keeps its placeholder;
text that is bound as a whole is not editable inline. Pasted text arrives as one plain line, and
emptying the field keeps the old text.
Select, turn and resize with the handles on the selection; see transform handles.
Right-click a widget for its context menu — Edit Events, arrange and align, copy, paste, duplicate, delete, and Edit Symbol on a symbol of your own.
Undo and saving Changed in 1.0.8
Saving no longer clears undo. A save is a new baseline, not a fresh start: you can undo past it, and the view then shows as unsaved again; redo back to the saved state and it is clean. Undo keeps up to 100 steps per view, and a held gesture — dragging a slider — is one step.
"Unsaved changes" is worked out by comparing the document with what was last saved, everywhere it is shown: the status bar, Save & Deploy, the dots in the project tree, and the warning when you leave the page. Before 1.0.8 an undo after a save could leave the Designer showing unsaved changes that Save never cleared. A move that ends where it started is not an edit.
Control size New in 1.0.8
Field and menu widgets share one size scale. Project settings → Theme → Control size sets it for the whole project — in the Designer canvas and in LiveView:
| Size | Field height | Text | Menu row and tab | Text widget body | For |
|---|---|---|---|---|---|
| XS | 28 px | 12 px | 28 px | 12 px | Very dense desktop dashboards |
| SM (default) | 36 px | 13 px | 32 px | 14 px | Desktop dashboards |
| MD | 44 px | 14 px | 36 px | 16 px | Touch — a 44 px target |
| LG | 52 px | 16 px | 44 px | 18 px | Touch panels |
| XL | 64 px | 18 px | 52 px | 20 px | Gloved hands, far-away displays |
These widgets follow it: Button, Input, Dropdown, Date Picker, Color Picker, Upload, Slider, Textarea, Checkbox, Radio and Switch, the Horizontal and Vertical Menus, Text, Form (all its fields and its Submit button) and the Tab Container's tabs. Each has a size property — Project default unless you set it — and the nearest setting wins, so one widget can be larger than the rest. A Text widget's own font size still wins over the scale, and a Tab Container's size applies to its tabs, not to the views inside them. A dropdown list or menu flyout follows the size of the field that opened it.
Before 1.0.8 these widgets drew at what is now MD. The default is SM, so after the upgrade an existing project's inputs, dropdowns and buttons are 36 px tall instead of 44, menus and tabs are tighter, and a Text paragraph is 14 px instead of 16. Nothing is lost and no view is rewritten, but a screen laid out around the old heights can look sparse, and a touch panel's targets get smaller.
For a touch-panel project, or to keep the old look, set Control size to MD. A Tab Container saved on its old default follows the project size; one set explicitly to small or large keeps it. Tabs no longer shrink to fit — the strip scrolls instead.
Screen structure that scales
Overview plant-wide status and alarm summary
Line1/Overview line status, embedded equipment cards
Line1/Detail equipment detail, parameterised
Diagnostics connection health, service status
- One overview per level of the plant hierarchy.
- One parameterised detail view per equipment class, not per instance.
- A diagnostics screen that shows connection and service health, so the first question after "the screen is blank" has an answer.
Design size and scaling
Coordinate views declare a design size and scale to the display. Author at the resolution of the primary target (typically the control-room panel) and verify on the smallest device that will use it.
For screens that must genuinely adapt rather than scale, use flex — scaling a coordinate view down makes text unreadable long before it makes the layout wrong.
Locking a view's theme
By default a view follows the theme around it: the project's theme in LiveView, and whatever the author has chosen in the Designer. That is right for an ordinary page and wrong for an HMI screen that was drawn for one palette — a dark mimic that turns white because someone flipped the app to light mode is not the screen that was signed off.
Select the view itself (click empty canvas, so no component is selected) and open themeLock
in the properties panel:
| Field | What it does |
|---|---|
enabled | Turns the lock on for this view. |
palette | The base palette — Light, Dark, or one of the named themes. A named theme applies fully only in a full-page LiveView, so check it there rather than on the canvas. |
accent | The accent colour. Leave it unset to use the palette's own; set it for combinations such as Light with a blue accent. |
The lock belongs to one view. It covers that view and everything rendered inside it — embedded views, flex and tab containers — and nothing else: in LiveView, the header, footer and sidebars the view is docked into keep the project's theme, so one locked screen does not repaint the runtime around it. A colour you set explicitly on a component still wins over the locked palette.
Every component follows the lock. Changed in 1.0.7 Before 1.0.7 some components kept the ambient theme's text, background and border colours inside a locked view, because those colours were resolved once for the whole page rather than where they are used. Inside a dark-locked view on a light desktop that produced dark text on a dark background — unreadable, on an operator screen, with nothing logged. The Markdown component had the same problem with its text and code-block colours. All of them now take their colours from the lock.
The WYSIWYG emoji picker opens on top of the page rather than inside the view, so it uses the page's theme, not the lock. That is the theme it is actually drawn against.
Performance
| Symptom | Cause | Fix |
|---|---|---|
| Slow to open | Very many components, or many bindings resolving at once | Split into embedded views; load detail on demand |
| Sluggish while running | High-rate bindings on many widgets | Raise tag deadbands; not every value needs 250 ms |
| Charts stutter | Too many series, or too long a window at full resolution | Reduce series; let the historian aggregate |
| Video stutters | Several full-resolution streams | Use sub-streams |
Screen performance is usually a data problem, not a rendering problem. Look at binding rates and tag deadbands first.
Export and import
Exporting and importing a project's view tree both require Manage Designer.
Use it to promote screens from development to production, or to template a standard line.
A view pack carries the symbols of your own that its views place 1.0.8. An imported view, or a restored project, shows on every open browser without a restart 1.0.8 — before 1.0.8 a browser could keep showing the pre-import view until QUBIQ was restarted.
Views from an older version
A view saved by an older QUBIQ is brought up to date the first time it is opened — including docked header, footer, sidebar and panel views, which load without being clicked. Nothing needs doing by hand, and the server stores only the new format. The 1.0.8 conversions are:
| What | Becomes |
|---|---|
| QR Code and Barcode settings | Grouped (logo, frame, colors …) |
| Line, Arrow and the other drawing tools | Grouped properties (stroke, flow, animation …) |
| Send message actions and message handlers | A subject instead of a type |
| A Tab Container on its old default size | Follows the project's control size |
A view saved by a newer QUBIQ is refused with a message saying so, rather than opened and saved back in a shape that version does not understand.