InfoCards
The Dashboard page opens with a set of infocards. Here is a simplified version of two of them.
<App
var.dashboardStats="{
{ value: [ { outstanding: 3569, paid_this_year: 1745} ] }
}"
>
<HStack>
<Card>
<Text>Outstanding</Text>
<Text>{ dashboardStats.value[0].outstanding } </Text>
</Card>
<Card>
<Text>Paid this year</Text>
<Text>{ dashboardStats.value[0].paid_this_year } </Text>
</Card>
</HStack>
</App><App
var.dashboardStats="{
{ value: [ { outstanding: 3569, paid_this_year: 1745} ] }
}"
>
<HStack>
<Card>
<Text>Outstanding</Text>
<Text>{ dashboardStats.value[0].outstanding } </Text>
</Card>
<Card>
<Text>Paid this year</Text>
<Text>{ dashboardStats.value[0].paid_this_year } </Text>
</Card>
</HStack>
</App>The definition of
var.dashboardStatsuses two sets of curly braces. The outer braces enclose the JavaScript expression to be evaluated. The inner braces enclose a literal object that emulates data returned from an API.
In the real app, dashboardStats is a DataSource.
<DataSource id="dashboardStats" url="/api/dashboard/stats" method="GET" />It returns a structure like the variable we've defined above: an object with a value key that points to a list of objects corresponding to rows in the database.
A custom Card
There are five infocards on the XMLUI Invoice dashboard. To style them all in a consistent way, the app defines an InfoCard that wraps Card and Text.
<Component name="InfoCard">
<Card width="{$props.width}" borderRadius="8px" boxShadow="$boxShadow-spread">
<Text>{$props.title}</Text>
<Text fontWeight="$fontWeight-extra-bold" fontSize="larger">
{ $props.currency === 'true' ? '$' + $props.value : $props.value }
</Text>
</Card>
</Component>These are in turn wrapped in a Dashboard that passes properties to InfoCard: title, width, value, and optionally a currency flag for $ formatting.
<Component name="Dashboard">
<DataSource id="dashboardStats" url="/api/dashboard/stats" method="GET"/>
<HStack>
<H1>Dashboard</H1>
<SpaceFiller/>
<Button label="Create Invoice" onClick="navigate('/invoices/new')"/>
</HStack>
<FlowLayout>
<InfoCard
width="20%"
title="Outstanding"
value="{ dashboardStats.value[0] }"
currency='true'
/>
<InfoCard
...
/>
<InfoCard
...
/>
<InfoCard
...
/>
<InfoCard
...
/>
<Statuses width="50%" title="Statuses"/>
<MonthlyStatus width="50%" title="Monthly Status"/>
</FlowLayout>
<DailyRevenue title="Daily Revenue"/>
</Component>A user-defined component like Dashboard can define any set of names and values. InfoCard receives them in its $props context variable. InfoCard is opinionated about borderRadius and boxShadow. It could also receive these in $props but chooses not to. And while it is strongly opinionated about the borderRadius, which it hardcodes, it is willing to use the theme variable $boxShadow-spread so that setting can be theme-governed.
Here's a more complete version of the row of InfoCards used in the Invoices app.
<App>
<Dashboard />
</App><App>
<Dashboard />
</App>