← TriNetFeature deep dive

Canadian
Holiday Calendar

From a hand-filled, faxed PDF to one central grid.

Canadian statutory holidays are gnarly — they vary province to province: BC’s Family Day, Manitoba’s Louis Riel Day, Quebec’s National Patriots’ Day. Companies needed a way to set which holidays counted as paid for their org, and the starting point was almost comically analog. I designed the admin panel that replaced it.

Canada 2018 — Holiday Schedule Selection
Holiday Schedule Selection
Calendar year2018 ▾
Select which statutory and non-statutory holidays are paid, by province.
All holidaysStatutoryNon-statutory
Search holidays+ Add Custom Holiday
HolidayTypeBCABSKMBONQCNBNSPENL
New Year's DaySTAT
Family DaySTAT
Louis Riel DaySTAT
Good FridaySTAT
Victoria DaySTAT
National Patriots' DaySTAT
Canada DaySTAT
Civic HolidayNON
Labour DaySTAT
ThanksgivingSTAT
Remembrance DayNON
Christmas DaySTAT
Boxing DayNON
13 holidays · 10 provinces & territories
CancelSave Schedule
01The problem

The starting point was comically analog.

To tell TriNet which holidays their employees were paid for, companies filled out a PDF by handand faxed it in — for someone to key in manually, errors and all. And the data itself is genuinely hard: statutory holidays vary province to province, with region-specific ones like Manitoba’s Louis Riel Day or Quebec’s National Patriots’ Day (which stands in for Victoria Day there).

A hand-filled PDF, faxed and re-keyed, is a data-entry error waiting to happen — for something as consequential as who gets paid, when.
holiday schedule selection — row per holiday, column per region
Holiday Schedule Selection
Calendar year2018 ▾
Select which statutory and non-statutory holidays are paid, by province.
All holidaysStatutoryNon-statutory
Search holidays+ Add Custom Holiday
HolidayTypeBCABSKMBONQCNBNSPENL
New Year's DaySTAT
Family DaySTAT
Louis Riel DaySTAT
Good FridaySTAT
Victoria DaySTAT
National Patriots' DaySTAT
Canada DaySTAT
Civic HolidayNON
Labour DaySTAT
ThanksgivingSTAT
Remembrance DayNON
Christmas DaySTAT
Boxing DayNON
13 holidays · 10 provinces & territories
CancelSave Schedule
DESIGNHoliday Schedule Selection

One grid: a row per holiday, a column per province.

I designed a Holiday Schedule Selection admin panel — a grid that lets an org manage paid holidays across every region from one screen, add custom holidays, and filter statutory vs. non-statutory. Each cell is a simple, legible yes/no, so the province-specific texture that made the PDF error-prone becomes something you can read at a glance.

The deliberate move was to keep the form-based layout close to the PDF’s structure, so the mental model people already had carried over — the same information, in the same shape, but native, validated, and central instead of hand-keyed.

Why mirror the old artifact

When you’re replacing a document people already know, matching its structure lowers the cost of the switch — the grid is the PDF, just finally in the system.

THE HARD PARTAn enormous data form

The one real risk was performance.

A row per holiday times a column per province is a lot of fields — an enormous data form that threatened to load painfully slowly. That’s the kind of thing that reads as “broken” to a user even when it’s working: a blank screen while the grid populates.

So when we saw the load times, the developers and I added a preloader — a clear loading state that keeps the screen from feeling stuck while all that data comes in. A small, honest fix for a real engineering constraint, made at the moment we actually observed the problem.

Design meets engineering reality

A loading state isn’t decoration — on a heavy form it’s the difference between “working” and “broken.”

holiday schedule — loading state
Holiday Schedule Selection
Loading holiday schedule…
Populating 13 holidays across 10 regions
Where it landed & what it taught me

Replacing a faxed PDF is a real UX win, quietly.

The admin panel took a hand-filled, faxed, re-keyed document and made it one central, validated grid — the same DNA as the rest of my TriNet payroll work: real-world complexity the interface hadn’t caught up to. The lesson that stuck was small and practical: watch for the performance cliff on data-dense screens, and fix it where it actually shows up.

Honest ending: I left before implementation wrapped, so I have no measured results (error-rate drop, time saved) to quote — the work is qualitatively validated, not numerically proven.