// template.typ
#let fill = (
red,
green,
blue,
aqua,
teal,
maroon
)
#let example(body) = context {
set text(size: 9pt)
show heading: it => {
set text(fill: fill.at(it.level - 1))
it
}
body
}
Elaborating a bit on the specific problem here: Show/set rules behave differently than show rules with anonymous functions. What I mean is that
#show heading.where(level: 1): it => {
set text(fill: fill.at(0))
it
}
is different from
#show heading.where(level: 1): set text(fill: fill.at(0))
The former is known as a transformational show rule and cannot be overridden by later show rules, because later show rules do not “know” what happens inside the function. The latter case is much simpler for typst to handle and therefore allows you to override it later.
This is mentioned in the show rule documentation, but admittedly it is quite hidden especially if you don’t know what you are looking for:
So, we can replace your original heading coloring rule by
show heading.where(level: 1): set text(fill: fill.at(0))
show heading.where(level: 2): set text(fill: fill.at(1))
show heading.where(level: 3): set text(fill: fill.at(2))
show heading.where(level: 4): set text(fill: fill.at(3))
show heading.where(level: 5): set text(fill: fill.at(4))
show heading.where(level: 6): set text(fill: fill.at(5))
Alternatively we could use a function instead of setting each level manually, but I find this less readable:
let body = fill.enumerate().fold(body, (body, (index, color)) => {
show heading.where(level: index + 1): set text(fill: color)
body
})
And with this, you are able to override the color in the later show rule: