Show the code
# Load necessary libraries
if (!require("gt")) install.packages("gt")
if (!require("dplyr")) install.packages("dplyr")
if (!require("tidyr")) install.packages("tidyr")
if (!require("glue")) install.packages("glue")
library(gt)
library(dplyr)
library(tidyr)
library(glue)
# 1. Define Helper Function for Text Color
get_text_color <- function(hex) {
if (is.na(hex)) return("black")
rgb <- col2rgb(hex)
lum <- (0.299 * rgb[1] + 0.587 * rgb[2] + 0.114 * rgb[3]) / 255
if (lum > 0.5) return("black") else return("white")
}
# 2. Define the Cell Formatting Function (Scalar Version)
fmt_color_cell_worker <- function(name, hex) {
# Handle NAs (Blank Cells)
if (is.na(name) || is.na(hex)) {
return("<div style='background-color: white; width: 100%; height: 100%;'></div>")
}
# Determine text color based on background
text_col <- get_text_color(hex)
# Return HTML
glue(
"<div style='
background-color: {hex};
color: {text_col};
width: 100%;
height: 100%;
padding: 8px;
border-radius: 4px;
font-weight: bold;
text-align: center;
font-size: 12px;'>
{name}
</div>"
)
}
# 3. Vectorize the Function
fmt_color_cell <- Vectorize(fmt_color_cell_worker)
# 4. Create the Data (Historically Accurate)
data_raw <- tribble(
~Year, ~Pantone_Name, ~Pantone_Hex, ~BM_Name, ~BM_Hex, ~SW_Name, ~SW_Hex, ~Akzo_Name, ~Akzo_Hex, ~Glid_Name, ~Glid_Hex, ~Dunn_Name, ~Dunn_Hex, ~Behr_Name, ~Behr_Hex, ~Val_Name, ~Val_Hex,
2026, "Cloud Dancer", "#F0EEE9", "Silhouette", "#4A413C", "Univ. Khaki", "#BCA68E", "Slow Swing", "#2C3E50", "Warm Mahogany", "#9D4A3C", "Midnight Garden", "#2E4035", "Hidden Gem", "#6A867F", "Warm Eucalyp.", "#7A8B78",
2025, "Mocha Mousse", "#A47864", "Cinn. Slate", "#AA8C96", "Quietude", "#A3AF9D", "True Joy", "#F7C04A", "Purple Basil", "#6A4B5F", "Caramelized", "#B58463", "Rumors", "#8A3324", "Encore", "#2C5282",
2024, "Peach Fuzz", "#FFBE98", "Blue Nova", "#5B6C91", "Upward", "#B4BEC3", "Sweet Embrace", "#E0C7D5", "Limitless", "#EFDECD", "Skipping Stones", "#7DA6B3", "Cracked Pepper", "#4E5052", "Renew Blue", "#97C5C9",
2023, "Viva Magenta", "#BE3455", "Rasp. Blush", "#D25A46", "Redend Point", "#AE8E7E", "Wild Wonder", "#D2C29D", "Vining Ivy", "#3A6A6C", "Terra Rosa", "#A66E6A", "Blank Canvas", "#F0ECE2", NA, NA,
2022, "Very Peri", "#6667AB", "October Mist", "#A3AA9E", "Evergreen Fog", "#95978A", "Bright Skies", "#87A9C3", "Guacamole", "#8C9C74", "Art & Craft", "#947B64", "Breezeway", "#B8CBC0", NA, NA,
2021, "Ult. Gray", "#939597", "Aegean Teal", "#647882", "Urbane Bronze", "#545E60", "Brave Ground", "#8D7F71", "Transcend", "#D0C5B3", "Wild Blue", "#7D8F9E", "Canyon Dusk", "#C09277", NA, NA,
2020, "Classic Blue", "#0F4C81", "First Light", "#EBE1E1", "Naval", "#2F3D4C", "Tranquil Dawn", "#C2CDBE", "Chin. Porcelain", "#304B64", "Minty Fresh", "#B6E0D2", "Back to Nature", "#97A878", NA, NA,
2019, "Living Coral", "#FF6F61", "Metropolitan", "#AFB4B4", "Cavern Clay", "#D1866A", "Spiced Honey", "#C49A6C", "Night Watch", "#004746", "Spice of Life", "#8D4E3C", "Blueprint", "#4D6C8C", NA, NA,
2018, "Ultra Violet", "#5F4B8B", "Caliente", "#AF2D2D", "Oceanside", "#195564", "Heart Wood", "#B5A29D", "Black Flame", "#202226", "Green Hour", "#3D4F46", "In The Moment", "#7E9995", NA, NA,
2017, "Greenery", "#88B04B", "Shadow", "#5F505F", "Poised Taupe", "#8C827D", "Denim Drift", "#7E8E9F", "Violet Verbena", "#7A5C6D", "Honey Glow", "#E3B668", "Comfortable", "#D5CDB5", NA, NA,
2016, "Rose Quartz", "#F7CAC9", "Simply White", "#F3F4ED", "Alabaster", "#EDEAE0", "Ochre Gold", "#D09D52", "Paradise Found", "#7B9683", NA, NA, NA, NA, NA, NA
)
# 5. Process the DataFrame
df_formatted <- data_raw %>%
mutate(
Pantone = fmt_color_cell(Pantone_Name, Pantone_Hex),
Benjamin_Moore = fmt_color_cell(BM_Name, BM_Hex),
Sherwin_Williams = fmt_color_cell(SW_Name, SW_Hex),
AkzoNobel = fmt_color_cell(Akzo_Name, Akzo_Hex),
Glidden = fmt_color_cell(Glid_Name, Glid_Hex),
Dunn_Edwards = fmt_color_cell(Dunn_Name, Dunn_Hex),
Behr = fmt_color_cell(Behr_Name, Behr_Hex),
Valspar = fmt_color_cell(Val_Name, Val_Hex)
) %>%
select(Year, Pantone, Benjamin_Moore, Sherwin_Williams, AkzoNobel, Glidden, Dunn_Edwards, Behr, Valspar)
# 6. Handle Split Years (The Fix)
# Instead of complex HTML, we use standard cells with "multi-color" and white background
df_formatted$Pantone[df_formatted$Year == 2021] <- fmt_color_cell("multi-color", "#FFFFFF")
df_formatted$Pantone[df_formatted$Year == 2016] <- fmt_color_cell("multi-color", "#FFFFFF")
# 7. Generate Table
gt_table <- df_formatted %>%
gt() %>%
fmt_markdown(columns = everything()) %>%
cols_label(
Year = "Year",
Pantone = "Pantone",
Benjamin_Moore = "Benj. Moore",
Sherwin_Williams = "Sherwin-W.",
AkzoNobel = "AkzoNobel",
Glidden = "Glidden",
Dunn_Edwards = "Dunn-Edw.",
Behr = "Behr",
Valspar = "Valspar"
) %>%
tab_header(
title = md("**The Spectrum of Choice (2016–2026)**"),
subtitle = "Color of the Year selections (Blank cells indicate no single COTY selected)"
) %>%
cols_width(
Year ~ px(50),
everything() ~ px(100)
) %>%
tab_style(
style = list(cell_fill(color = "#f4f4f4"), cell_text(weight = "bold")),
locations = cells_body(columns = Year)
) %>%
tab_style(
style = list(cell_text(weight = "bold", size = "large")),
locations = cells_column_labels()
)
# Print
gt_table| The Spectrum of Choice (2016–2026) | ||||||||
| Color of the Year selections (Blank cells indicate no single COTY selected) | ||||||||
| Year | Pantone | Benj. Moore | Sherwin-W. | AkzoNobel | Glidden | Dunn-Edw. | Behr | Valspar |
|---|---|---|---|---|---|---|---|---|
| 2026 | Cloud Dancer
Cloud Dancer
|
Silhouette
Silhouette
|
Univ. Khaki
Univ. Khaki
|
Slow Swing
Slow Swing
|
Warm Mahogany
Warm Mahogany
|
Midnight Garden
Midnight Garden
|
Hidden Gem
Hidden Gem
|
Warm Eucalyp.
Warm Eucalyp.
|
| 2025 | Mocha Mousse
Mocha Mousse
|
Cinn. Slate
Cinn. Slate
|
Quietude
Quietude
|
True Joy
True Joy
|
Purple Basil
Purple Basil
|
Caramelized
Caramelized
|
Rumors
Rumors
|
Encore
Encore
|
| 2024 | Peach Fuzz
Peach Fuzz
|
Blue Nova
Blue Nova
|
Upward
Upward
|
Sweet Embrace
Sweet Embrace
|
Limitless
Limitless
|
Skipping Stones
Skipping Stones
|
Cracked Pepper
Cracked Pepper
|
Renew Blue
Renew Blue
|
| 2023 | Viva Magenta
Viva Magenta
|
Rasp. Blush
Rasp. Blush
|
Redend Point
Redend Point
|
Wild Wonder
Wild Wonder
|
Vining Ivy
Vining Ivy
|
Terra Rosa
Terra Rosa
|
Blank Canvas
Blank Canvas
|
|
| 2022 | Very Peri
Very Peri
|
October Mist
October Mist
|
Evergreen Fog
Evergreen Fog
|
Bright Skies
Bright Skies
|
Guacamole
Guacamole
|
Art & Craft
Art & Craft
|
Breezeway
Breezeway
|
|
| 2021 | multi-color
multi-color
|
Aegean Teal
Aegean Teal
|
Urbane Bronze
Urbane Bronze
|
Brave Ground
Brave Ground
|
Transcend
Transcend
|
Wild Blue
Wild Blue
|
Canyon Dusk
Canyon Dusk
|
|
| 2020 | Classic Blue
Classic Blue
|
First Light
First Light
|
Naval
Naval
|
Tranquil Dawn
Tranquil Dawn
|
Chin. Porcelain
Chin. Porcelain
|
Minty Fresh
Minty Fresh
|
Back to Nature
Back to Nature
|
|
| 2019 | Living Coral
Living Coral
|
Metropolitan
Metropolitan
|
Cavern Clay
Cavern Clay
|
Spiced Honey
Spiced Honey
|
Night Watch
Night Watch
|
Spice of Life
Spice of Life
|
Blueprint
Blueprint
|
|
| 2018 | Ultra Violet
Ultra Violet
|
Caliente
Caliente
|
Oceanside
Oceanside
|
Heart Wood
Heart Wood
|
Black Flame
Black Flame
|
Green Hour
Green Hour
|
In The Moment
In The Moment
|
|
| 2017 | Greenery
Greenery
|
Shadow
Shadow
|
Poised Taupe
Poised Taupe
|
Denim Drift
Denim Drift
|
Violet Verbena
Violet Verbena
|
Honey Glow
Honey Glow
|
Comfortable
Comfortable
|
|
| 2016 | multi-color
multi-color
|
Simply White
Simply White
|
Alabaster
Alabaster
|
Ochre Gold
Ochre Gold
|
Paradise Found
Paradise Found
|
|||