<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.spiretrading.com/index.php?action=history&amp;feed=atom&amp;title=Components</id>
	<title>Components - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.spiretrading.com/index.php?action=history&amp;feed=atom&amp;title=Components"/>
	<link rel="alternate" type="text/html" href="https://wiki.spiretrading.com/index.php?title=Components&amp;action=history"/>
	<updated>2026-05-04T19:43:49Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.34.1</generator>
	<entry>
		<id>https://wiki.spiretrading.com/index.php?title=Components&amp;diff=162&amp;oldid=prev</id>
		<title>Jon: Describes components.xd for a UI component specification: how to get started, how to define a component in terms of its children, how to define scenarios using selectors, and how to set property declarations.</title>
		<link rel="alternate" type="text/html" href="https://wiki.spiretrading.com/index.php?title=Components&amp;diff=162&amp;oldid=prev"/>
		<updated>2023-05-25T20:18:37Z</updated>

		<summary type="html">&lt;p&gt;Describes components.xd for a UI component specification: how to get started, how to define a component in terms of its children, how to define scenarios using selectors, and how to set property declarations.&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;User interfaces are composed of reusable semantic elements called components. Each component is specified by a set of documents: &amp;lt;code&amp;gt;model.txt&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;preview.xd&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;components.xd&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;layout.xd&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;user_flow.drawio&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;use_cases.drawio&amp;lt;/code&amp;gt;. This page covers the &amp;lt;code&amp;gt;components.xd&amp;lt;/code&amp;gt; document.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;components.xd&amp;lt;/code&amp;gt; lists all children for the component. Children may be omitted where there is no customization done and their inclusion is made clear from &amp;lt;code&amp;gt;layout.xd&amp;lt;/code&amp;gt; . If the component has no children (e.g. it is primitive or purely layout) then &amp;lt;code&amp;gt;components.xd&amp;lt;/code&amp;gt; is omitted. Most components will require &amp;lt;code&amp;gt;components.xd&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Component Breakdown ==&lt;br /&gt;
&lt;br /&gt;
The question of when to define a component on its own rather than as a child of its parent is generally one of complexity: when the child is so complex that defining it within the &amp;lt;code&amp;gt;components.xd&amp;lt;/code&amp;gt; of the parent impedes readability, it should be split off into its own component. The following heuristics are helpful in determining whether a child should become its own component:&lt;br /&gt;
&lt;br /&gt;
* It is shared by multiple parents and should be generally available in the application (e.g. &amp;lt;code&amp;gt;FilterPanel&amp;lt;/code&amp;gt; could be defined in &amp;lt;code&amp;gt;TableView&amp;lt;/code&amp;gt;, but filtering could conceivably be used outside of a table)&lt;br /&gt;
* It has multiple children that require conditional styling (e.g. &amp;lt;code&amp;gt;HeaderCell&amp;lt;/code&amp;gt; could be defined in &amp;lt;code&amp;gt;TableView&amp;lt;/code&amp;gt;, but it has many children with lots of conditional styling that would be harder to follow alongside all the other children of &amp;lt;code&amp;gt;TableView&amp;lt;/code&amp;gt;)&lt;br /&gt;
* It contains its own logic that is best described by its own model and user flow (e.g. &amp;lt;code&amp;gt;OverflowLabel&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;CategoricalList&amp;lt;/code&amp;gt;)&lt;br /&gt;
* It contains children that themselves must have conditional styling based on their state (e.g. &amp;lt;code&amp;gt;ColorSwatch&amp;lt;/code&amp;gt; in &amp;lt;code&amp;gt;ColorBox&amp;lt;/code&amp;gt;)&lt;br /&gt;
&lt;br /&gt;
== Getting Started ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;components.xd&amp;lt;/code&amp;gt; comes after &amp;lt;code&amp;gt;preview.xd&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;model.txt&amp;lt;/code&amp;gt;. From &amp;lt;code&amp;gt;preview.xd&amp;lt;/code&amp;gt;, the children can be listed and the essential scenarios understood. From &amp;lt;code&amp;gt;model.txt&amp;lt;/code&amp;gt;, specific data, styles and states can be referenced.&lt;br /&gt;
&lt;br /&gt;
=== Example: AccountListItem ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;Data:&lt;br /&gt;
  identicon: A unique icon identifier for the account.&lt;br /&gt;
  id: A unique username for the account.&lt;br /&gt;
  name: The full name associated with the account.&amp;lt;/pre&amp;gt;&lt;br /&gt;
The above model for &amp;lt;code&amp;gt;AccountListItem&amp;lt;/code&amp;gt; shows 3 pieces of data. There are no component-specific states or styles described in the model. We infer that the job of &amp;lt;code&amp;gt;components.xd&amp;lt;/code&amp;gt; will be to indicate where these 3 pieces of data will appear and how they will be displayed.&lt;br /&gt;
&lt;br /&gt;
[[File:AccountListItem_preview.png|360px|Preview of a list item displaying a user account]]&lt;br /&gt;
&lt;br /&gt;
From the above preview, there are no scenarios showcased: the component appears to be display-only, without any specific interactions. There are (at least) 3 children:&lt;br /&gt;
* &amp;lt;code&amp;gt;Icon&amp;lt;/code&amp;gt; for &amp;lt;code&amp;gt;identicon&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;Label&amp;lt;/code&amp;gt; for &amp;lt;code&amp;gt;id&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;Label&amp;lt;/code&amp;gt; for &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The designer could split the children into other components (e.g. a &amp;lt;code&amp;gt;Box&amp;lt;/code&amp;gt;) for styling purposes, so we can have more than the expected 3 children. Based on &amp;lt;code&amp;gt;preview.xd&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;model.txt&amp;lt;/code&amp;gt;, we infer that &amp;lt;code&amp;gt;components.xd&amp;lt;/code&amp;gt; will list the 3 expected children and cascade the data to the appropriate child. It should also describe the font settings for the &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt;, which have been customized away from the default.&lt;br /&gt;
&lt;br /&gt;
[[File:AccountListItem_components.png|720px|Definition cards for AccountListItem's children]]&lt;br /&gt;
&lt;br /&gt;
Reviewing the actual &amp;lt;code&amp;gt;components.xd&amp;lt;/code&amp;gt;, that is exactly what we get. A &amp;lt;code&amp;gt;Box&amp;lt;/code&amp;gt; has been used to contain the &amp;lt;code&amp;gt;Icon&amp;lt;/code&amp;gt; so that some padding can be added to it. The children are siblings, so they are ordered left-to-right and top-to-bottom.&lt;br /&gt;
&lt;br /&gt;
We note that &amp;lt;code&amp;gt;id&amp;lt;/code&amp;gt; is assigned to the &amp;lt;code&amp;gt;current&amp;lt;/code&amp;gt; property of the &amp;lt;code&amp;gt;Label&amp;lt;/code&amp;gt; named &amp;lt;code&amp;gt;ID&amp;lt;/code&amp;gt;: for a &amp;lt;code&amp;gt;Label&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;current&amp;lt;/code&amp;gt; refers to its displayed text. Also, &amp;lt;code&amp;gt;name&amp;lt;/code&amp;gt; is assigned to the &amp;lt;code&amp;gt;current&amp;lt;/code&amp;gt; property of the &amp;lt;code&amp;gt;Label&amp;lt;/code&amp;gt; named &amp;lt;code&amp;gt;Name&amp;lt;/code&amp;gt;. At the top, &amp;lt;code&amp;gt;identicon&amp;lt;/code&amp;gt; is assigned to the &amp;lt;code&amp;gt;icon&amp;lt;/code&amp;gt; property of the &amp;lt;code&amp;gt;Icon&amp;lt;/code&amp;gt; named &amp;lt;code&amp;gt;Identicon&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
It is common practice to name children by the data that they display when they are solely responsible for one piece of data. The capitalization conventions ('''snake_case''' for properties and '''PascalCase''' for components is used to disambiguate the child from the value).&lt;br /&gt;
&lt;br /&gt;
== Anatomy ==&lt;br /&gt;
&lt;br /&gt;
The structure of &amp;lt;code&amp;gt;components.xd&amp;lt;/code&amp;gt; is a vertical list of cards. Each card displays exactly one child and its scenarios. Wherever possible, a visual preview of the child should be displayed for each scenario.&lt;br /&gt;
&lt;br /&gt;
=== Example: LabelButton ===&lt;br /&gt;
&lt;br /&gt;
[[File:LabelButton_anatomy.png|720px|Definition Card anatomical breakdown for the Label in LabelButton]]&lt;br /&gt;
&lt;br /&gt;
Each card consists of a heading and table of scenarios for the child. Often, there may only be one scenario, the &amp;lt;code&amp;gt;default&amp;lt;/code&amp;gt;: a condition is not necessary, but &amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt; may be used to indicate that it applies to any state. Each column in the scenario table has a condition that describes it, a visual preview, and a list of property declarations. Property declarations are how values are assigned to the child.&lt;br /&gt;
&lt;br /&gt;
The visual preview is non-normative and intended only as a guide. The property declarations are authoritative so take care to get them right.&lt;br /&gt;
&lt;br /&gt;
== Heading ==&lt;br /&gt;
&lt;br /&gt;
The heading is the name of the child. It is used to identify what component is being used. Any referenced component should already be defined in the specifications. If there are multiple children that are instances of the same component (e.g. two labels), they should be renamed using an alias.&lt;br /&gt;
&lt;br /&gt;
=== Aliases ===&lt;br /&gt;
&lt;br /&gt;
Aliases are named instances of components. An alias can have conditional styling not present on the main component. Aliases take the format &amp;lt;code&amp;gt;OriginalComponentName:Alias&amp;lt;/code&amp;gt; (e.g. &amp;lt;code&amp;gt;TableRow:EmptyRow&amp;lt;/code&amp;gt;). An alias is referred to by its assigned name (&amp;lt;code&amp;gt;EmptyRow&amp;lt;/code&amp;gt; is how we refer to the child).&lt;br /&gt;
&lt;br /&gt;
Aliases can be a convenient way to customize a component and reuse the customization without having to redeclare the customization for each use case.&lt;br /&gt;
&lt;br /&gt;
=== Example: TitleBar ===&lt;br /&gt;
&lt;br /&gt;
[[File:TitleBar_preview.png|492px|Preview of the TitleBar component]] &lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;TitleBar&amp;lt;/code&amp;gt; customizes the &amp;lt;code&amp;gt;IconButton&amp;lt;/code&amp;gt; for use as the minimize, maximize, and close buttons. Because the custom styling is shared, aliasing provides a concise way to declare the customizations.&lt;br /&gt;
&lt;br /&gt;
[[File:TitleBar_components.png|720px|Definition cards for TitleBar's children]]&lt;br /&gt;
&lt;br /&gt;
In the example, &amp;lt;code&amp;gt;TitleBarButton&amp;lt;/code&amp;gt; is an alias for &amp;lt;code&amp;gt;IconButton&amp;lt;/code&amp;gt; with customizations for when it is &amp;lt;code&amp;gt;not active&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;hover&amp;lt;/code&amp;gt; '''or''' &amp;lt;code&amp;gt;press&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The buttons &amp;lt;code&amp;gt;Minimize&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;Maximize&amp;lt;/code&amp;gt;, and &amp;lt;code&amp;gt;Close&amp;lt;/code&amp;gt; are themselves aliases for &amp;lt;code&amp;gt;TitleBarButton&amp;lt;/code&amp;gt;, with further customization for the icon and, in the case of &amp;lt;code&amp;gt;Close&amp;lt;/code&amp;gt;, a different styling for &amp;lt;code&amp;gt;hover&amp;lt;/code&amp;gt; '''or''' &amp;lt;code&amp;gt;press&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Aliases make the scenarios more readable, as only the differences are listed for each alias. For &amp;lt;code&amp;gt;Maximize&amp;lt;/code&amp;gt;, it is more clear that there is conditional styling for the icon used than it would be if all scenarios were declared on the same card.&lt;br /&gt;
&lt;br /&gt;
Note that &amp;lt;code&amp;gt;TitleBarButton&amp;lt;/code&amp;gt; is a ''virtual child'': it doesn’t actually appear anywhere in the layout of &amp;lt;code&amp;gt;TitleBar&amp;lt;/code&amp;gt;. The designer is free to make arbitrary virtual children provided they make the document more readable.&lt;br /&gt;
&lt;br /&gt;
=== Multiples ===&lt;br /&gt;
&lt;br /&gt;
Frequently, the children of a component will be multiples of the same type, and the same conditional styles apply to all of them. In these cases, one child is given a card and it is referred to as one item in a list using array indexing (e.g. &amp;lt;code&amp;gt;Label&amp;lt;/code&amp;gt; becomes &amp;lt;code&amp;gt;Label[i]&amp;lt;/code&amp;gt; to indicate the ''ith'' &amp;lt;code&amp;gt;Label&amp;lt;/code&amp;gt; in a list).&lt;br /&gt;
&lt;br /&gt;
=== Example: ClosedFilterPanel ===&lt;br /&gt;
&lt;br /&gt;
[[File:ClosedFilterPanel_components.png|720px|Definition cards for ClosedFilerPanel's children]]&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;ScrollableListBox&amp;lt;/code&amp;gt; contains customized &amp;lt;code&amp;gt;ListItem&amp;lt;/code&amp;gt;. These are indicated as &amp;lt;code&amp;gt;ListItem[i]&amp;lt;/code&amp;gt;. Each &amp;lt;code&amp;gt;ListItem&amp;lt;/code&amp;gt; contains a &amp;lt;code&amp;gt;CheckBox&amp;lt;/code&amp;gt;, which becomes &amp;lt;code&amp;gt;CheckBox[i]&amp;lt;/code&amp;gt; in the card, as there are multiple checkboxes. This notation can also be used to target specific items in the list, such as only the even items (&amp;lt;code&amp;gt;2i&amp;lt;/code&amp;gt;) or the first item (&amp;lt;code&amp;gt;0&amp;lt;/code&amp;gt;), but such usage is rare.&lt;br /&gt;
&lt;br /&gt;
== Scenarios ==&lt;br /&gt;
&lt;br /&gt;
Scenarios are conditions in which children can be in. These are like variants or states.&lt;br /&gt;
&lt;br /&gt;
Scenarios are used to set properties on children. Data and styling properties are set in &amp;lt;code&amp;gt;components.xd&amp;lt;/code&amp;gt;, while layout properties (e.g. &amp;lt;code&amp;gt;height&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;width&amp;lt;/code&amp;gt;) are reserved for &amp;lt;code&amp;gt;layout.xd&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Example: LabelButton ===&lt;br /&gt;
&lt;br /&gt;
[[File:LabelButton_components.png|720px|Definition card for the LabelButton's children]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;LabelButton&amp;lt;/code&amp;gt; has conditional styling based on whether the &amp;lt;code&amp;gt;Button&amp;lt;/code&amp;gt; is:&lt;br /&gt;
* &amp;lt;code&amp;gt;disabled&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;focus_visible&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;press&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;hover&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
These conditions are the scenarios.&lt;br /&gt;
&lt;br /&gt;
Scenarios are evaluated from right to left: the first scenario that matches is the one that is evaluated.&lt;br /&gt;
&lt;br /&gt;
All properties declared under a scenario are applied. Any undeclared properties are inherited from the &amp;lt;code&amp;gt;default&amp;lt;/code&amp;gt; scenario. Any properties undeclared in the &amp;lt;code&amp;gt;default&amp;lt;/code&amp;gt; scenario are inherited from the defaults for that child.&lt;br /&gt;
&lt;br /&gt;
=== Example: HeaderCell ===&lt;br /&gt;
&lt;br /&gt;
Scenarios can consist of one or more selectors, which can be chained using newlines or commas to indicate &amp;lt;code&amp;gt;or&amp;lt;/code&amp;gt; conditions.&lt;br /&gt;
&lt;br /&gt;
[[File:ResizeHandle_definition.png|720px|Definition card for ResizeHandle from HeaderCell]]&lt;br /&gt;
&lt;br /&gt;
In the example, &amp;lt;code&amp;gt;ResizeHandle&amp;lt;/code&amp;gt; receives a specific &amp;lt;code&amp;gt;background_color&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;pointer&amp;lt;/code&amp;gt; when &amp;lt;code&amp;gt;Sash&amp;lt;/code&amp;gt; is &amp;lt;code&amp;gt;hover&amp;lt;/code&amp;gt; '''or''' when &amp;lt;code&amp;gt;Sash&amp;lt;/code&amp;gt; is &amp;lt;code&amp;gt;drag&amp;lt;/code&amp;gt;. &amp;lt;code&amp;gt;Sash&amp;lt;/code&amp;gt; is another child of &amp;lt;code&amp;gt;HeaderCell&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
== Selectors ==&lt;br /&gt;
&lt;br /&gt;
Selectors are used to compose conditions for scenarios. They take the form:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;A state [[combinator B and state]]&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;A&amp;lt;/code&amp;gt; is the name of the child being defined. It may be omitted. &amp;lt;code&amp;gt;state&amp;lt;/code&amp;gt; is the state of &amp;lt;code&amp;gt;A&amp;lt;/code&amp;gt;. The double-bracket enclosed parts are optional.&lt;br /&gt;
&lt;br /&gt;
=== State ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;any&amp;lt;/code&amp;gt; is used when no specific state applies and may be omitted for the &amp;lt;code&amp;gt;default&amp;lt;/code&amp;gt; scenario. Outside of the &amp;lt;code&amp;gt;default&amp;lt;/code&amp;gt; scenario, &amp;lt;code&amp;gt;state&amp;lt;/code&amp;gt; is mandatory.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;state&amp;lt;/code&amp;gt; must refer to a property that exists on the child. If it exists, it is declared in the model of the child (or the model of the component that the child wraps or extends). For example: &amp;lt;code&amp;gt;hover&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;disabled&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;focus&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;focus_visible&amp;lt;/code&amp;gt; are all declared in the model for &amp;lt;code&amp;gt;component&amp;lt;/code&amp;gt;, which is the base for all components.&lt;br /&gt;
&lt;br /&gt;
=== Combinators ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;combinator&amp;lt;/code&amp;gt; are operators that indicate a relation between two components. The child being styled is always on the left, the &amp;lt;code&amp;gt;combinator&amp;lt;/code&amp;gt; indicates the relation between child and the component that determines the condition:&lt;br /&gt;
&lt;br /&gt;
* &amp;lt;code&amp;gt;A &amp;amp;lt; B&amp;lt;/code&amp;gt; means &amp;lt;code&amp;gt;B&amp;lt;/code&amp;gt; is a parent of &amp;lt;code&amp;gt;A&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;A &amp;amp;gt; B&amp;lt;/code&amp;gt; means &amp;lt;code&amp;gt;B&amp;lt;/code&amp;gt; is a child of &amp;lt;code&amp;gt;A&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;A ~ B&amp;lt;/code&amp;gt; means &amp;lt;code&amp;gt;B&amp;lt;/code&amp;gt; is a general sibling of &amp;lt;code&amp;gt;A&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;A&amp;lt;/code&amp;gt; can be omitted, as it always refers to the child being defined. When &amp;lt;code&amp;gt;B&amp;lt;/code&amp;gt; is omitted and the combinator is &amp;lt;code&amp;gt;&amp;amp;lt;&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;B&amp;lt;/code&amp;gt; is implicitly interpreted to be the parent for the &amp;lt;code&amp;gt;components.xd&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Example: HeaderCell ===&lt;br /&gt;
&lt;br /&gt;
[[File:ResizeHandle_definition.png|720px|Definition card for ResizeHandle from HeaderCell]]&lt;br /&gt;
&lt;br /&gt;
Returning to the &amp;lt;code&amp;gt;ResizeHandle&amp;lt;/code&amp;gt;, the &amp;lt;code&amp;gt;&amp;amp;lt;&amp;lt;/code&amp;gt; combinator tells us that &amp;lt;code&amp;gt;Sash&amp;lt;/code&amp;gt; is a parent of &amp;lt;code&amp;gt;ResizeHandle&amp;lt;/code&amp;gt;. The &amp;lt;code&amp;gt;ResizeHandle&amp;lt;/code&amp;gt; is styled based on when its parent &amp;lt;code&amp;gt;Sash&amp;lt;/code&amp;gt; is &amp;lt;code&amp;gt;hover&amp;lt;/code&amp;gt; '''or''' &amp;lt;code&amp;gt;drag&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Visual Preview ===&lt;br /&gt;
&lt;br /&gt;
The visual preview is non-normative but should be provided wherever possible and made as correct as is feasible. When data is displayed in the preview, variables may be cascaded using angle brackets &amp;amp;lt; &amp;amp;gt;, or representative data may be used. Generally, cascading the variables is preferred, but optimize for readability.&lt;br /&gt;
&lt;br /&gt;
== Properties ==&lt;br /&gt;
&lt;br /&gt;
Properties come from the child being defined. To see what properties are available on a component, refer to its &amp;lt;code&amp;gt;model.txt&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Common Components ===&lt;br /&gt;
&lt;br /&gt;
The most commonly referenced properties come from the following:&lt;br /&gt;
&lt;br /&gt;
==== Component ====&lt;br /&gt;
&lt;br /&gt;
All components have these properties available, it is worth being familiar with them. The most commonly referenced states (&amp;lt;code&amp;gt;hover&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;disabled&amp;lt;/code&amp;gt;, &amp;lt;code&amp;gt;active&amp;lt;/code&amp;gt;, etc.) are available through &amp;lt;code&amp;gt;Component&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== Box ====&lt;br /&gt;
&lt;br /&gt;
All styled components are derived from &amp;lt;code&amp;gt;Box&amp;lt;/code&amp;gt;. All the common style properties (padding, borders, color, etc.) are available through &amp;lt;code&amp;gt;Box&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
==== TextBox ====&lt;br /&gt;
&lt;br /&gt;
All displayed text is derived from &amp;lt;code&amp;gt;TextBox&amp;lt;/code&amp;gt;. Text styling properties (font, alignment, text color, etc.) are available through &amp;lt;code&amp;gt;TextBox&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Property Definitions ===&lt;br /&gt;
&lt;br /&gt;
If a property is not defined in the model, it doesn’t exist, even if a similar property exists in CSS or some other language. New properties can be added as needed by updating the appropriate model.&lt;br /&gt;
&lt;br /&gt;
When a component changes its appearance based on a composite of conditions, it can be convenient to use a named property for those conditions. That enables other components to easily style the component as a child, based on the property. Consider the following excerpt from the model for &amp;lt;code&amp;gt;DecimalBox&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;  up_tick: The current value has increased.&lt;br /&gt;
  down_tick: The current value has decreased.&lt;br /&gt;
  positive: The current value is positive.&lt;br /&gt;
  negative: The current value is negative.&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;code&amp;gt;DecimalBox&amp;lt;/code&amp;gt; can be readily styled based on whether the current value has increased or decreased or is positive or negative without having to define that logic anytime the styling is desired.&lt;br /&gt;
&lt;br /&gt;
=== Slots ===&lt;br /&gt;
&lt;br /&gt;
There is precedent for using properties to swap one child for another, akin to using slots in some templating frameworks (slots here refer to placeholder components and not functions in the Qt sense of the term). It is preferrable to plan for this by assigning a name for the intended slots in the model, but it can be done without a specific property in the model provided the components being swapped have the same functionality or will not otherwise interfere with the user flow.&lt;br /&gt;
&lt;br /&gt;
==== Example: QuantityFilterPanel ====&lt;br /&gt;
&lt;br /&gt;
[[File:QuantityFilterPanel_components.png|720px|Definition cards for QuantityFilterPanel's children]]&lt;br /&gt;
&lt;br /&gt;
In the example, &amp;lt;code&amp;gt;ScalarFilterPanel&amp;lt;/code&amp;gt; has two &amp;lt;code&amp;gt;DecimalBox&amp;lt;/code&amp;gt; children aliased as &amp;lt;code&amp;gt;MinValue&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;MaxValue&amp;lt;/code&amp;gt;. These are swapped with the children &amp;lt;code&amp;gt;MinQuantity&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;MaxQuantity&amp;lt;/code&amp;gt; using property assignment, themselves aliased &amp;lt;code&amp;gt;QuantityBox&amp;lt;/code&amp;gt; children. Because &amp;lt;code&amp;gt;QuantityBox&amp;lt;/code&amp;gt; is simply a customized &amp;lt;code&amp;gt;DecimalBox&amp;lt;/code&amp;gt;, this swap is non-breaking.&lt;br /&gt;
&lt;br /&gt;
While properties are always '''snake_case''', named components are '''PascalCase'''.&lt;br /&gt;
&lt;br /&gt;
==== Example: Box ====&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;Data:&lt;br /&gt;
  body: The component displayed in the box.&amp;lt;/pre&amp;gt;&lt;br /&gt;
The above excerpt from the model for &amp;lt;code&amp;gt;Box&amp;lt;/code&amp;gt; defines &amp;lt;code&amp;gt;body&amp;lt;/code&amp;gt; as a property that is a component. This makes it clear that any component can be displayed inside &amp;lt;code&amp;gt;Box&amp;lt;/code&amp;gt;. This is the preferred way for defining a slot in a component. When the component needs to be type-restricted (e.g. only a &amp;lt;code&amp;gt;DecimalBox&amp;lt;/code&amp;gt;), this can be made explicit in the model.&lt;br /&gt;
&lt;br /&gt;
=== Animations ===&lt;br /&gt;
&lt;br /&gt;
Animations are just values in Spire, so they can be declared directly as property values.&lt;br /&gt;
&lt;br /&gt;
To have an animated color sequence on a &amp;lt;code&amp;gt;Box&amp;lt;/code&amp;gt;, its &amp;lt;code&amp;gt;background_color&amp;lt;/code&amp;gt; property would be declared using a function that switches between colors.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;css&amp;quot;&amp;gt;border_color: chain(timeout(#B71C1C, 550ms), revert)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
In the above snippet, the &amp;lt;code&amp;gt;border_color&amp;lt;/code&amp;gt; property is set to change to a red color for 550ms and then revert to its previous color.&lt;br /&gt;
&lt;br /&gt;
=== Filepaths ===&lt;br /&gt;
&lt;br /&gt;
Filepaths are valid values for certain properties, such as SVGs for icons. The root folder is the folder for the component. By convention, assets belong in an /assets folder. To specify an icon:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;css&amp;quot;&amp;gt;icon: /assets/custom-icon.svg&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
The parent folder for all specs can also be referenced as the root folder:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;css&amp;quot;&amp;gt;icon: /ui_kit/assets/window_icons/dashboard.svg&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Variables and Strings ===&lt;br /&gt;
&lt;br /&gt;
Whether the property declaration is a variable or should be interpreted as a string value is inferred from context. Variables are normally assumed. Double quotes can be used to indicate that a string is being specified (useful when there is whitespace). Variables can be output inside a string using concatenation or angle brackets for string interpolation.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;css&amp;quot;&amp;gt;current: “The price is &amp;lt;price&amp;gt;”&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
In the above example, a variable named &amp;lt;code&amp;gt;price&amp;lt;/code&amp;gt; is interpolated into a string. The output would look like: '''The price is 9.99'''. The following achieves the same result:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;css&amp;quot;&amp;gt;current: “The price is ” + price&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Expressions ===&lt;br /&gt;
&lt;br /&gt;
Any expression that evaluates to a value can be set as a property. Revisiting the animation example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;css&amp;quot;&amp;gt;border_color: chain(timeout(#B71C1C, 550ms), revert)&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;chain(X, Y)&amp;lt;/code&amp;gt; is an animation that applies animated style &amp;lt;code&amp;gt;X&amp;lt;/code&amp;gt; until &amp;lt;code&amp;gt;X&amp;lt;/code&amp;gt; ends, and then applies style &amp;lt;code&amp;gt;Y&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;timeout(X, Y)&amp;lt;/code&amp;gt; applies the style &amp;lt;code&amp;gt;X&amp;lt;/code&amp;gt; for a period of &amp;lt;code&amp;gt;Y&amp;lt;/code&amp;gt;&lt;br /&gt;
* &amp;lt;code&amp;gt;revert&amp;lt;/code&amp;gt; is a style that applies whatever style would have otherwise been applied&lt;br /&gt;
&lt;br /&gt;
The result is a sequence of values for &amp;lt;code&amp;gt;border_color&amp;lt;/code&amp;gt; that changes over time. Basic math operators and self-explanatory functions can also be used. This can be useful for formatting, as in the following &amp;lt;code&amp;gt;FormattedDecimalLabel&amp;lt;/code&amp;gt; example:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;css&amp;quot;&amp;gt;current: “&amp;lt;DecimalLabel.current * 100&amp;gt;%”&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
The variable &amp;lt;code&amp;gt;DecimalLabel.current&amp;lt;/code&amp;gt; is multiplied by 100 and then formatted with a % sign.&lt;br /&gt;
&lt;br /&gt;
Generally it is preferable to avoid using complex expressions in property declarations as it makes &amp;lt;code&amp;gt;components.xd&amp;lt;/code&amp;gt; less readable. Expressions should be done in consultation with a developer. If considering conditional expressions, try to restructure it into a separate scenario with a comparatively simple expression.&lt;br /&gt;
&lt;br /&gt;
=== Bindings ===&lt;br /&gt;
&lt;br /&gt;
When a property declaration expression contains dependencies (other variables) and those dependencies update, the property is automatically assumed to update. In the following example from &amp;lt;code&amp;gt;FormattedDecimalLabel&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;css&amp;quot;&amp;gt;current: “&amp;lt;DecimalLabel.current * 100&amp;gt;%”&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Whenever &amp;lt;code&amp;gt;DecimalLabel.current&amp;lt;/code&amp;gt; changes, &amp;lt;code&amp;gt;current&amp;lt;/code&amp;gt; here will also change. It is not simply an initialization that is set once. Presently, there is no formal way of specifying that a declaration should be an initialization only and non-binding as a use-case has not come up.&lt;br /&gt;
&lt;br /&gt;
== Ordering ==&lt;br /&gt;
&lt;br /&gt;
List children top to bottom from innermost to outermost. If there are children at the same level in the hierarchy (siblings), they should be ordered from simplest to most complex (a more complex component is one with more children, e.g. &amp;lt;code&amp;gt;ListItem&amp;lt;/code&amp;gt; is simpler than &amp;lt;code&amp;gt;ScrollableListBox&amp;lt;/code&amp;gt;). If siblings have the same complexity, they should appear in the order they occur when scanning the component from left to right and top to bottom. Each child occupies a full row, with its scenarios separated into columns.&lt;br /&gt;
&lt;br /&gt;
=== Example: AccountListItem ===&lt;br /&gt;
&lt;br /&gt;
[[File:AccountListItem_preview_outline.png|Preview of AccountListItem with children marked]]&lt;br /&gt;
&lt;br /&gt;
In the &amp;lt;code&amp;gt;AccountListItem&amp;lt;/code&amp;gt; example, there are three children responsible for displaying three pieces of data: - Identicon: an &amp;lt;code&amp;gt;Icon&amp;lt;/code&amp;gt; that displays the identicon for the account - ID: a &amp;lt;code&amp;gt;Label&amp;lt;/code&amp;gt; that displays the account user id - Name: a &amp;lt;code&amp;gt;Label&amp;lt;/code&amp;gt; that displays the name associated with the account&lt;br /&gt;
&lt;br /&gt;
[[File:AccountListItem_components.png|720px|Definition cards for AccountListItem's children]]&lt;br /&gt;
&lt;br /&gt;
With the exception of &amp;lt;code&amp;gt;Identicon&amp;lt;/code&amp;gt;, the children are siblings, so the ordering of them follows their layout. Note that there is a &amp;lt;code&amp;gt;Box&amp;lt;/code&amp;gt; named &amp;lt;code&amp;gt;IdenticonBox&amp;lt;/code&amp;gt; that contains the &amp;lt;code&amp;gt;Identicon&amp;lt;/code&amp;gt; and it comes below the &amp;lt;code&amp;gt;Identicon&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Example: OpenFilterPanel ===&lt;br /&gt;
&lt;br /&gt;
[[File:OpenFilterPanel_preview_outline.png|720px|Preview of OpenFilterPanel with children marked]]&lt;br /&gt;
&lt;br /&gt;
The outermost component is &amp;lt;code&amp;gt;FilterPanel&amp;lt;/code&amp;gt;. It contains a reset button and a slot for placing the specific filtering controls. Since the &amp;lt;code&amp;gt;components.xd&amp;lt;/code&amp;gt; for &amp;lt;code&amp;gt;FilterPanel&amp;lt;/code&amp;gt; already handles the reset button, it doesn’t need to be handled here. The direct children of the slot are &amp;lt;code&amp;gt;RadioButtons&amp;lt;/code&amp;gt;, a group of two radio buttons, and &amp;lt;code&amp;gt;TagComboBox&amp;lt;/code&amp;gt;. The radio buttons &amp;lt;code&amp;gt;Include&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;Exclude&amp;lt;/code&amp;gt; are the children of &amp;lt;code&amp;gt;RadioButtons&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[File:OpenFilterPanel_components.png|720px|Definition cards for OpenFilterPanel's children]]&lt;br /&gt;
&lt;br /&gt;
In the breakdown, &amp;lt;code&amp;gt;Include&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;Exclude&amp;lt;/code&amp;gt; come first, followed by &amp;lt;code&amp;gt;RadioButtons&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;TagComboBox&amp;lt;/code&amp;gt;, with &amp;lt;code&amp;gt;FilterPanel&amp;lt;/code&amp;gt; last.&lt;br /&gt;
&lt;br /&gt;
== Usage ==&lt;br /&gt;
&lt;br /&gt;
It is recommended to use &amp;lt;code&amp;gt;components.xd&amp;lt;/code&amp;gt; as fully as possible before considering putting information into &amp;lt;code&amp;gt;layout.xd&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;user_flow.drawio&amp;lt;/code&amp;gt;. Conditional styling via scenarios is a powerful and readable way to declaratively style a component.&lt;/div&gt;</summary>
		<author><name>Jon</name></author>
		
	</entry>
</feed>