Can I use Hydra or equivalent for Fancy right margin with Section titles (just like header)?

Hi,

I am looking to add fancy section titles on the right margin (just like Hydra does in the header) on everypage.

An example project showing the intent -
https://typst.app/project/wYFzOdTITgm-IGwgkdtI2z

Any tips would be super helpful.

Thanks to pointers from @SillyFreak - :pray: -
Here is a solution that sort of works (though I could not figure out why the stack function behaved the way it did) -

#set page(
  columns: 1,
  paper: "a4",
  flipped: false,
  margin: (x: 16mm, y: 27.5mm),
  // introspection APIs
  header: context { 
    if counter(page).get().first() > 1 [
      // #let sec_title = pad(top: 60pt, rotate(-90deg)[*Section-1*])
      #let sec_title = [sec-1]
      #let fancy_margin = {
        stack(
          dir: ttb,
          // spacing: 5mm, // did not work, not sure why?
          rect(height: 60mm, width: 14mm, fill: aqua)[sec-1],
          v(45mm), 
          rect(height: 60mm, width: 14mm, fill: gray)[sec-2],
          v(65mm),
          rect(height: 60mm, width: 14mm, fill: gray)[sec-3]
        )
      }
      #place(
        // top + center,
        top,
        dx: 182mm,
        dy: 50mm,
        scope: "parent",
        float: true,
        // rect(height: 15%, width: 28pt, fill: aqua),
        fancy_margin
      )
    ]
  }
)

#set text(9pt)

#set par(justify: true)
#lorem(300)

#let myboxes = {
  stack(
    dir: ttb,
    spacing: 5mm,
    rect(height: 40mm, width: 20mm, fill: aqua)[some text],
    // v(5mm), 
    rect(height: 40mm, width: 20mm, fill: gray),
    // v(5mm),
    rect(height: 40mm, width: 20mm, fill: gray)
  )
}

#myboxes

#pagebreak()

#lorem(300)

#pagebreak()

#lorem(250)
1 Like

It seems to have something to do with placing the stack somewhere where the height is not fixed. I didn’t go into detail about why this causes the stack to “collapse”, but a workaround (that imo results in a nice layout of the title margin) is to make sure that the placed margin has a defined height.

I came up with this, based on the solution from your message:

#set page(
  margin: (x: 16mm, y: 27.5mm),
  header: context {
    let sec-title(body, active: false) = {
      let fill = if active { aqua } else { gray }
      let body = rotate(-90deg, reflow: true, strong(body))
      rect(height: 60mm, width: 100%, fill: fill, strong(body))
    }
    let fancy-titles = {
      stack(
        dir: ttb,
        spacing: 5mm,
        sec-title(active: true)[Section-1],
        sec-title[Section-2],
        sec-title[Section-3],
      )
    }
    if counter(page).get().first() > 1 {
      let title-width = 14mm
      place(
        // place relative to the top center of the page
        top + center,
        // move to the right edge of the page
        dx: page.width / 2 - title-width / 2,
        block(
          // span the whole page, and the configured width
          height: page.height,
          width: title-width,
          // stroke: red,  // debug: are we really correctly placed?
          // vertically center the titles
          align(horizon, fancy-titles)
        )
      )
    }
  }
)

The most important thing is the full-height margin block that contains a vertically centered stack of section titles. I took the liberty and assumed/inferred a few things about your layout and tried to structure the code cleanly based on that understanding, i.e. using a active parameter to decide background color.