Quarto Semantic Components — examples

Quarto Semantic Components logo

Quarto Semantic Components is a small collection of reusable Markdown/Pandoc primitives for technical documentation. The components stay close to ordinary Markdown, become richer in HTML, and remain readable when rendered to PDF or DOCX.

This page is both a gallery and a usage guide. Every example follows the same pattern: source first, rendered output second.

Version: 0.1.0

At a glance

Component Best suited for HTML enhancement
badge Inline status, versions, labels Variants, sizes, shapes, links, theme-aware colors
steps Procedures, workflows, timelines Continuous numbered or dot connectors
roadmap Milestones, product plans, project journeys Responsive sinuous SVG road with horizontal/vertical layouts
circle-list Compact ordered lists Circled numbers
tree Generic hierarchies and classifications Connectors and expandable branches
git-tree Git histories, branches and merges SVG commit DAG
file-tree Project layouts and repository structure Icons, info hints, expandable folders
properties Key/value metadata Responsive description-list grid
article Self-contained blocks of content Rounded container, accent, collapse/expand
progress / meter Quantitative indicators Native HTML indicators
kbd / abbr Inline semantics Native <kbd> and <abbr> elements

The extension intentionally avoids components that Quarto already handles well. A timeline can be expressed with steps type="dots"; roadmap is reserved for milestone paths and project journeys where the route itself is part of the presentation. General diagrams can use Mermaid.

Quick start

Install the extension:

quarto add lsbjordao/quarto-semantic-components

Enable it in a document or project:

filters:
  - semantic-components

Then use any component directly in Markdown:

:::steps
## Install
Install the extension.

## Configure
Set project defaults if needed.

## Write
Use ordinary Markdown inside components.

## Render
Render to HTML, PDF, or DOCX.
:::

Project defaults in _quarto.yml

Component defaults can be centralized at the project level. This repository intentionally leaves most colors automatic so Quarto can choose values that work naturally in both light and dark themes.

extensions:
  badge:
    - key: stable
      label: Stable
      type: success
      appearance: solid
      icon: "✓"
    - key: experimental
      label: Experimental
      type: info
      appearance: outline
      icon: "⚗"
    - key: deprecated
      label: Deprecated
      type: danger
      appearance: soft
      icon: "!"

  steps:
    dot-size: "0.72rem"
    line-width: "1.5px"

  roadmap:
    orientation: horizontal
    curve: "0.6"
    markers: dot
    road-dash: "10px 8px"

  tree:
    expanded: true
    indent: "1.5rem"

  file-tree:
    icons: devicon
    expanded: true
    indent: "1.8rem"

  properties:
    term-width: "9rem"

  git-tree:
    direction: TB
    line-width: "2px"
    node-size: "0.68rem"
    lane-gap: "0.82rem"
    row-height: "36px"
    content-gap: "0.55rem"

  article:
    radius: "0.75rem"
    padding: "1rem 1.1rem"
    accent: none

For properties that support presets, the effective value follows this precedence:

project defaults → preset → component attributes → item attributes

Theme-aware colors

Color options support a common light/dark convention. The unsuffixed option remains the fallback for both themes; -light and -dark override it only in the corresponding color mode.

property-light / property-dark
            ↓
      property
            ↓
automatic theme default

For example:

::: {.steps
  line-color="#6b7280"
  line-color-dark="#adb5bd"}
...
:::

Here #6b7280 is used in both themes unless a more specific override exists. The dark theme uses #adb5bd; the light theme falls back to line-color.

You can also specify both values explicitly:

::: {.steps
  surface-color-light="#f3f4f6"
  surface-color-dark="#2b3035"
  line-color-light="#6b7280"
  line-color-dark="#adb5bd"
...
:::

The theme-aware color API is available wherever a component exposes color customization:

Component Theme-aware properties
steps surface-color, line-color, dot-color, dot-fill
roadmap road-color, point-color, surface-color
circle-list border-color, text-color, background-color
tree line-color
git-tree line-color, node-bg
article border-color, background, accent-color
badge fg, bg, border
progress / meter color, track-color

Each property accepts the normal form plus -light and -dark, such as accent-color, accent-color-light, and accent-color-dark.

If you do not provide a color, the component keeps its automatic theme-aware default.

Badges

Badges are compact inline labels for status, versions, categories, environments, or any other short metadata. The public shortcode is badge.

The mcanouil/quarto-badge extension also defines a badge shortcode. A project should choose which extension owns that shortcode.

Project presets

Presets keep repeated labels consistent across a project.

{{< badge stable >}}
{{< badge experimental >}}
{{< badge deprecated >}}
{{< badge "Stable release" key="stable" >}}

Output:

✓ Stable ⚗ Experimental ! Deprecated ✓ Stable release

Variants and appearances

type controls the semantic variant and appearance controls how strongly it is rendered.

{{< badge "Info" type="info" appearance="soft" >}}
{{< badge "Ready" type="success" appearance="solid" >}}
{{< badge "Review" type="warning" appearance="outline" >}}
{{< badge "Blocked" type="danger" appearance="soft" >}}
{{< badge "Featured" type="accent" appearance="solid" >}}

Output:

Info Ready Review Blocked Featured

Sizes and shapes

{{< badge "XS" size="xs" shape="pill" >}}
{{< badge "Small" size="sm" shape="pill" >}}
{{< badge "Medium" size="md" shape="rounded" >}}
{{< badge "Large" size="lg" shape="square" >}}

Output:

XS Small Medium Large

Theme-specific badge colors

{{< badge "Adaptive"
  fg-light="#1f2937" bg-light="#e5e7eb" border-light="#9ca3af"
  fg-dark="#f9fafb" bg-dark="#374151" border-dark="#6b7280" >}}

Output:

Adaptive

AST-native form

Use the AST-native form when the label itself should contain inline Markdown.

[**Stable**]{.badge type="success" appearance="outline" size="md"}
[`v0.1.0`]{.badge type="accent" font="mono"}

Output: Stable v0.1.0

Steps

steps turns headings into a structured sequence. The same source remains meaningful without the HTML styling, which makes it suitable for tutorials, protocols, workflows, and teaching material.

Numbered steps

The numbered mode uses a continuous connector behind the numbered markers. The marker interior follows the current surface, so the line does not show through the circle.

:::steps
## Install the extension
Run `quarto add lsbjordao/quarto-semantic-components`.

## Enable the filter
Add `semantic-components` to `filters`.

## Configure the project
Set defaults in `_quarto.yml` when useful.

## Write normally
Each heading starts a new step.
:::

Output:

  1. Install the extension

    Run quarto add lsbjordao/quarto-semantic-components.

  2. Enable the filter

    Add semantic-components to filters.

  3. Configure the project

    Set defaults in _quarto.yml when useful.

  4. Write normally

    Each heading starts a new step.

Numbered steps on a custom surface

When you choose explicit colors, use theme-specific values if the light and dark themes need different contrast.

::: {.steps
  surface-color-light="#f3f4f6"
  surface-color-dark="#2b3035"
  line-color-light="#6b7280"
  line-color-dark="#adb5bd"
  line-width="2px"}

## Prepare
Create the working directory.

## Import
Load the source data.

## Validate
Check required fields.

## Export
Write the validated result.
:::

Output:

  1. Prepare

    Create the working directory.

  2. Import

    Load the source data.

  3. Validate

    Check required fields.

  4. Export

    Write the validated result.

Dot steps

Dot steps are useful when the sequence should feel lighter than a numbered procedure. The connector remains continuous behind the dots, while the marker center masks the line.

Default dots

With no explicit colors, the component follows the current theme automatically.

::: {.steps type="dots"}
## Extract
Download the data.

## Validate
Validate the records.

## Transform
Prepare the data.

## Publish
Publish the result.
:::

Output:

  • Extract

    Download the data.

  • Validate

    Validate the records.

  • Transform

    Prepare the data.

  • Publish

    Publish the result.

Per-step color and size

Block attributes define defaults; heading attributes override individual nodes. Theme suffixes can also be used on individual headings.

::: {.steps type="dots"
  dot-size="0.78rem"
  line-width="1.5px"}

## Extract {dot-color-light="#2563eb" dot-color-dark="#60a5fa"}
Download the new records.

## Deduplicate {dot-color-light="#d97706" dot-color-dark="#fbbf24" dot-size="0.95rem"}
Reconcile collections and identifications.

## Review {dot-color-light="#7c3aed" dot-color-dark="#c4b5fd"}
Review the processed dataset.

## Publish {dot-color-light="#15803d" dot-color-dark="#4ade80"}
Update the curated dataset.
:::

Output:

  • Extract

    Download the new records.

  • Deduplicate

    Reconcile collections and identifications.

  • Review

    Review the processed dataset.

  • Publish

    Update the curated dataset.

Filled and hollow states

::: {.steps type="dots" line-width="2px"}
## Pending
The default node remains hollow.

## In progress {dot-color="#2563eb" dot-fill="#2563eb"}
A single unsuffixed color is intentionally reused in both themes.

## Under review {dot-color-light="#d97706" dot-fill-light="#d97706" dot-color-dark="#fbbf24" dot-fill-dark="#fbbf24"}
This state uses separate light and dark colors.

## Completed {dot-color-light="#15803d" dot-fill-light="#15803d" dot-color-dark="#4ade80" dot-fill-dark="#4ade80" dot-border-width="2px"}
The final stage is complete.
:::

Output:

  • Pending

    The default node remains hollow.

  • In progress

    A single unsuffixed color is intentionally reused in both themes.

  • Under review

    This state uses separate light and dark colors.

  • Completed

    The final stage is complete.

Timeline pattern

A timeline does not need a dedicated component. Dates can be represented with inline badges while steps type="dots" provides the vertical timeline geometry.

::: {.steps type="dots" line-width="2px" dot-size="0.78rem"}
## [2024]{.badge type="success" appearance="outline" size="xs"} Prototype {dot-color="#16a34a"}
First implementation of the component.

## [2025]{.badge type="info" appearance="outline" size="xs"} Beta {dot-color="#2563eb"}
Validation and visual refinement.

## [2026-06]{.badge type="warning" appearance="outline" size="xs"} Release candidate {dot-color="#f59e0b"}
API freeze for final testing.

## [2026-09]{.badge type="success" appearance="solid" size="xs"} Release {dot-color="#16a34a"}
Stable version released.
:::

Output:

  • 2024 Prototype

    First implementation of the component.

  • 2025 Beta

    Validation and visual refinement.

  • 2026-06 Release candidate

    API freeze for final testing.

  • 2026-09 Release

    Stable version released.

Roadmap

roadmap is for milestone paths and project journeys where the route itself carries part of the visual meaning. In HTML the route is a responsive SVG: the outer road bed stays continuous while the narrower center line is dashed by default, which gives the curve a road-like appearance. Horizontal roadmaps automatically become vertical on narrow screens.

Roadmap of this extension

The first example uses the component to describe Quarto Semantic Components itself and links to the other rendered formats.

::: {.roadmap orientation="horizontal" curve="0.65" markers="dot"}

::: {.roadmap-item title="Semantic core" status="done"}
Pandoc-AST components that remain meaningful outside HTML.
:::

::: {.roadmap-item title="Component library" status="done"}
Steps, trees, badges, articles, properties, progress, meter, `kbd`, `abbr`, and roadmap.
:::

::: {.roadmap-item title="Cross-format outputs" status="done"}
Open the [PDF](quarto-semantic-components.pdf) or [DOCX](quarto-semantic-components.docx) version of this gallery.
:::

::: {.roadmap-item title="Version 0.1.0" status="milestone"}
A coherent first release with theme-aware colors and graceful degradation.
:::

::: {.roadmap-item title="Next iterations" status="future"}
Refine components from real documentation use and add only primitives that earn their place.
:::

:::

Output:

Status: done

Semantic core

Pandoc-AST components that remain meaningful outside HTML.

Status: done

Component library

Steps, trees, badges, articles, properties, progress, meter, kbd, abbr, and roadmap.

Status: done

Cross-format outputs

Open the PDF or DOCX version of this gallery.

Status: milestone

Version 0.1.0

A coherent first release with theme-aware colors and graceful degradation.

Status: future

Next iterations

Refine components from real documentation use and add only primitives that earn their place.

Vertical orientation

orientation="vertical" keeps the same curved-road idea while moving the road into a left-side gutter. It does not require a separate component.

::: {.roadmap orientation="vertical" markers="numbers" curve="0.8"}

::: {.roadmap-item title="Install" status="done"}
Add the extension to a Quarto project.
:::

::: {.roadmap-item title="Configure" status="done"}
Set project defaults in `_quarto.yml`.
:::

::: {.roadmap-item title="Compose" status="current"}
Use semantic components in Markdown.
:::

::: {.roadmap-item title="Publish" status="future"}
Render the project to the required formats.
:::

:::

Output:

Status: done

Install

Add the extension to a Quarto project.

Status: done

Configure

Set project defaults in _quarto.yml.

Status: current

Compose

Use semantic components in Markdown.

Status: future

Publish

Render the project to the required formats.

Marker styles

The markers option accepts dot, numbers, or none.

Dots

::: {.roadmap markers="dot" curve="0.5"}

::: {.roadmap-item title="Alpha"}
First stage.
:::

::: {.roadmap-item title="Beta"}
Second stage.
:::

::: {.roadmap-item title="Stable"}
Third stage.
:::

:::

Output:

Alpha

First stage.

Beta

Second stage.

Stable

Third stage.

Numbers

::: {.roadmap markers="numbers" curve="0.5"}

::: {.roadmap-item title="Alpha"}
First stage.
:::

::: {.roadmap-item title="Beta"}
Second stage.
:::

::: {.roadmap-item title="Stable"}
Third stage.
:::

:::

Output:

Alpha

First stage.

Beta

Second stage.

Stable

Third stage.

No markers

::: {.roadmap markers="none" curve="0.5"}

::: {.roadmap-item title="Alpha"}
First stage.
:::

::: {.roadmap-item title="Beta"}
Second stage.
:::

::: {.roadmap-item title="Stable"}
Third stage.
:::

:::

Output:

Alpha

First stage.

Beta

Second stage.

Stable

Third stage.

Curvature

curve accepts values from 0 to 1. 0 removes the wave, while 1 uses the full amplitude.

curve="0"

A

Straight.

B

Straight.

C

Straight.

D

Straight.

curve="0.35"

A

Subtle curve.

B

Subtle curve.

C

Subtle curve.

D

Subtle curve.

curve="1"

A

Full curve.

B

Full curve.

C

Full curve.

D

Full curve.

Item states

A single roadmap can mix all four item states: done, current, future, and milestone.

::: {.roadmap curve="0.65" markers="dot"}

::: {.roadmap-item title="Done" status="done"}
A completed item.
:::

::: {.roadmap-item title="Current" status="current"}
The active item receives stronger emphasis.
:::

::: {.roadmap-item title="Future" status="future"}
Future content is intentionally quieter.
:::

::: {.roadmap-item title="Milestone" status="milestone"}
A milestone uses a diamond marker.
:::

:::

Output:

Status: done

Done

A completed item.

Status: current

Current

The active item receives stronger emphasis.

Status: future

Future

Future content is intentionally quieter.

Status: milestone

Milestone

A milestone uses a diamond marker.

Road width, border, dash, and point size

The visual proportions are independent. road-background-width controls the continuous outer road bed; road-width controls the dashed center line; road-dash controls its dash pattern; and point-size controls the marker.

::: {.roadmap
  curve="0.75"
  road-background-width="18px"
  road-width="4px"
  road-dash="14px 10px"
  point-size="20px"}

::: {.roadmap-item title="Wide road"}
A wider continuous road bed.
:::

::: {.roadmap-item title="Long dashes"}
A custom center-line rhythm.
:::

::: {.roadmap-item title="Large points"}
Larger markers.
:::

:::

Output:

Wide road

A wider continuous road bed.

Long dashes

A custom center-line rhythm.

Large points

Larger markers.

Set road-dash="none" when a continuous center line is desired. The outer road bed remains continuous in either case.

::: {.roadmap road-dash="none" road-background-width="14px" road-width="3px"}

::: {.roadmap-item title="Continuous"}
No center dashes.
:::

::: {.roadmap-item title="Still a road"}
The outer road bed remains continuous.
:::

::: {.roadmap-item title="Finish"}
Same geometry.
:::

:::

Output:

Continuous

No center dashes.

Still a road

The outer road bed remains continuous.

Finish

Same geometry.

Theme-aware colors

road-color, point-color, and surface-color follow the extension-wide color rule: the unsuffixed property applies to both modes and -light / -dark can override it for one theme.

::: {.roadmap
  road-color-light="#64748b"
  road-color-dark="#cbd5e1"
  point-color-light="#2563eb"
  point-color-dark="#60a5fa"
  surface-color-light="#ffffff"
  surface-color-dark="#212529"
  curve="0.7"}

::: {.roadmap-item title="Default point" status="done"}
Uses the roadmap-level point color.
:::

::: {.roadmap-item title="Per-item override" status="current"
  point-color-light="#7c3aed"
  point-color-dark="#c4b5fd"}
This item overrides only its marker color.
:::

::: {.roadmap-item title="Future" status="future"
  point-color="#16a34a"}
An unsuffixed value is reused in both themes.
:::

:::

Output:

Status: done

Default point

Uses the roadmap-level point color.

Status: current

Per-item override

This item overrides only its marker color.

Status: future

Future

An unsuffixed value is reused in both themes.

Roadmap option reference

Option Accepted values / purpose Default Aliases
orientation horizontal, vertical horizontal direction, layout
curve 0 to 1 0.6 curvature, sinuosity
markers dot, numbers, none dot marker, marker-style
road-color CSS color automatic line-color, path-color
road-color-light light-theme road color fallback line-color-light, path-color-light
road-color-dark dark-theme road color fallback line-color-dark, path-color-dark
point-color CSS marker color automatic marker-color, dot-color
point-color-light light-theme marker color fallback marker-color-light, dot-color-light
point-color-dark dark-theme marker color fallback marker-color-dark, dot-color-dark
surface-color card / marker surface automatic card-color, card-background
surface-color-light light-theme surface fallback card-color-light, card-background-light
surface-color-dark dark-theme surface fallback card-color-dark, card-background-dark
road-width center-line width 3px line-width, path-width
road-background-width continuous road-bed width 10px road-bed-width, path-background-width
road-dash SVG dash pattern or none 10px 8px dash, dash-pattern, line-dash
point-size marker diameter 14px marker-size, dot-size

Per .roadmap-item, title creates the card title, status accepts done, current, future, or milestone, and point-color, point-color-light, and point-color-dark can override the marker color. Status aliases accepted by the filter are complete / completed, active / now / in-progress, pending / planned, and major.

In PDF and DOCX the SVG route intentionally degrades to a readable ordered list, preserving item titles, statuses, links, and Markdown content. The PDF and DOCX links in the first roadmap are therefore also a demonstration of the cross-format strategy.

Circled Ordered List

circle-list keeps ordinary ordered-list semantics and changes only the visual treatment of the number marker.

Basic list

:::circle-list
1. First item
2. Second item, with normal **Markdown**
3. Third item
4. Fourth item
:::

Output:

  1. First item
  2. Second item, with normal Markdown
  3. Third item
  4. Fourth item

Custom colors

The circle border, the number/text, and the background can be colored independently. An unsuffixed value applies to both light and dark themes.

::: {.circle-list
  border-color="#7c3aed"
  text-color="#ffffff"
  background-color="#7c3aed"}
1. Research
2. Prototype
3. Validate
4. Release
:::

Output:

  1. Research
  2. Prototype
  3. Validate
  4. Release

Light and dark theme colors

Use the -light and -dark variants when the circle needs different contrast in each color mode.

::: {.circle-list
  border-color-light="#2563eb"
  border-color-dark="#60a5fa"
  text-color-light="#1e3a8a"
  text-color-dark="#f8fafc"
  background-color-light="#dbeafe"
  background-color-dark="#1e3a8a"}
1. Install
2. Configure
3. Compose
4. Publish
:::

Output:

  1. Install
  2. Configure
  3. Compose
  4. Publish

The canonical color properties are border-color, text-color, and background-color; each accepts the extension-wide base / -light / -dark convention.

A compact procedure

Because the content remains ordinary Markdown, links, code, emphasis, and other inline content can be used normally.

:::circle-list
1. Create `_quarto.yml` in the project root.
2. Add `semantic-components` to the **filters** list.
3. Run [`quarto preview`](https://quarto.org/docs/get-started/hello/vscode.html).
4. Render the final document with `quarto render`.
:::

Output:

  1. Create _quarto.yml in the project root.
  2. Add semantic-components to the filters list.
  3. Run quarto preview.
  4. Render the final document with quarto render.

Git tree

git-tree represents a Git history as a commit DAG rather than as a generic tree. A dot is a commit, an edge is a parent → child relationship, a branch split starts at a commit, and a merge ends at a commit.

Simple syntax — TB direction

::: {.git-tree direction="TB"}
- `main` initial commit
- `main` creates the base architecture
  - `feature/icons` opens the icons branch
  - `feature/icons` adds Devicon
    - `docs/icons` documents providers
    - `docs/icons` adds examples
  - `feature/icons` merge docs/icons
  - `feature/icons` adds file links
- `main` merge feature/icons
- `main` starts inline components
  - `feature/badges` creates badge
  - `feature/badges` adds visual customization
    - `test/badges` covers variants
    - `test/badges` covers links
  - `feature/badges` merge test/badges
- `main` merge feature/badges
- `main` release v0.1.0
:::

Output:

main initial commit
main creates the base architecture
feature/icons opens the icons branch
feature/icons adds Devicon
docs/icons documents providers
docs/icons adds examples
feature/icons merge docs/icons
feature/icons adds file links
main merge feature/icons
main starts inline components
feature/badges creates badge
feature/badges adds visual customization
test/badges covers variants
test/badges covers links
feature/badges merge test/badges
main merge feature/badges
main release v0.1.0

Same topology — BT direction

::: {.git-tree direction="BT"}
- `main` initial commit
- `main` base architecture
  - `feature/api` creates API
  - `feature/api` implements endpoints
- `main` merge feature/api
- `main` release
:::

Output:

main release
main merge feature/api
feature/api implements endpoints
feature/api creates API
main base architecture
main initial commit

A branch created from another branch

Nested branches are valid Git histories. Here test/badges starts from a commit on feature/badges, then merges back before feature/badges itself merges into main.

:::git-tree
- `main` project skeleton
  - `feature/badges` creates badge renderer
  - `feature/badges` adds presets
    - `test/badges` adds variant tests
    - `test/badges` adds link tests
  - `feature/badges` merge test/badges
  - `feature/badges` documents badge API
- `main` merge feature/badges
:::

Output:

main project skeleton
feature/badges creates badge renderer
feature/badges adds presets
test/badges adds variant tests
test/badges adds link tests
feature/badges merge test/badges
feature/badges documents badge API
main merge feature/badges

Theme-specific graph colors

::: {.git-tree
  line-color-light="#6b7280"
  line-color-dark="#adb5bd"
  node-bg-light="#ffffff"
  node-bg-dark="#212529"}
- `main` initial commit
  - `feature/theme` adds color-mode support
  - `feature/theme` documents overrides
- `main` merge feature/theme
:::

Output:

main initial commit
feature/theme adds color-mode support
feature/theme documents overrides
main merge feature/theme

Explicit DAG — ids, parents, tag, and HEAD

Use explicit relationships for histories where indentation alone is not enough. parents= takes precedence over automatic inference.

:::git-tree
- `main`{#c1} initial commit
- `main`{#c2 parent="c1"} base architecture
  - `feature/badges`{#c3 parent="c2"} creates badge
  - `feature/badges`{#c4 parent="c3"} visual customization
    - `test/badges`{#c5 parent="c4"} covers variants
    - `test/badges`{#c6 parent="c5"} covers links
  - `feature/badges`{#c7 parents="c4,c6"} merge test/badges
- `main`{#c8 parents="c2,c7" tag="v0.1.0" head="true"} merge feature/badges
:::

Output:

main initial commit
main base architecture
feature/badges creates badge
feature/badges visual customization
test/badges covers variants
test/badges covers links
feature/badges merge test/badges
main HEAD v0.1.0 merge feature/badges

Tree

tree is a neutral hierarchy component. Unlike file-tree, it does not assume that nodes are files or folders; unlike git-tree, it does not model commits or parent relationships. It simply renders nested Markdown lists as a readable hierarchy.

Taxonomic hierarchy

:::tree
- Plantae
  - Fabaceae
    - Mimosa
      - Mimosa pudica
      - Mimosa caesalpiniifolia
    - Acacia
  - Asteraceae
:::

Output:

  • Plantae
    • Fabaceae
      • Mimosa
        • Mimosa pudica
        • Mimosa caesalpiniifolia
      • Acacia
    • Asteraceae

Expand, collapse, info, and indentation

Any item with children becomes a branch in HTML. The whole tree can define a default state, and individual branches can override it.

::: {.tree expanded="false" indent="1.8rem"}
- [Life]{expanded="true" info="Top-level classification"}
  - Eukaryota
  - [Plantae]{expanded="true"}
    - Fabaceae
      - Mimosa
      - Acacia
    - Asteraceae
  - Animalia
:::

Output:

  • Life i
    • Eukaryota
    • Plantae
        • Mimosa
        • Acacia
      • Asteraceae
    • Animalia

Branches are inferred solely from nested children. Use expanded=, open=, or collapsed= on a span when a branch needs a specific initial state. line-color-light and line-color-dark can tune connector contrast by theme.

Optional tree controls

Add controls="true" to render a compact HTML control panel above the tree. The panel provides global Expand all / Collapse all actions and synchronized expand/collapse buttons for every branch depth detected in the tree.

::: {.tree controls="true" expanded="false"}
- Life
  - Eukaryota
    - Plantae
      - Angiosperms
        - Fabaceae
          - Mimosa
          - Acacia
          - Senna
        - Asteraceae
          - Aster
          - Helianthus
        - Orchidaceae
          - Vanilla
          - Cattleya
      - Bryophytes
        - Sphagnaceae
          - Sphagnum
    - Animalia
      - Chordata
        - Mammalia
          - Primates
          - Carnivora
        - Aves
          - Passeriformes
      - Arthropoda
        - Insecta
          - Coleoptera
          - Lepidoptera
  - Bacteria
    - Proteobacteria
      - Alphaproteobacteria
        - Rhizobiales
      - Gammaproteobacteria
        - Enterobacterales
  - Archaea
    - Euryarchaeota
      - Methanobacteria
        - Methanobacteriales
:::

Output:

            • Mimosa
            • Acacia
            • Senna
            • Aster
            • Helianthus
            • Vanilla
            • Cattleya
            • Sphagnum
            • Primates
            • Carnivora
            • Passeriformes
            • Coleoptera
            • Lepidoptera
          • Rhizobiales
          • Enterobacterales
          • Methanobacteriales

For example, clicking + beside L1 expands every level-1 branch at once, while − collapses all level-1 branches. The same behavior is generated automatically for L2, L3, and deeper levels when present. Individual branch toggles continue to work normally.

panel="true" and toolbar="true" are accepted as aliases for controls="true". The control panel is HTML-only; PDF and DOCX preserve the full semantic tree without interactive controls.

File tree

file-tree describes a project or directory hierarchy using an ordinary nested list. File names are automatically mapped to useful icons, while links, inline code, comments, info hints, custom icons, and collapsible folders remain optional.

Deep project structure

:::file-tree
- +project
  - +src
    - +pipelines
      - +python
        - pipeline.py ingestion
        - validate.py validation
      - +r
        - analysis.R statistical analysis
        - report.Rmd report
      - +web
        - +src
          - +components
            - chart.ts
            - table.ts
          - app.ts
    - +database
      - +migrations
        - schema.sql
  - +docs
    - report.qmd
  - +data
    - +processed
      - occurrences.parquet
  - README.md
  - _quarto.yml
:::

Output:

  • project
    • src
      • pipelines
        • python
          • pipeline.py ingestion
          • validate.py validation
        • r
          • analysis.R statistical analysis
          • report.Rmd report
        • web
          • src
            • components
              • chart.ts
              • table.ts
            • app.ts
      • database
        • migrations
          • schema.sql
    • docs
      • report.qmd
    • data
      • processed
        • occurrences.parquet
    • README.md
    • _quarto.yml

schema.sql receives the classic database-cylinder icon automatically, while common programming languages and formats are detected from the file name or extension.

Plain text versus inline code

The author controls whether a file name looks like code. A plain filename remains plain text; backticks explicitly request inline-code styling.

:::file-tree
- analysis.R plain filename
- `analysis.R` inline-code filename
- [app.ts](https://github.com/lsbjordao/quarto-semantic-components) regular link
- [`steps.lua`](https://github.com/lsbjordao/quarto-semantic-components/blob/main/_extensions/semantic-components/steps.lua) linked inline-code filename
:::

Output:

  • analysis.R plain filename
  • analysis.R inline-code filename
  • app.ts regular link
  • steps.lua linked inline-code filename

Info hints

info= adds a small, keyboard-focusable information marker. In HTML, its text is exposed through title and aria-label.

:::file-tree
- [analysis.R]{info="Main R analysis script"}
- [`pipeline.py`]{info="Ingestion and validation pipeline"}
- [schema.sql]{info="Relational schema used by the application"}
:::

Output:

  • analysis.R i
  • pipeline.py i
  • schema.sql i

Custom icons and providers

:::file-tree
- `pipeline.py`{icon="devicon:python"}
- `species.csv`{icon="leaf"}
- `golden.parquet`{icon="★"}
- `deploy.sh`{icon="rocket"}
:::

Output:

  • pipeline.py
  • species.csv
  • ★ golden.parquet
  • deploy.sh

Horizontal indentation

indent controls the horizontal distance added at every nested level.

::: {.file-tree indent="1rem"}
- +src
  - +components
    - Button.ts
    - Card.ts
  - app.ts
- +database
  - schema.sql
:::

Output:

  • src
    • components
      • Button.ts
      • Card.ts
    • app.ts
  • database
    • schema.sql

Compare with a wider hierarchy:

::: {.file-tree indent="2.4rem"}
- +src
  - +components
    - Button.ts
    - Card.ts
  - app.ts
:::

Output:

  • src
    • components
      • Button.ts
      • Card.ts
    • app.ts

Expand and collapse folders

Folders with children are interactive in HTML. The tree can define a default state, while individual folders can override it.

::: {.file-tree expanded="false"}
- [+src]{expanded="true"}
  - +components
    - Button.ts
    - Card.ts
  - app.ts
- [+docs]{open="false"}
  - index.qmd
  - api.qmd
- [+data]{collapsed="true"}
  - raw.csv
  - processed.parquet
:::

Output:

  • src
      • Button.ts
      • Card.ts
    • app.ts
    • index.qmd
    • api.qmd
    • raw.csv
    • processed.parquet

Article

article is the generic block for self-contained content. It deliberately does not encode a specific use case: the same primitive can represent a note, release entry, specification, summary, changelog entry, or collapsible explanation.

The outer HTML element is always a real <article>.

Generic article

:::article
## Technical note
This is the default `article`, with no accent and no collapse.

The content can contain ordinary **Markdown**, lists, links, and code.
:::

Output:

Technical note

This is the default article, with no accent and no collapse.

The content can contain ordinary Markdown, lists, links, and code.

Left accent

accent="left" turns the left border into an accent. accent-color accepts any CSS color or semantic names aligned with Quarto callout colors: note, info, warning, danger, caution, success, tip, and important.

::: {.article accent="left" accent-color="warning"}
## Attention
This article uses the warning accent color.
:::

Output:

Attention

This article uses the warning accent color.

Theme-specific article colors

::: {.article
  accent="left"
  accent-color-light="#7c3aed"
  accent-color-dark="#c4b5fd"
  border-color-light="#d1d5db"
  border-color-dark="#4b5563"
  background-light="#fafafa"
  background-dark="#1f2937"}
## Adaptive article
The border, background, and accent are tuned independently for each theme.
:::

Output:

Adaptive article

The border, background, and accent are tuned independently for each theme.

Semantic accent presets

::: {.article accent="left" accent-color="note"}
## Note
Useful contextual information.
:::

::: {.article accent="left" accent-color="success"}
## Success
The operation completed successfully.
:::

Output:

Note

Useful contextual information.

Success

The operation completed successfully.

Collapsed by default

A collapsible article uses native HTML <details> inside the <article> wrapper. No JavaScript is required, and the content remains fully visible in PDF/DOCX.

::: {.article collapsible="true" summary="Technical details" expanded="false"}
The content starts collapsed in HTML.

- normal Markdown
- lists
- code
- other components
:::

Output:

Technical details

The content starts collapsed in HTML.

  • normal Markdown
  • lists
  • code
  • other components

Expanded by default with an accent

::: {.article accent="left" accent-color="note" collapsible="true" summary="Methodology" expanded="true"}
This example starts expanded and combines the accent with native collapse/expand behavior.
:::

Output:

Methodology

This example starts expanded and combines the accent with native collapse/expand behavior.

Changelog pattern

A changelog does not require a dedicated component. It is simply one possible use of article.

:::article
## 0.1.0 — 2026-09-18

### Added
- Generic `tree` and semantic `properties`.
- Native `progress` and `meter` indicators.
- Inline `kbd` and `abbr` primitives.

### Changed
- Theme-aware colors continue to support unsuffixed, `-light`, and `-dark` values.
:::

Output:

0.1.0 — 2026-09-18
Added
  • Theme-specific color overrides with -light and -dark suffixes.
  • Theme-aware examples for steps, badges, Git trees, and articles.
Changed
  • Automatic theme colors remain the default whenever no explicit color is supplied.

Properties

properties enhances an ordinary Pandoc definition list. The underlying structure remains semantic in PDF and DOCX, while HTML presents it as a responsive key/value grid.

Basic metadata

:::properties
Project
: Quarto Semantic Components

Version
: 0.1.0

Language
: Lua

License
: MIT
:::

Output:

Project
Quarto Semantic Components
Version
0.1.0
Language
Lua
License
MIT

Rich values

Definition values can contain ordinary Markdown.

::: {.properties term-width="10rem"}
Repository
: [lsbjordao/quarto-semantic-components](https://github.com/lsbjordao/quarto-semantic-components)

Formats
: **HTML**, PDF, and DOCX

Status
: [Stable]{.badge type="success" appearance="solid" size="xs"}

Entry point
: `_extensions/semantic-components/`
:::

Output:

Repository
lsbjordao/quarto-semantic-components
Formats
HTML, PDF, and DOCX
Status
Stable
Entry point
_extensions/semantic-components/

Use compact="true" for denser metadata and term-width= (alias key-width=) to control the first column.

Progress

progress uses the native HTML <progress> element. It is appropriate for completion or advancement toward a goal.

{{< progress value="72" label="Build" >}}
{{< progress value="43" max="60" label="Processed records" value-label="43 / 60" >}}

Output:

Build72%72%

Processed records43 / 6043 / 60

Theme-specific colors follow the same fallback rule used elsewhere:

{{< progress value="84" label="Coverage"
  color-light="#2563eb" color-dark="#60a5fa"
  track-color-light="#e5e7eb" track-color-dark="#374151" >}}

Output:

Coverage84%84%

Meter

meter uses the native HTML <meter> element. Unlike progress, it represents a scalar measurement within a known range rather than task completion.

{{< meter value="82" min="0" max="100" label="Test coverage" value-label="82%" >}}
{{< meter value="7.2" min="0" max="10" low="4" high="8" optimum="9" label="Quality score" >}}

Output:

Test coverage82%82%

Quality score7.2 / 107.2 / 10

The attributes low, high, and optimum preserve the semantics of native <meter>.

Keyboard input

kbd renders keyboard input with the native HTML <kbd> element. A +-separated shortcut is automatically split into individual keys.

Press {{< kbd "Ctrl+Shift+P" >}} to open the command palette.

Use {{< kbd "Ctrl+C" >}} and {{< kbd "Ctrl+V" >}} to copy and paste.

Output:

Press Ctrl+Shift+P to open the command palette.

Use Ctrl+C and Ctrl+V to copy and paste.

Abbreviations

abbr emits the native HTML <abbr> element with its expansion in title. In non-HTML formats it degrades to the abbreviation followed by its full form.

A {{< abbr KBA "Key Biodiversity Area" >}} identifies a site of global importance for biodiversity.

The extension is built on the {{< abbr AST "Abstract Syntax Tree" >}} produced by Pandoc.

Output:

A KBA identifies a site of global importance for biodiversity.

The extension is built on the AST produced by Pandoc.

Combining components

The primitives are intentionally composable. A component can contain normal Markdown and, where the document structure permits it, other semantic components.

Release package example

:::: {.article accent="left" accent-color="success"}
## Release package [v0.1.0]{.badge type="success" appearance="solid" size="xs"}

The release contains the extension source, documentation, and examples.

:::file-tree
- +semantic-components
  - theme-colors.lua
  - steps.lua
  - roadmap.lua
  - tree.lua
  - file-tree.lua
  - git-tree.lua
  - properties.lua
  - article.lua
  - primitives.lua
  - badges.lua
  - semantic-shortcodes.lua
- README.md
- index.qmd
:::
::::

Output:

Release package v0.1.0

The release contains the extension source, documentation, and examples.

  • semantic-components
    • theme-colors.lua
    • steps.lua
    • roadmap.lua
    • file-tree.lua
    • git-tree.lua
    • article.lua
    • badges.lua
  • README.md
  • index.qmd

Output formats

The components are designed around Pandoc structure rather than HTML-only widgets.

Format Behavior
HTML Full styling, light/dark color overrides, sinuous roadmaps, generic/file trees, SVG Git DAG, native progress/meter, keyboard/abbreviation semantics, and article collapse/expand
PDF Structural content, roadmap items, statuses, links, and other content are preserved as readable static output
DOCX Lists, headings, roadmap items, links, and text remain editable

Inspiration

The Steps and File Tree ideas were inspired by components from Vocs. The implementation here is original and built around the Pandoc AST, project-level configuration, and cross-format rendering.