Configuration
Blocks
Configure reusable UI components for page layouts
Overview
Blocks are reusable UI components that display data. They are defined once in the blocks array and referenced by ID in page configurations.
import type { Config } from "@envisioning/app";
const blocks: Config["navigation"]["blocks"] = [
{
id: "entitiesList",
block: "GridBlock",
schemaKey: "entities",
itemBlockId: "entityListItem",
gap: 1.5,
},
];Block Structure
Every block has:
| Property | Type | Required | Description |
|---|---|---|---|
id | string | Yes | Unique identifier referenced in pages |
block | string | Yes | Block type name |
...config | various | Varies | Block-specific configuration |
Available Block Types
| Block Type | Description |
|---|---|
GridBlock | Grid layout for lists of items |
ListItemBlock | Single list item with icon, labels |
CardItemBlock | Card with image and nested blocks |
ItemTitleBlock | Title display with main/extra labels |
TextBlock | Simple text display |
MarkdownBlock | Markdown content rendering |
ImageBlock | Image display with various options |
MiniChartBlock | Small metric visualization |
DivisionBlock | Section divider with optional label |
DashBlock | Decorative dash/line |
SourceListBlock | List of sources/links |
PaginationBlock | Next/previous navigation |
SearchFieldBlock | Search input field |
ScopeMenuBlock | Scope selector |
MetricHelperBlock | Metric explanation panel |
ChartLegendBlock | Chart legend display |
CopyrightBlock | Copyright notice |
See the Blocks reference for detailed documentation of each block type.
Template Syntax
Block properties support template interpolation with {placeholder} syntax:
{
id: "entityTitle",
block: "ItemTitleBlock",
mainLabel: "{context.title}",
extraLabel: "{context.collection.title}",
}Available prefixes:
context- Current item data (in detail pages)block- Current block's resolved datadata- Full application dataconfig- Configuration object
Common Patterns
List with Items
A grid displaying multiple items, each rendered with a sub-block:
// Grid block
{
id: "entitiesList",
block: "GridBlock",
schemaKey: "entities", // Data source from schema
itemBlockId: "entityItem", // Block to render each item
gap: 1.5,
}
// Item block
{
id: "entityItem",
block: "ListItemBlock",
schemaKey: "entities",
iconName: "circleFillEv",
iconColor: "accent",
mainLabel: "{context.title}",
extraLabel: "{context.collection.title}",
to: { page: "technology" },
showFavorite: true,
variant: "labelTop",
size: "lg",
}Cards Grid
// Cards container
{
id: "entitiesCards",
block: "GridBlock",
schemaKey: "entities",
itemBlockId: "entityCard",
gap: 3,
}
// Card item
{
id: "entityCard",
block: "CardItemBlock",
schemaKey: "entities",
mainLabel: "{context.title}",
extraLabel: "{context.collection.title}",
to: { page: "technology" },
showFavorite: true,
contentBlocks: ["trlChart", "spacer", "costChart"],
variant: "labelTop",
size: "md",
}Text Content
{
id: "contextSummary",
block: "MarkdownBlock",
markdown: "{context.summary}",
}
{
id: "aboutText",
block: "MarkdownBlock",
markdown: "{data.project.about}",
}Metric Charts
{
id: "trlChart",
block: "MiniChartBlock",
noDataLabel: "N/A",
metricJoinKey: "trl",
textSize: "md",
chartSize: "sm",
chartType: "ProgressSteps",
colorOn: "accent",
addBox: true,
resultMain: "{block.label}",
resultMore: "{block.description}",
resultShort: "{block.value}/{config.schema.objects.trl.metricDomain[1]}",
ticksMode: "default",
showHelp: true,
}Layout Helpers
// Spacers
{
id: "spacerLg",
block: "DivisionBlock",
marginTop: "lg",
}
// Dividers with labels
{
id: "divisionSources",
block: "DivisionBlock",
label: "SOURCES ({context.sources.length})",
labelColor: "dimmed",
marginTop: "md",
labelSize: "xs",
}
// Decorative dash
{
id: "dash",
block: "DashBlock",
color: "accent",
size: "lg",
gap: "xl",
align: "left",
}
// Horizontal rule
{
id: "hr",
block: "DashBlock",
color: "border",
size: "full",
gap: "xl2",
align: "center",
}Navigation
{
id: "techsPagination",
block: "PaginationBlock",
color: "accent",
background: "panel",
mode: "nextPrevious",
path: "{data.allEntities}",
isCyclic: true,
pathToLabel: "title",
}
{
id: "panelSearch",
block: "SearchFieldBlock",
}Images
{
id: "coverImage",
block: "ImageBlock",
url: "/cover.png",
bgSize: "cover",
rounded: true,
aspectRatio: "video",
}
{
id: "techImage",
block: "ImageBlock",
url: "{context.image.url}",
rounded: true,
isExpandable: false,
color: "panel-down",
bgSize: "cover",
aspectRatio: "video",
maxHeight: 400,
}Color Values
Common color values used in blocks:
| Color | Description |
|---|---|
accent | Primary accent color |
foreground | Main text color |
dimmed | Muted text color |
border | Border color |
panel | Panel background |
panel-down | Darker panel |
transparent | No color |
gray | Gray color |
Size Values
Common size values:
| Size | Description |
|---|---|
xs | Extra small |
sm | Small |
md | Medium |
lg | Large |
xl | Extra large |
xl2, xl3 | Larger variants |
Complete Example
export const blocks: Config["navigation"]["blocks"] = [
// List blocks
{
id: "entitiesList",
block: "GridBlock",
schemaKey: "entities",
itemBlockId: "entityListItem",
gap: 1.5,
},
{
id: "entityListItem",
block: "ListItemBlock",
schemaKey: "entities",
iconName: "circleFillEv",
iconColor: "accent",
mainLabel: "{context.title}",
extraLabel: "{context.collection.title}",
to: { page: "technology" },
showFavorite: true,
variant: "labelTop",
size: "lg",
},
// Content blocks
{
id: "contextSummary",
block: "MarkdownBlock",
markdown: "{context.summary}",
},
{
id: "trlChart",
block: "MiniChartBlock",
metricJoinKey: "trl",
chartType: "ProgressSteps",
colorOn: "accent",
resultMain: "{block.label}",
showHelp: true,
},
// Layout blocks
{
id: "spacerMd",
block: "DivisionBlock",
marginTop: "md",
},
{
id: "dash",
block: "DashBlock",
color: "accent",
size: "lg",
align: "left",
},
// Navigation
{
id: "panelSearch",
block: "SearchFieldBlock",
},
{
id: "pagination",
block: "PaginationBlock",
mode: "nextPrevious",
path: "{data.allEntities}",
isCyclic: true,
},
] as const;