Deprecate Link to prop — standardize on href + LinkProvider#498
Deprecate Link to prop — standardize on href + LinkProvider#498mattrothenberg merged 3 commits intomainfrom
to prop — standardize on href + LinkProvider#498Conversation
…tion Link is a presentational component — routing belongs in the application layer. The `to` prop is a router-framework concept that leaked into the component API, causing confusion about which prop to use for navigation. - Add @deprecated JSDoc on `to` in LinkComponentProps - Add dev-mode console.warn when `to` is used on Link - Document LinkProvider integration patterns (React Router, Next.js) - Add comprehensive tests for href, LinkProvider, render prop, and the to→href migration path
commit: |
Docs PreviewCommit: |
to prop — standardize on href + LinkProviderto prop — standardize on href + LinkProvider
- Add LinkProvider integration section with React Router example - Document render prop as escape hatch for exceptional cases - Add to prop as deprecated in API reference table - Update framework integration guidelines - Update installation page LinkProvider snippet
|
/bonk review and approve please |
There was a problem hiding this comment.
Review: Approve
This is a well-executed soft deprecation that addresses a real architectural issue.
What I like
Clean inversion of control: Moving routing-framework concerns out of the presentational component and into LinkProvider is the right pattern. Kumo defines the interface (href), apps inject the implementation.
Thorough documentation: The updated docs explain not just what changed, but why and how to migrate. The React Router and Next.js examples in link-provider.tsx are concrete and copy-pasteable.
Comprehensive test coverage: The 26 tests cover:
hrefbehavior (standard usage)LinkProviderintegration patternsrenderprop bypass behavior- Backwards compatibility for
to - Deprecation warning emission
- The "footgun" case where a wrapper only reads
to
Safe migration path: The to prop still works, just emits a dev-mode warning. No breaking changes.
Implementation details verified
- ✅
console.warnonly fires in dev (guarded byprocess.env.NODE_ENV) - ✅ One-time warning via empty deps
useEffect - ✅
@deprecatedJSDoc on both the type and usage sites - ✅
DefaultLinkComponentstill handleshref ?? tofor backwards compatibility - ✅ Changeset present with correct patch classification
Minor notes
The visual regression changes (Dialog, Select) appear unrelated to this PR — likely baseline timing differences with open states.
Suggestion for follow-up
Consider adding a lint rule (similar to no-deprecated-props) to catch to={...} usage at build time, not just runtime.
Great work on the RFC-quality PR description and the thorough test coverage. This is how deprecations should be done.
|
I've reviewed and approved PR #498. SummaryChanges:
Key points from my review:
The failing tests in CI are unrelated to this PR — they're CLI tests that depend on |






Summary
toprop onLinkandLinkComponentPropsin favor ofhreftois usedLinkProviderintegration pattern for framework routershref,LinkProvider,renderprop, and the deprecationProblem
Kumo's
Linkcomponent accepts bothhrefandtofor specifying the destination URL. This causes a real-world bug when applications configure aLinkProviderwith a client-side router:<Link href="https://example.com">(the natural, platform-standard prop)LinkProviderwraps a router component (e.g. React Router's<Link>) that readstofor navigationhref— the external link silently breaks, navigating to a broken internal route insteadThe workaround has been to use
<Link to="https://example.com">instead, but this doesn't actually work either — React Router's<Link to>does not support fully qualified URLs. It resolves everything as a path within the app.The full matrix
With a LinkProvider wrapping React Router:
/dashboardhrefhref, readsto(undefined)/dashboardtoto, client-side navhttps://example.comhrefhrefhttps://example.comtoNo single prop solves external links without the wrapper being explicit about it.
Why
toexists todaytois a React Router-ism that was added toLinkComponentPropsso theDefaultLinkComponentcould accept either prop. This leaked a routing-framework concept into a presentational component's API.The scope of the workaround inside Kumo
Five places inside Kumo itself defensively pass
to={href}to work around this:LinkButtonto={typeof href === "string" ? href : undefined}Sidebar.MenuButton(2 sites)to={href}DropdownMenu.LinkItemto={href}Breadcrumbs.Linkto={href}Solution
1. Deprecate
to, standardize onhref(this PR)Link should only speak
href(the platform primitive). Routing integration is the application's responsibility viaLinkProvider. This is inversion of control: Kumo defines the interface, the application injects the routing implementation.This PR:
towith@deprecatedJSDoc and a dev-modeconsole.warnLinkProviderwith concrete examples for React Router and Next.jshref,LinkProvider,renderprop, backwards compatibility, and the deprecation warningtois not removed — it continues to work for backwards compatibility. Consumers get a dev-mode warning guiding them to migrate.2. Consumer apps build a smart
LinkProviderwrapper (downstream follow-up)The recommended pattern is for consumer apps to provide a
LinkProvidercomponent that:hrefto the router's navigation prop for internal links<a>for external linkstarget,rel, etc. as appropriateEngineers then just use
hrefeverywhere — the wrapper handles the rest:For exceptional cases where direct router control is needed, the
renderprop remains as an escape hatch:Breaking change?
Soft deprecation only.
tocontinues to work — consumers just get a dev-mode warning guiding them to migrate. A future major version could removetoentirely.