๐ Introductionโ
CDS 9 builds on the foundation laid in v8 and focuses on stability, modernization, and addressing specific debt that improves future maintainability.
Highlights of this release:
- ๐ฎ React 19 support on web (with backwards compatibility for React 18)
- ๐ฑ React Native 0.81 / Expo SDK 54 support on mobile
- ๐ Eliminates hard-coded fixed widths/heights from all components to improve customizability and themeability
- ๐ฏ Consolidates standalone visualization packages in order to simplify the CDS ecosystem
- ๐ฌ๏ธ NEW migrator tool (
@coinbase/cds-migrator) to help with this and future upgrades
๐ฆ Packagesโ
The following CDS packages are receiving new versions:
@coinbase/cds-common@9.0.0-rc.2@coinbase/cds-web@9.0.0-rc.2@coinbase/cds-mobile@9.0.0-rc.2@coinbase/cds-mcp-server@9.0.0-rc.2@coinbase/cds-migrator@1.0.0New
CDS 9 is currently in release candidate status. There are no breaking changes planned prior to the official release of 9.0.0. So it is safe to upgrade to 9.0.0-rc.2 if you want to get an early start.
In CDS 9, we are deprecating the standalone visualization packages. See the Deprecated packages for more details.
@coinbase/cds-web-visualizationDeprecated@coinbase/cds-mobile-visualizationDeprecated
โ Upgrade Stepsโ
1. Prerequisitesโ
CDS 9 no longer bundles the v7 shim (cds-web/v7/cds-mobile/v7).
Incremental upgrade strategies, which this pattern enabled, are no longer recommended.
Starting with CDS 9, major releases will minimize breaking changes relateive to the prior version, making major upgrades possible to land in a single PR, even for large monorepos.
Before upgrading to v9:
- Search your codebase for any remaining
cds-web/v7/cds-mobile/v7imports. - Complete any partial migrations from the v7 shim to proper CDS 8 imports by following the v8 Migration Guide.
- Once all v7 imports are eliminated, you can upgrade to v9.
2. Update Packagesโ
No required peer dependency changes for web.
3. Run Automated Codemodsโ
The new @coinbase/cds-migrator will help expedite your upgrade to CDS 9.
It encapsulates individual changes in transforms, and groups related transforms into versioned presets.
For upgrades from CDS 8 to CDS 9, use the v8-to-v9 preset.
For detailed CLI documentation and individual transform/preset details, see the package README.
We will continually publish new transforms and presets to proactively address deprecations in preparation of the following major release.
Running the codemodsโ
You can also run a single transform:
The migrator tool records what it has already run in .cds-migration-history.json and leaves // TODO [cds-migrator:<transform-name>] comments in the source code for cases that may need manual review.
Manual upgrade effortโ
The CDS 9 codemods should address the vast majority of potential incompatibility issues, however there are a few specific edge cases that may require manual attention.
- Tightening some TypeScript types (
Carousel,Drawer,Tray,Modal,TableCell.end, etc.) - Updating custom Stepper progress UIs and
SlideButtonslot components to use Reanimated /framer-motioninstead ofreact-spring - See Breaking Change Overview for more details
๐ฅ Breaking Change Overviewโ
Hard-Coded Dimensions Removedโ
CDS 9 removes hard-coded fixed heights and widths from all components. Components are now driven by their content, your layout, or theme tokens. As a side effect, several constants and utilities that exposed those fixed pixel values are deprecated (see New Deprecations). Review any surfaces that depended on CDS components occupying fixed dimensions, since those layouts may need small visual adjustments after upgrading.
Packages & Importsโ
- v7 import paths dropped โ
@coinbase/cds-web/v7and@coinbase/cds-mobile/v7are no longer bundled. Apps must finish their CDS 8 upgrade before jumping to CDS 9. - Visualization packages merged โ deep paths on
@coinbase/cds-(web|mobile)-visualizationmay no longer resolve. Use the new@coinbase/cds-(web|mobile)/visualizations/*exports.
Cutting react-spring referencesโ
CDS is migrating away from react-spring, which is poorly maintained and has been the source of recurring bugs.
The implementation detail leaked into the public API of two components โ Stepper and SlideButton.
These APIs need to be adjusted before CDS can transition to the preferred animation libraries, framer-motion and react-native-reanimated.
Stepper Web Mobileโ
If you supply a custom step / progress UI to Stepper, the progress prop is now a plain number between 0 and 1 instead of a react-spring value. For built-in progress animation, configure timing via the new progressTimingConfig / defaultProgressTimingConfig props. The legacy progressSpringConfig prop is ignored on this animation path.
SlideButton Mobileโ
Custom SlideButtonBackgroundComponent and SlideButtonHandleComponent slots now receive progress as a Reanimated SharedValue<number> instead of a react-spring SpringValue<number>. Any custom slot that drove animation with spring helpers must switch to Reanimated.
Spring config: animationConfig on DefaultSlideButtonHandle is deprecated. Use slideButtonSpringConfig together with Reanimated's withSpring.
Layout: SlideButton now applies default heights (40 for compact, 56 for regular) and derives the handle's minWidth from height. If you previously omitted height and relied on the old interactable-height + spring-driven sizing, double-check the rendered layout โ you may need to set height explicitly to preserve v8 behavior.
TypeScript Type Changesโ
A handful of CDS types have been tightened to better reflect runtime behavior or to align with React 19's updated typedefs. These changes are runtime-compatible but may surface as TypeScript errors after you upgrade.
In most cases, removing explicit type annotations and letting TypeScript infer the type from CDS is the simplest fix.
React.FC type removed for render-children types WebMobileโ
The following components' render functions are now typed as (props) => ReactNode instead of using the deprecated React.FC type:
CarouselItemDrawerTrayModal
TableCell.end and SelectOptionGroupComponent.accessory Webโ
Both components' props now require a stricter type: React.ReactElement<CellAccessoryProps>.
Input onFocus / onBlur Event Types Mobileโ
Certain mobile component APIs that accept focus/blur event handlers now use simpler typing
Removed APIs (Dropped Deprecations)โ
The following @deprecated APIs are fully removed in v9.
| Package | Dropped deprecations |
|---|---|
Common | emptyObject, StickyFooterProps |
Web | AnnouncementCardProps, FeatureEntryCardProps, RadioGroupProps, CheckboxGroupProps, FeedCardProps, IconCounterButton.iconSize |
Mobile | AnnouncementCardProps, FeatureEntryCardProps, RadioGroupProps, CheckboxGroupProps, FeedCardProps, LinearGradient.isBelowChildren, IconCounterButton.iconSize |
โ ๏ธ New Deprecationsโ
The following APIs are still available in v9 but are scheduled for removal in CDS 10. Migrators and/or AI agents will be released following the v9 launch to help with each. You can also start migrating manually using the guidance below.
Packagesโ
| Package | Notes |
|---|---|
@coinbase/cds-web-visualization | Use @coinbase/cds-web/visualizations/{chart,sparkline} instead. Remove the dependency once your imports are migrated. |
@coinbase/cds-mobile-visualization | Use @coinbase/cds-mobile/visualizations/{chart,sparkline} instead. Remove the dependency once your imports are migrated. |
The CDS migrator's v8-to-v9 preset will update these packages' import paths for you.
Componentsโ
| Deprecation | Package | Notes |
|---|---|---|
| AvatarButton border props | Web Mobile | Border-related props have no effect; remove them. |
| IconCounterButton.dangerouslySetColor | Web Mobile | Use styles.icon, classNames.icon, or color on web. Use styles.icon or color on mobile. |
| Spinner | Web Mobile | Prefer indeterminate ProgressCircle and ActivityIndicator on mobile where documented. |
| Stepper.progressSpringConfig / Stepper.defaultProgressSpringConfig | Web Mobile | Use progressTimingConfig / defaultProgressTimingConfig. |
| Text.dangerouslySetColor | Web Mobile | Use style, className, or color on web. Use style or the color style prop on mobile. |
| TextBody, TextCaption, TextDisplay*, TextHeadline, TextInherited, TextLabel*, TextLegal, TextTitle* | Web Mobile | Use Text with the matching font. |
| DefaultSlideButtonHandle.animationConfig | Mobile | Use slideButtonSpringConfig with Reanimated withSpring. |
Hooks & Functionsโ
| Deprecation | Package | Notes |
|---|---|---|
| getButtonSpacingProps | Common | Going away without a built-in replacement. Handle button spacing locally or with your own helper. |
| getDotSize | Common | Fixed pixel sizing for dots is no longer provided as a shared helper. |
| useMergeRefs | Common | Use mergeRefs from @coinbase/cds-common/utils/mergeRefs. Automated by migrate-use-merge-refs-import. |
| usePopper | Web | Temporary compatibility shim. Use Floating UI directly in your app if you still need popper-like positioning. |
| useStatusBarHeight | Mobile | Use useSafeAreaInsets().top from react-native-safe-area-context. |
| useHasNotch | Mobile | Replace with useSafeAreaInsets().top > 20 from react-native-safe-area-context if you need an equivalent. |
Tokens & Constantsโ
The following tokens were fixed pixel values that pin component sizing. With v9 removing hard-coded heights/widths, they are no longer published. Define your own values or rely on layout-driven sizing.
| Deprecation | Package | Notes |
|---|---|---|
[tokens/cell] compactListHeight, listHeight, selectOptionHeight | Common | Define your own values or rely on layout-driven sizing. |
[tokens/dot] dotSizeTokens | Common | Define your own values or rely on layout-driven sizing. |
Typesโ
| Deprecation | Package | Notes |
|---|---|---|
| MobileBannerProps | Mobile | Use BannerProps. |
[types/BoxBaseProps] PositionStyles | Common | Prefer PositionStyles from mobile styleProps or web styleProps where the guidance applies. |
| CardHeaderProps | Common | Use ContentCardHeaderProps for content cards. |
| CardMediaProps | Common | Use SpotSquare, Pictogram, or RemoteImage by type, per JSDoc. |
| DimensionStyles value types | Common | Prefer dimension props with 'auto' | number | string. |
[types/Position] Position | Common | Use CSSProperties['position'] on web or ViewStyle['position'] on React Native. |