# Prop Naming Conventions

**Source:** INFRA-F59 — 2026-07-09  
**SoT file:** `prop-naming-conventions.json` (machine-read by `scripts/audit-prop-naming.mjs`)

---

## Principles

1. **Same concept, same name across all components.** When two components express the same semantic axis (e.g. fill-vs-outline appearance), their prop must share one canonical name.
2. **One glance, one meaning.** A consumer reading `<TvuButton fill="ghost">` should understand the axis without looking up the docs. Opaque names (`property1`, `variant`) violate this.
3. **When in doubt, look at Element Plus (EP) — then fall back to `type` or `tag`.** EP is the TVU UI reference; its naming is the first tiebreaker. If EP doesn't cover the concept, `type` is the safe generic fallback.

---

## Convention Table

| Axis | Code prop name | Rationale |
|------|---------------|-----------|
| `fill` | `fill` | Fill/outline/rimless appearance variant. EP uses `type` for this in `<el-button>`, but TVU chose `fill` for clarity; locked in INFRA-F59. |
| `kind` | `type` | Shape/form variant where no better axis name exists (Badge Circle/Rectangle, Steps number/icon, Pagination Classic/Simple/Small). EP uses `type` consistently for this. |
| `color` | `color` | Semantic color variant (neutral/blue/green/orange/red). Natural English, unambiguous. |
| `state` | `state` | Interaction-state annotation (Normal/Active/Disabled). Named `state` not `status` to distinguish from machine-status (on-air/preview/inactive). |
| `size` | `size` | Size tier. Values must use the allowed casing set: `XS S M L XL` (all caps). Lower-case variants (`m`, `xl`) are forbidden — they break Figma round-trip. |

---

## Blocklist

| Blocked name | Why |
|---|---|
| `style` | JavaScript footgun: `element.style` is the built-in `CSSStyleDeclaration`. Assigning a string to it silently fails or throws. Never use as a prop name. |
| `variant` | Old remap name from the pre-F59 Figma-extraction era. Kept in blocklist to prevent regressions if future code-gen tries to restore it. |
| `canonicalStyle` | Another old remap name from pre-F59. Same reason. |
| `/^property\d+$/` | Figma auto-generated garbage names (`property1`, `property2`, …). These must always be renamed before shipping. |

---

## Enforcement

- **L4 (pre-commit):** `.husky/pre-commit` runs `node scripts/audit-prop-naming.mjs` when `components.config.ts`, any canonical `.vue`, `prop-naming-conventions.json`, or the audit script itself is staged.
- **L5 (prepublishOnly):** `package.json` `prepublishOnly` chain includes `pnpm run audit:prop-naming`. A violation blocks the npm publish.

The audit script (`scripts/audit-prop-naming.mjs`) reads this JSON at runtime — zero hardcoding. To add a new convention or blocklist entry, update the JSON; the gate enforces it automatically.
