Table with progress bars for comparing two things and show automated colored visualization

Hope someone will found it in Google search. Thanks @sijo from Typsts’ Discord server for help with gradient fill.

Use out of ten points (or use floats to make it out of hundred) to compare two things by some criterias. Set yellow_delta to control interval of the yellow color.

#let prepare_cell(percent, color, text) = {
  let grad_fill(percent, color) = gradient.linear(
    (color.lighten(100%), 0%), 
    (color.lighten(20%), percent),
    (white.lighten(100%), percent), 
    (white.lighten(100%), 100%)
  )
  return table.cell(fill: grad_fill(percent, color))[#text]
}

#let determine_color(min, max, yellow_delta) = {
  let delta = max - min
  if delta <= yellow_delta { yellow } else { red }
}

#let prepare_pairs(pair, yellow_delta) = {
  let percent0 = pair.at(0) / 10 * 100%
  let percent1 = pair.at(1) / 10 * 100%
  
  if pair.at(0) == pair.at(1) {
    (prepare_cell(percent0, green, pair.at(0)), 
    prepare_cell(percent1, green, pair.at(1)))
  } else if pair.at(0) > pair.at(1) {
    let lose_color = determine_color(pair.at(1), pair.at(0), yellow_delta)
    (prepare_cell(percent0, green, pair.at(0)), 
    prepare_cell(percent1, lose_color, pair.at(1)))
  } else {
    let lose_color = determine_color(pair.at(0), pair.at(1), yellow_delta)
    (prepare_cell(percent0, lose_color, pair.at(0)), 
    prepare_cell(percent1, green, pair.at(1)))
  }
}

#let prepare_cells(column0, column1, yellow_delta) = {
  column0.zip(column1).map(pair => prepare_pairs(pair, yellow_delta))
}

#let compare(content, yellow_delta: 2, length: 10em) = {
  let pairs = prepare_cells(
    content.first_item, 
    content.second_item, 
    yellow_delta
  )
  
  table(
    columns: (auto, length, length),
    [*Criteria*], [*#content.first_name*], [*#content.second_name*],
    ..for (criteria, cells) in content.criterias.zip(pairs) {
      ( [#criteria], cells.at(0), cells.at(1) )
    }
  )
}

#compare(
  yellow_delta: 2,
  (
    first_name: "LaTeX",
    second_name: "Typst",
    criterias: (
      "Speed",
      "Comfort",
      "Flexibility",
      "Something to be yellow"
    ),
    first_item: (
      3, 
      5,
      10,
      6
    ),
    second_item: (
      10,
      8,
      10,
      7
    ),
  )
)

4 Likes