Runtime attributes
The data-dash roles and every data attribute the Dashies dashboard runtime reads, including the viewer controls and time intelligence.
A published dashboard is one HTML file. The runtime finds every element carrying
data-dash, reads the other data-* attributes on it to learn what to render,
and resolves each value against the data island.
You get these attributes for free when you publish
a spec with tiles. You write them by hand only in
look mode, where the markup is yours. Either way the same
runtime reads them, and every binding must resolve against a declared dataset or
the publish is refused.
Roles
data-dash names what an element is. Seventeen values are recognised.
| Role | Rendered by the spec tile |
|---|---|
metric | kpi |
chart | chart |
table | table |
matrix | matrix |
heatmap | heatmap |
scatter | scatter |
treemap | treemap |
waterfall | waterfall |
funnel | funnel |
drilldown | drilldown |
stacked | stacked |
combo | combo |
pie | pie |
donut | donut |
gauge | gauge |
filter | filter |
updated-at | emitted once per dashboard, not by a tile |
The kpi tile compiles to data-dash="metric"; that is the only case where the
tile type and the role differ in name. The text and custom tiles carry no
data-dash at all: one is prose and the other is markup you own.
data-dash="updated-at" marks the span that receives the freshness stamp. It
takes no other attributes.
Routing
| Attribute | Value | Notes |
|---|---|---|
data-dataset | a dataset name | Which dataset this tile reads. Emitted on every bound tile when the dashboard declares more than one; with a single dataset it is omitted and the runtime uses that one. |
Binding a value
| Attribute | Value | Read by |
|---|---|---|
data-measure | a measure key | Every role that shows a figure. |
data-measures | comma-separated measure keys | chart, for a multi-series chart. |
data-measure2 | a measure key | combo, the secondary axis. |
data-num, data-den | measure keys | Any role showing a ratio. The ratio is computed under the current filters, never stored. |
data-num-scope, data-den-scope | all | Computes that side of the ratio over the unfiltered dataset, which is how a share-of-total is expressed. |
data-num2, data-den2 | measure keys | combo, a ratio on the secondary axis. |
data-agg | an aggregate name | An override the compiler never emits. It is honoured only where it agrees with the stored measure; a claim the data cannot support renders unavailable. |
Naming a dimension
| Attribute | Value | Read by |
|---|---|---|
data-x | a dimension key | chart, stacked, combo, treemap, waterfall, funnel, pie, donut. |
data-rows, data-cols | dimension keys | matrix, heatmap. |
data-point | a dimension key | scatter, one point per member. |
data-levels | comma-separated dimension keys | drilldown, outermost first. |
data-series | a dimension key | chart, stacked. |
data-dim | a dimension key | filter. |
Shape and scale
| Attribute | Value | Read by |
|---|---|---|
data-type | bar, hbar, line, area | chart, stacked. |
data-type2 | bar, line, area | combo, the secondary series. |
data-stack | normal, percent | stacked. |
data-axis-sync | present | combo, forces both axes onto one scale. |
data-subtotals | both, row, col, none | matrix, heatmap. |
data-color | heat, diverging | matrix, heatmap. |
data-min, data-max, data-target | numbers | gauge. These are numeric literals, not measure keys. |
data-stages | comma-separated dimension values | funnel, in the order the funnel runs. |
data-top-n, data-other, data-total | a number, then two flags | drilldown. |
How much, and how big
| Attribute | Value | Read by |
|---|---|---|
data-limit | an integer | Members rendered before truncation. The ceiling differs per role: see Tile types. |
data-sort | value-desc, value-asc, or <key>:asc / <key>:desc on a table | chart, table. |
data-columns, data-group | column keys | table. |
data-height | 120 to 800 | Every drawn chart role. |
Display
| Attribute | Value | Notes |
|---|---|---|
data-label | a string | The visible label, on a filter. |
data-format | a format name | How to render the figure. data-format2 is the combo secondary. |
data-currency | an ISO 4217 code | Emitted only where it differs from the dashboard's global currency. |
data-decimals | 0 to 6 | Same rule. |
data-scale | a divisor | Inert. The compiler emits it on a ratio binding and no runtime fragment reads it, so it changes nothing. It is why a measure declaring scale: cents or scale: points is refused at publish rather than rendered at 100 times its value. |
Viewer controls
These are what make a published page interactive without a server. Each is read at view time and changes only what is on screen.
| Attribute | Value | Effect |
|---|---|---|
data-multi | present | The filter becomes a multi-select listbox instead of a single-select. |
data-range | present | The filter becomes a range selector. A tile may carry data-multi or data-range, never both. |
data-controls | control names | Adds live sort and limit controls to a chart or table, so a reader can reorder or widen it. |
data-xfilter | present | Clicking a bar filters the rest of the dashboard by that member. |
data-drill | a dataset name | Clicking the tile opens a modal showing that dataset's detail for the clicked member. |
data-tile | a tile id | The identity a control or cross-filter addresses. Emitted alongside the two above. |
A multi-select or range filter changes which cells the resolver has to combine,
which is why declaring one can change the dataset mode a spec needs. See
how mode is resolved.
Time intelligence
Four attributes, on a metric tile only. The compiler does not emit these;
they are available in look mode and on hand-written markup.
| Attribute | Value |
|---|---|
data-timeintel | the date dimension key to walk |
data-compare | yoy, qoq, mom, pop, ytd, running, movavg |
data-compare-as | pct, delta, prior, current. Defaults to pct. Applies to a shift mode only |
data-window | 2 to 1,000, required by movavg |
yoy, qoq and mom shift the anchor period back 12, 3 and 1 months. pop
steps to the previous period actually present in the series rather than a
calendar guess. ytd and running accumulate up to and including the anchor.
Every one of these resolves at view time out of cells a lattice already precomputed, so the comparison stays correct under whatever filter is applied. A comparison composes two resolutions, so both must be exact: where a prior period is missing, the tile renders unavailable rather than treating the absence as a zero and reporting a confident growth figure.
That means a comparison needs a lattice or hybrid dataset. On a plain cube
or a row-level dataset the tile says so and renders nothing.
What a tile cannot do
A published dashboard is served with Content-Security-Policy: sandbox allow-scripts. Scripts run, including a custom tile's js, but the page is
placed in an opaque origin. That is not configurable.
| Capability | Under the sandbox |
|---|---|
| Script execution | allowed, which is what allow-scripts grants |
localStorage, sessionStorage, IndexedDB, cookies | denied, and access throws |
| Same-origin authenticated fetch | denied, because the origin is opaque |
Cross-origin fetch | not restricted |
This isolates the page from your Dashies account. It does not confine the page.
There is no connect-src and no default-src in that header, so a
cross-origin fetch from a custom tile is not blocked. The product relies
on exactly that: the row-level query engine is loaded cross-origin from
data.dashies.xyz under this same header, and that cross-origin split is what
preserves the isolation in the first place.
What the sandbox buys is the thing that matters on a shared origin. A published
dashboard is served from a host the Dashies app also uses, so without the opaque
origin any markup an author included could read a viewer's session out of
localStorage. The sandbox makes that impossible. It is not a promise that the
page talks to nothing.
Two variants add a framing rule on top: a private dashboard is served with
frame-ancestors 'none', and a preview with frame-ancestors 'self'. Those
constrain who may frame the page, not what the page may read.
The practical consequence for a custom tile is still that it should draw only
from the datasets named in its reads, which the runtime hands it directly.
Anything it fetches itself is outside the refresh contract: it is not versioned,
not seeded, not re-run on the schedule, and not covered by any of the
correctness checks on this site.
Check it worked
Open the published dashboard and change a filter. Every bound tile should either
update or state a reason it cannot. A tile that renders a stale figure after a
filter change is reading something other than the resolver, which for a custom
tile means its js is holding its own copy of the numbers.