Component Health Index (CHI)
What is the Component Health Index?
The Component Health Index (CHI) is a mathematical score — ranging from 0 to 100 — that evaluates the structural quality and design-system compliance of a UI component. It combines four independent dimensions: how complex the component’s API is, how complete its variant grid is, how large its theoretical state space is, and how well its visual values are tokenized.
A CHI of 100 represents an ideal component: lean API, complete variant coverage, and fully tokenized anatomy. A CHI near 0 indicates a component that is overloaded, undertokenized, or combinatorially bloated — making it hard to maintain and risky to evolve.
The CHI is calculated automatically on every sync and shown as the Health · CHI card on the Overview tab of each component’s detail panel, and in full in the health panel that card opens.
Why Does Grails Include the CHI?
Design systems accumulate complexity silently. Properties added ad hoc, variant states that were never cleaned up, and style values hardcoded in anatomy frames — none of these feel dramatic in isolation, but their combined effect erodes a system’s reliability over time. The CHI exists to give teams an objective, auditable signal before that complexity becomes a production risk.
The CHI is especially useful for:
- Design leads — identify which components need a refactor sprint before they block engineers.
- Engineers — understand the maintenance overhead of a component before adopting it in code.
- Product managers — monitor the overall health of the design system over time.
Status Ranges
| Score | Status | Meaning |
|---|---|---|
| ≥ 95 | ✨ OPTIMAL | The component is lean, well-tokenized, and fully maintainable. |
| 60 – 94 | ✅ GOOD | Healthy component with minor room for improvement. |
| 30 – 59 | ⚠️ MONITOR | Complexity is elevated. Watch for growth before it becomes a burden. |
| < 30 | 🔴 POOR | Structural complexity is unsustainable. Refactor recommended. |

How the Score is Calculated
The CHI starts at a base score of 100 and deducts penalty points based on five independent metrics. Each metric has a specific weight:
| Metric | Abbrev. | Weight |
|---|---|---|
| Property Count | PC | 20% |
| Design Coverage | DC | 15% |
| Variant Grid | VG | 10% |
| Toggles | TG | 15% |
| Token Adherence | TA | 40% |
Property Count’s penalty is capped at 1.5× its weight, and Variant Grid’s and Toggles’ at their weight, to prevent a single extreme value from collapsing the entire score. The final CHI is 100 − (sum of all penalties), clamped to the 0–100 range.
Metrics
PC — Property Count
What it evaluates: The number of props the component exposes relative to a healthy ceiling of 15 properties (“Apropcalypse” limit). An API with more than 15 properties is hard to document, hard to test, and risky to change.
Capacity Bar: Shows the remaining healthy capacity (15 - N) / 15 × 100%.
- 0 to 9 props: Green bar (high capacity remaining).
- 10 to 15 props: Yellow bar (low capacity remaining, ≤ 40%).
- > 15 props: Full Red bar (overloaded alert).
How to fix it: Group related props (e.g., collapse
paddingTop+paddingBottominto a singlepaddingprop). Prune rare configurations that no real consumer uses. Favor composition over configuration by providing focused sub-components instead of a single mega-component.
DC — Design Coverage
What it evaluates: The ratio of physically designed variants to the theoretical variant grid — the complete set of combinations derivable from Variant-type properties.
Coverage Bar: Shows the percentage of designed combinations (V / C_grid) × 100%.
- ≥ 75% designed (e.g. 20/20): Full Green bar.
- 40% to 74% designed: Yellow bar.
- Under 40% designed: Red bar (indicates sparse variant coverage).
How to fix it: Complete the missing combinations in the variant grid. Alternatively, refine the component’s API to make impossible states logically unreachable — for example, by making two properties mutually exclusive through a single combined property.
VG — Variant Grid
What it evaluates: How many combinations the Variant properties describe: the variants someone has to design and keep consistent. It is counted in decisions: 32 variants are 5 binary choices, so doubling the grid always costs the same.
Grid Bar:
- Up to 32 combinations: Full Green bar (no penalty).
- 33 to 191: Yellow, then Red, as the penalty grows toward the full weight.
- 192 or more: Full Red bar (full 10 points).
How to fix it: Reduce the options of each variant property, or split the component into smaller, more focused ones.
TG — Toggles
What it evaluates: The Boolean and Slot / Instance Swap properties. Each one is one more decision for whoever uses the component, whether or not anyone designed a variant for it.
Toggles Bar:
- Up to 5: Full Green bar (no penalty).
- 6 to 9: Yellow, then Red; each toggle past 5 costs the same, 3 points.
- 10 or more: Full Red bar (full 15 points).
How to fix it: Fold related booleans into a single variant property, and compose smaller components instead of switching parts of one on and off.
TA — Token Adherence
What it evaluates: The percentage of visual style values in the component’s anatomy that are bound to a design token or Figma Style, rather than hardcoded as inline values. TA is the metric with the highest weight (40%) because untokenized values create drift.
TA % = tokenized values / (tokenized + raw hardcoded values) × 100What counts as one value. A value is one style property on one layer. The same padding on the same layer counts once, however many variants repeat it; a variant that changes it adds the new value. A text with no Text Style counts by its parts — family, weight, size, line height, letter spacing and paragraph spacing — so a size and line height bound to variables count as two tokenized values even when the family is typed in. A line height of auto is not counted.
| TA Score | Status |
|---|---|
| 100% | ✨ OPTIMAL — every evaluable value is tokenized |
| 75–99% | ✅ GOOD — minor raw values present |
| 40–74% | ⚠️ MONITOR — significant hardcoded values |
| 0% (100% raw) | 🔴 POOR — Full Red bar (untokenized alert) |
How to fix it: Open the component in Figma and apply design tokens (variables) or Figma Styles to fill colors, text styles, spacing values, and border radii. After re-syncing via the plugin, the TA score will update automatically.
Special Cases
Component has no properties
A component with no Figma properties has no API surface, so PC, DC, VG and TG are 0 and its CHI comes from Token Adherence alone: 100 − (100 − TA%) × 0.4. Its score is always between 60 and 100.
The score changed and the design did not
When the way the CHI is calculated changes, Grails recalculates every stored score the following night, from each component’s latest synced version. A component can move a few points with nothing changed in Figma: the measurement changed, not the component. The recalculation does not change the component’s last-modified date.
Component needs re-sync
If the Health · CHI card on the Overview tab, or the health panel, shows a “CHI score available after re-sync” message, the score was calculated by an older version of the CHI engine. Grails recalculates it overnight; re-syncing from the Figma plugin updates it right away.