Template Components

Hierarchical Table

A multi-level adaptive table in VaultPDF. Renders deeply nested JSON arrays as progressive depth tables with per-level styling, overflow sub-rows, conditional cell styles, computations, and hierarchyRules-driven layout.

Overview

A Hierarchical Table (hierarchical_table) is VaultPDF's most powerful data rendering node. It recursively processes any nested array structure (e.g. orders, line items, serial numbers) and renders each depth level as its own table, indented beneath the parent row.

Place one hierarchical_table node in your template and bind it to a top-level array in the payload. Visual defaults adapt automatically to the data volume, and hierarchyRules give you fine-grained control over every depth level.


Title & Icon

PropertyTypeDefaultDescription
titlestringnoneHeading rendered above the table. Supports {FIELDNAME} tokens.
titleIconselectnoneIcon key displayed next to the title (e.g. package, user, calendar).
idstringnoneUnique identifier for this node. Required when multiple hierarchical tables exist in the same template to prevent column display conflicts between nodes.

Data Binding

PropertyPathDescription
dataSourceprops.dataSourcePlaceholder that resolves to the root array at render time. Must use double-brace syntax: {{arrayFieldName}}. Example: {{salesOrders}}.
maxColsprops.maxColsMaximum number of columns that the adaptive renderer will display per depth level before auto-truncating.
marginprops.marginFour-element pt margin [left, top, right, bottom] applied to the entire rendered block.

hierarchyRules

hierarchyRules is the JSON object that controls everything about how each depth level of the hierarchy is displayed. It lives at the top level of your JSON payload (or on the template's docDefinition) and is threaded through to the adaptive renderer automatically.

{
  "hierarchyRules": {
    "fieldVisibility": { },
    "levelStyling": { "2": { }, "3": { } },
    "computations": [ ]
  }
}

fieldVisibility

Controls which fields are shown or hidden per depth level. Values can be:

  • true / false - always show / always hide across all levels.
  • A JavaScript expression string (evaluated with level and the row's data context in scope).
"fieldVisibility": {
  "internalCode": false,
  "adjustedQty":  "level >= 3 && adjustedQty > 0"
}

levelStyling

levelStyling is a map from depth-level number (as a string key, e.g. "2", "3") to a LevelStyling object that overrides the defaults for that level.

Level numbering: Level 1 is the root scalar/header section. Level 2 is the first array (main table). Level 3 is a nested array within each level-2 row, and so on.

Default behavior by level:

LevelDefault borderStyleDefault fontSizeDefault format
2"full"10pt"table"
3"minimal"9pt"table"
4"none"8.5pt"table"
5+"none"8pt"compact-kv"

Theme-Aware Colors

Color properties in levelStyling are theme-aware by default when omitted. The renderer falls back to theme.primary for headerBackground, theme.textOnPrimary for headerText, theme.borderColor for borderColor, and theme.stripeShade for stripeShade. Only set these explicitly when you need to override the active theme for a specific level.

LevelStyling Properties

PropertyTypeDescription
fontSizenumberFont size (pt) for all data cells at this level.
borderStyle"full" | "minimal" | "none""full" - full grid. "minimal" - row separators only. "none" - no borders.
borderColorstringHex color for all table lines at this level.
colorstringDefault text color for data cells.
fillColorstringRow background color applied to all rows (bypasses zebra stripes when set).
indentationnumberLeft indent (pt) added to the nested table to visually represent hierarchy depth.
maxColumnsnumberMaximum columns rendered at this level (extra columns are truncated). Default: 20.
showHeadersbooleanShow or hide the header row at this level. Default: true for levels 2-4.
format"table" | "compact-kv" | "mini-table"Rendering format. "table" - standard row/column grid. "compact-kv" - key-value pairs in a tight two-column layout. "mini-table" - compact table with reduced padding.
hiddenColumnsnumber[]Zero-based column indices to suppress from the output at this level.
showSummarybooleanRender a summary bar below this level's table.
summaryFieldsstring[]Field names included in the summary bar (requires showSummary: true).
headerBackgroundstringHex color override for the header row fill color at this level.
headerTextstringHex color override for header label text at this level.
stripeShadestringHex color override for zebra-stripe rows at this level.
stripeOpacitynumber (0-1)Opacity of zebra stripes. 0 disables stripes entirely, 1 is full opacity.
vLineWidthnumberVertical line width (pt) - only applied when borderStyle is "full".
hLineWidthnumberHorizontal row-separator line width (pt).
headerLineWidthnumberHeader separator line width (pt).
titleIconstringIcon key shown next to the section/table title at this level in the adaptive renderer.
columnFormatsRecord<string, string>Lightweight per-field format map - alternative to a full columnManifest. Keys are field names; values are format strings ("currency", "number", "date", "datetime", "boolean").
columnManifestColumnManifestFull column manifest (see Column Manifest below). When present, overrides all auto-detected column layout for this level.

Theme-driven (recommended):

Omitting color properties entirely lets every table inherit the active theme automatically. Only set what you want to override.

"hierarchyRules": {
  "levelStyling": {
    "2": {
      "fontSize": 10,
      "borderStyle": "full",
      "stripeOpacity": 0.4,
      "columnFormats": { "unitPrice": "currency", "qty": "number", "shipDate": "date" }
    },
    "3": {
      "fontSize": 9,
      "borderStyle": "minimal",
      "format": "compact-kv"
    }
  }
}

With explicit color overrides:

Provide hex values only when the active theme should be overridden for a specific level.

"hierarchyRules": {
  "levelStyling": {
    "2": {
      "fontSize": 10,
      "borderStyle": "full",
      "headerBackground": "#1E3A5F",
      "headerText": "#FFFFFF",
      "borderColor": "#CBD5E1",
      "stripeShade": "#F1F5F9",
      "stripeOpacity": 0.5
    }
  }
}

Theme Token Mapping

The Universal Adaptive Renderer maps theme tokens to visual elements as follows. All three render paths use the same mapping.

Header Background Colors

LevelToken ResolvedFallback Chain
Level 2 (main table)primary#F0F0F0
Level 3+ (nested tables)secondaryheaderShade#DBEAFE
"colors": {
  "primary":     "#1D4ED8",   // Level 2 header fill (bold branded bar)
  "secondary":   "#E0F2FE",   // Level 3+ header fill (lighter nested header)
  "headerShade": "#F4F4F6"    // Fallback for level 3+ when secondary is absent
}

Token Precedence

secondary and headerShade are distinct tokens and never cross-resolve. If your theme defines headerShade but not secondary, level 3+ headers fall back through headerShade. If both are defined, secondary always wins for nested table headers.

Full Theme Token Reference

TokenUsed ForExample
primaryLevel 2 table header fill; card accent bars; primary buttons"#1D4ED8"
secondaryLevel 3+ table header fill; accent fills"#E0F2FE"
headerShadeFallback header fill when secondary is absent"#F4F4F6"
stripeShadeZebra-stripe row background"#F9FAFB"
textOnPrimaryHeader text on primary-colored cells"#FFFFFF"
textOnShadeHeader text on secondary/headerShade-colored cells; body text"#0F172A"
borderColorAll table lines, card borders, separator lines"#BFDBFE"
secondaryTextAccented value text (e.g., links, highlighted values)"#0673BC"
successConditional-style icon/text for success states"#16A34A"
warningConditional-style icon/text for warning states"#D97706"
errorConditional-style icon/text for error states"#DC2626"
infoConditional-style icon/text for informational states"#2563EB"

Theme Source Priority

The renderer resolves the active theme in the following order (first match wins):

  1. Payload theme block — a "theme" key at the root of the API request body.
  2. Data theme block — a "theme" key inside the data payload JSON itself.
  3. Template theme block — the "theme" object in the .vpdf template file.

In production, theme is almost always supplied by the template. The payload theme is only used for one-off overrides during testing. If no theme is found, all colors fall back to built-in defaults.

// Template theme block (recommended — lives in the .vpdf file)
"theme": {
  "type": "modern",
  "colors": {
    "primary":       "#1D4ED8",
    "secondary":     "#E0F2FE",
    "headerShade":   "#F4F4F6",
    "stripeShade":   "#F9FAFB",
    "textOnPrimary": "#FFFFFF",
    "textOnShade":   "#0F172A",
    "borderColor":   "#BFDBFE"
  },
  "typography": { "font": "Inter" }
}

computations

Computations are aggregation rules applied before rendering. They allow derived fields (sums, counts, averages) to be computed from deeper arrays and written back onto the parent-level records at render time.

PropertyDescription
levelThe depth level where the computation result is written (e.g. 2 = write onto the main array row).
fieldThe field name to write the result into on the parent record.
labelOptional display label used in summary bars (e.g. "Total Quantity").
typeAggregate function: "sum", "count", "avg", "min", "max", or "formula".
formulaMath expression string (e.g. "quantity * unitPrice") evaluated per record. Required when type is "formula".
sourceNested array field name to aggregate from (e.g. "bins" to sum bins[].quantity).
aggregateFieldField name within the source array to aggregate (e.g. "quantity").
conditionJavaScript expression that must be truthy for a record to be included (e.g. "quantity > 0").
formatOptional format hint applied to the result when rendering ("currency", "number", etc.).

Example - sum quantities from a nested bins array onto each order row:

"computations": [
  {
    "level": 2,
    "field": "totalQty",
    "label": "Total Quantity",
    "type": "sum",
    "source": "bins",
    "aggregateField": "quantity",
    "format": "number"
  },
  {
    "level": 2,
    "field": "lineTotal",
    "type": "formula",
    "formula": "qty * unitPrice",
    "format": "currency"
  }
]

Column Manifest

A ColumnManifest gives you full, explicit control over column layout, overflow rows, and per-cell conditional styling. It can be placed either directly in the template node's props.columnManifest or inside hierarchyRules.levelStyling["2"].columnManifest.

Minimal starting point:

"columnManifest": {
  "maxCols": 5,
  "columns": [
    { "key": "id",          "label": "ID",          "displayOrder": 1, "primary": true,  "width": 60,  "align": "left" },
    { "key": "description", "label": "Description", "displayOrder": 2, "primary": true,  "width": "*", "align": "left" },
    { "key": "qty",         "label": "Qty",         "displayOrder": 3, "primary": true,  "width": 50,  "align": "right", "format": "number" },
    { "key": "unitPrice",   "label": "Unit Price",  "displayOrder": 4, "primary": true,  "width": 70,  "align": "right", "format": "currency" },
    { "key": "notes",       "label": "Notes",       "displayOrder": 5, "primary": false,
      "layout": { "span": "full", "icon": "FileText" }
    }
  ],
  "overflowStrategy": {
    "mode": "additionalRow",
    "columnsPerRow": 2,
    "indent": 12,
    "columnGap": 8,
    "borderStyle": "dashed",
    "fontSizeAdjustment": -1
  }
}

ColumnManifest Properties

PropertyTypeDescription
maxColsnumberInformational hint - the actual visible column count is driven by primary flags on each ColumnDefinition.
columnsColumnDefinition[]Ordered list of all columns (primary and overflow).
overflowStrategyOverflowStrategyDescribes how non-primary columns are rendered below each data row.
allCapsbooleanWhen true, all data-cell text is rendered in upper case. Header labels are unaffected. Default: false.
fontSizenumberOverride the font size (pt) for every data cell in the table.
valueBoldbooleanWhen true, all data-cell values are rendered bold. Default: false.

ColumnDefinition Properties

PropertyTypeDescription
keystringData field name - maps to the row object's property.
labelstringColumn header text.
displayOrdernumber1-based sort order. Lower values appear first. Must be unique per manifest.
primarybooleantrue - rendered in the main row. false - rendered in the overflow sub-row.
widthnumber | "auto" | "*"Column width passed to the document engine.
align"left" | "right" | "center"Text alignment for header and data cells.
formatstringFormat hint: text, number, currency, date, datetime, boolean, percentage, barcode, qr.
labelWidthnumberFixed pt width for the label portion inside an overflow key-value pair.
currencyPartial<CurrencySettings>Per-column currency override (wins over templateSettings.currency).
numberPartial<NumberSettings>Per-column number format override.
booleanPartial<BooleanSettings>Per-column boolean label/icon override.
fontSizenumberPer-column font size (overrides manifest-level fontSize).
allCapsbooleanPer-column upper-case override.
valueBoldbooleanPer-column bold override.
conditionalStylesConditionalStyle[]Value-driven per-cell styling rules (see below).
layoutobjectOverflow layout options (see below).

Conditional Styles

conditionalStyles is an ordered list of ConditionalStyle rules. The first matching rule wins. Use "default" as the value for a catch-all fallback.

"conditionalStyles": [
  { "value": "Success", "icon": "CheckCircle",   "color": "#10B981", "bgColor": "#ECFDF5" },
  { "value": "Fail",    "icon": "XCircle",       "color": "#EF4444", "bgColor": "#FEF2F2" },
  { "value": "Warning", "icon": "AlertTriangle", "color": "#B45309", "bgColor": "#FEF3C7" },
  { "value": "default", "icon": "",              "color": "#374151", "bgColor": "#F9FAFB" }
]
PropertyDescription
valueCell value to match (case-insensitive). Use "default" for a catch-all.
iconIcon key from the icon registry, or "" for no icon.
colorText color (and icon stroke) when the rule matches. Hex string.
bgColorCell background fill color when the rule matches. Hex string.

Column Layout (Overflow)

The optional layout object on a ColumnDefinition controls how that column appears in the overflow sub-row.

PropertyTypeDescription
span"auto" | "full""auto" (default) - participates in the grid. "full" - spans the full overflow row width; any partially-filled grid row is flushed first.
iconstringIcon key rendered before the label. Only meaningful when span: "full".
displayAsListbooleanWhen true and the column value is an array, render each element as a bullet-point line. Only meaningful when span: "full".
showTitlebooleanWhen false, the label cell is omitted and the value spans the full row width. Default: true. Only meaningful when span: "full".
style.bgColorstringOverride overflow row background fill.
style.textColorstringOverride overflow row text color.
style.fontWeight"bold" | "normal"Override overflow row font weight.

OverflowStrategy Properties

PropertyTypeDescription
mode"additionalRow"Currently the only supported mode. Non-primary columns appear as an additional sub-row per data row.
columnsPerRownumberNumber of overflow key-value pairs rendered side-by-side per sub-row line.
indentnumberLeft margin (pt) of the overflow cell - creates visual indentation.
columnGapnumberGap (pt) between neighboring key-value pairs within one sub-row line.
borderStyle"dashed" | "solid" | "none"Style of the separator line between the main row and the overflow sub-row. "dashed" is recommended.
fontSizeAdjustmentnumberSigned delta applied to the base font size for overflow content (e.g. -1 to make overflow text slightly smaller).
separator.enabledbooleanShow a vertical separator glyph between grid pairs.
separator.typestringCharacter(s) to use as the separator (e.g. "|", "•").
separator.widthnumberColumn width (pt) reserved for the separator glyph. Default: 6.
separator.colorstringHex color for the separator. Falls back to theme.borderColor.

Sections (Level-1 Key-Value)

When the JSON payload root is a plain object (not an array), the Universal Adaptive Renderer automatically renders its scalar fields as a header key-value section before the first array table. This section is referred to as the Level-1 section.

  • Scalar fields and primitive arrays are collected and rendered as bold key: value pairs.
  • Plain nested objects (non-array) are rendered as indented sub-sections with their own bold headers.
  • Record arrays at the root level become the Level-2 tables.

Fields are excluded from the Level-1 section when:

  • Their key starts with _.
  • They are reserved control keys: theme, activeTheme, metadata, hierarchyRules, __meta, __schema.
  • fieldVisibility sets them to false.

Tip

To control which scalars appear in the header section, use hierarchyRules.fieldVisibility to hide fields you don't need at the top level. For example: "fieldVisibility": { "internalId": false, "rawPayload": false }.


Auto-Generated Sections

Each record array within the JSON payload produces a titled section block in the rendered document. VaultPDF assigns a title to each block derived from the array's key name (formatted to title case). These sections:

  • Can be numbered sequentially when templateSettings.sectionNumbering is true.
  • Can appear in the Table of Contents when templateSettings.toc.enabled is true.
  • Respect per-section TOC exclusions via hierarchyRules or section settings.

Styling (Inspector)

The following properties are exposed in the Designer inspector under the Styling panel for hierarchical_table nodes:

PropertyPathDescription
stripeOpacityprops.stripeOpacityOpacity of zebra-stripe rows across all levels (0-1). Overrides the levelStyling value for the root table.

Deeper per-level overrides (header colors, borders, line widths) are set via hierarchyRules.levelStyling in the JSON payload.


Pagination

Pagination for hierarchical tables is controlled by the parent section's or node's pagination settings. Block margins are set automatically based on the volume of data in the payload.


Examples

1 - Simple flat list (no hierarchy)

The simplest case: a single-level array, theme-driven colors, basic column formats.

{
  "hierarchyRules": {
    "levelStyling": {
      "2": {
        "fontSize": 10,
        "borderStyle": "full",
        "stripeOpacity": 0.4,
        "columnFormats": {
          "unitPrice": "currency",
          "qty": "number",
          "shipDate": "date"
        }
      }
    }
  },
  "items": [
    { "partNumber": "P-1001", "description": "Widget Alpha", "qty": 5, "unitPrice": 49.99, "shipDate": "2026-03-20" }
  ]
}

2 - Overflow columns: grid layout

Overflow columns with primary: false and span: "auto" are placed in a key-value grid below each main row. columnsPerRow controls how many pairs sit side-by-side.

{
  "hierarchyRules": {
    "levelStyling": {
      "2": {
        "fontSize": 10,
        "borderStyle": "full",
        "columnManifest": {
          "maxCols": 5,
          "columns": [
            { "key": "partNumber",  "label": "Part #",      "displayOrder": 1, "primary": true,  "width": 80,  "align": "left" },
            { "key": "description", "label": "Description", "displayOrder": 2, "primary": true,  "width": "*", "align": "left" },
            { "key": "qty",         "label": "Qty",         "displayOrder": 3, "primary": true,  "width": 50,  "align": "right", "format": "number" },
            { "key": "unitPrice",   "label": "Unit Price",  "displayOrder": 4, "primary": true,  "width": 70,  "align": "right", "format": "currency" },
            { "key": "warehouse",   "label": "Warehouse",   "displayOrder": 5, "primary": false, "align": "left" },
            { "key": "batchNumber", "label": "Batch #",     "displayOrder": 6, "primary": false, "align": "left" },
            { "key": "expiryDate",  "label": "Expiry",      "displayOrder": 7, "primary": false, "align": "left", "format": "date" },
            { "key": "supplier",    "label": "Supplier",    "displayOrder": 8, "primary": false, "align": "left" }
          ],
          "overflowStrategy": {
            "mode": "additionalRow",
            "columnsPerRow": 2,
            "indent": 12,
            "columnGap": 8,
            "borderStyle": "dashed",
            "fontSizeAdjustment": -1
          }
        }
      }
    }
  },
  "items": [
    {
      "partNumber": "P-1001", "description": "Widget Alpha", "qty": 5, "unitPrice": 49.99,
      "warehouse": "WH-A", "batchNumber": "B-20260301", "expiryDate": "2027-03-01", "supplier": "Acme Corp"
    }
  ]
}

Empty Overflow Columns

Overflow columns are skipped automatically when their value is empty or null for a given row - no blank sub-rows appear.


3 - Overflow columns: full-span rows

Use span: "full" for long text fields (notes, descriptions, addresses) that should occupy the entire row width. Full-span rows always appear on their own line and flush any in-progress grid row first.

{
  "hierarchyRules": {
    "levelStyling": {
      "2": {
        "fontSize": 10,
        "borderStyle": "full",
        "columnManifest": {
          "maxCols": 4,
          "columns": [
            { "key": "id",          "label": "ID",          "displayOrder": 1, "primary": true,  "width": 60,  "align": "left" },
            { "key": "subject",     "label": "Subject",     "displayOrder": 2, "primary": true,  "width": "*", "align": "left" },
            { "key": "priority",    "label": "Priority",    "displayOrder": 3, "primary": true,  "width": 70,  "align": "center" },
            { "key": "status",      "label": "Status",      "displayOrder": 4, "primary": true,  "width": 70,  "align": "center" },
            {
              "key": "description", "label": "Description", "displayOrder": 5, "primary": false,
              "layout": { "span": "full", "icon": "FileText", "showTitle": true }
            },
            {
              "key": "resolution",  "label": "Resolution",  "displayOrder": 6, "primary": false,
              "layout": {
                "span": "full", "icon": "CheckCircle", "showTitle": true,
                "style": { "bgColor": "#ECFDF5", "textColor": "#065F46", "fontWeight": "bold" }
              }
            }
          ],
          "overflowStrategy": {
            "mode": "additionalRow",
            "columnsPerRow": 2,
            "indent": 0,
            "columnGap": 8,
            "borderStyle": "solid",
            "fontSizeAdjustment": 0
          }
        }
      }
    }
  },
  "tickets": [
    {
      "id": "T-001", "subject": "Login failure on mobile", "priority": "High", "status": "Resolved",
      "description": "Users on iOS 17 cannot log in after the March update. Affects all accounts using SSO.",
      "resolution": "Rolled back SSO provider to v2.3.1. Permanent fix scheduled for April sprint."
    }
  ]
}

4 - Mixed overflow: grid pairs and full-span rows

Combine span: "auto" grid columns with span: "full" rows in the same manifest. Grid pairs render first (in column order), then full-span rows follow - each flushing any partial grid row before starting.

"columnManifest": {
  "maxCols": 5,
  "columns": [
    { "key": "partNumber",  "label": "Part #",      "displayOrder": 1, "primary": true,  "width": 80 },
    { "key": "description", "label": "Description", "displayOrder": 2, "primary": true,  "width": "*" },
    { "key": "qty",         "label": "Qty",         "displayOrder": 3, "primary": true,  "width": 50,  "format": "number" },
    { "key": "unitPrice",   "label": "Unit Price",  "displayOrder": 4, "primary": true,  "width": 70,  "format": "currency" },
    { "key": "warehouse",   "label": "Warehouse",   "displayOrder": 5, "primary": false },
    { "key": "batchNumber", "label": "Batch #",     "displayOrder": 6, "primary": false },
    {
      "key": "notes", "label": "Notes", "displayOrder": 7, "primary": false,
      "layout": { "span": "full", "icon": "FileText" }
    },
    {
      "key": "tags", "label": "Tags", "displayOrder": 8, "primary": false,
      "layout": { "span": "full", "icon": "Tag", "displayAsList": true }
    }
  ],
  "overflowStrategy": {
    "mode": "additionalRow",
    "columnsPerRow": 2,
    "indent": 12,
    "columnGap": 8,
    "borderStyle": "dashed",
    "fontSizeAdjustment": -1
  }
}

displayAsList

displayAsList: true renders an array value as a bullet-point list, one element per line. Only meaningful on span: "full" columns.


5 - Overflow with vertical separator

Add a visual | separator between key-value pairs in the grid row.

"overflowStrategy": {
  "mode": "additionalRow",
  "columnsPerRow": 3,
  "indent": 12,
  "columnGap": 10,
  "borderStyle": "dashed",
  "fontSizeAdjustment": -1,
  "separator": {
    "enabled": true,
    "type": "|",
    "width": 8,
    "color": "#CBD5E1"
  }
}

6 - showSummary with computations

showSummary renders a themed summary bar (primary color fill, right-aligned) at the bottom of each level-2 item block. Fields listed in summaryFields are excluded from the main table columns and shown only in the bar.

The typical pattern:

  1. Add a computation that aggregates nested data into a field on the parent row.
  2. List that field name in summaryFields.
  3. Enable showSummary: true.
{
  "hierarchyRules": {
    "levelStyling": {
      "2": {
        "fontSize": 10,
        "borderStyle": "full",
        "showSummary": true,
        "summaryFields": ["totalQty", "totalValue"]
      },
      "3": {
        "fontSize": 9,
        "borderStyle": "minimal"
      }
    },
    "computations": [
      {
        "level": 2,
        "field": "totalQty",
        "label": "Total Qty",
        "type": "sum",
        "source": "lines",
        "aggregateField": "qty",
        "format": "number"
      },
      {
        "level": 2,
        "field": "totalValue",
        "label": "Order Value",
        "type": "sum",
        "source": "lines",
        "aggregateField": "lineTotal",
        "format": "currency"
      }
    ]
  },
  "orders": [
    {
      "orderNumber": "SO-1001",
      "customer": "Acme Corp",
      "lines": [
        { "partNumber": "P-101", "description": "Widget", "qty": 10, "lineTotal": 499.90 },
        { "partNumber": "P-102", "description": "Gadget", "qty": 5,  "lineTotal": 249.95 }
      ]
    }
  ]
}

Summary Bar Format

The summary bar displays as: Total Qty: 15 | Order Value: $749.85 - using a pipe delimiter between fields. Field labels come from the label property on the matching computation, falling back to a formatted version of the field name.


7 - Three-level hierarchy

Level 2 = orders (full grid), level 3 = line items (minimal borders), level 4 = serial numbers (compact key-value). Each level inherits theme colors unless overridden.

{
  "hierarchyRules": {
    "fieldVisibility": {
      "_internal": false
    },
    "levelStyling": {
      "2": {
        "fontSize": 10,
        "borderStyle": "full",
        "stripeOpacity": 0.3,
        "showSummary": true,
        "summaryFields": ["totalLines"]
      },
      "3": {
        "fontSize": 9,
        "borderStyle": "minimal",
        "indentation": 8,
        "columnFormats": { "unitPrice": "currency", "qty": "number" }
      },
      "4": {
        "fontSize": 8,
        "borderStyle": "none",
        "format": "compact-kv",
        "indentation": 16,
        "showHeaders": false
      }
    },
    "computations": [
      {
        "level": 2,
        "field": "totalLines",
        "label": "Line Count",
        "type": "count",
        "source": "lines"
      }
    ]
  },
  "orders": [
    {
      "orderNumber": "SO-1001",
      "customer": "Acme Corp",
      "orderDate": "2026-03-15",
      "lines": [
        {
          "partNumber": "P-101", "qty": 10, "unitPrice": 49.99,
          "serials": [
            { "serialNumber": "SN-001", "condition": "New" },
            { "serialNumber": "SN-002", "condition": "New" }
          ]
        }
      ]
    }
  ]
}

8 - Conditional cell styles on a status column

{
  "key": "status",
  "label": "Status",
  "displayOrder": 5,
  "primary": true,
  "width": 80,
  "align": "center",
  "conditionalStyles": [
    { "value": "Active",    "icon": "CheckCircle",   "color": "#10B981", "bgColor": "#ECFDF5" },
    { "value": "Pending",   "icon": "AlertTriangle", "color": "#B45309", "bgColor": "#FEF3C7" },
    { "value": "Cancelled", "icon": "XCircle",       "color": "#EF4444", "bgColor": "#FEF2F2" },
    { "value": "On Hold",   "icon": "AlertTriangle", "color": "#7C3AED", "bgColor": "#EDE9FE" },
    { "value": "default",   "icon": "",              "color": "#374151", "bgColor": "#F9FAFB" }
  ]
}

conditionalStyles also work on overflow columns in the sub-row - the icon and colors are applied identically regardless of whether the column is primary: true or primary: false.


Full Example

A complete, ready-to-paste payload. Color properties on levelStyling are omitted so they inherit the active theme automatically - add explicit hex overrides only when you need to deviate from the theme.

{
  "hierarchyRules": {
    "fieldVisibility": {
      "internalRef": false
    },
    "levelStyling": {
      "2": {
        "fontSize": 10,
        "borderStyle": "full",
        "stripeOpacity": 0.4,
        "columnManifest": {
          "maxCols": 6,
          "columns": [
            { "key": "partNumber",  "label": "Part #",      "displayOrder": 1, "primary": true,  "width": 80,  "align": "left" },
            { "key": "description", "label": "Description", "displayOrder": 2, "primary": true,  "width": "*", "align": "left" },
            { "key": "qty",         "label": "Qty",         "displayOrder": 3, "primary": true,  "width": 50,  "align": "right", "format": "number" },
            { "key": "unitPrice",   "label": "Unit Price",  "displayOrder": 4, "primary": true,  "width": 70,  "align": "right", "format": "currency" },
            { "key": "status",      "label": "Status",      "displayOrder": 5, "primary": true,  "width": 70,  "align": "center",
              "conditionalStyles": [
                { "value": "Active",    "icon": "CheckCircle",   "color": "#10B981", "bgColor": "#ECFDF5" },
                { "value": "On Hold",   "icon": "AlertTriangle", "color": "#B45309", "bgColor": "#FEF3C7" },
                { "value": "Cancelled", "icon": "XCircle",       "color": "#EF4444", "bgColor": "#FEF2F2" },
                { "value": "default",   "icon": "",              "color": "#374151", "bgColor": "#F9FAFB" }
              ]
            },
            { "key": "notes",       "label": "Notes",       "displayOrder": 6, "primary": false,
              "layout": { "span": "full", "icon": "FileText", "showTitle": true }
            }
          ],
          "overflowStrategy": {
            "mode": "additionalRow",
            "columnsPerRow": 2,
            "indent": 12,
            "columnGap": 8,
            "borderStyle": "dashed",
            "fontSizeAdjustment": -1
          }
        }
      },
      "3": {
        "fontSize": 9,
        "borderStyle": "minimal",
        "format": "table"
      }
    },
    "computations": [
      {
        "level": 2,
        "field": "lineTotal",
        "type": "formula",
        "formula": "qty * unitPrice",
        "format": "currency"
      }
    ]
  },
  "salesOrders": [
    {
      "partNumber": "P-1001",
      "description": "Widget Alpha",
      "qty": 5,
      "unitPrice": 49.99,
      "status": "Active",
      "notes": "Expedite required - customer priority order.",
      "bins": [
        { "binCode": "A-12", "quantity": 3 },
        { "binCode": "B-07", "quantity": 2 }
      ]
    }
  ]
}

On this page