How to best create Signature and Date lines?

I have two working options below, but both seem overly fiddly. Is there a simpler way or a package for adding signature and date lines to the bottom of a document? I may need more than one set on occasion.

// Inline
#let signature-line(width: 1fr) = box(width: width, line(length: 100%))
QA Manager:
#signature-line(width: 40%)
#h(3em)
Date:
#signature-line()

// Grid
#grid(
  columns: (auto, 50%, auto, 1fr),
  align: bottom,
  [QA Manager:~], line(length: 80%),
  [Date:~], line(length: 100%),
)

image

There are many ways to do it but you can use a simple version:

#let ll = 6cm
#let sign-line = [QA Manager: #box()[#line(length: ll)] #h(1fr) Date: #box()[#line(length: ll)]]

#sign-line

#sign-line

Most of the exam packages will have some sort of way of implementing it, which you could use as an example.

1 Like

Is there a good way to get all the signature lines to stop at the same horizontal point on the page, a few spaces before “Date:”?

#let signature-line(person, date-line-length: 1.5in) = [
  #person: #box(line(length: 40%))
  #h(1fr)
  Date: #box(line(length: date-line-length))
]

#signature-line()[Quality Manager]

#signature-line()[Product Manager]

#signature-line()[Authorized Inspector]

I tried using the end line parameter, but it didn’t seem to work any differently than length in that regard.

Next, I’m thinking I could measure the page width and subtract the date and person portions to get the remaining line length, but I don’t know how to dynamically get the page width.

like this, for example:

#let signature-line(person, date-line-length: 1.5in) = [
  #person: #box(width: 1fr, line(length: 100%))
  #h(3em)
  Date: #box(line(length: date-line-length))
]

#signature-line()[Quality Manager]

#signature-line()[Product Manager]

#signature-line()[Authorized Inspector]

A line() can’t have a 1fr length, but you can make it fill (100%) a box that has width 1fr, which torns out the same.

3 Likes

Oh right. I was almost there!

Here is a take on @ensko’s answer that allows passing all names to one function. One side negative effect this may have is for screen readers.

#let signatures(..person-list) = {
  set line(length: 100%)
  set box(width: 1fr)
  v(0pt, weak: true)                    //Collapse any previous spaces
  grid(
    column-gutter: .5em,
    rows: 3em,                          //Vertical space for each signature
    columns: (1fr, auto, 1.5in),
    
    align: bottom,
    ..person-list.pos().map(person => ( //For each given person...
      [#person: #box(line())],          //Name and signature line
      [Date:],                          //Date
      line())).flatten()                //Date line
  )
}

Text before
#signatures[Quality Manager][Product Manager][Authorized Inspector]
Text after

The row height of 3em was used so there is some space for the signatures

1 Like