back to work
  1. overview
  2. problem
  3. users
  4. solution
  5. outcome
  6. reflection
workaboutresume

Case study · Enactus UBC

Turning teacher and PA availability into a schedule one admin can trust

  • Design Systems
  • Product Design
  • Accessibility
  • Design-Dev Handoff

Status: Live prototype · iterating

Role
UI/UX Designer, sole designer on this ticket
Team
Enactus UBC Technology team (designers + devs)
Timeline
June 2026, second pass Oct 2026
Tools
Figma, shadcn/ui, Linear
The admin dashboard: a navy sidebar, round status, stats, upcoming workshops, and a Needs attention list.
The admin dashboard: what needs attention, upcoming workshops, and how the round is going.

At a glance

A full product, not just a style guide

I designed the visual system, a component kit and 26 screens across three roles for Enactus UBC’s Workshop Scheduler, plus the PRD and token mapping for the devs. The first version is live as a coded prototype, and the team is iterating on it with feedback.

26

screens across 3 roles, including empty, error and no-access states

17

color tokens, with one variable swap per brand

4

component sets mapped to shadcn/ui

Context

Enactus UBC runs monthly workshops at partner schools. The Workshop Scheduler is a platform to manage them for three kinds of users.

As a UI/UX Designer on the Technology team, I owned the full design foundation for it.

Problem

Something devs could build directly

The dev team needed a visual system, components, and screens they could build from directly.

It had to work for three roles with different needs, and be co-branded across two programs: Ennovate UBC and Enspire UBC.

How might we let a small admin team schedule workshops across many schools, while teachers and PAs only see what needs them?

3

user roles: Admin, Teacher, and PA

2

co-branded programs

1

shared design system

Users

Three roles, three sets of needs

I wrote a persona for each role around its main goal and what it needs to see first after signing in.

Three persona cards. Admin: keep every school's workshops scheduled, staffed and on track; sees first what needs attention. Teacher: get the right workshop booked for their class and know it's covered; sees first anything to confirm. PA: know where to be and when, with everything needed to run the session; sees first their next workshop.

Structure

Every role lands on its own home

Site map: sign in, check role, then an Admin, Teacher or Program assistant area, each with its own home. System pages for loading, empty, error and no access.
Everyone signs in on one page and lands in their own area with its own home. Loading, empty, error and no-access pages work in every area.

Solution

A system the devs could pick up and build

8a

Colors borrowed from Enactus, each with one job

The first palette (charcoal, teal, gold) had no link to Enactus, and teachers usually meet the club through its website first. I pulled the colors from enactusubc.ca’s stylesheet so the tool feels like part of the club.

I kept the palette small on purpose: one dark, one link blue, one yellow for attention, and warm neutrals. With so few colors, each one can carry a meaning instead of decorating.

Color tokens grouped into brand, neutrals, on navy and status, each with its hex value, use and contrast ratio.
Colors from enactusubc.ca: navy #053268, blue #325DC4 and yellow #FFC21F on a warm off-white. Inter, a 4px spacing base and radius 6 / 8 / 12. Every color is a Figma variable.

Enactus yellow is the brand’s most recognizable color, but at 1.62:1 on white it can’t be used for text. Darkening the brand color would have changed the brand, so instead each marker color became two tokens: the bright one for dots, bars and fills, and a darker text variant that passes AA.

Status also never relies on color alone. Every dot sits next to a plain label.

Contrast check. Yellow #FFC21F is 1.62:1 on white, so it is for markers and fills only; its text variant #8A6400 is 5.38:1 and passes AA. Grey #98A1AE is 2.61:1, for dots only; its text variant #5A6577 is 5.89:1.
Yellow and grey stay as markers. Text gets its own AA-safe variants, so contrast holds without changing the brand.

8b

Two brands, one token swap

Ennovate and Enspire run the same workshops under different names. Two full themes would double the upkeep for a volunteer dev team, so the programs share every token except one.

The same dashboard in two brands: Enspire with a dark teal sidebar (#264653) and Ennovate with a navy sidebar (#053268).
Co-branding is one variable mode. Switching to Enspire changes brand/navy; every other token is shared.

8c

A component kit mapped to shadcn/ui

The devs build with shadcn/ui, so I named and structured the components to match it (Button, Badge, Input) instead of inventing my own. I also kept the kit to what the screens actually use. A smaller kit is easier for a student team to keep in sync with the code.

Component kit: buttons, status, navigation item and inputs, each with variants.
Buttons, status, nav items and inputs are Figma components with variants, bound to the tokens. Each maps to its shadcn/ui counterpart.

Three roles could have meant three separate apps. One shell with a role-specific sidebar means the devs maintain a single layout, and each role’s home page answers one question: what do I need to do now?

The app shell: navy sidebar on the left and page content on the right.
One shell holds all three roles: a navy sidebar with that role’s pages, and the page on the right.
The three role home screens: admin dashboard, teacher's My workshops, and program assistant's Assignments.
Each role lands on what it needs most: admins see what needs attention, teachers see what to confirm, and PAs see their next workshop.

8d

Nothing saves until the admin reviews it

Scheduling is a matching problem with hard rules: class meeting times, PA availability, and at least two PAs per workshop. An algorithm can solve most of it, but some workshops will have no valid time at all.

My first idea was to auto-confirm everything that passed and email the admin about the rest. But problems hidden in an email get missed, and a wrong booking at a partner school costs trust. So the scheduler only proposes. Problems are pulled to the top of the review and stay there until someone fixes or accepts them.

The review step: stats for scheduled, short-staffed and couldn't schedule, a warning callout, and a Needs attention table.
The review step: problems are pulled to the top and stay there until they are fixed or accepted.
The other three steps: set up, running the scheduler, and schedule confirmed.
Set up, run, review, confirm. The admin always sees the result before anything is saved.

8e

One availability grid for teachers and PAs

Teachers and PAs both have to say when they’re free. Separate forms would mean two mental models, and data the scheduler has to translate.

I chose a grid you paint over a time-picker form because people picture their week visually, and school blocks like lunch can be shown right where they apply.

The teacher and program assistant availability screens side by side, both using the same half-hour grid.
Both roles mark time on the same half-hour grid, so the scheduler compares like with like. Lunch is blocked by the school, and dragging marks several slots at once.

8f

Designing the unhappy paths

The first version only covered the happy path. A new admin opening the app would land on an empty dashboard with no idea where to start.

I designed a state for every way a page can be empty or fail, and each one tells the person what to do next.

Empty state: No schools yet, with Add a school and Import from spreadsheet buttons.
Empty states say what to do next, not just that there is nothing here.
Loading skeleton, error state and no-access state.
Loading uses skeletons in the real layout, errors say the data is safe, and the no-access page says which account you are signed in with.

8g

A second pass: making it feel like Enactus

Version 1, with pastel icon tiles and a floating sidebar, next to version 2, with a flush navy sidebar and plain stats.
My first pass leaned on common dashboard defaults: pastel icon tiles, colored stripes, a gradient banner and glowing buttons. In the second pass I took the colors from enactusubc.ca and gave color a job: yellow means something needs you, green means done.

8h

Handoff devs could build from

The PRD's requirements table next to globals.css mapping the tokens to shadcn/ui.
A PRD for the app shell, plus a globals.css that maps the tokens to shadcn/ui, including the one-line brand swap.

Outcome

A live prototype, improving through feedback

The first version is live as a coded prototype. We are iterating on it with feedback, and the second-pass design in 8g is the next version.

See the live v1 prototype →

Reflection

What I learned

My first version leaned on dashboard defaults and looked generic. Taking the palette from Enactus’s own site, and giving every color one job, made the tool feel like it belonged to the club and made screens faster to scan.

Next case study

Turning a newsletter signup into direct school inquiries

Beewell Indonesia · Website redesign

Read the case study →