Skip to content

Tree — Visuals

Typed Visual subtypes. KPI, Table, BarChart, Sankey are the load-bearing kinds across the four shipped apps; TextBox carries rich-text content for Getting Started sheets. Each subtype validates its dataset / column references at emit time.

visuals

Typed Visual subtypes — one per visual kind in active use.

L.1.1 catalog: KPI ×29, Table ×22, BarChart ×13, Sankey ×2 across the three apps. Each subtype owns its field-well shape and emits the corresponding models.py Visual instance.

VisualLike

Bases: Protocol

Structural type for tree-level visual nodes.

Typed subtypes (KPI / Table / BarChart / Sankey) satisfy this Protocol — duck-typed so subtypes don't have to inherit from a base class. Subtypes contribute to the L.1.7 dependency-graph walk via datasets() / calc_fields().

All visual nodes also satisfy LayoutNode (in structure.py) via element_id + element_type so they can be placed in a sheet's grid layout (sheet.layout.row(...).add_<kind>(...)).

visual_id is VisualId | AutoResolved — typed subtypes default to AUTO and App._resolve_auto_ids replaces it with the derived id before emit. The walker / emit assert via isinstance narrowing.

visual_id instance-attribute

visual_id: VisualId | AutoResolved

emit

emit() -> Visual

datasets

datasets() -> set[Dataset]

calc_fields

calc_fields() -> set[CalcField]

KPI dataclass

KPI visual — single number per values entry, no grouping.

Field-well shape: Values=[Measure, ...]. Most KPIs use one measure; multiple are allowed and render as side-by-side numbers.

visual_id is optional (L.1.8.5 auto-ID). When omitted, the App's tree walker assigns v-kpi-s{sheet_idx}-{visual_idx} at emit time. Pass an explicit VisualId(...) to override.

title instance-attribute

title: str

subtitle class-attribute instance-attribute

subtitle: str | None = None

values class-attribute instance-attribute

values: list[Measure] = field(default_factory=list[Measure])

visual_id class-attribute instance-attribute

visual_id: VisualId | AutoResolved = AUTO

element_id property

element_id: str

element_type property

element_type: GridLayoutElementType

__init__

__init__(title: str, subtitle: str | None = None, values: list[Measure] = list[Measure](), visual_id: VisualId | AutoResolved = AUTO) -> None

datasets

datasets() -> set[Dataset]

calc_fields

calc_fields() -> set[CalcField]

CalcFields this visual references via its field-well leaves.

emit

emit() -> Visual

Table dataclass

Table visual — two field-well shapes:

  • Aggregated (default): group_by=[Dim, ...] + values=[Measure, ...]. One row per distinct group_by combination, aggregated by values. Emits TableAggregatedFieldWells.
  • Unaggregated: pass columns=[Dim, ...] (and leave group_by / values empty). Each cell shows the raw column value — no aggregation, one row per source row. Emits TableUnaggregatedFieldWells. Use this for detail/drill-source tables (AR Balances, AR Daily Statement transaction list).

Optional sort_by is a (field_ref, direction) tuple — direction is "ASC" or "DESC".

Optional conditional_formatting passes through to the model's raw dict (see common/clickability.py for the standard accent-text and tint-background helpers).

visual_id is optional (L.1.8.5 auto-ID).

title instance-attribute

title: str

subtitle class-attribute instance-attribute

subtitle: str | None = None

group_by class-attribute instance-attribute

group_by: list[Dim] = field(default_factory=list[Dim])

values class-attribute instance-attribute

values: list[Measure] = field(default_factory=list[Measure])

columns class-attribute instance-attribute

columns: list[Dim] = field(default_factory=list[Dim])

sort_by class-attribute instance-attribute

sort_by: tuple[FieldRef, Literal['ASC', 'DESC']] | list[tuple[FieldRef, Literal['ASC', 'DESC']]] | None = None

actions class-attribute instance-attribute

actions: list[Action] = field(default_factory=list[Action])

conditional_formatting class-attribute instance-attribute

conditional_formatting: list[CellFormat] | None = None

visual_id class-attribute instance-attribute

visual_id: VisualId | AutoResolved = AUTO

element_id property

element_id: str

element_type property

element_type: GridLayoutElementType

__init__

__init__(title: str, subtitle: str | None = None, group_by: list[Dim] = list[Dim](), values: list[Measure] = list[Measure](), columns: list[Dim] = list[Dim](), sort_by: tuple[FieldRef, Literal['ASC', 'DESC']] | list[tuple[FieldRef, Literal['ASC', 'DESC']]] | None = None, actions: list[Action] = list[Action](), conditional_formatting: list[CellFormat] | None = None, visual_id: VisualId | AutoResolved = AUTO) -> None

__post_init__

__post_init__() -> None

datasets

datasets() -> set[Dataset]

calc_fields

calc_fields() -> set[CalcField]

emit

emit() -> Visual

BarChart dataclass

Bar chart visual — one bar per distinct category, height by values.

Field-well shape: Category=[Dim, ...] + Values=[Measure, ...].

orientation ("VERTICAL" or "HORIZONTAL") and bars_arrangement ("CLUSTERED" / "STACKED" / "STACKED_PERCENT") pass through to the underlying BarChartConfiguration. sort_by is a (field_id, direction) tuple — direction "ASC" or "DESC" — and emits a CategorySort entry. All three default to None so the QuickSight defaults apply when not specified.

visual_id is optional (L.1.8.5 auto-ID).

title instance-attribute

title: str

subtitle class-attribute instance-attribute

subtitle: str | None = None

category class-attribute instance-attribute

category: list[Dim] = field(default_factory=list[Dim])

values class-attribute instance-attribute

values: list[Measure] = field(default_factory=list[Measure])

colors class-attribute instance-attribute

colors: list[Dim] = field(default_factory=list[Dim])

orientation class-attribute instance-attribute

orientation: Literal['HORIZONTAL', 'VERTICAL'] | None = None

bars_arrangement class-attribute instance-attribute

bars_arrangement: Literal['CLUSTERED', 'STACKED', 'STACKED_PERCENT'] | None = None

category_label class-attribute instance-attribute

category_label: str | None = None

value_label class-attribute instance-attribute

value_label: str | None = None

color_label class-attribute instance-attribute

color_label: str | None = None

sort_by class-attribute instance-attribute

sort_by: tuple[FieldRef, Literal['ASC', 'DESC']] | None = None

actions class-attribute instance-attribute

actions: list[Action] = field(default_factory=list[Action])

visual_id class-attribute instance-attribute

visual_id: VisualId | AutoResolved = AUTO

element_id property

element_id: str

element_type property

element_type: GridLayoutElementType

__init__

__init__(title: str, subtitle: str | None = None, category: list[Dim] = list[Dim](), values: list[Measure] = list[Measure](), colors: list[Dim] = list[Dim](), orientation: Literal['HORIZONTAL', 'VERTICAL'] | None = None, bars_arrangement: Literal['CLUSTERED', 'STACKED', 'STACKED_PERCENT'] | None = None, category_label: str | None = None, value_label: str | None = None, color_label: str | None = None, sort_by: tuple[FieldRef, Literal['ASC', 'DESC']] | None = None, actions: list[Action] = list[Action](), visual_id: VisualId | AutoResolved = AUTO) -> None

datasets

datasets() -> set[Dataset]

calc_fields

calc_fields() -> set[CalcField]

emit

emit() -> Visual

LineChart dataclass

Line chart visual — one line per distinct colors value, plotted across category (x-axis) with height by values (y-axis).

Field-well shape: Category=[Dim, ...] + Values=[Measure, ...] + Colors=[Dim, ...].

chart_type selects LINE (default), AREA, or STACKED_AREA. sort_by is a (field_id, direction) tuple — direction "ASC" or "DESC" — and emits a CategorySort entry. All optional fields default to None so the QuickSight defaults apply when not specified.

visual_id is optional (L.1.8.5 auto-ID).

title instance-attribute

title: str

subtitle class-attribute instance-attribute

subtitle: str | None = None

category class-attribute instance-attribute

category: list[Dim] = field(default_factory=list[Dim])

values class-attribute instance-attribute

values: list[Measure] = field(default_factory=list[Measure])

colors class-attribute instance-attribute

colors: list[Dim] = field(default_factory=list[Dim])

chart_type class-attribute instance-attribute

chart_type: Literal['LINE', 'AREA', 'STACKED_AREA'] | None = None

category_label class-attribute instance-attribute

category_label: str | None = None

value_label class-attribute instance-attribute

value_label: str | None = None

sort_by class-attribute instance-attribute

sort_by: tuple[FieldRef, Literal['ASC', 'DESC']] | None = None

actions class-attribute instance-attribute

actions: list[Action] = field(default_factory=list[Action])

visual_id class-attribute instance-attribute

visual_id: VisualId | AutoResolved = AUTO

element_id property

element_id: str

element_type property

element_type: GridLayoutElementType

__init__

__init__(title: str, subtitle: str | None = None, category: list[Dim] = list[Dim](), values: list[Measure] = list[Measure](), colors: list[Dim] = list[Dim](), chart_type: Literal['LINE', 'AREA', 'STACKED_AREA'] | None = None, category_label: str | None = None, value_label: str | None = None, sort_by: tuple[FieldRef, Literal['ASC', 'DESC']] | None = None, actions: list[Action] = list[Action](), visual_id: VisualId | AutoResolved = AUTO) -> None

datasets

datasets() -> set[Dataset]

calc_fields

calc_fields() -> set[CalcField]

emit

emit() -> Visual

Sankey dataclass

Sankey diagram visual — flows from source nodes to target nodes, ribbon thickness by weight.

Field-well shape: each of source / target / weight is a single Dim / Measure (the underlying model expects lists, but every usage today has exactly one entry; emit wraps).

items_limit caps the number of source / destination nodes rendered (matches the ItemsLimit shape on the underlying sort configuration). OtherCategories defaults to "INCLUDE" so capped flows roll into a "(others)" bucket rather than being dropped silently.

visual_id is optional (L.1.8.5 auto-ID).

title instance-attribute

title: str

subtitle class-attribute instance-attribute

subtitle: str | None = None

source class-attribute instance-attribute

source: Dim | None = None

target class-attribute instance-attribute

target: Dim | None = None

weight class-attribute instance-attribute

weight: Measure | None = None

items_limit class-attribute instance-attribute

items_limit: int | None = None

actions class-attribute instance-attribute

actions: list[Action] = field(default_factory=list[Action])

visual_id class-attribute instance-attribute

visual_id: VisualId | AutoResolved = AUTO

element_id property

element_id: str

element_type property

element_type: GridLayoutElementType

__init__

__init__(title: str, subtitle: str | None = None, source: Dim | None = None, target: Dim | None = None, weight: Measure | None = None, items_limit: int | None = None, actions: list[Action] = list[Action](), visual_id: VisualId | AutoResolved = AUTO) -> None

datasets

datasets() -> set[Dataset]

calc_fields

calc_fields() -> set[CalcField]

emit

emit() -> Visual

text_boxes

Tree-side wrapper for models.SheetTextBox — the rich-text box nodes used on landing-page sheets (Getting Started).

QuickSight splits a sheet's contents into Visuals and TextBoxes in the underlying model, but at the layout level both occupy GridLayoutElement slots — only the ElementType differs ("VISUAL" vs "TEXT_BOX"). The LayoutNode Protocol in structure.py abstracts over that split so callers see a single Sheet.place(node, ...) API regardless of which underlying field the node will eventually emit into.

TextBox dataclass

Tree-side rich-text box.

Mirrors the KPI / Table / BarChart / Sankey typed wrapper pattern: callers construct typed nodes; the tree owns layout / id resolution / emission. Compose content via the common.rich_text helpers (rt.text_box(...)) and pass the string in.

text_box_id is required (no auto-ID for text boxes — they don't carry a _AUTO_KIND). The ID surfaces in the layout's ElementId and the sheet's TextBoxes list.

text_box_id instance-attribute

text_box_id: str

content instance-attribute

content: str

element_id property

element_id: str

element_type property

element_type: GridLayoutElementType

__init__

__init__(text_box_id: str, content: str) -> None

emit

emit() -> SheetTextBox