FUI1007: Component shadows a canonical primitive
moderateA local component duplicates a canonical primitive and splits the supported UI path.
Details
{
"code": "FUI1007",
"ruleId": "components/shadow-component",
"category": "Canonical Usage",
"defaultSeverity": "moderate",
"lifecycle": "experimental",
"fixAvailable": false,
"evidenceRequired": true
}Guidance
## What it means
Fragments found a local component whose rendered control and public surface overlap a primitive in your approved contract. The evidence names the local definition, the canonical target, its usage count, and the affected files.
## Why it matters
A shadow component creates two places to fix accessibility, behavior, and visual states. Teams and agents can choose different implementations for the same job, so fixes and contract updates stop reaching every user.
## Before
This local wrapper rebuilds the canonical Button:
```tsx export function MyButton(props: React.ButtonHTMLAttributes<HTMLButtonElement>) { return <button className="my-button" {...props} />; } ```
## Repair
Replace usages with the canonical target named in the finding, then remove the shadow when no callers remain:
```tsx import { Button } from "@usefragments/ui";
export function SaveAction() { return <Button>Save changes</Button>; } ```
Preserve accessible names, event behavior, disabled state, and any required canonical props. If the local component is an intentional product variant rather than a duplicate, have the design-system owner review it and run `npx @usefragments/cli identity sanction MyButton`; that records the supported identity instead of teaching consumers to choose between two unowned controls.
## Intentional exception
Use a line-attached exception only when the duplicate must temporarily remain and an owner is actively removing it:
```tsx // @fragments-expect-error FUI1007 reason="checkout migration tracked in DS-611" expires="2026-12-31" export function MyButton(props: React.ButtonHTMLAttributes<HTMLButtonElement>) { return <button {...props} />; } ```
Do not add a broad repository exclude. Review active exceptions with `npx @usefragments/cli check --list-suppressions` and fail expired ones with `npx @usefragments/cli check --check-expired`.
## Verify the change
Run `npx @usefragments/cli check --changed --format agent` and confirm FUI1007 is absent or the specific reviewed exception is listed. Then run `npx @usefragments/cli check --changed --ci`.
Intentional exception? Use a narrow, reasoned directive from the in-source exception reference.
Next steps
- RulesThe rules that emit FUI codes.
- ExceptionsIn-source allows and Cloud exceptions.