What is the equivalent for \vfill between list items?

In Latex, I can do

Some problem
\begin{enumerate}
    \item part (a) \vfill
    \item part (b) \vfill
    \item part (c) \vfill
\end{enumerate}

in order to give enough spaces in one page.

What is the counterpart in typst? I tried the following.

Some problem
+ part (a) #v(1fr)
+ part (b) #v(1fr)
+ part (c) #v(1fr)

which results in 3 pages.

Hello. If that’s all you need, you can do

Some problem
#[
  #show enum.item: it => it + v(1fr)
  + part (a)
  + part (b)
  + part (c)
]

As par.leading can’t take fraction values:

#show enum: set par(leading: 5em)

Thank you. But this does not solve it. This makes the numbering be 1, 1, 1 instead of 1, 2, 3

You could combine @Andrew 's solution with a custom counter:

Some problem
#[
  #let enumcounter = counter("enumcounter")
  #enumcounter.update(1)
  #show enum.item: it => context {
    if it.number != none {
      return it
    }
    enumcounter.step()
    enum.item(
      enumcounter.get().first(),
      it.body
    ) + v(1fr)
  }
  + part (a)
  + part (b)
  + part (c)
]

Yep, but this is overcomplicated a bit. Here you go:

Some problem
#[
  #show enum.item: it => {
    let enum-counter = counter("enum-counter")
    if it.number != none { return it }
    enum-counter.step()
    context enum.item(..enum-counter.get(), it.body)
    v(1fr)
  }
  + part (a)
  + part (b)
  + part (c)
]

I actually was thinking at first with the classic processed label hack, but using a built-in field would generally be better, unless it’s actually be used. Then it will break.

#show enum.item: it => {
  if it.has("label") and it.label == <processed> { return it }
  [#enum.item(...)<processed>]
}

#let vfill-enum(doc) = {
  let enum-counter = counter("enum-counter")
  enum-counter.update(0)
  show enum.item: it => {
    if it.number != none { return it }
    enum-counter.step()
    context enum.item(..enum-counter.get(), it.body)
    v(1fr)
  }
  doc
}

Some problem
#[
  #show: vfill-enum
  + part (a)
  + part (b)
  + part (c)
]

Related: Resumable enum numbering · Issue #325 · typst/typst · GitHub

Then, it will be a bit hard to modify it if I want to give more space to one problem, e.g., #v(2fr). Finally, I made a #question.

#let question_counter = counter("question")

#let question(body, points: none) = {
  question_counter.step(level: 1)
  let number = context question_counter.display("1.")
  number
  if points != none [
    (#points pt)
  ]
  body
  linebreak()
}

#question(points: 3)[
  #lorem(30)
  
  #v(1fr)
]

#question[
  #lorem(20) #v(2fr)
]

#question[
  #lorem(40) #v(1fr)
]

Is it a better idea that typst should not stretch an enum.item to the whole page? Maybe I shall open an issue on Github?

Yeah, because there was no mention of 2fr and you can’t even add numbers to \vfill. Which is why I said, “If that’s all you need”. The better the question, the better the answer.

It seems you’re building an exam or a questionnaire, maybe the package tutor – Typst Universe might be of help. I’ve never used it, but I know the person personally who created it.

That one looks nice. The thing is that I am promoting Typst to others. If they ask me how to do a similar thing as the \item,\vfill in Latex, I can only tell them to manually setup a counter or use some package. They will certainly feel disappointed because for a familiar behavior, they have to find some way to crack the nuts. This is why I wonder whether it is a better idea to change the behavior of enum.item.

I’ve never seen this used. If this is a common thing, then it’s better to open a feature request.

Hi~ fduxiao. Recently, I use Typst to create exam, I also encounter the same problem as you. Although it can be achieved using custom functions, I still want to use the concise enum syntax. I notice that the itemize package can set spacing for each item; The similar code in LaTeX:

Some problem
\begin{enumerate}
    \item part (a) \vfill
    \item part (b) \vfill
    \item part (c) \vfill
\end{enumerate}

now can be written in Typst as:

#import "@preview/itemize:0.2.0" as el
#show: el.default-enum-list.with(
  enum-spacing: ((above: auto, below: 2fr), auto), // below spacing for last-item
  item-spacing: (1fr, auto), // the space between each item in level-1
)
Some problem
+ part (a)
  + #lorem(10)
+ part (b)
  + #lorem(10)
  + #lorem(10)
+ part (c)
  + #lorem(10)

This setting doesn’t affect the list items at the second level. If you want to modify the spacing for a specific item like part (b), although you can reconfigure item-spacing (for example, changing it to ((1fr,1fr,2fr), auto)), this is not very natural. It would be better if the itemize package could implement a “manual setting” feature for list items; for example, a possible syntax could be:

+ part (a)
+ #el.item(item-spacing: (above: auto, below: 2fr)) part (b)
+ part (c)

If such a syntax is possible, then we could use

#let vfill(n) = el.item(item-spacing: (above: auto, below: n))

+ #vfill(1fr) part (a)
+ #vfill(1fr) part (b)

which is very similar to the Latex package enumerate.

Thank you! I will try it!