Indeed, showybox is a great package for this, but unfortunately it slightly lacks configuration flexibility. You can use shadow for this, but for shadow you can only set fill
, but not stroke
. Here I modified it (don’t know how long will the link last, maybe you should pitch the feature to the author so it can be included in the official package version):
showybox:2.0.1.zip
With this I can do:
#import "@preview/showybox:2.0.1": showybox
#showybox(
width: 11cm,
frame: (title-color: white, radius: 0pt),
shadow: (color: black, offset: 0.2em),
title-style: (
color: black,
boxed-style: (
anchor: (x: start, y: top),
offset: (x: -1.4em, y: -0.4em),
radius: 0pt,
),
),
title: lorem(2),
lorem(25),
)
And here is my one-file solution:
#let shadow-box(title, body, offset: 2pt, title-offset: 2pt) = {
let frame = block.with(
width: 11cm, // This probably should be removed.
inset: (top: 3em, rest: 0.7em),
fill: white,
stroke: black,
)
let title-frame = frame.with(width: auto, inset: 0.7em)
context {
let body-height = measure(frame(body)).height
place(dx: offset, dy: offset, frame(hide(body))) // shadow
frame(body)
place(dx: -offset, dy: -body-height - offset, title-frame(hide(title))) // shadow
let offset = title-offset + offset
place(dx: -offset, dy: -body-height - offset, title-frame(title))
}
}
#shadow-box(lorem(2), lorem(25))
Output