How can I define custom colored blocks, e.g. green "Do" and red "Don't" blocks?

I have a document with many “do” and “don’t” examples. I want to fill “dos” with green and “donts” with red. How is it possible without specifying color for each block again and again?

Here is my current attempt (Doesn’t work. Both “do” and “dont” blocks are white.):

// This is for "do" and "don't" blocks.
// Not sure it will affect them.
#set block(
  inset: 8pt,
  radius: 4pt,
)

#let do() = {
  fill: green
}

#let dont() = {
  fill: red
}

= Heading

Body text.

#do[
  Do this. This should be green.
]

#dont[
  Don't do this. This should be red.
]

Body text.

Currently, your #do and #dont functions do not generate blocks but rather they just enter code mode and imitate dictionary syntax but not in a valid way. You have to explicitly return a block with the fill applied like this:

#let do = block.with(fill: green)

#do[
  Do this. This should be green.
]
1 Like

It will if functions are defined something like this.

1 Like

But then inset and radius affect headings, aren’t they?

To add inset and radius for “dos” and “donts” only, I currently use this:

#let do = block.with(fill: green, inset: 8pt, radius: 4pt)
#let dont = block.with(fill: red, inset: 8pt, radius: 4pt)

But I would prefer to avoid using inset: 8pt, radius: 4pt twice. Maybe there exists something like this?

#let [do, dont](inset: 8pt, radius: 4pt)
#let do = block.with(fill: green)
#let dont = block.with(fill: red)

with() makes a new function out of a different function by setting some of its parameters, so you can call with() again on its result. That means you can do the following:

#let block-template = block.with(inset: 8pt, radius: 4pt)

#let do = block-template.with(fill: green)
#let dont = block-template.with(fill: red)
5 Likes