typst

Retrieve the value of a color type variable in Typst


I am using Typst, and I am working on a very simple Polylux theme. Below my actual code (saved in a file named sorbonne-slides.typ)

#import "@preview/polylux:0.3.1": *

// Color definitions
#let sorbonne-blue = rgb("#1D2769")
#let sorbonne-red = rgb("#AC182E")
#let sorbonne-lightblue = rgb("#52B5E5")
#let sorbonne-yellow = rgb("#FFB700")
#let sorbonne-text = rgb("#263068")

// Primary background color
#let primary-color = state("faculty-color", none)

#let sorbonne-theme(
  aspect-ratio: "16-9", 
  fontsize: 3em,
  faculty: none,
  body) = {

  set page(
    paper: "presentation-" + aspect-ratio,
  )

  set text(font: "Fira Sans", size: fontsize, fill: sorbonne-text)
  
  // update primary color according to variable 'faculty'
  if faculty == "sante" {
    primary-color.update(sorbonne-red)
  } else if faculty == "sciences" {
    primary-color.update(sorbonne-lightblue)
  } else if faculty == "lettres" {
    primary-color.update(sorbonne-yellow)
  } else {
    primary-color.update(sorbonne-blue)
  }
  
  body
}

// title-slide 
#let title-slide(
  title: [], 
  subtitle: [],
  author: [], 
  date: [], 
  location: []
  ) = {

    // background of the title slide
    let background = context primary-color.get()
    set page (
      fill: background,
    )

    set text(
      fill: white, 
      size: 35pt
    )
  
    grid(
      columns: auto, 
      rows: (0.60fr, 0.40fr), 
      row-gutter: 1em,
      align(horizon)[
        #strong(title)
        #parbreak()
        #strong(text(size: .7em,  subtitle))
      ],
      align(top)[
        #text(size: .7em, author)
        #parbreak()
        #text(size: .7em, location)
        #parbreak()
        #text(size: .7em, date)
      ] 
    )    
  }

When I try to create a title slide using the following code:

#import "sorbonne-slides.typ": *

#show: sorbonne-theme.with(aspect-ratio: "16-9", faculty: "sante")

#title-slide(
  title: [A funny title], 
  subtitle: [A funny subtitle],
  author: [A funny author],
  date: [2024-03-18], 
  location: [A funny department], 
)

I have the following error:

error: expected color, gradient, pattern, or none, found content
   ┌─ \\?\C:\Users\3121805\Dropbox\programmes\polylux templates\sorbonne-slides-typst\sorbonne-slides.typ:45:12
   │
45 │       fill: background,
   │             ^^^^^^^^^^

help: error occurred in this call of function `title-slide`

I really don’t understand where this error could be coming from, and why the ‘background’ variable doesn’t ultimately contain the color I’m trying to assign to it based on the value of the ‘faculty’ parameter. Does anyone have an idea of what the issue might be here?


Solution

  • Why context primary-color.get() doesn't work

    context will always return content:

    #type(5) // "integer"
    
    #type(context 5) // "content"
    

    The trick is to perform all operations that need a context inside that context:

    #let title-slide(..) = context {
    //                     ^^^^^^^ This is the change
    // ...
    
    // Now that we're inside a context, this will work as expected
    let background = primary-color.get()
    
    // ...
    }
    

    With this change, the whole title-slide gets access to the context which lets you use states as expected.

    Why your code produces unexpected results