How to reference styled figures?

Dear community,

I am currently trying to create a Tufte-style document. I am aware of the tufte-memo template on Typst universe, since I latook inspiration from it. However, I need to apply more style to obtain the look and feel of LaTeX tufte-book class.

Overall, I succeeded to create all the elements I need. However, I am struggling in referencing the figure elements. I have seen this discussion on the forum. It explains the problem, but the solution seems to not fit my needs.

The problem is the following. I want to create a sidefigure that can take any kind of content (image, table) which follows the general numbering of figures or tables. To this end, I use the drafting package.

Here is a MWE of the template

// mwe.typ
#import "@preview/drafting:0.2.2": *

#let template(body) = {
  set par(justify: true)

  set page(
    paper: "a4",
    margin: (
      left: 1.5cm,
      right: 7cm
    )
  )

  set-page-properties()
  set-margin-note-defaults(
    stroke: none,
    side: right,
    margin-right: 5cm,
    margin-left: 1.75cm,
  )

  body
}

#let sidefigure(content, caption: none, dy: - 1.5em) = margin-note(
 context {
  show figure.caption: it => context [
    #set align(left)
    #let kind = none
    #if it.supplement.text.contains("Fig") {
      kind = image
    } else if it.supplement.text.contains("Tab") {
      kind = table
    }
    #it.supplement #counter(figure.where(kind: kind)).display()#it.separator #it.body
  ]
  set figure.caption(position: bottom)
  figure(
    content,
    caption: caption
  )
  }, dy: dy
)

Here is the main.typ

// main.typ
#import "mwe.typ": *

#show: template.with()

= Section 1

#lorem(50)

#sidefigure(
  rect(),
  caption: "Figure Caption",
  dy: -2em
) <fig:1>

// @fig:1 (it throws an error)

As you will see, the figure and its caption are correct. However, I can’t cite this figure in the text because the result of the sidefigure function is not a figure.

I tried something like #let subfigure = figure.with(kind: "subfig", supplement:[Figure]) and #show figure.where(kind: "subfig"): it => {...}, but I would like to avoid to have custom counters and a function for each kind of elements (e.g. sidetable, …).

Is there a workaround ?

Thank you.

Perhaps using this trick to reference metadata?

#show ref: it => {
  if it.element != none and it.element.func() == metadata {
    // do whatever here using it.element
    link(it.element.location())[_referencing metadata with value_ «#it.element.value;»]
  } else {
    it
  }
}

#sidefigure(
  rect(),
  caption: "Figure Caption",
  dy: -2em,
) #metadata("Bar")<fig:1>

@fig:1 // works
1 Like

Thank you it wotks like a charm !

@vmartel08’s solution works, but IMO you don’t actually need to write a ref show rule unless you’d like to keep the original label syntax.

A simpler approach by adding a label parameter to your sidefigure could look like this.

#sidefigure(
  rect(),
  caption: "Figure Caption",
  dy: -2em,
  label: <fig:1>
)

Some comments:

  • You don’t actually need to use so many context expressions. The only contextual statement is the counter display, so just preprend context to that!
  • Nested context can and will result in problems later on, especially if you have multiple show rules.
  • You can probably use a figure(kind: "sidefigure") and write your show rules separately in the template body on figure.where(kind: "sidefigure"), that would make the function sidefigure simpler to read, and modify.
#let sidefigure(content, caption: none, dy: -1.5em, label: none) = margin-note(
  {
    show figure.caption: it => [
      #set align(left)
      #let kind = none
      #if it.supplement.text.contains("Fig") {
        kind = image
      } else if it.supplement.text.contains("Tab") {
        kind = table
      }
      #it.supplement #context it.counter.display(it.numbering) #it.separator #it.body
    ]
    set figure.caption(position: bottom)
    [#figure(
      content,
      caption: caption,
    )#label]
  },
  dy: dy,
)

#show: template.with()

= Section 1

#lorem(50)

#sidefigure(
  rect(),
  caption: "Figure Caption",
  dy: -2em,
  label: <fig:1>
)

@fig:1
4 Likes

Additionally

1 Like