ADG/REI Systems

2022 - 2025

Shipped & ongoing

Earning the seat, then moving a federal platform off AngularJS

I led the design side of a move from AngularJS to React on one internal federal application. The code was not the hard part. Trust was.

Role

UX Designer, design systems specialist

Senior UX Designer, Strategic Partner

UX Designer, design systems specialist

Timeline

2022-2025

2025 - Now

2022-2025

Scop

One federal app, 15+ product teams

5 product teams | 3 efforts

One federal app, 15+ product teams

Platform

Internal enterprise casework application

Internal Enterprise Platform

Internal enterprise casework application

Overview

I could not migrate a platform until people trusted design enough to invite us in.

Federal staff used one internal application to document cases and move them through a long, form heavy process. People at the end were waiting on a decision about their lives. Where the system failed, work went back to paper.

The app ran on AngularJS, which was no longer supported, with an old design system that had grown one request at a time.

I led the design side of the move to React. The hard part was never the code. Trust had been spent before I arrived, and product owners and technical leads were wary of anyone who said โ€œdesign.โ€

Three questions guide this work

01

Can staff get through a case without going back to paper?

02

Can teams build from one trusted set of parts?

03

Can the system keep going without me?

What has changed so far

50+

Reusable components, 47 at WCAG AA

Counted

โ‰ˆ40%

Shorter engineering implementation cycles

Benchmark

โ‰ˆ50%

Fewer visual regressions across 15+ teams

Benchmark

Stakes

The people on the other side of the screen were doing important work with broken tools.

01

Friction

Paper kept winning.

When the system failed, people worked around it.

02

Friction

An unsupported framework.

AngularJS was no longer supported, and every fix added weight.

03

Friction

A system grown one request at a time.

The old design system had no shared rules left.

Confidentiality Note

Not every part of this is mine to share, so I kept the agency and the case details general on purpose.

Before state ยท where the digital flow broke

01

Start case

โ†’

02

Gather details

โ†ณ Back to paper

โ†’

03

Review

โ†’

04

Resolve gaps

โ†ณ Back to paper

โ†’

05

Decision

Evidence

I went to where the work happens.

I traveled to multiple sites around the country, interviewed the people who use the application every day, and mapped their full workflow from start to finish.

01

Visit the sites

->

02

Interview users

->

03

Map the workflow

01

Can staff get through a case without going back to paper?

02

Can teams build from one trusted set of parts?

03

Can the system keep going without me?

How solid is this?

The conversations

Observed

Direct conversations at multiple sites, not a formal study.

The workflow maps

Observed

Drawn by me and checked with the people who do the work.

The impact

Estimated

Rounded from internal analytics.

Generalized end to end workflow

Staff

Open case

Collect

Review

Decide

System

Create

Validate

Route

Close

Paper

Pain point 1

Pain point 2

I turned evidence into a migration sequence.

The work stayed traceable from field signal to product decision to system effect.

Signal from the work

Design move

What it changed upstream

01

Paper appeared when the digital flow broke.

โ†’

Map the whole case, not one screen.

โ†’

Sequence the migration around workflow breaks.

02

Teams rebuilt similar patterns in different ways.

โ†’

Turn repeated work into shared components.

โ†’

Give the application kit one trusted base.

03

Partners were wary of another design-led promise.

โ†’

Join the work and close useful gaps.

โ†’

Make shared governance feel ordinary.

Decision

Nobody gave us a seat, so we kept showing up until it became ordinary.

01

Wait to be invited.

Safe, and nothing changes while we wait.

02

Ask leadership for a mandate.

Fast on paper. People follow a mandate carefully and own it never.

03

Chosen

Show up, be useful, repeat.

Slow, and it works.

Migration bet 01

Chosen

Show up, be useful, repeat.

Gained

Feedback sooner, less disruption, and room to adjust.

Accepted

Temporary inconsistency while old and new patterns overlapped.

Migration bet 01

Chosen

Show up, be useful, repeat.

Gained

Feedback sooner, less disruption, and room to adjust.

Accepted

Temporary inconsistency while old and new patterns overlapped.

Migration bet 02

Chosen

Build the application kit from the shared system.

Gained

Product speed without cutting the application loose from the base.

Accepted

More coordination across design, engineering, and product.

Migration bet 02

Chosen

Build the application kit from the shared system.

Gained

Product speed without cutting the application loose from the base.

Accepted

More coordination across design, engineering, and product.

The tradeoff was on purpose

This looks less like a plan at first. There is no launch and no big reveal. But every win came from showing up and being useful before anyone asked.

How it compounded

Small, practical help became trust. Trust became access. Access became a better platform.

01

Make the case

Our design lead held countless one on ones to include us.

02

Show up

We joined meetings that were not ours, sometimes just to listen.

03

Close a gap

A missing spec, a mapping nobody owned, so we took every chance.

04

Become the habit

Product owners started bringing us in early without being asked.

What changed

The lead product owner began treating me as a strategic partner on how to move forward with the migration.

Solution

One application, and a design lifecycle that never stopped.

We did not design the future in one go. We took snapshots of the current state, picked the low hanging fruit, shipped it, and took another. A cross functional tiger team of leads set priorities, and there was politics to navigate along the way.

A loop, not a launch

1

Snapshot

โ†’

2

Prioritize

โ†’

3

Ship

Then look again

One table, five perspectives

Priorities for the app and the design system

Design

Engineering

Product

QA

Accessibility

The principal-level move

A component swap would have been easier to explain. It would not have fixed the system.

Not enough

Repaint the old screen

The same workflow problems survive under cleaner components.

โ†’

What changed

Start with the work

Use workflow breaks to decide what earns a place in the migration.

โ†’

How it scales

Codify the answer

Turn a solved product problem into a reusable pattern and shared rule.

Generalized Visuals

What changed at component level

These are redrawn examples, not real federal screens. They show the design logic without exposing the agency, product, or case data.

Generalized component example

Actions gained a clear hierarchy.

Problem:

Every action competed at the same volume, so the next step was hard to scan.

Design response:

Give primary, secondary, and quiet actions distinct jobs, then make focus visible.

Before

Continue

Save

Cancel

โ†’

After

Continue

Save

Cancel

One obvious next step

Visible keyboard focus

Destructive actions stay distinct

Generalized component example

Dense tables became easier to read.

Problem:

Heavy grids made every cell feel equally important and status was buried in text.

Design response:

Reduce visual noise, open the spacing, and let labeled status markers carry meaning.

Before

Case

Status

Action

Case 018

In review

View

Case 024

Needs info

View

โ†’

After

Case

โ†’

Status

Action

Case 018

In review

View

Case 024

Needs info

View

Faster visual scanning

Status uses text and shape

Rows have a clear action

Generalized component example

Forms started helping before people got stuck.

Problem:

Labels, focus, and errors did not explain what happened or how to recover.

Design response:

Pair persistent labels with contextual help, visible focus, and errors that say what to do.

Before

Case category

Select a category

What happened?

Add a short description

โ†’

After

Case category

Select a category

What happened?

Add a short description

This helps the next reviewer understand the case.

Errors explain recovery

Labels stay attached

Focus follows reading order

Three states, built for the whole journey

Rebuilt

A clearer default

The focus order follows the reading order.

error

Tell us what happened before continuing.

An error that helps

The error is announced to a screen reader.

empty

No case notes yet

Add the first note when you are ready.

An empty state with a next step

Text and controls meet 4.5:1 contrast.

System

Two levels of governance, so teams moved fast without drifting.

Level 1

Design system Storybook

Generic building blocks every product can use.

->

Level 2

Application Storybook kit

Components, patterns and layouts ready for this applicationโ€™s real work.

->

Level 3

15+ product teams

Build from the kit while change flows one way from the base.

Built for real use

Production, not a picture of production.

50+ reusable components mapped to production code. 47 at WCAG AA, tested with keyboard and screen reader.

Handoff, replaced

We wrote the contract together.

Component specs were written with engineers. My design systems partner led the token work, and we supported each other on nearly everything.

Deep dive

How the tokens connect

+

Results

Here is what I can count, and what I can estimate.

Fewer visual regressions across 15+ teams

โ‰ˆ50%

Estimated

Shorter engineering implementation cycles

โ‰ˆ40%

Estimated

Less rework

โ‰ˆ25%

Estimated

Better task completion

โ‰ˆ15%

Estimated

50+

Reusable components

47 at WCAG AA

Counted

Internal analytics, rounded. Exact figures withheld because this is federal work.

What I canโ€™t claim

A single dollar figure for this work.

Reflection

A migration is a trust project with a code project inside it.

01

What Iโ€™d do differently.

Trust came from being in the room, in meetings that were not ours and in countless one on ones led by our design lead. Next time I would start that work on day one and plan it like a real workstream, not something that happens on the side.

02

What surprised me.

How little of this was technical. I expected the hard part to be the code. The hard part was earning trust from people who had been burned by a design agency before us. Sometimes sitting quietly in a meeting and just listening was the work.


03

What I do in week two now.

I find out who got burned before me, and I go to their meetings. Then I look for one small gap nobody owns and close it. It is a small act, and it is how the invitation starts.




ADG/REI Systems

Shipped

Refining CSS variables, so one design system could scale

Our CSS had grown one request at a time, so the same color lived in many places. We rebuilt it as three tiers of tokens that design and engineering could share. My design systems partner led the effort, and I worked beside them.

Role

Design systems specialist

Timeline

Needs input ยท [Years]

Scope

One federal application,

Needs input ยท [Number of teams, 15+ or 30+]

Platform

Internal enterprise casework application

Primitive

Semantic

Component

Illustrative, generalized

Components / Button

Default

Button

Hover

Button

Focus

Button

--ds-primitive-blue-500

--ds-color-action-primary-bg

--_bg

local to the Button

.ds-button {

--_bg: var(--ds-color-action-primary-bg);

background: var(--_bg);

border-radius: var(--ds-radius-md);

padding: var(--ds-spacing-sm) var(--ds-spacing-lg);

}

--ds-color-focus-ring

Overview

A design system cannot scale when every team spells the same color differently.

The application carried years of CSS written one request at a time. Colors, spacing and type were hardcoded in many places, so a small change meant a long hunt through stylesheets.

A move to React and Tailwind was coming. It needed one source of truth that design and engineering could both trust. A design audit showed we could not scale without one.

My design systems partner led this effort. I worked beside them on

Needs input ยท [What I owned, in one line]

.

Three questions guide this work

01

Can design and engineering use the same name for the same thing?

02

Can a theme change without touching every component?

03

Can a team add a new token without breaking the rest?

3

Tiers of tokens: primitive, semantic, component

Counted

โ‰ˆ50%

Fewer styling defects in quality assurance (QA)

~

Estimated

Needs input ยท [How this was measured]

Needs input ยท [Teams using the tokens]

Product teams using the tokens

Needs input ยท [What "using" means, and whether 100% adoption is true]

Rounded estimates. Exact figures withheld because this is federal work.

Hardcoded CSS felt fast on day one and expensive on day one hundred.

01

Friction

Many spellings of one color.

The same color appeared in slightly different values across stylesheets.

02

Friction

Design and code used different names.

Figma and code did not share a vocabulary, so every handoff needed translating.

03

Friction

A framework move was coming.

Moving from AngularJS to React meant every style had to move too, and scattered CSS would arrive scattered.

Needs input ยท [Confirm these three frictions match what you saw]

One color, spelled six ways

#2353D9

Button

#2455DA

Link

#2A57D8

Header

#2250D6

Tag

#2656DB

Chart

#2152D8

Banner

Six blues that look the same and are not. Illustrative, redrawn example, not real federal code.

Needs input ยท [How many variants the audit really found]

Not every part of this is mine to share, so I kept the agency and the case details general on purpose.

I audited before I trusted anything.

A design audit came first. Before naming a single token, we listed what the stylesheets really used: colors, spacing, type and radii, and where each one showed up.

Needs input ยท [Number of unique values found, rounded]

Needs input ยท [Number of stylesheets or components reviewed]

1

Inventory the values.

2

Group the duplicates.

3

Name the jobs.

01

Many values, few real decisions.

02

The same job was done by different values.

03

Names described looks, not jobs. For example "blue" instead of "primary action."

Many values became a few jobs

Raw values

โ†’

Jobs they were doing

โ†’

Three tiers

Illustrative. Real counts are withheld. The shape is the point.

How solid is this?

The audit findings.

Observed

What my partner and I found in the stylesheets. Not a formal study.

The defect change.

~

Estimated

A rounded estimate of fewer styling defects in quality assurance.

The adoption.

Needs input ยท [Source and definition]

We could document the mess, flatten it, or give it three tiers.

Needs input ยท [Confirm these were the real options]

01

Document the CSS we had.

Cheapest to start. The drift stays, and the docs go stale.

02

One flat list of variables.

Easy to learn. A new theme still touches every component.

03

Chosen

Chosen. Three tiers: primitive, semantic, component.

More naming discipline up front. A theme changes in one place and components never change.

The tradeoff was on purpose.

Three tiers ask more of people at the start. Names have jobs, and not every value earns a token. We accepted more rules to teach and follow, because a system that could change in one place was worth it.

Gained: change a theme or a brand in one place.

Accepted: more naming rules to teach and follow.

How teams adopted it.

01

Name it together.

02

Show a working component.

03

Move one component at a time.

04

Make it the default.

Needs input ยท [Draft, replace each step with what really happened]

From scattered values to a system, in six steps.

01

Audit the CSS.

โ†’

02

Name tokens by their job.

โ†’

03

Map them to Tailwind.

04

Move components one at a time.

โ†’

05

Check before shipping.

โ†’

06

Keep the rules in the system.

Needs input ยท [Draft, confirm each step]

Same button, two spellings

Before

background: #2455DA;

the value is typed straight into the component

โ†’

After

background: var(--_bg);

the component asks the system

--ds-primitive-blue-500

โ†’

--ds-color-action-primary-bg

โ†’

--_bg

Redrawn example, not real federal code.

One state, checked two ways

Default

Button

Focus

Button

Focus ring is visible against the page and the fill.

Label text meets 4.5:1.

The same button is shown in its default and keyboard focus states. The focus state has a visible two pixel ring, and both labels meet the Web Content Accessibility Guidelines (WCAG) text contrast minimum.

Error

Token check failed.

Fix the contrast before this change can merge.

Illustrative

Empty

No token changes to review.

The system is up to date.

Illustrative

Three tiers, so a theme changes in one place and components never change.

Tier 1

Primitive

Raw values like --ds-primitive-blue-500. A rebrand changes these.

โ†’

Tier 2

Semantic

Names a job, like --ds-color-action-primary-bg. A new theme, such as Light and Dark, changes these.

โ†’

Tier 3

Component

Local names, like --_bg inside the Button, that only point to semantic tokens. These never change.

Primitive values feed semantic jobs. Semantic jobs feed local component aliases.

Two levels of governance.

A base design system Storybook holds the tokens. An application Storybook kit is built from it and uses them.

How names are chosen.

One simple pattern, category then role then state, like color-action-primary-bg-hover.

Illustrative

Deep dive

A small version you can open.

I rebuilt the idea as a small public example. Figma variables export to JSON, a script builds CSS variables, and Storybook shows a Button and a chart. A build check blocks the merge if contrast fails.

Light and Dark

3 tiers

38 checks

WCAG contrast

Personal example, not federal work. Sample data is illustrative.

I used Claude to scaffold the code and the Figma file. I made the design decisions and checked the results.

Open the repo

github.com/jc575/design-token-pipeline

Here is what I can count, and what I can estimate.

Tiers of tokens

3

Counted

Fewer styling defects in quality assurance (QA)

about 50%

~

Estimated

Product teams using the tokens

Needs input ยท [Number and definition]

From the small version.

Counted

Personal example.

A focus ring measured 2.82:1 against the primary button fill, under the 3:1 minimum. The build check caught it. After the fix it measures 3.78:1.

38 automated checks pass, 19 in Light and 19 in Dark.

Every checked pair clears its minimum, and two clear it narrowly.

0

6

12

18

Text on page

16.90

Secondary text on surface

7.19

Secondary button text on its fill

8.87

Danger button text on its fill

5.62

Primary button text on its fill

4.75

Margin 0.25

Focus ring on primary fill

3.78

Focus ring on danger fill

3.20

Margin 0.20

Severity, medium step, on surface

3.29

Source: the check script in the open example, Light mode, 18 pairs per mode.

Read this as text

Counted

Text on page: 16.90 against a minimum of 4.5.

Secondary text on surface: 7.19 against a minimum of 4.5.

Secondary button text on its fill: 8.87 against a minimum of 4.5.

Danger button text on its fill: 5.62 against a minimum of 4.5.

Primary button text on its fill: 4.75 against a minimum of 4.5. Margin 0.25.

Focus ring on primary fill: 3.78 against a minimum of 3.

Focus ring on danger fill: 3.20 against a minimum of 3. Margin 0.20.

Severity, medium step, on surface: 3.29 against a minimum of 2.

What I can't claim

Leading this effort. My design systems partner did. And a single dollar figure for this work.

Needs input ยท [Confirm]

A token system is a naming project with a code project inside it.

01

What I'd do differently.

Needs input ยท [My real answer]

02

What surprised me.

Needs input ยท [My real answer]

03

The name I'd change first.

Needs input ยท [My real answer]

Keep reading

Illustrative, generalized

Components / Button

Default

Button

Hover

Button

Focus

Button

--ds-primitive-blue-500

--ds-color-action-primary-bg

--_bg

local to the Button

.ds-button {

--_bg: var(--ds-color-action-primary-bg);

background: var(--_bg);

border-radius: var(--ds-radius-md);

padding: var(--ds-spacing-sm) var(--ds-spacing-lg);

}

Earning the seat, then moving a federal platform off AngularJS.

ADG/REI Systems

Illustrative, generalized

Components / Button

Default

Button

Hover

Button

Focus

Button

--ds-primitive-blue-500

--ds-color-action-primary-bg

--_bg

local to the Button

.ds-button {

--_bg: var(--ds-color-action-primary-bg);

background: var(--_bg);

border-radius: var(--ds-radius-md);

padding: var(--ds-spacing-sm) var(--ds-spacing-lg);

}

Many tools, one standard teams want to use.

Fidelity

Back to top