# How Component Variants (Hover States) Are Defined in DESIGN.md

> Learn how to define component variants like hover states in DESIGN.md with state-specific YAML entries and property inheritance. Optimize your UI with clear state management.

- Repository: [Google Labs Code/design.md](https://github.com/google-labs-code/design.md)
- Tags: deep-dive
- Published: 2026-07-04

---

**Component variants in DESIGN.md are defined as separate YAML entries using state-specific suffixes like `-hover` or `-active`, where each variant inherits base component properties and overrides only the values that change for that specific UI state.**

The [`google-labs-code/design.md`](https://github.com/google-labs-code/design.md/blob/main/google-labs-code/design.md) specification treats interactive UI states as first-class citizens through its variant system. Rather than embedding state logic within a single component definition, DESIGN.md utilizes a flat key structure that appends state modifiers to base component names. This approach enables precise, per-state styling while maintaining a concise, DRY configuration format.

## Variant Naming Convention in DESIGN.md

The design system establishes a strict naming pattern for state-dependent styling. Each variant is identified by a compound key consisting of the base component name followed by a hyphenated state suffix.

### State-Specific Suffix Pattern

Valid variant keys append specific UI state identifiers to the base component key. According to [`docs/spec.md`](https://github.com/google-labs-code/design.md/blob/main/docs/spec.md) (lines 305-306), supported suffixes include:

- **`-hover`** for mouse-over states
- **`-active`** for currently selected elements  
- **`-pressed`** for depressed or clicked states

For example, a primary button exists as `button-primary`, while its hover state counterpart is defined as `button-primary-hover`. The specification explicitly states: "Those variant components may be defined under a different but related key, for example, `button-primary`, `button-primary-hover`, `button-primary-active`."

## Inheritance and Property Override Behavior

Variants operate on a sparse override model. When you define a variant, you only specify properties that differ from the base component; all other values are inherited automatically.

In [`docs/spec.md`](https://github.com/google-labs-code/design.md/blob/main/docs/spec.md) (lines 307-316), the specification demonstrates this with a concrete example where `button-primary-hover` redefines only the `backgroundColor` property:

```yaml
components:
  button-primary:
    backgroundColor: "{colors.primary-60}"
    textColor: "{colors.primary-20}"
    rounded: "{rounded.md}"
    padding: 12px
  button-primary-hover:
    backgroundColor: "{colors.primary-70}"

```

The system resolves the final appearance by first loading the base `button-primary` tokens, then overlaying the `button-primary-hover` values when the hover state is active. This inheritance mechanism eliminates redundancy while ensuring state-specific fidelity.

## Practical Examples of Component Variants

Implementing variants requires minimal YAML configuration. Below are concrete implementations demonstrating the pattern across different component types.

### Basic Button Hover State

Define the base button and its hover variant as sibling entries under the `components` key:

```yaml
components:
  button-primary:
    backgroundColor: "{colors.primary-60}"
    textColor: "{colors.primary-20}"
    rounded: "{rounded.md}"
    padding: 12px

  button-primary-hover:
    backgroundColor: "{colors.primary-70}"

```

When rendered, the hover state retains the text color, border radius, and padding from `button-primary` while applying the darker background color.

### Card Component with Hover Variant

Interactive surfaces like cards benefit from subtle background shifts. The [`examples/totality-festival/DESIGN.md`](https://github.com/google-labs-code/design.md/blob/main/examples/totality-festival/DESIGN.md) file (lines 202-210) demonstrates this pattern:

```yaml
components:
  card:
    backgroundColor: "{colors.surface-variant}"
    borderColor: "{colors.outline-variant}"
    rounded: "{rounded.sm}"
    padding: 16px

  card-hover:
    backgroundColor: "{colors.secondary-70}"

```

During resolution, the variant merges onto the base `card` definition, preserving structural properties while updating the background for the hover interaction.

### Reusing Variant Styles Across Components

You can reference existing variant definitions using YAML anchors to maintain consistency. For instance, a chip component might reuse a button's hover styling:

```yaml
components:
  chip-primary:
    backgroundColor: "{colors.primary-30}"
    textColor: "{colors.on-primary}"
    rounded: "{rounded.full}"
    padding: 8px

  chip-primary-hover:
    <<: *button-primary-hover
    textColor: "{colors.on-primary}"

```

This technique ensures that hover states remain consistent across related interactive elements without duplicating token values.

## Runtime Resolution in the DESIGN.md CLI

The variant system is enforced by the linter and generator tools in the repository. In [`packages/cli/src/linter/model/spec.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/model/spec.ts), the parser materializes component objects by first resolving the base key, then conditionally overlaying any matching variant key based on the current UI state context.

This resolution strategy means consumers (such as build tools or design-to-code generators) receive a fully merged property set for the active state without manually traversing inheritance chains.

## Summary

- **Component variants** in DESIGN.md use hyphenated suffixes (`-hover`, `-active`, `-pressed`) appended to base component keys.
- Variants inherit all properties from their base component and override only specific values for that UI state.
- The specification in [`docs/spec.md`](https://github.com/google-labs-code/design.md/blob/main/docs/spec.md) (lines 291-306) formalizes this pattern as the standard method for handling interactive states.
- Real-world implementations appear in [`examples/totality-festival/DESIGN.md`](https://github.com/google-labs-code/design.md/blob/main/examples/totality-festival/DESIGN.md), demonstrating practical usage of hover variants on card components.
- The CLI linter at [`packages/cli/src/linter/model/spec.ts`](https://github.com/google-labs-code/design.md/blob/main/packages/cli/src/linter/model/spec.ts) handles runtime resolution by overlaying variant properties onto base components.

## Frequently Asked Questions

### What file defines the variant specification in DESIGN.md?

The authoritative definition resides in [`docs/spec.md`](https://github.com/google-labs-code/design.md/blob/main/docs/spec.md) at lines 291-306. This section establishes the naming convention, inheritance model, and valid state suffixes for component variants such as hover and active states.

### How does a variant inherit properties from its base component?

The system uses a sparse override mechanism. When resolving a component, the parser first loads all properties from the base key (e.g., `button-primary`), then overlays only the properties defined in the variant key (e.g., `button-primary-hover`). Unspecified properties in the variant retain their base values automatically.

### Can I use YAML anchors to reuse variant styles across different components?

Yes. The specification supports standard YAML merge keys (`<<: *anchor-name`) to reference variant definitions from other components. This allows you to share hover state configurations across disparate elements like buttons and chips while maintaining a single source of truth for the token values.

### What UI states are supported for component variants?

The specification explicitly mentions **active**, **hover**, and **pressed** as standard UI states. You define these by appending the respective suffix to your base component key (e.g., `component-name-hover`). The system treats any key matching the base name plus suffix pattern as a valid variant regardless of the specific state semantics.