Agency Themes

New York State has more than 45 agencies, each with its own identity. The NYS Design System supports this through agency themes — a set of color overrides that let you build with shared components while maintaining each agency's visual identity.

Think of it like a magic paintbrush: you build your interface once using NYSDS components and semantic tokens, then switch the agency theme and everything updates automatically — buttons, headers, tables, form controls, and every other component that uses theme colors.

How Themes Work

NYSDS themes work through the design token system. Here is the key idea:

Every component that needs a brand color references a theme token like --nys-color-theme instead of a specific color value. When you activate a theme, the system remaps those theme tokens to a different color palette. The component code does not change — only the token values do.

Theme token scale

Each theme provides seven color values at different intensities:

Token Purpose
--nys-color-theme-faint Very subtle backgrounds, barely visible tints
--nys-color-theme-weaker Light backgrounds for hover states, selected rows
--nys-color-theme-weak Soft accent backgrounds, active states
--nys-color-theme-mid Medium-emphasis elements, secondary indicators
--nys-color-theme Primary brand color — buttons, links, headers
--nys-color-theme-strong Hover states on primary elements
--nys-color-theme-stronger Active/pressed states, high-contrast text on light backgrounds

For a deeper explanation of token layers and naming conventions, see Design Tokens.

Theme color intensity scale

Select a theme below to see all seven intensity levels in action. Notice how the full palette shifts when you change themes, while the hierarchy (faint to stronger) stays consistent:

Faint
--nys-color-theme-faint
Weaker
--nys-color-theme-weaker
Weak
--nys-color-theme-weak
Mid
--nys-color-theme-mid
Primary
--nys-color-theme
Strong
--nys-color-theme-strong
Stronger
--nys-color-theme-stronger

The token resolution chain

NYSDS tokens are organized in layers. Themes rely on how those layers connect:

  1. Primitive tokens define raw color values. For example, --nys-color-state-blue-700 is #154973 and --nys-color-environment-green-700 is #233f2b.
  2. Theme tokens point to a primitive color based on the active theme. By default, --nys-color-theme points to --nys-color-state-blue-700. Under the Environment theme, it points to --nys-color-environment-green-700 instead.
  3. Components reference theme tokens. A button's background color uses --nys-color-theme. A checked checkbox uses --nys-color-theme. A table header uses --nys-color-theme. When the underlying token changes, they all update.

This means you never need to restyle individual components when switching agencies. You change the theme once and the system handles the rest.

Available Themes

NYSDS includes eight themes that map to groups of New York State agencies:

Theme ID Group Name Primary Color Example Agencies
default NY.gov (Default) #154973 General state sites, NY.gov
admin Administration #a2350a Budget, Civil Service, General Services
business Business #084b52 Empire State Development, Dept. of Labor, Dept. of Taxation and Finance
environment Environment #233f2b DEC, Parks Recreation and Historic Preservation, Agriculture and Markets
health Health #43285d Dept. of Health, Office of Mental Health, OASAS
local Local Government #402217 Local government entities across New York State
safety Public Safety #435d6e DHSES, State Police, Division of Criminal Justice Services
transportation Transportation #0b5583 DOT, DMV, MTA

Not sure which group your agency falls under? Contact the NYSDS team through office hours or the Teams channel.

Applying a Theme

To apply an agency theme, add the data-theme attribute to the <body> element of your page. Every NYSDS component on the page will update automatically.

Copy Code
<!DOCTYPE html>
<html lang="en">
<head>
  <title>NYS Department of Environmental Conservation</title>
  <link rel="stylesheet" href="path/to/nysds.min.css">
</head>
<body data-theme="environment">
  <nys-globalheader></nys-globalheader>
  <main>
    <h1>Hunting and Fishing Licenses</h1>
    <nys-button label="Apply for a license"></nys-button>
    <nys-button label="Renew existing license" variant="outline"></nys-button>
  </main>
  <nys-globalfooter></nys-globalfooter>
  <script src="path/to/nysds.min.js"></script>
</body>
</html>

In this example, the buttons, global header, and global footer will all render using the Environment theme's green palette instead of the default State Blue.

Theming a section of a page

You can scope a theme to a specific section rather than the entire page. Place data-theme on any ancestor element to theme its descendants:

Copy Code
<body>
  <!-- Default theme applies here -->
  <section data-theme="health">
    <!-- Health theme applies to everything in this section -->
    <nys-button label="Schedule an appointment"></nys-button>
  </section>
  <!-- Back to default theme here -->
  <nys-button label="Contact us"></nys-button>
</body>

This is useful when a page needs to feature content from multiple agencies, or when embedding an agency-branded widget in a shared portal.

What Themes Change

Themes override the --nys-color-theme-* family of CSS custom properties. Any component or custom element that references these tokens will respond to theme changes.

The following NYSDS components use theme tokens and will update when you switch themes:

  • Button — Background, border, and text colors for filled, outline, and ghost variants
  • Global Header — Header bar background and accent colors
  • Global Footer — Footer background and link colors
  • Table — Header row background and striped row accents
  • Checkbox — Checked state background and border
  • Radio Button — Selected state indicator
  • Toggle — Active toggle background
  • Stepper — Active and completed step indicators
  • Avatar — Avatar background and text colors
  • File Input — Upload button accent

Themes do not change semantic colors like --nys-color-danger, --nys-color-success, or --nys-color-info. These remain consistent across all agencies to preserve the meaning of error states, success messages, and informational alerts.

Using Theme Tokens in Custom Styles

If you are building custom components or page layouts alongside NYSDS components, use theme tokens so your styles respond to agency themes automatically.

Use --nys-color-theme and related theme tokens in your CSS. The correct primary color is applied automatically when you set a theme. You never need to look up or specify individual color values.

Copy Code
<style>
  .agency-hero {
    background-color: var(--nys-color-theme-faint);
    border-left: 4px solid var(--nys-color-theme);
    padding: var(--nys-space-400);
  }
  .agency-hero h2 {
    color: var(--nys-color-theme-stronger);
  }
  .agency-hero a {
    color: var(--nys-color-theme);
  }
  .agency-hero a:hover {
    color: var(--nys-color-theme-strong);
  }
</style>
<div class="agency-hero">
  <h2>Welcome to the Department of Health</h2>
  <p>Find resources for Medicaid enrollment, immunization records,
  and vital records requests.</p>
  <a href="/services">View all services</a>
</div>

When this page runs under the Health theme, the hero section picks up the purple palette. Under the Transportation theme, it picks up the blue palette. You write the CSS once.

Do not hardcode agency-specific colors. If you write background-color: #43285d instead of var(--nys-color-theme), your component will not respond to theme changes and will break if the agency's palette is updated.

How Theme Files Work

When you install @nysds/components or include the NYSDS token stylesheet, all theme overrides are included in the main tokens.css file. Each theme is defined as a CSS rule block that targets its [data-theme] selector:

Copy Code
/* Excerpt from tokens.css — generated automatically, do not edit */
[data-theme="environment"],
.nys-theme-environment {
  --nys-color-theme: var(--nys-color-environment-green-700);
  --nys-color-theme-faint: var(--nys-color-environment-green-10);
  --nys-color-theme-mid: var(--nys-color-environment-green-500);
  --nys-color-theme-strong: var(--nys-color-environment-green-800);
  --nys-color-theme-stronger: var(--nys-color-environment-green-900);
  --nys-color-theme-weak: var(--nys-color-environment-green-100);
  --nys-color-theme-weaker: var(--nys-color-environment-green-50);
}

You do not need to load a separate file for each theme. The token file handles all themes and selects the right overrides based on the data-theme attribute on the page.

Creating a Custom Theme

If your agency is not covered by one of the existing theme groups, you can create a custom theme by overriding the theme tokens in your own stylesheet.

Step 1: Define your theme tokens

Create a CSS rule that targets your custom theme selector and overrides all seven theme token values:

Copy Code
/* custom-agency-theme.css */
[data-theme="my-agency"],
.nys-theme-my-agency {
  --nys-color-theme-faint: #f5f0f8;
  --nys-color-theme-weaker: #e8ddf0;
  --nys-color-theme-weak: #c9b3d9;
  --nys-color-theme-mid: #7a4fa0;
  --nys-color-theme: #5c2d82;
  --nys-color-theme-strong: #3d1d57;
  --nys-color-theme-stronger: #1f0f2c;
}

Step 2: Ensure your colors meet accessibility standards

Every theme color must work in the contexts where it is used. At a minimum:

  • --nys-color-theme on a white background must meet WCAG 2.2 AA contrast (4.5:1 for text, 3:1 for large text and UI elements).
  • --nys-color-theme-strong and --nys-color-theme-stronger must also meet contrast requirements — these are used for hover and active states.
  • White text on --nys-color-theme must be readable — this is how filled buttons render.

Use WebAIM's contrast checker to verify.

Step 3: Load your theme stylesheet after the NYSDS tokens

Your custom theme CSS must load after the NYSDS token stylesheet so your overrides take precedence:

Copy Code
<link rel="stylesheet" href="path/to/nysds.min.css">
<link rel="stylesheet" href="path/to/custom-agency-theme.css">

Step 4: Test across components

After defining your theme, test it across several components to make sure the full range of token intensities works well together. Check these at a minimum:

  • nys-button in filled, outline, and ghost variants
  • nys-globalheader and nys-globalfooter with navigation links
  • nys-checkbox and nys-radiobutton in checked and unchecked states
  • nys-table with striped rows and a sortable header

If a component looks wrong under your theme, the issue is almost always a contrast problem in one of the weaker or stronger token values. Adjust the scale until all seven values work together.

Best Practices

  • Set the theme once on <body>. Avoid setting data-theme on individual components. Apply it at the page level and let CSS inheritance handle the rest.
  • Use theme tokens, not primitive colors. Write var(--nys-color-theme) in your custom styles, not var(--nys-color-state-blue-700). Primitives do not respond to theme changes.
  • Do not override semantic status colors. --nys-color-danger, --nys-color-success, --nys-color-warning, and --nys-color-info are intentionally consistent across themes. Changing them breaks the meaning of error and status states for users.
  • Test with real content. Theme colors look different surrounding white space than they do in a dense form or data table. Test your theme on actual pages, not just isolated swatches.