Warn when a component's built-in content is duplicated manually
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 15
- Forks
- 3
- Avg merge
- 1d 17h
- Merged PRs (30d)
- 184
Description
What happens
Link renders IconExternalLink by itself when target="_blank" — on the link and,
via its props context, inside a nested Button as well:
// LinkIcon.tsx
else if (target === "_blank")
icon = <IconExternalLink aria-label={stringFormatter.format("external")} />;
So writing the icon by hand produces a duplicate:
<Link href={url} target="_blank">
<Button size="s" variant="outline">
<Icon size="s"><IconExternalLink /></Icon> {/* ← rendered twice */}
<Text>Open in GitLab</Text>
</Button>
</Link>
Nothing warns. It type-checks, it renders, there are just two arrows.
Why this belongs in Flow
We hit this four times in a single application. The three sources you consult while
building all pointed the wrong way:
- the design handoff named the icon ("a
Buttonsize s withIconExternalLink") —
describing the result, read as an instruction - the static HTML mock had the SVG inside the button markup
- surrounding code in the same repository already did it
The only authoritative source is LinkIcon.tsx, and there is no reason to open it
unless you already suspect something.
This is a class, not a one-off. Our project's agent instructions have accumulated a
list of exactly this shape:
TextField type="password"brings its own visibility toggle- a
LabelwithoutisRequiredgets "(optional)" appended SubmitButtonsetscolor="success"internallyFieldsetsisRequired/isInvalid/ the value through a props contextLinkappends a zero-width joiner to the accessible name
Every one of those lines exists because someone was burned. That knowledge currently
lives in consuming repositories instead of in the design system.
Proposal
1. A development-mode warning where the duplicate is detectable
Link already routes every Icon in its children through a props context tunnel
(tunnel: { component: "Link", id: "icon" }), so it knows an icon was passed. In dev
it could compare that against the icon LinkIcon is about to add:
[flow] <Link target="_blank"> contains an IconExternalLink. Flow adds it itself — the icon will be rendered twice.
There is precedent for dev-time warnings in DeprecationWarningProvider.
2. Document behaviour, not just props, in component-index.json
The index lists every prop of Link (target, download, href, …) and says nothing
about what the component renders on its own — which is precisely the part that causes
duplication:
"Link": {
"rendersItself": [
"IconExternalLink when target='_blank' — also inside a nested Button",
"IconDownload when download is set",
"a zero-width joiner at the end of the accessible name"
]
}
Same for llms.txt.
Note on AI coding agents
Two of our four occurrences were written by an AI agent, two were already in the
existing code — this is not an agent-specific problem, but agents make it more
frequent, because they take the surrounding code as the house style.
That also makes the ranking clear. A dev-time console warning is the highest-leverage
fix: agents run the app and read the console, so it catches the mistake even when the
docs are never opened. The index entry catches the agent that does its homework —
cheap, and worth having for both.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with LinkIcon.tsx and trace the Link icon props context, then read the precedent in DeprecationWarningProvider. Check component-index.json and llms.txt for the existing Link metadata. Done means duplicate built-in content is warned about in development and the documented Link behavior includes its built-in icons and accessible-name change.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- react, typescript
- Domain
- accessibility, documentation, frontend
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100