Typst doesn’t have a dedicated feature for this, but the feasibility of using workarounds depends on what you’re trying to do. Most involve the usage of introspection (in particular, counters).
Styling just the first paragraph after the heading
If you just want to style the first paragraph after the heading, you can try something such as this - be warned that false-positives are likely, so ensure the first thing after a heading (other than another heading) is a paragraph:
#let head-par-counter = counter("heading-par")
#show heading: it => {
head-par-counter.update(0)
it
head-par-counter.update(it.level)
}
#show par: it => context {
head-par-counter.update(0)
// Note: context is frozen at the start of the context block,
// so .get() below happens before the .update(0) above
let current-level = head-par-counter.get().first()
if current-level > 0 {
pad(left: current-level * 2em, it)
} else {
it
}
}
// Sample usage:
#set page(width: 200pt, height: auto, margin: 1cm)
Hello world, this paragraph is not indented.
= First
Hello world, this paragraph is a little indented.
== Second
Hello world, this one is even further indented.
Not affected here! (Not the first paragraph.)
=== Third
Hello world
Not affected.
Styling all paragraphs after a heading
For all paragraphs following those headings, it’s harder to get a satisfying and uniform result, but you can try to adapt the above solution by not resetting the counter on each paragraph. However, to avoid unexpected results on other elements, such as tables, you may need to add some exceptions, as seen below:
#let head-par-counter = counter("heading-par")
#show heading: it => {
head-par-counter.update(0)
it
head-par-counter.update(it.level)
}
// Indent paragraphs and figures (may need to add more here)
#show selector.or(par, figure): it => context {
// No resetting
let current-level = head-par-counter.get().first()
if current-level > 0 {
pad(left: current-level * 2em, it)
} else {
it
}
}
// Disable this behavior inside those elements
#show selector.or(grid, table): it => {
head-par-counter.update(0)
it
}
// Sample usage:
#set page(width: 200pt, height: auto, margin: 1cm)
Hello world
= First
Hello world, this paragraph is indented
== Second
Hello world, this one also is
Hello world
=== Third
Hello world
Hello world
#figure(table(
columns: 2,
[*Name*], [*Data*],
[ABC], [DEF]
), caption: [Caption])
Just keep in mind that, the further you go, the more you may have to add exceptions or change the targets a little bit… but maybe this is more or less what you were thinking of. Let us know if that wasn’t the case.