@coinbase/cds-mcp-server 8.53.1 → 8.55.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +8 -0
- package/mcp-docs/mobile/components/Calendar.txt +518 -0
- package/mcp-docs/mobile/components/DateInput.txt +1 -0
- package/mcp-docs/mobile/components/DatePicker.txt +156 -28
- package/mcp-docs/mobile/components/IconButton.txt +2 -0
- package/mcp-docs/mobile/components/SelectChip.txt +2 -0
- package/mcp-docs/mobile/components/Tooltip.txt +51 -12
- package/mcp-docs/mobile/components/Tray.txt +2 -0
- package/mcp-docs/mobile/guides/v8-migration-guide.txt +1762 -0
- package/mcp-docs/mobile/routes.txt +6 -1
- package/mcp-docs/web/components/Calendar.txt +132 -4
- package/mcp-docs/web/components/DatePicker.txt +28 -26
- package/mcp-docs/web/components/Tray.txt +1 -0
- package/mcp-docs/web/guides/v8-migration-guide.txt +1762 -0
- package/mcp-docs/web/routes.txt +4 -0
- package/package.json +1 -1
|
@@ -0,0 +1,1762 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: v8-migration-guide
|
|
3
|
+
title: v8 Migration Guide
|
|
4
|
+
slug: /guides/v8-migration-guide
|
|
5
|
+
hide_title: true
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
import { MDXSection } from '@site/src/components/page/MDXSection';
|
|
9
|
+
import { MDXArticle } from '@site/src/components/page/MDXArticle';
|
|
10
|
+
import { ContentHeader } from '@site/src/components/page/ContentHeader';
|
|
11
|
+
import { VStack } from '@coinbase/cds-web/layout';
|
|
12
|
+
import { Tag } from '@coinbase/cds-web/tag/Tag';
|
|
13
|
+
import { Icon } from '@coinbase/cds-web/icons';
|
|
14
|
+
|
|
15
|
+
<VStack gap={5}>
|
|
16
|
+
<ContentHeader title="v8 Migration Guide" />
|
|
17
|
+
|
|
18
|
+
<MDXSection>
|
|
19
|
+
<MDXArticle>
|
|
20
|
+
|
|
21
|
+
## Introduction
|
|
22
|
+
|
|
23
|
+
CDS v8 is our most feature packed release ever! Including but not limited to:
|
|
24
|
+
|
|
25
|
+
- 🔮 Expanded styling and customization options
|
|
26
|
+
- 🔥 Faster renders and smaller flamegraphs
|
|
27
|
+
- 🦾 Improved accessibility of components and theming
|
|
28
|
+
- 🧩 Simplified and more predictable internal architecture
|
|
29
|
+
|
|
30
|
+
To enable global theming and style customization for all CDS components, some APIs were deprecated or outright deleted. We appreciate the impact this will have on teams adopting CDS v8 and are committed to supporting developers through this upgrade 🏎️
|
|
31
|
+
|
|
32
|
+
If you experience any trouble migrating we're ready to help! Just reach out via Slack.
|
|
33
|
+
|
|
34
|
+
</MDXArticle>
|
|
35
|
+
</MDXSection>
|
|
36
|
+
|
|
37
|
+
<MDXSection>
|
|
38
|
+
<MDXArticle>
|
|
39
|
+
|
|
40
|
+
## New Packages
|
|
41
|
+
|
|
42
|
+
- `@coinbase/cds-common@8.1.0`
|
|
43
|
+
- `@coinbase/cds-mobile@8.1.0`
|
|
44
|
+
- `@coinbase/cds-mobile-visualization@3.0.0`
|
|
45
|
+
- `@coinbase/cds-web@8.1.0`
|
|
46
|
+
- `@coinbase/cds-web-visualization@3.0.0`
|
|
47
|
+
- `@coinbase/cds-icons@5.0.0`
|
|
48
|
+
- `@coinbase/cds-lottie-files@3.0.0`
|
|
49
|
+
|
|
50
|
+
</MDXArticle>
|
|
51
|
+
</MDXSection>
|
|
52
|
+
|
|
53
|
+
<MDXSection>
|
|
54
|
+
<MDXArticle>
|
|
55
|
+
|
|
56
|
+
## Migration Script
|
|
57
|
+
|
|
58
|
+
Before diving into the breaking changes, we highly recommend starting with our automated migration script. The `@coinbase/cds-migrator` package handles many of the repetitive transformations automatically, saving you significant time and effort.
|
|
59
|
+
|
|
60
|
+
### What the Migration Script Automates
|
|
61
|
+
|
|
62
|
+
The migration script handles these transformations automatically:
|
|
63
|
+
|
|
64
|
+
- **Icon migrations**: Active/inactive suffix removal, renamed icons, and active prop additions
|
|
65
|
+
- **Color token updates**: Converts old color names to new semantic tokens
|
|
66
|
+
- **Border radius/width tokens**: Updates string tokens to numeric values and CSS variables
|
|
67
|
+
- **Import path updates**: Fixes outdated import paths throughout your codebase
|
|
68
|
+
- **Component prop changes**: Updates `responsiveConfig` to direct responsive props
|
|
69
|
+
- **Hook migrations**: Updates `useSpectrum`, `useAccessibleForeground`, and other deprecated hooks
|
|
70
|
+
|
|
71
|
+
Look for the <Tag intent="promotional" colorScheme="blue">Migration Script ✓</Tag> tags throughout this guide to identify what's automated.
|
|
72
|
+
|
|
73
|
+
### Running the Migration Script (Internal to Coinbase)
|
|
74
|
+
|
|
75
|
+
For detailed instructions on running the migration script, refer to the Migrator Guide, reach out via Slack if you need help finding the guide.
|
|
76
|
+
|
|
77
|
+
### What Requires Manual Migration
|
|
78
|
+
|
|
79
|
+
While the script handles most changes, some breaking changes require manual intervention:
|
|
80
|
+
|
|
81
|
+
- **ThemeProvider setup**: Converting from legacy providers to the new ThemeProvider
|
|
82
|
+
- **Scale/density system removal**: Creating custom dense themes
|
|
83
|
+
- **Custom styling**: Updating CSS-in-JS and styled components
|
|
84
|
+
- **Type definitions**: Updating polymorphic component prop types
|
|
85
|
+
- **Complex component patterns**: Advanced usage that can't be automatically detected
|
|
86
|
+
|
|
87
|
+
</MDXArticle>
|
|
88
|
+
</MDXSection>
|
|
89
|
+
|
|
90
|
+
<MDXSection>
|
|
91
|
+
<MDXArticle>
|
|
92
|
+
|
|
93
|
+
## Dependency Updates
|
|
94
|
+
|
|
95
|
+
### Linaria Dependency Requirements
|
|
96
|
+
|
|
97
|
+
**Important:** If you are using `@linaria/core` in your application code, you must properly declare it in your `package.json` dependencies. In CDS v8, we moved `@linaria/core` from `dependencies` to `devDependencies`, which means it will no longer be automatically available to consuming applications.
|
|
98
|
+
|
|
99
|
+
```json
|
|
100
|
+
{
|
|
101
|
+
"dependencies": {
|
|
102
|
+
"@linaria/core": "^6.0.0"
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
This is required if your application directly imports from `@linaria/core`:
|
|
108
|
+
|
|
109
|
+
```tsx
|
|
110
|
+
import { css, cx } from '@linaria/core';
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
**Alternative for `cx` function:** If you're only using the `cx` function from `@linaria/core`, you can import it directly from `@coinbase/cds-web` instead of adding the dependency:
|
|
114
|
+
|
|
115
|
+
```tsx
|
|
116
|
+
// ❌ Requires @linaria/core dependency
|
|
117
|
+
import { cx } from '@linaria/core';
|
|
118
|
+
|
|
119
|
+
// ✅ No additional dependency needed
|
|
120
|
+
import { cx } from '@coinbase/cds-web';
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
</MDXArticle>
|
|
124
|
+
</MDXSection>
|
|
125
|
+
|
|
126
|
+
<MDXSection>
|
|
127
|
+
<MDXArticle>
|
|
128
|
+
|
|
129
|
+
## 💥 Breaking Change Overview
|
|
130
|
+
|
|
131
|
+
Here's a high-level overview of the major breaking changes in v8:
|
|
132
|
+
|
|
133
|
+
### 🎨 Theming System Changes
|
|
134
|
+
|
|
135
|
+
- **New ThemeProvider**: Requires `theme` and `activeColorScheme` props (no defaults)
|
|
136
|
+
- **Provider consolidation**: `SpectrumProvider`, `DarkModeProvider`, `LightModeProvider`, and scale providers replaced by single `ThemeProvider`
|
|
137
|
+
- **Spectrum vs Color**: Distinction between spectrum (`"r,g,b"`) and color (CSS values) - prefer color tokens
|
|
138
|
+
- **CSS variables**: Preferred way to access theme values on web for performance
|
|
139
|
+
- **No inheritance**: ThemeProvider no longer auto-inherits from parent providers
|
|
140
|
+
- **Color scheme classes**: ThemeProvider adds `.dark`/`.light` classes to container
|
|
141
|
+
- **Scale/density removed**: No scale system - create custom themes for dense styles
|
|
142
|
+
- **Theme inversion**: `invertSpectrum` → `invertColorScheme`, new `InvertedThemeProvider`
|
|
143
|
+
|
|
144
|
+
### 🎭 Style System Changes
|
|
145
|
+
|
|
146
|
+
- **Safari support**: Requires Safari 15.4+ for web (CSS layers, `:focus-visible`, `:has()`)
|
|
147
|
+
- **CSS layers**: All CDS styles scoped to `@layer cds` for better specificity control
|
|
148
|
+
- **CSS reset**: New global styles override browser defaults for polymorphic components
|
|
149
|
+
- **Improved polymorphism**: Better type safety for polymorphic components with `as` prop
|
|
150
|
+
- **Elevation simplified**: Streamlined system without `ElevationProvider`/`useElevationStyles`
|
|
151
|
+
- **CSS-in-JS**: Static CSS variables and Linaria-compiled styles instead of runtime calculations
|
|
152
|
+
|
|
153
|
+
### 🪙 Token Changes
|
|
154
|
+
|
|
155
|
+
- **Color tokens**: Complete redesign with semantic naming:
|
|
156
|
+
- Foreground: `foreground` → `fg`, `primary` → `fgPrimary`
|
|
157
|
+
- Background: `background` → `bg`, `primary` → `bgPrimary`
|
|
158
|
+
- Border: `line` → `bgLine`, `primary` → `bgLinePrimary`
|
|
159
|
+
- **Border radius**: String tokens → numeric (`rounded` → `200`, `roundedFull` → `1000`)
|
|
160
|
+
- **Border width**: String tokens → numeric (`button` → `100`, `focusRing` → `200`)
|
|
161
|
+
- **Import paths**: Many token imports moved to new package locations
|
|
162
|
+
|
|
163
|
+
### ⭐ Icon Changes
|
|
164
|
+
|
|
165
|
+
- **Active states**: Controlled by `active` prop instead of icon name suffixes (`starFilled` → `<Icon name="star" active />`)
|
|
166
|
+
- **Renamed icons**: Several icons renamed for clarity
|
|
167
|
+
- **Removed props**: `bordered` prop removed from Icon component
|
|
168
|
+
- **Removed components**: `NavigationIcon` and `NavigationIconButton` removed
|
|
169
|
+
|
|
170
|
+
### 🧩 Component Changes
|
|
171
|
+
|
|
172
|
+
- **Responsive props**: `responsiveConfig` prop removed, use direct responsive props
|
|
173
|
+
- **Media queries**: `deviceBreakpoints`/`deviceMqs` → `breakpoints`/`media`
|
|
174
|
+
- **Removed providers**: `DevicePreferencesProvider`, `BreakpointsProvider`, `FeatureFlagProvider`
|
|
175
|
+
- **Removed components**: Several utility components removed or renamed (`InteractableContent` → `Interactable`)
|
|
176
|
+
- **Import paths**: Component import paths updated to new package structure
|
|
177
|
+
|
|
178
|
+
### 🔧 Hook & Utility Changes
|
|
179
|
+
|
|
180
|
+
- **useTheme**: Replaces `useSpectrum`, `useScale`, and other theming hooks
|
|
181
|
+
- **Accessibility**: `useAccessibleForeground` → `getAccessibleColor` with new API
|
|
182
|
+
- **Spacing**: `useSpacingScale`/`useSpacingValue` → direct theme token access
|
|
183
|
+
- **Typography**: `useTypographyStyles` → direct theme property access
|
|
184
|
+
- **Scale hooks**: `useScale`, `useScaleConditional` removed (no scale system)
|
|
185
|
+
- **Palette utilities**: `paletteValueToRgbaString`, `usePalette` → theme-based approach
|
|
186
|
+
|
|
187
|
+
### 📝 Type Changes
|
|
188
|
+
|
|
189
|
+
- **Polymorphic types**: Now require type arguments (`TextProps<'h1'>`, `BoxProps<'div'>`)
|
|
190
|
+
- **Default elements**: `TextDefaultElement`, `BoxDefaultElement` exported for defaults
|
|
191
|
+
- **Removed types**: `HTMLNonHeadingTextTags`, `NoopFn`, `SetState`, `Overflow`, `IconPixelSize`
|
|
192
|
+
- **Updated types**: `GapSpacing` → `ThemeVars.Space`
|
|
193
|
+
|
|
194
|
+
</MDXArticle>
|
|
195
|
+
</MDXSection>
|
|
196
|
+
|
|
197
|
+
<MDXSection>
|
|
198
|
+
<MDXArticle>
|
|
199
|
+
|
|
200
|
+
## Theming Updates
|
|
201
|
+
|
|
202
|
+
### The New ThemeProvider
|
|
203
|
+
|
|
204
|
+
In CDS v8, the theming system has been completely redesigned. The new `ThemeProvider` is the single source of truth for all styling and requires both `theme` and `activeColorScheme` props.
|
|
205
|
+
|
|
206
|
+
**Basic Setup:**
|
|
207
|
+
|
|
208
|
+
```tsx
|
|
209
|
+
import { ThemeProvider } from '@coinbase/cds-web/system/ThemeProvider';
|
|
210
|
+
import { defaultTheme } from '@coinbase/cds-web/themes/defaultTheme';
|
|
211
|
+
|
|
212
|
+
const App = () => {
|
|
213
|
+
return (
|
|
214
|
+
<ThemeProvider theme={defaultTheme} activeColorScheme="light">
|
|
215
|
+
<YourAppContent />
|
|
216
|
+
</ThemeProvider>
|
|
217
|
+
);
|
|
218
|
+
};
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
**Custom Theme:**
|
|
222
|
+
|
|
223
|
+
```tsx
|
|
224
|
+
const customTheme = {
|
|
225
|
+
...defaultTheme,
|
|
226
|
+
lightColor: {
|
|
227
|
+
...defaultTheme.lightColor,
|
|
228
|
+
bgPrimary: 'rgb(255, 0, 0)',
|
|
229
|
+
},
|
|
230
|
+
space: {
|
|
231
|
+
...defaultTheme.space,
|
|
232
|
+
5: 32,
|
|
233
|
+
},
|
|
234
|
+
};
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
### The useTheme Hook
|
|
238
|
+
|
|
239
|
+
The `useTheme()` hook provides access to the current theme and active color scheme:
|
|
240
|
+
|
|
241
|
+
```tsx
|
|
242
|
+
const MyComponent = () => {
|
|
243
|
+
const theme = useTheme();
|
|
244
|
+
console.log(theme.activeColorScheme); // "light" or "dark"
|
|
245
|
+
console.log(theme.spectrum); // Reference to lightSpectrum or darkSpectrum
|
|
246
|
+
console.log(theme.color); // Reference to lightColor or darkColor
|
|
247
|
+
console.log(theme.color.bgPrimary); // "rgb(0,82,255)" or "rgb(87,139,250)"
|
|
248
|
+
console.log(theme.space[2]); // "16px"
|
|
249
|
+
console.log(theme.borderRadius[200]); // "8px"
|
|
250
|
+
console.log(theme.fontSize.display3); // "2.5rem"
|
|
251
|
+
};
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
**Performance Note:** Whenever possible, use CSS variables on web instead of the `useTheme()` hook to ensure best performance.
|
|
255
|
+
|
|
256
|
+
### Note about Spectrum vs Color
|
|
257
|
+
|
|
258
|
+
The difference between `theme.spectrum` and `theme.color` is that spectrum values are just `"r,g,b"` strings while color values are valid CSS values. The `theme.color` values have semantic names and you should always prefer to use these values instead of spectrum values when styling UI.
|
|
259
|
+
|
|
260
|
+
```tsx
|
|
261
|
+
const lightSpectrum = {
|
|
262
|
+
red60: '207,32,47',
|
|
263
|
+
};
|
|
264
|
+
|
|
265
|
+
const theme = {
|
|
266
|
+
lightSpectrum,
|
|
267
|
+
lightColor: {
|
|
268
|
+
bgNegative: `rgb(${lightSpectrum.red60})`,
|
|
269
|
+
},
|
|
270
|
+
};
|
|
271
|
+
|
|
272
|
+
// In components:
|
|
273
|
+
const theme = useTheme();
|
|
274
|
+
console.log(theme.spectrum.red60); // "207,32,47"
|
|
275
|
+
console.log(theme.color.bgNegative); // "rgb(207,32,47)"
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
### CSS Variables (Web)
|
|
279
|
+
|
|
280
|
+
On web, `ThemeProvider` creates CSS variables for all theme values:
|
|
281
|
+
|
|
282
|
+
| JS variable | CSS variable |
|
|
283
|
+
| ------------------------- | -------------------- |
|
|
284
|
+
| `theme.color.bgPrimary` | `--color-bgPrimary` |
|
|
285
|
+
| `theme.space[2]` | `--space-2` |
|
|
286
|
+
| `theme.borderRadius[200]` | `--borderRadius-200` |
|
|
287
|
+
|
|
288
|
+
### Color Scheme Classes (Web)
|
|
289
|
+
|
|
290
|
+
On web, the ThemeProvider adds a `.dark` or `.light` class to its container element depending on the `activeColorScheme`. You can use this class for writing styles specific to the color schemes.
|
|
291
|
+
|
|
292
|
+
```css
|
|
293
|
+
const myStyles = css`
|
|
294
|
+
.dark {
|
|
295
|
+
background-image: url('http://example.com/dark.png');
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
.light {
|
|
299
|
+
background-image: url('http://example.com/light.png');
|
|
300
|
+
}
|
|
301
|
+
`;
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
### ThemeProvider Requirements
|
|
305
|
+
|
|
306
|
+
The ThemeProvider no longer includes default values for the `theme` or `activeColorScheme` props. These props are now required on every ThemeProvider. Any component calling the `useTheme()` hook without a parent ThemeProvider will throw an error, and component styles will be broken.
|
|
307
|
+
|
|
308
|
+
### ThemeProvider Inheritance
|
|
309
|
+
|
|
310
|
+
The ThemeProvider no longer automatically inherits and merges themes from parent ThemeProviders. However you can manually inherit the theme if you want:
|
|
311
|
+
|
|
312
|
+
```tsx
|
|
313
|
+
const MyPage = () => {
|
|
314
|
+
const theme = useTheme();
|
|
315
|
+
|
|
316
|
+
const customTheme = {
|
|
317
|
+
...theme,
|
|
318
|
+
fontFamily: {
|
|
319
|
+
...theme.fontFamily,
|
|
320
|
+
label1: 'Arial',
|
|
321
|
+
},
|
|
322
|
+
};
|
|
323
|
+
|
|
324
|
+
return (
|
|
325
|
+
<ThemeProvider theme={customTheme} activeColorScheme={theme.activeColorScheme}>
|
|
326
|
+
Customized theming!
|
|
327
|
+
</ThemeProvider>
|
|
328
|
+
);
|
|
329
|
+
};
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
### Scale/Density System Removed
|
|
333
|
+
|
|
334
|
+
In CDS v8, the concept of scale/density no longer exists. To achieve dense/xSmall scale styles, you can create a new theme that updates the values of `space`, `fontSize`, `lineHeight`, `controlSize`, `iconSize`, etc.
|
|
335
|
+
|
|
336
|
+
We have an example `coinbaseDenseTheme` you can use to emulate the old dense/xSmall scale styles - [web link](https://github.com/coinbase/cds-staging/blob/master/packages/web/src/themes/coinbaseDenseTheme.ts) and [mobile link](https://github.com/coinbase/cds-staging/blob/master/packages/mobile/src/themes/coinbaseDenseTheme.ts). However you need to copy this theme into your application, it will be deleted from CDS in the next major release.
|
|
337
|
+
|
|
338
|
+
### Inverting the Theme
|
|
339
|
+
|
|
340
|
+
Some component props like `invertSpectrum` allow inverting a component tree to use the opposite of the current `activeColorScheme`. These props have been renamed to `invertColorScheme`.
|
|
341
|
+
|
|
342
|
+
We have a new InvertedThemeProvider that will do this inversion automatically if the opposite color palette is defined in the theme. If the opposite colors are not defined then the InvertedThemeProvider does nothing.
|
|
343
|
+
|
|
344
|
+
```tsx
|
|
345
|
+
const MyComponent = ({ invertColorScheme }) => {
|
|
346
|
+
const Wrapper = invertColorScheme ? InvertedThemeProvider : React.Fragment;
|
|
347
|
+
return <Wrapper>Hello world</Wrapper>;
|
|
348
|
+
};
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
### Removed Theming APIs
|
|
352
|
+
|
|
353
|
+
The following theming-related APIs have been removed:
|
|
354
|
+
|
|
355
|
+
**Providers:**
|
|
356
|
+
|
|
357
|
+
- `SpectrumProvider` / `RootSpectrumProvider` - [see migration instructions](#migrating-rootspectrumprovider)
|
|
358
|
+
- `DarkModeProvider` / `LightModeProvider` - [see migration instructions](#migrating-darkmodeprovider--lightmodeprovider)
|
|
359
|
+
- `ScaleProvider` / `RootScaleProvider` / `DenseScaleProvider` / `NormalScaleProvider` - [see dense theme migration](#creating-dense-themes)
|
|
360
|
+
|
|
361
|
+
**Hooks:**
|
|
362
|
+
|
|
363
|
+
- `useSpectrum` - Replaced by `useTheme` hook
|
|
364
|
+
- `useScale` / `useScaleConditional` - [see migration instructions](#migrating-scale-related-hooks-no-direct-replacement)
|
|
365
|
+
- `useSpectrumConditional` - [see migration instructions](#migrating-usespectrumconditional)
|
|
366
|
+
|
|
367
|
+
</MDXArticle>
|
|
368
|
+
</MDXSection>
|
|
369
|
+
|
|
370
|
+
<MDXSection>
|
|
371
|
+
<MDXArticle>
|
|
372
|
+
|
|
373
|
+
## Style Updates
|
|
374
|
+
|
|
375
|
+
### Safari Web Support
|
|
376
|
+
|
|
377
|
+
CDS v8 for web supports Safari 15.4 and later, released March 14, 2022. We make use of features like CSS layers and selectors like `:focus-visible` and `:has()`.
|
|
378
|
+
|
|
379
|
+
### CSS Layers
|
|
380
|
+
|
|
381
|
+
All CDS web CSS is now scoped to a [CSS layer](https://developer.mozilla.org/en-US/docs/Web/CSS/@layer) for better specificity control:
|
|
382
|
+
|
|
383
|
+
```css
|
|
384
|
+
@layer cds {
|
|
385
|
+
.hello-world {
|
|
386
|
+
color: red;
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
This causes CDS CSS to have lower style specificity than styles that are not on a CSS layer - which makes it easy to ensure your custom styles always overwrite CDS. This solves problems with non-deterministic styles based on stylesheet load order.
|
|
392
|
+
|
|
393
|
+
### New Web Global Styles
|
|
394
|
+
|
|
395
|
+
CDS web global styles now include a CSS reset which override the browser default styles for some elements. This ensures that polymorphic components render correctly, regardless of their HTML element. See the [full style reset here](https://github.com/coinbase/cds-staging/blob/master/packages/web/src/styles/global.ts).
|
|
396
|
+
|
|
397
|
+
### Improved Polymorphism
|
|
398
|
+
|
|
399
|
+
Many web components are now fully polymorphic with strong type checking:
|
|
400
|
+
|
|
401
|
+
```tsx
|
|
402
|
+
// Without the `as` prop, href throws a type error
|
|
403
|
+
<Button href="example.com" />
|
|
404
|
+
// With the `as` prop, all native anchor props are valid
|
|
405
|
+
<Button as="a" href="example.com" />
|
|
406
|
+
```
|
|
407
|
+
|
|
408
|
+
### Elevation Changes
|
|
409
|
+
|
|
410
|
+
CDS v8 introduces a simplified elevation system that replaces the complex context-based approach with streamlined implementations for both web and mobile platforms. The elevation prop continues to support the same levels (0, 1, 2), but the underlying implementation has been significantly simplified for better performance and developer experience.
|
|
411
|
+
|
|
412
|
+
In CDS web, the new elevation system uses static CSS variables and Linaria-compiled styles instead of runtime calculations. v8 removes the `ElevationProvider` context and `useElevationStyles` hook in favor of direct component props. This change eliminates the need for context providers and custom hooks while providing more consistent visual results across light and dark themes.
|
|
413
|
+
|
|
414
|
+
In CDS mobile, the complex `ElevationConfigsProvider` and `createElevationConfigForSpectrum` system has been replaced with direct theme-based styling through the `getElevationStyles` function, removing the need for context providers and wrapper components.
|
|
415
|
+
|
|
416
|
+
### Removed Style APIs
|
|
417
|
+
|
|
418
|
+
The following style-related APIs have been removed:
|
|
419
|
+
|
|
420
|
+
**Providers:**
|
|
421
|
+
|
|
422
|
+
- `ElevationConfigsProvider` - [see migration instructions](#migrating-elevationconfigsprovider)
|
|
423
|
+
|
|
424
|
+
**Hooks:**
|
|
425
|
+
|
|
426
|
+
- `useTypographyStyles` - [see migration instructions](#migrating-usetypographystyles)
|
|
427
|
+
- `useThemeProviderStyles` - [see migration instructions](#migrating-usethemeproviderstyles)
|
|
428
|
+
- `useSpacingStyles` - [see migration instructions](#migrating-usespacingstyles)
|
|
429
|
+
- `useSpacingScale` / `useSpacingValue` - [see migration instructions](#migrating-usespacingscale--usespacingvalue)
|
|
430
|
+
|
|
431
|
+
### New Style Tokens
|
|
432
|
+
|
|
433
|
+
CDS v8 introduces many new themeable style tokens. The value of these tokens is configured in the ThemeProvider.
|
|
434
|
+
|
|
435
|
+
**Example: Using New Color Tokens**
|
|
436
|
+
|
|
437
|
+
```tsx
|
|
438
|
+
// ❌ Before (v7)
|
|
439
|
+
<Box background="primary" color="primaryForeground">
|
|
440
|
+
<Text color="secondary">Hello</Text>
|
|
441
|
+
</Box>
|
|
442
|
+
|
|
443
|
+
// ✅ After (v8)
|
|
444
|
+
<Box background="bgPrimary" color="fgInverse">
|
|
445
|
+
<Text color="fgMuted">Hello</Text>
|
|
446
|
+
</Box>
|
|
447
|
+
```
|
|
448
|
+
|
|
449
|
+
### CSS Variables in Styled Components
|
|
450
|
+
|
|
451
|
+
```tsx
|
|
452
|
+
// ❌ Before (v7)
|
|
453
|
+
const StyledCard = styled.div`
|
|
454
|
+
background: ${palette.background};
|
|
455
|
+
border: 1px solid ${palette.line};
|
|
456
|
+
padding: ${spacing[3]};
|
|
457
|
+
`;
|
|
458
|
+
|
|
459
|
+
// ✅ After (v8)
|
|
460
|
+
const StyledCard = styled.div`
|
|
461
|
+
background: var(--color-bg);
|
|
462
|
+
border: var(--borderWidth-100) solid var(--color-bgLine);
|
|
463
|
+
padding: var(--space-3);
|
|
464
|
+
`;
|
|
465
|
+
```
|
|
466
|
+
|
|
467
|
+
### Mobile StyleSheet Updates
|
|
468
|
+
|
|
469
|
+
```tsx
|
|
470
|
+
// ❌ Before (v7)
|
|
471
|
+
import { borderRadius, colors } from '@coinbase/cds-mobile/tokens';
|
|
472
|
+
|
|
473
|
+
const styles = StyleSheet.create({
|
|
474
|
+
card: {
|
|
475
|
+
backgroundColor: colors.background,
|
|
476
|
+
borderRadius: borderRadius.rounded,
|
|
477
|
+
},
|
|
478
|
+
});
|
|
479
|
+
|
|
480
|
+
// ✅ After (v8)
|
|
481
|
+
import { useTheme } from '@coinbase/cds-mobile/hooks/useTheme';
|
|
482
|
+
|
|
483
|
+
const MyComponent = () => {
|
|
484
|
+
const theme = useTheme();
|
|
485
|
+
|
|
486
|
+
const styles = StyleSheet.create({
|
|
487
|
+
card: {
|
|
488
|
+
backgroundColor: theme.color.bg,
|
|
489
|
+
borderRadius: theme.borderRadius[200],
|
|
490
|
+
},
|
|
491
|
+
});
|
|
492
|
+
|
|
493
|
+
return <View style={styles.card} />;
|
|
494
|
+
};
|
|
495
|
+
```
|
|
496
|
+
|
|
497
|
+
</MDXArticle>
|
|
498
|
+
</MDXSection>
|
|
499
|
+
|
|
500
|
+
<MDXSection>
|
|
501
|
+
<MDXArticle>
|
|
502
|
+
|
|
503
|
+
## Token Updates
|
|
504
|
+
|
|
505
|
+
### Foreground Color Token Mapping
|
|
506
|
+
|
|
507
|
+
| v7 Token | v8 Token |
|
|
508
|
+
| --------------------- | ------------- |
|
|
509
|
+
| `foreground` | `fg` |
|
|
510
|
+
| `foregroundMuted` | `fgMuted` |
|
|
511
|
+
| `primary` | `fgPrimary` |
|
|
512
|
+
| `primaryForeground` | `fgInverse` |
|
|
513
|
+
| `secondary` | `bgSecondary` |
|
|
514
|
+
| `secondaryForeground` | `fg` |
|
|
515
|
+
| `positive` | `fgPositive` |
|
|
516
|
+
| `positiveForeground` | `fgInverse` |
|
|
517
|
+
| `negative` | `fgNegative` |
|
|
518
|
+
| `negativeForeground` | `fgInverse` |
|
|
519
|
+
| `warning` | `bgWarning` |
|
|
520
|
+
| `warningForeground` | `fgWarning` |
|
|
521
|
+
|
|
522
|
+
### Background Color Token Mapping
|
|
523
|
+
|
|
524
|
+
| v7 Token | v8 Token |
|
|
525
|
+
| --------------------- | ---------------- |
|
|
526
|
+
| `background` | `bg` |
|
|
527
|
+
| `backgroundAlternate` | `bgAlternate` |
|
|
528
|
+
| `backgroundOverlay` | `bgOverlay` |
|
|
529
|
+
| `backgroundInverse` | `bgInverse` |
|
|
530
|
+
| `primary` | `bgPrimary` |
|
|
531
|
+
| `secondary` | `bgSecondary` |
|
|
532
|
+
| `positive` | `bgPositive` |
|
|
533
|
+
| `negative` | `bgNegative` |
|
|
534
|
+
| `warning` | `bgWarning` |
|
|
535
|
+
| `primaryWash` | `bgPrimaryWash` |
|
|
536
|
+
| `negativeWash` | `bgNegativeWash` |
|
|
537
|
+
| `transparent` | `transparent` |
|
|
538
|
+
|
|
539
|
+
### Border Color Token Mapping
|
|
540
|
+
|
|
541
|
+
| v7 Token | v8 Token |
|
|
542
|
+
| ------------------- | --------------------- |
|
|
543
|
+
| `primary` | `bgLinePrimary` |
|
|
544
|
+
| `primaryWash` | `bgLinePrimarySubtle` |
|
|
545
|
+
| `secondary` | `bgLine` |
|
|
546
|
+
| `positive` | `bgPositive` |
|
|
547
|
+
| `negative` | `bgNegative` |
|
|
548
|
+
| `line` | `bgLine` |
|
|
549
|
+
| `lineHeavy` | `bgLineHeavy` |
|
|
550
|
+
| `transparent` | `transparent` |
|
|
551
|
+
| `warning` | `bgWarning` |
|
|
552
|
+
| `warningForeground` | `fgWarning` |
|
|
553
|
+
|
|
554
|
+
### Border Radius Token Mapping
|
|
555
|
+
|
|
556
|
+
| v7 Token | v8 Token |
|
|
557
|
+
| --------------- | -------- |
|
|
558
|
+
| `roundedNone` | `0` |
|
|
559
|
+
| `roundedSmall` | `100` |
|
|
560
|
+
| `rounded` | `200` |
|
|
561
|
+
| `roundedMedium` | `300` |
|
|
562
|
+
| `roundedLarge` | `400` |
|
|
563
|
+
| `roundedXLarge` | `500` |
|
|
564
|
+
| `roundedFull` | `1000` |
|
|
565
|
+
|
|
566
|
+
### Border Width Token Mapping
|
|
567
|
+
|
|
568
|
+
| v7 Token | v8 Token |
|
|
569
|
+
| ----------- | -------- |
|
|
570
|
+
| `none` | `0` |
|
|
571
|
+
| `button` | `100` |
|
|
572
|
+
| `card` | `100` |
|
|
573
|
+
| `checkbox` | `200` |
|
|
574
|
+
| `radio` | `200` |
|
|
575
|
+
| `sparkline` | `200` |
|
|
576
|
+
| `focusRing` | `200` |
|
|
577
|
+
| `input` | `100` |
|
|
578
|
+
|
|
579
|
+
### Removed Token APIs
|
|
580
|
+
|
|
581
|
+
The following token-related APIs have been removed:
|
|
582
|
+
|
|
583
|
+
**Functions:**
|
|
584
|
+
|
|
585
|
+
- `paletteValueToRgbaString` - [see migration instructions](#migrating-color-palette-functions)
|
|
586
|
+
- `paletteAliasToRgbaString` - [see migration instructions](#migrating-color-palette-functions)
|
|
587
|
+
|
|
588
|
+
**Hooks:**
|
|
589
|
+
|
|
590
|
+
- `usePalette` - [see migration instructions](#migrating-color-palette-functions)
|
|
591
|
+
- `usePaletteConfig` - [see migration instructions](#migrating-color-palette-functions)
|
|
592
|
+
|
|
593
|
+
**Constants:**
|
|
594
|
+
|
|
595
|
+
- `defaultPalette` - [see migration instructions](#migrating-color-palette-functions)
|
|
596
|
+
|
|
597
|
+
</MDXArticle>
|
|
598
|
+
</MDXSection>
|
|
599
|
+
|
|
600
|
+
<MDXSection>
|
|
601
|
+
<MDXArticle>
|
|
602
|
+
|
|
603
|
+
## Icon Updates
|
|
604
|
+
|
|
605
|
+
### Renamed Icons
|
|
606
|
+
|
|
607
|
+
<Tag intent="promotional">Migration Script ✓</Tag>
|
|
608
|
+
|
|
609
|
+
The following icons have been renamed:
|
|
610
|
+
|
|
611
|
+
- `visibleInactive` → `invisible`
|
|
612
|
+
- `followInactive` → `followAdd`
|
|
613
|
+
- `visibleFilled` → `visible`
|
|
614
|
+
- `rocketInactive` → `noRocket`
|
|
615
|
+
- `followActive` → `following`
|
|
616
|
+
|
|
617
|
+
### Active State Changes
|
|
618
|
+
|
|
619
|
+
<Tag intent="promotional">Migration Script ✓</Tag>
|
|
620
|
+
|
|
621
|
+
For certain UI icons whose names end with Active or Inactive suffixes, their active state is now controlled by a boolean `active` prop -- see the complete [migration instructions](#icon-components-with-active-states).
|
|
622
|
+
|
|
623
|
+
**Affected icons**: See the complete [UI Icon Exceptions list](#icon-components-with-active-states) in the migration instructions.
|
|
624
|
+
|
|
625
|
+
**Affected components**: `Icon`, `CellMedia`, `IconButton`, `Button`, `Banner`.
|
|
626
|
+
|
|
627
|
+
### Removed Icon APIs
|
|
628
|
+
|
|
629
|
+
The following icon-related APIs have been removed:
|
|
630
|
+
|
|
631
|
+
**Props:**
|
|
632
|
+
|
|
633
|
+
- `bordered` prop from `Icon` component - [see migration instructions](#migrating-bordered-icon-prop)
|
|
634
|
+
|
|
635
|
+
**Components:**
|
|
636
|
+
|
|
637
|
+
- `NavigationIcon` & `NavigationIconButton` - Use standard `Icon` and `IconButton` instead - [see migration instructions](#migrating-navigationiconnavigationiconbutton)
|
|
638
|
+
|
|
639
|
+
</MDXArticle>
|
|
640
|
+
</MDXSection>
|
|
641
|
+
|
|
642
|
+
<MDXSection>
|
|
643
|
+
<MDXArticle>
|
|
644
|
+
|
|
645
|
+
## Component Updates
|
|
646
|
+
|
|
647
|
+
### Responsive Props
|
|
648
|
+
|
|
649
|
+
<Tag intent="promotional">Migration Script ✓</Tag>
|
|
650
|
+
|
|
651
|
+
The `responsiveConfig` prop has been removed. Pass responsive values directly to each prop:
|
|
652
|
+
|
|
653
|
+
```tsx
|
|
654
|
+
// ❌ Before
|
|
655
|
+
const responsiveConfig = { desktop: { gap: 2 }, tablet: { gap: 3 } };
|
|
656
|
+
<Box responsiveConfig={responsiveConfig}>Content</Box>
|
|
657
|
+
|
|
658
|
+
// ✅ After
|
|
659
|
+
<Box gap={{ desktop: 2, tablet: 3 }}>Content</Box>
|
|
660
|
+
```
|
|
661
|
+
|
|
662
|
+
### Breakpoints & Media Queries
|
|
663
|
+
|
|
664
|
+
Import paths and values have been updated:
|
|
665
|
+
|
|
666
|
+
```tsx
|
|
667
|
+
// ❌ Before (v7)
|
|
668
|
+
import { deviceBreakpoints, deviceMqs } from '@coinbase/cds-web/layout/breakpoints';
|
|
669
|
+
|
|
670
|
+
// ✅ After (v8)
|
|
671
|
+
import { breakpoints, media } from '@coinbase/cds-web/styles/media';
|
|
672
|
+
```
|
|
673
|
+
|
|
674
|
+
### Removed Component APIs
|
|
675
|
+
|
|
676
|
+
The following component-related APIs have been removed:
|
|
677
|
+
|
|
678
|
+
**Providers:**
|
|
679
|
+
|
|
680
|
+
- `DevicePreferencesProvider` - [see migration instructions](#migrating-devicepreferencesprovider)
|
|
681
|
+
- `BreakpointsProvider` - [see migration instructions](#migrating-breakpointsprovider)
|
|
682
|
+
- `FeatureFlagProvider` - [see migration instructions](#migrating-featureflagprovider)
|
|
683
|
+
|
|
684
|
+
**Components:**
|
|
685
|
+
|
|
686
|
+
- `InteractableContent` - Renamed to `Interactable` - [see migration instructions](#migrating-interactablecontent)
|
|
687
|
+
|
|
688
|
+
**Hooks:**
|
|
689
|
+
|
|
690
|
+
- `useMergedRef` - [see migration instructions](#migrating-usemergedref)
|
|
691
|
+
- `useToggler` - [see migration instructions](#migrating-usetoggler)
|
|
692
|
+
- `useMediaQuery` / `useDeviceColorScheme` - Use theme-based approach instead
|
|
693
|
+
- `useIconSize` / `useAvatarSize` - [see migration instructions](#migrating-scale-related-hooks-no-direct-replacement)
|
|
694
|
+
- `useInteractableHeight` - [see migration instructions](#migrating-scale-related-hooks-no-direct-replacement)
|
|
695
|
+
|
|
696
|
+
**Utilities:**
|
|
697
|
+
|
|
698
|
+
- `overflowClassName` - Replace with inline CSS: `{ overflow: auto; text-overflow: unset; white-space: normal; }` - [see migration instructions](#migrating-overflowclassname)
|
|
699
|
+
|
|
700
|
+
</MDXArticle>
|
|
701
|
+
</MDXSection>
|
|
702
|
+
|
|
703
|
+
<MDXSection>
|
|
704
|
+
<MDXArticle>
|
|
705
|
+
|
|
706
|
+
## Type Updates
|
|
707
|
+
|
|
708
|
+
### Polymorphic Component Props
|
|
709
|
+
|
|
710
|
+
All polymorphic component prop types now require a type argument:
|
|
711
|
+
|
|
712
|
+
```tsx
|
|
713
|
+
// ❌ Before (v7)
|
|
714
|
+
interface MyComponentProps {
|
|
715
|
+
textProps: TextProps;
|
|
716
|
+
boxProps: BoxProps;
|
|
717
|
+
}
|
|
718
|
+
|
|
719
|
+
// ✅ After (v8)
|
|
720
|
+
import { TextProps, TextDefaultElement } from '@coinbase/cds-web/typography/Text';
|
|
721
|
+
import { BoxProps, BoxDefaultElement } from '@coinbase/cds-web/layout/Box';
|
|
722
|
+
|
|
723
|
+
interface MyComponentProps {
|
|
724
|
+
textProps: TextProps<TextDefaultElement>;
|
|
725
|
+
boxProps: BoxProps<BoxDefaultElement>;
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
// Or with specific element types
|
|
729
|
+
interface MySpecificComponentProps {
|
|
730
|
+
headingProps: TextProps<'h1'>;
|
|
731
|
+
linkProps: BoxProps<'a'>;
|
|
732
|
+
}
|
|
733
|
+
```
|
|
734
|
+
|
|
735
|
+
### Removed Type APIs
|
|
736
|
+
|
|
737
|
+
The following type-related APIs have been removed:
|
|
738
|
+
|
|
739
|
+
**Types:**
|
|
740
|
+
|
|
741
|
+
- `HTMLNonHeadingTextTags` - Define locally if needed - [see migration instructions](#migrating-removed-types)
|
|
742
|
+
- `LinkTypography` - Replace with `LinkProps<LinkDefaultElement>['font']`
|
|
743
|
+
- `BoxElement` - Use `BoxDefaultElement` or define as `keyof JSX.IntrinsicElements`
|
|
744
|
+
- `Overflow` - Define locally as `{ overflow?: 'visible' | 'hidden' | 'scroll' | 'auto' | 'clip' }` - [see migration instructions](#migrating-removed-types)
|
|
745
|
+
|
|
746
|
+
**Constants:**
|
|
747
|
+
|
|
748
|
+
- `paletteForegrounds`, `paletteBackgrounds`, `paletteBorders`
|
|
749
|
+
|
|
750
|
+
</MDXArticle>
|
|
751
|
+
</MDXSection>
|
|
752
|
+
|
|
753
|
+
<MDXSection>
|
|
754
|
+
<MDXArticle>
|
|
755
|
+
|
|
756
|
+
## FAQ
|
|
757
|
+
|
|
758
|
+
### Why upgrade to v8?
|
|
759
|
+
|
|
760
|
+
CDS v8 brings faster performance, full theming and customization, powerful new APIs, and improved accessibility. It also includes React 19 support, a rebuilt docs site, and an MCP server to streamline development.
|
|
761
|
+
|
|
762
|
+
### What new features are included?
|
|
763
|
+
|
|
764
|
+
This release includes:
|
|
765
|
+
|
|
766
|
+
- Theming and customization
|
|
767
|
+
- Drastically improved performance
|
|
768
|
+
- CDS MCP Server
|
|
769
|
+
- Powerful new APIs
|
|
770
|
+
- All new docs site
|
|
771
|
+
- React 19 support
|
|
772
|
+
- 5 new components
|
|
773
|
+
|
|
774
|
+
### Are migration scripts available?
|
|
775
|
+
|
|
776
|
+
Yes! We provide the `@coinbase/cds-migrator` package to assist with automated migration. For detailed instructions, refer to the [Migrator Guide](https://github.com/coinbase/cds-staging/blob/master/packages/migrator/README.md).
|
|
777
|
+
|
|
778
|
+
</MDXArticle>
|
|
779
|
+
</MDXSection>
|
|
780
|
+
|
|
781
|
+
<MDXSection>
|
|
782
|
+
<MDXArticle>
|
|
783
|
+
|
|
784
|
+
## Appendix: Detailed Migration Instructions
|
|
785
|
+
|
|
786
|
+
This section provides step-by-step instructions for migrating specific APIs and components that have been removed or updated. Each section corresponds to the breaking changes outlined above.
|
|
787
|
+
|
|
788
|
+
**Note:** Code examples may show platform-specific import paths (e.g., `@coinbase/cds-web` or `@coinbase/cds-mobile`). Adjust the import paths based on your target platform.
|
|
789
|
+
|
|
790
|
+
### Theming Migration Instructions
|
|
791
|
+
|
|
792
|
+
_See [Theming Updates](#theming-updates) for overview_
|
|
793
|
+
|
|
794
|
+
#### Migrating DevicePreferencesProvider
|
|
795
|
+
|
|
796
|
+
**On Web:**
|
|
797
|
+
|
|
798
|
+
```tsx
|
|
799
|
+
// ❌ Before (v7)
|
|
800
|
+
import { DevicePreferencesProvider } from '@coinbase/cds-web/system';
|
|
801
|
+
|
|
802
|
+
const App = () => (
|
|
803
|
+
<DevicePreferencesProvider>
|
|
804
|
+
<YourAppContent />
|
|
805
|
+
</DevicePreferencesProvider>
|
|
806
|
+
);
|
|
807
|
+
|
|
808
|
+
// ✅ After (v8)
|
|
809
|
+
import { ThemeProvider } from '@coinbase/cds-web/system/ThemeProvider';
|
|
810
|
+
import { defaultTheme } from '@coinbase/cds-web/themes/defaultTheme';
|
|
811
|
+
import { MediaQueryProvider } from '@coinbase/cds-web/system/MediaQueryProvider';
|
|
812
|
+
import { useMediaQuery } from '@coinbase/cds-web/hooks/useMediaQuery';
|
|
813
|
+
|
|
814
|
+
const App = () => {
|
|
815
|
+
const prefersDark = useMediaQuery('(prefers-color-scheme: dark)');
|
|
816
|
+
const activeColorScheme = prefersDark ? 'dark' : 'light';
|
|
817
|
+
|
|
818
|
+
return (
|
|
819
|
+
<MediaQueryProvider>
|
|
820
|
+
<ThemeProvider theme={defaultTheme} activeColorScheme={activeColorScheme}>
|
|
821
|
+
<YourAppContent />
|
|
822
|
+
</ThemeProvider>
|
|
823
|
+
</MediaQueryProvider>
|
|
824
|
+
);
|
|
825
|
+
};
|
|
826
|
+
```
|
|
827
|
+
|
|
828
|
+
**On Mobile:**
|
|
829
|
+
|
|
830
|
+
```tsx
|
|
831
|
+
// ❌ Before (v7)
|
|
832
|
+
import { DevicePreferencesProvider } from '@coinbase/cds-mobile/system';
|
|
833
|
+
|
|
834
|
+
// ✅ After (v8)
|
|
835
|
+
import { ThemeProvider } from '@coinbase/cds-mobile/system/ThemeProvider';
|
|
836
|
+
import { defaultTheme } from '@coinbase/cds-mobile/themes/defaultTheme';
|
|
837
|
+
import { useDeviceColorScheme } from '@coinbase/cds-mobile/hooks/useDeviceColorScheme';
|
|
838
|
+
|
|
839
|
+
const App = () => {
|
|
840
|
+
const deviceColorScheme = useDeviceColorScheme();
|
|
841
|
+
const [userPreference, setUserPreference] = useState<'system' | 'light' | 'dark'>('system');
|
|
842
|
+
|
|
843
|
+
const activeColorScheme = userPreference === 'system' ? deviceColorScheme : userPreference;
|
|
844
|
+
|
|
845
|
+
return (
|
|
846
|
+
<ThemeProvider theme={defaultTheme} activeColorScheme={activeColorScheme}>
|
|
847
|
+
<YourApp />
|
|
848
|
+
{/* Somewhere in your settings */}
|
|
849
|
+
<Button onPress={() => setUserPreference('dark')}>Dark Mode</Button>
|
|
850
|
+
<Button onPress={() => setUserPreference('light')}>Light Mode</Button>
|
|
851
|
+
<Button onPress={() => setUserPreference('system')}>Follow System</Button>
|
|
852
|
+
</ThemeProvider>
|
|
853
|
+
);
|
|
854
|
+
};
|
|
855
|
+
```
|
|
856
|
+
|
|
857
|
+
#### Migrating BreakpointsProvider
|
|
858
|
+
|
|
859
|
+
**Steps:**
|
|
860
|
+
|
|
861
|
+
1. Remove the `BreakpointsProvider` import
|
|
862
|
+
2. Add `import { MediaQueryProvider } from '@coinbase/cds-web/system/MediaQueryProvider'`
|
|
863
|
+
3. Replace `BreakpointsProvider` with `MediaQueryProvider`
|
|
864
|
+
4. Add the `defaultValues` prop if needed
|
|
865
|
+
|
|
866
|
+
```tsx
|
|
867
|
+
// ❌ Before (v7)
|
|
868
|
+
import { BreakpointsProvider } from '@coinbase/cds-web/system/BreakpointsProvider';
|
|
869
|
+
|
|
870
|
+
// ✅ After (v8)
|
|
871
|
+
import { MediaQueryProvider } from '@coinbase/cds-web/system/MediaQueryProvider';
|
|
872
|
+
|
|
873
|
+
const App = () => (
|
|
874
|
+
<MediaQueryProvider>
|
|
875
|
+
<YourApp />
|
|
876
|
+
</MediaQueryProvider>
|
|
877
|
+
);
|
|
878
|
+
```
|
|
879
|
+
|
|
880
|
+
#### Migrating RootSpectrumProvider
|
|
881
|
+
|
|
882
|
+
**Steps:**
|
|
883
|
+
|
|
884
|
+
1. Replace `RootSpectrumProvider` with `ThemeProvider`
|
|
885
|
+
2. Add your own device color scheme detection logic using `useDeviceColorScheme()` hook
|
|
886
|
+
3. Implement user preference state management
|
|
887
|
+
|
|
888
|
+
```tsx
|
|
889
|
+
// ❌ Before (v7)
|
|
890
|
+
import { RootSpectrumProvider } from '@coinbase/cds-mobile/system';
|
|
891
|
+
|
|
892
|
+
// ✅ After (v8) - Manual override with state management
|
|
893
|
+
import { ThemeProvider } from '@coinbase/cds-mobile/system/ThemeProvider';
|
|
894
|
+
import { defaultTheme } from '@coinbase/cds-mobile/themes/defaultTheme';
|
|
895
|
+
import { useDeviceColorScheme } from '@coinbase/cds-mobile/hooks/useDeviceColorScheme';
|
|
896
|
+
|
|
897
|
+
const App = () => {
|
|
898
|
+
const deviceColorScheme = useDeviceColorScheme();
|
|
899
|
+
const [userPreference, setUserPreference] = useState<'system' | 'light' | 'dark'>('system');
|
|
900
|
+
|
|
901
|
+
const activeColorScheme = userPreference === 'system' ? deviceColorScheme : userPreference;
|
|
902
|
+
|
|
903
|
+
return (
|
|
904
|
+
<ThemeProvider theme={defaultTheme} activeColorScheme={activeColorScheme}>
|
|
905
|
+
<YourApp />
|
|
906
|
+
{/* Somewhere in your settings */}
|
|
907
|
+
<Button onPress={() => setUserPreference('dark')}>Dark Mode</Button>
|
|
908
|
+
<Button onPress={() => setUserPreference('light')}>Light Mode</Button>
|
|
909
|
+
<Button onPress={() => setUserPreference('system')}>Follow System</Button>
|
|
910
|
+
</ThemeProvider>
|
|
911
|
+
);
|
|
912
|
+
};
|
|
913
|
+
```
|
|
914
|
+
|
|
915
|
+
#### Migrating DarkModeProvider / LightModeProvider
|
|
916
|
+
|
|
917
|
+
**Steps:**
|
|
918
|
+
|
|
919
|
+
1. Remove `DarkModeProvider` and `LightModeProvider` imports
|
|
920
|
+
2. Replace with `ThemeProvider` that has `activeColorScheme` set to `"dark"` or `"light"`
|
|
921
|
+
|
|
922
|
+
```tsx
|
|
923
|
+
// ❌ Before (v7)
|
|
924
|
+
import { DarkModeProvider, LightModeProvider } from '@coinbase/cds-mobile/system';
|
|
925
|
+
|
|
926
|
+
<DarkModeProvider>
|
|
927
|
+
<YourApp />
|
|
928
|
+
</DarkModeProvider>
|
|
929
|
+
|
|
930
|
+
<LightModeProvider>
|
|
931
|
+
<YourApp />
|
|
932
|
+
</LightModeProvider>
|
|
933
|
+
|
|
934
|
+
// ✅ After (v8)
|
|
935
|
+
import { ThemeProvider } from '@coinbase/cds-mobile/system/ThemeProvider';
|
|
936
|
+
import { defaultTheme } from '@coinbase/cds-mobile/themes/defaultTheme';
|
|
937
|
+
|
|
938
|
+
<ThemeProvider theme={defaultTheme} activeColorScheme="dark">
|
|
939
|
+
<YourApp />
|
|
940
|
+
</ThemeProvider>
|
|
941
|
+
|
|
942
|
+
<ThemeProvider theme={defaultTheme} activeColorScheme="light">
|
|
943
|
+
<YourApp />
|
|
944
|
+
</ThemeProvider>
|
|
945
|
+
```
|
|
946
|
+
|
|
947
|
+
#### Migrating FeatureFlagProvider
|
|
948
|
+
|
|
949
|
+
**Steps:**
|
|
950
|
+
|
|
951
|
+
1. Simply remove `FeatureFlagProvider` from your component tree
|
|
952
|
+
2. The benefits it provided are now automatic in v8
|
|
953
|
+
|
|
954
|
+
```tsx
|
|
955
|
+
// ❌ Before (v7)
|
|
956
|
+
import { FeatureFlagProvider } from '@coinbase/cds-web/system';
|
|
957
|
+
|
|
958
|
+
<FeatureFlagProvider>
|
|
959
|
+
<YourApp />
|
|
960
|
+
</FeatureFlagProvider>
|
|
961
|
+
|
|
962
|
+
// ✅ After (v8)
|
|
963
|
+
// Simply remove the provider - modern behaviors like CSS gap are now default
|
|
964
|
+
<YourApp />
|
|
965
|
+
```
|
|
966
|
+
|
|
967
|
+
**What was automated:**
|
|
968
|
+
|
|
969
|
+
- CSS gap support
|
|
970
|
+
- Fabric support
|
|
971
|
+
- Other modern behaviors that required opt-in
|
|
972
|
+
|
|
973
|
+
#### Migrating ElevationConfigsProvider
|
|
974
|
+
|
|
975
|
+
**Steps:**
|
|
976
|
+
|
|
977
|
+
1. Remove `ElevationConfigsProvider` from your component tree
|
|
978
|
+
2. The elevation system has been simplified and no longer needs this provider
|
|
979
|
+
|
|
980
|
+
```tsx
|
|
981
|
+
// ❌ Before (v7)
|
|
982
|
+
import { ElevationConfigsProvider } from '@coinbase/cds-mobile/system';
|
|
983
|
+
|
|
984
|
+
<ElevationConfigsProvider>
|
|
985
|
+
<YourApp />
|
|
986
|
+
</ElevationConfigsProvider>
|
|
987
|
+
|
|
988
|
+
// ✅ After (v8)
|
|
989
|
+
// Simply remove the provider - elevation is now handled directly by components
|
|
990
|
+
<YourApp />
|
|
991
|
+
```
|
|
992
|
+
|
|
993
|
+
#### Creating Dense Themes
|
|
994
|
+
|
|
995
|
+
_Related to the scale system removal mentioned in [Theming Updates](#theming-updates)_
|
|
996
|
+
|
|
997
|
+
**Steps:**
|
|
998
|
+
|
|
999
|
+
1. Copy the example `coinbaseDenseTheme` from CDS
|
|
1000
|
+
2. Create theme switching logic
|
|
1001
|
+
|
|
1002
|
+
**Example:**
|
|
1003
|
+
|
|
1004
|
+
```tsx
|
|
1005
|
+
import { ThemeProvider } from '@coinbase/cds-web/system/ThemeProvider';
|
|
1006
|
+
import { coinbaseDenseTheme } from '@coinbase/cds-web/themes/coinbaseDenseTheme';
|
|
1007
|
+
import { coinbaseTheme } from '@coinbase/cds-web/themes/coinbaseTheme';
|
|
1008
|
+
|
|
1009
|
+
// override the dense theme with your own values if needed
|
|
1010
|
+
const myDenseTheme = {
|
|
1011
|
+
...coinbaseDenseTheme,
|
|
1012
|
+
id: 'dense-theme',
|
|
1013
|
+
space: {
|
|
1014
|
+
'0': 0,
|
|
1015
|
+
'0.25': 2,
|
|
1016
|
+
'0.5': 4,
|
|
1017
|
+
'0.75': 6,
|
|
1018
|
+
'1': 8,
|
|
1019
|
+
'1.5': 10,
|
|
1020
|
+
'2': 12, // vs 16 in default
|
|
1021
|
+
'3': 16, // vs 24 in default
|
|
1022
|
+
'4': 20, // vs 32 in default
|
|
1023
|
+
'5': 24, // vs 40 in default
|
|
1024
|
+
// ... other smaller values
|
|
1025
|
+
},
|
|
1026
|
+
fontSize: {
|
|
1027
|
+
headline: 14, // vs 16 in default
|
|
1028
|
+
body: 14, // vs 16 in default
|
|
1029
|
+
// ... other smaller font sizes
|
|
1030
|
+
},
|
|
1031
|
+
// ... other dense tokens
|
|
1032
|
+
};
|
|
1033
|
+
|
|
1034
|
+
const App = ({ activeColorScheme }) => {
|
|
1035
|
+
const [isDense, setIsDense] = React.useState(false);
|
|
1036
|
+
const theme = isDense ? myDenseTheme : coinbaseTheme;
|
|
1037
|
+
|
|
1038
|
+
return (
|
|
1039
|
+
<ThemeProvider theme={theme} activeColorScheme={activeColorScheme}>
|
|
1040
|
+
<Button onClick={() => setIsDense((d) => !d)}>Toggle Density</Button>
|
|
1041
|
+
<YourApp />
|
|
1042
|
+
</ThemeProvider>
|
|
1043
|
+
);
|
|
1044
|
+
};
|
|
1045
|
+
```
|
|
1046
|
+
|
|
1047
|
+
### Style Migration Instructions
|
|
1048
|
+
|
|
1049
|
+
_See [Style Updates](#style-updates) for overview_
|
|
1050
|
+
|
|
1051
|
+
#### Migrating useThemeProviderStyles
|
|
1052
|
+
|
|
1053
|
+
**Steps:**
|
|
1054
|
+
|
|
1055
|
+
1. Update the import path: `import { useThemeProviderStyles } from '@coinbase/cds-web/system/ThemeProvider';`
|
|
1056
|
+
2. Remove `className` references (no longer returned)
|
|
1057
|
+
3. Update hook usage
|
|
1058
|
+
|
|
1059
|
+
```tsx
|
|
1060
|
+
// ❌ Before (v7)
|
|
1061
|
+
const { className, style } = useThemeProviderStyles();
|
|
1062
|
+
|
|
1063
|
+
// ✅ After (v8)
|
|
1064
|
+
import { useThemeProviderStyles } from '@coinbase/cds-web/system/ThemeProvider';
|
|
1065
|
+
const style = useThemeProviderStyles();
|
|
1066
|
+
```
|
|
1067
|
+
|
|
1068
|
+
#### Migrating useTypographyStyles
|
|
1069
|
+
|
|
1070
|
+
_Related to new style tokens mentioned in [Style Updates](#style-updates)_
|
|
1071
|
+
|
|
1072
|
+
**On Web:**
|
|
1073
|
+
|
|
1074
|
+
```tsx
|
|
1075
|
+
// ❌ Before (v7)
|
|
1076
|
+
const styles = useTypographyStyles('body');
|
|
1077
|
+
|
|
1078
|
+
// ✅ After (v8)
|
|
1079
|
+
const styles = {
|
|
1080
|
+
fontFamily: 'var(--fontFamily-text)',
|
|
1081
|
+
fontSize: 'var(--fontSize-body)',
|
|
1082
|
+
lineHeight: 'var(--lineHeight-body)',
|
|
1083
|
+
};
|
|
1084
|
+
|
|
1085
|
+
// For display typography:
|
|
1086
|
+
const displayStyles = {
|
|
1087
|
+
fontFamily: 'var(--fontFamily-display1)',
|
|
1088
|
+
fontSize: 'var(--fontSize-display1)',
|
|
1089
|
+
fontWeight: 'var(--fontWeight-display1)',
|
|
1090
|
+
lineHeight: 'var(--lineHeight-display1)',
|
|
1091
|
+
};
|
|
1092
|
+
```
|
|
1093
|
+
|
|
1094
|
+
**On Mobile:**
|
|
1095
|
+
|
|
1096
|
+
```tsx
|
|
1097
|
+
// ❌ Before (v7)
|
|
1098
|
+
const styles = useTypographyStyles('headline');
|
|
1099
|
+
|
|
1100
|
+
// ✅ After (v8)
|
|
1101
|
+
const theme = useTheme();
|
|
1102
|
+
const headlineStyles = useMemo(
|
|
1103
|
+
() => ({
|
|
1104
|
+
fontSize: theme.fontSize.headline,
|
|
1105
|
+
lineHeight: theme.lineHeight.headline,
|
|
1106
|
+
fontWeight: theme.fontWeight.headline,
|
|
1107
|
+
fontFamily: theme.fontFamily.headline,
|
|
1108
|
+
}),
|
|
1109
|
+
[theme],
|
|
1110
|
+
);
|
|
1111
|
+
|
|
1112
|
+
// Or access individual values directly
|
|
1113
|
+
const bodyLineHeight = theme.lineHeight.body;
|
|
1114
|
+
```
|
|
1115
|
+
|
|
1116
|
+
#### Migrating useSpacingStyles
|
|
1117
|
+
|
|
1118
|
+
**Steps:**
|
|
1119
|
+
|
|
1120
|
+
1. Remove the import of `useSpacingStyles`
|
|
1121
|
+
2. Replace with native padding/margin style properties
|
|
1122
|
+
|
|
1123
|
+
```tsx
|
|
1124
|
+
// ❌ Before (v7)
|
|
1125
|
+
const spacingStyles = useSpacingStyles();
|
|
1126
|
+
|
|
1127
|
+
// ✅ After (v8)
|
|
1128
|
+
// web
|
|
1129
|
+
const styles = css`
|
|
1130
|
+
padding: var(--space-1)
|
|
1131
|
+
margin: calc(-1 * var(--space-1)))
|
|
1132
|
+
`;
|
|
1133
|
+
|
|
1134
|
+
// mobile
|
|
1135
|
+
const theme = useTheme();
|
|
1136
|
+
const styles = {
|
|
1137
|
+
padding: theme.space[1],
|
|
1138
|
+
margin: -theme.space[1],
|
|
1139
|
+
};
|
|
1140
|
+
```
|
|
1141
|
+
|
|
1142
|
+
### Token Migration Instructions
|
|
1143
|
+
|
|
1144
|
+
_See [Token Updates](#token-updates) for overview and mapping tables_
|
|
1145
|
+
|
|
1146
|
+
#### Migrating useSpacingScale / useSpacingValue
|
|
1147
|
+
|
|
1148
|
+
**On Web:**
|
|
1149
|
+
|
|
1150
|
+
```tsx
|
|
1151
|
+
// ❌ Before (v7)
|
|
1152
|
+
import { useSpacingValue } from '@coinbase/cds-web/hooks/useSpacingValue';
|
|
1153
|
+
const paddingValue = useSpacingValue(3);
|
|
1154
|
+
|
|
1155
|
+
// ✅ After (v8) - CSS Variables
|
|
1156
|
+
const paddingValue = 'var(--space-3)';
|
|
1157
|
+
|
|
1158
|
+
// Or direct calculation
|
|
1159
|
+
const paddingValue = 3 * 8; // 24px
|
|
1160
|
+
```
|
|
1161
|
+
|
|
1162
|
+
**On Mobile:**
|
|
1163
|
+
|
|
1164
|
+
```tsx
|
|
1165
|
+
// ❌ Before (v7)
|
|
1166
|
+
import { useSpacingValue } from '@coinbase/cds-mobile/hooks/useSpacingValue';
|
|
1167
|
+
const spacing = useSpacingValue(1);
|
|
1168
|
+
|
|
1169
|
+
// ✅ After (v8)
|
|
1170
|
+
import { useTheme } from '@coinbase/cds-mobile/hooks/useTheme';
|
|
1171
|
+
const theme = useTheme();
|
|
1172
|
+
const spacing = theme.space[1];
|
|
1173
|
+
```
|
|
1174
|
+
|
|
1175
|
+
#### Migrating borderRadius Tokens
|
|
1176
|
+
|
|
1177
|
+
_Refer to [Border Radius Token Mapping](#token-updates) table_
|
|
1178
|
+
|
|
1179
|
+
**Steps:**
|
|
1180
|
+
|
|
1181
|
+
1. Remove the import of `borderRadius`
|
|
1182
|
+
2. Replace usage with CSS variables or theme tokens
|
|
1183
|
+
|
|
1184
|
+
```tsx
|
|
1185
|
+
// ❌ Before (v7)
|
|
1186
|
+
import { borderRadius } from '@coinbase/cds-common/tokens/borderRadius';
|
|
1187
|
+
const radius = borderRadius.rounded;
|
|
1188
|
+
|
|
1189
|
+
// ✅ After (v8) - CSS Variables
|
|
1190
|
+
const radius = 'var(--borderRadius-200)';
|
|
1191
|
+
|
|
1192
|
+
// Or using useTheme Hook:
|
|
1193
|
+
const theme = useTheme();
|
|
1194
|
+
const radius = theme.borderRadius[200];
|
|
1195
|
+
```
|
|
1196
|
+
|
|
1197
|
+
#### Migrating borderWidth Tokens
|
|
1198
|
+
|
|
1199
|
+
_Refer to [Border Width Token Mapping](#token-updates) table_
|
|
1200
|
+
|
|
1201
|
+
**Steps:**
|
|
1202
|
+
|
|
1203
|
+
1. Remove the import of `borderWidth`
|
|
1204
|
+
2. Import `useTheme` if needed
|
|
1205
|
+
3. Replace with theme tokens
|
|
1206
|
+
|
|
1207
|
+
```tsx
|
|
1208
|
+
// ❌ Before (v7)
|
|
1209
|
+
import { borderWidth } from '@coinbase/cds-common/tokens/borderWidth';
|
|
1210
|
+
const width = borderWidth.button;
|
|
1211
|
+
|
|
1212
|
+
// ✅ After (v8)
|
|
1213
|
+
import { useTheme } from '@coinbase/cds-mobile/hooks/useTheme';
|
|
1214
|
+
const theme = useTheme();
|
|
1215
|
+
const width = theme.borderWidth[100];
|
|
1216
|
+
```
|
|
1217
|
+
|
|
1218
|
+
#### Migrating Color Palette Functions
|
|
1219
|
+
|
|
1220
|
+
_Refer to [Color Token Mapping](#token-updates) table_
|
|
1221
|
+
|
|
1222
|
+
**paletteValueToRgbaString:**
|
|
1223
|
+
|
|
1224
|
+
```tsx
|
|
1225
|
+
// ❌ Before (v7)
|
|
1226
|
+
import { paletteValueToRgbaString } from '@coinbase/cds-common/palette/paletteValueToRgbaString';
|
|
1227
|
+
const color = paletteValueToRgbaString('green0', activeColorScheme);
|
|
1228
|
+
|
|
1229
|
+
// ✅ After (v8)
|
|
1230
|
+
import { useTheme } from '@coinbase/cds-mobile/hooks/useTheme';
|
|
1231
|
+
const theme = useTheme();
|
|
1232
|
+
const color = `rgba(${theme.spectrum.green0}, 0.1)`;
|
|
1233
|
+
```
|
|
1234
|
+
|
|
1235
|
+
**paletteValueToHex:**
|
|
1236
|
+
|
|
1237
|
+
```tsx
|
|
1238
|
+
// ❌ Before (v7)
|
|
1239
|
+
import { paletteValueToHex } from '@coinbase/cds-common/palette/paletteValueToHex';
|
|
1240
|
+
const color = paletteValueToHex('gray60', activeColorScheme);
|
|
1241
|
+
|
|
1242
|
+
// ✅ After (v8)
|
|
1243
|
+
import { useTheme } from '@coinbase/cds-web/hooks/useTheme';
|
|
1244
|
+
const theme = useTheme();
|
|
1245
|
+
const color = theme.spectrum.gray60;
|
|
1246
|
+
```
|
|
1247
|
+
|
|
1248
|
+
**paletteAliasToRgbaString:**
|
|
1249
|
+
|
|
1250
|
+
```tsx
|
|
1251
|
+
// ❌ Before (v7)
|
|
1252
|
+
import { paletteAliasToRgbaString } from '@coinbase/cds-common/palette/paletteAlias';
|
|
1253
|
+
const color = paletteAliasToRgbaString('primary', activeColorScheme);
|
|
1254
|
+
|
|
1255
|
+
// ✅ After (v8)
|
|
1256
|
+
import { useTheme } from '@coinbase/cds-web/hooks/useTheme';
|
|
1257
|
+
const theme = useTheme();
|
|
1258
|
+
const color = theme.color.fgPrimary;
|
|
1259
|
+
```
|
|
1260
|
+
|
|
1261
|
+
**usePalette:**
|
|
1262
|
+
|
|
1263
|
+
```tsx
|
|
1264
|
+
// ❌ Before (v7)
|
|
1265
|
+
import { usePalette } from '@coinbase/cds-web/hooks/usePalette';
|
|
1266
|
+
const palette = usePalette();
|
|
1267
|
+
const color = palette.foregroundMuted;
|
|
1268
|
+
|
|
1269
|
+
// ✅ After (v8)
|
|
1270
|
+
import { useTheme } from '@coinbase/cds-web/hooks/useTheme';
|
|
1271
|
+
const theme = useTheme();
|
|
1272
|
+
const color = theme.color.fgMuted;
|
|
1273
|
+
```
|
|
1274
|
+
|
|
1275
|
+
**Palette Constants (paletteForegrounds, paletteBackgrounds, paletteBorders):**
|
|
1276
|
+
|
|
1277
|
+
```tsx
|
|
1278
|
+
// ❌ Before (v7)
|
|
1279
|
+
import {
|
|
1280
|
+
paletteBackgrounds,
|
|
1281
|
+
paletteForegrounds,
|
|
1282
|
+
paletteBorders,
|
|
1283
|
+
} from '@coinbase/cds-common/palette/constants';
|
|
1284
|
+
const bgColor = paletteBackgrounds[1];
|
|
1285
|
+
const textColor = paletteForegrounds[0];
|
|
1286
|
+
const borderColor = paletteBorders[2];
|
|
1287
|
+
|
|
1288
|
+
// ✅ After (v8)
|
|
1289
|
+
// Use specific color token names instead
|
|
1290
|
+
const bgColor = 'bgAlternate';
|
|
1291
|
+
const textColor = 'fg';
|
|
1292
|
+
const borderColor = 'bgLine';
|
|
1293
|
+
```
|
|
1294
|
+
|
|
1295
|
+
**Steps:**
|
|
1296
|
+
|
|
1297
|
+
1. Identify the palette color name from the [v7 array](https://github.com/coinbase/cds-staging/blob/v7/packages/common/src/palette/constants.ts#L81-L122)
|
|
1298
|
+
2. Find the corresponding new color token from the [color mapping tables](#token-updates)
|
|
1299
|
+
3. Replace array access with direct token name
|
|
1300
|
+
|
|
1301
|
+
**defaultPalette / usePaletteConfig:**
|
|
1302
|
+
|
|
1303
|
+
```tsx
|
|
1304
|
+
// ❌ Before (v7)
|
|
1305
|
+
import { defaultPalette } from '@coinbase/cds-common/palette/constants';
|
|
1306
|
+
import { usePaletteConfig } from '@coinbase/cds-common/palette/usePaletteConfig';
|
|
1307
|
+
|
|
1308
|
+
// ✅ After (v8) - CSS Variables
|
|
1309
|
+
const bgColor = 'var(--color-bg)';
|
|
1310
|
+
|
|
1311
|
+
// Or using useTheme
|
|
1312
|
+
const theme = useTheme();
|
|
1313
|
+
const bg = theme.color.bg;
|
|
1314
|
+
|
|
1315
|
+
// If passing to ThemeProvider, use coinbaseTheme instead:
|
|
1316
|
+
import { coinbaseTheme } from '@coinbase/cds-web/themes/coinbaseTheme';
|
|
1317
|
+
```
|
|
1318
|
+
|
|
1319
|
+
### Icon Migration Instructions
|
|
1320
|
+
|
|
1321
|
+
_See [Icon Updates](#icon-updates) for overview_
|
|
1322
|
+
|
|
1323
|
+
#### Icon Components with Active States
|
|
1324
|
+
|
|
1325
|
+
_Related to [Active State Changes](#icon-updates) mentioned above_
|
|
1326
|
+
|
|
1327
|
+
**Component-to-Prop Mapping:**
|
|
1328
|
+
|
|
1329
|
+
- **Icon**: `['name', 'active']`
|
|
1330
|
+
- **CellMedia**: `['name', 'active']`
|
|
1331
|
+
- **DotSymbol**: `['iconName', 'active']`
|
|
1332
|
+
- **IconButton**: `['name', 'active']`
|
|
1333
|
+
- **InputIcon**: `['name', 'active']`
|
|
1334
|
+
- **InputIconButton**: `['name', 'active']`
|
|
1335
|
+
- **Banner**: `['startIcon', 'startIconActive']`
|
|
1336
|
+
- **Button**: `[['startIcon', 'startIconActive'], ['endIcon', 'endIconActive']]`
|
|
1337
|
+
|
|
1338
|
+
**UI Icon Exceptions List:**
|
|
1339
|
+
Only apply active prop logic if the icon name is in this list: `add`, `affiliates`, `airdrop`, `artwork`, `avatar`, `bell`, `book`, `briefcase`, `calculator`, `camera`, `chartBar`, `chartPie`, `chartPieCircle`, `chatBubble`, `circleCheckmark`, `circleCross`, `clock`, `coinbaseOne`, `crypto`, `cryptobasics`, `currencies`, `defi`, `dot`, `email`, `error`, `ethereum`, `flame`, `games`, `gavel`, `gear`, `giftCard`, `group`, `heart`, `home`, `info`, `institute`, `keyboard`, `lightbulb`, `lightningBolt`, `lock`, `marketCap`, `megaphone`, `microphone`, `music`, `newsFeed`, `newsletter`, `nft`, `orderHistory`, `paperAirplane`, `passport`, `pencil`, `play`, `profile`, `questionMark`, `regulated`, `safe`, `save`, `shield`, `sortDoubleArrow`, `sortDown`, `sortDownCenter`, `sortUp`, `sortUpCenter`, `soundOff`, `soundOn`, `sparkle`, `speaker`, `stake`, `taxesReceipt`, `telephone`, `thumbsDown`, `thumbsUp`, `trashCan`, `trophy`, `unlock`, `verifiedBadge`, `visibleFilled`, `wallet`, `warning`, `wrapToken`.
|
|
1340
|
+
|
|
1341
|
+
**Steps:**
|
|
1342
|
+
|
|
1343
|
+
If the icon name ends with Active or Inactive:
|
|
1344
|
+
|
|
1345
|
+
1. Remove the suffix from the icon name
|
|
1346
|
+
2. Add the active prop for icons with Active suffix
|
|
1347
|
+
|
|
1348
|
+
**Example:**
|
|
1349
|
+
|
|
1350
|
+
```tsx
|
|
1351
|
+
// ❌ Before
|
|
1352
|
+
<Icon name="bellActive" />
|
|
1353
|
+
<Icon name="heartInactive" />
|
|
1354
|
+
<Button startIcon="bellActive" endIcon="heartInactive" />
|
|
1355
|
+
|
|
1356
|
+
// ✅ After
|
|
1357
|
+
<Icon name="bell" active />
|
|
1358
|
+
<Icon name="heart" />
|
|
1359
|
+
<Button startIcon="bell" startIconActive endIcon="heart" />
|
|
1360
|
+
```
|
|
1361
|
+
|
|
1362
|
+
#### Migrating bordered Icon Prop
|
|
1363
|
+
|
|
1364
|
+
_Related to [Removed bordered Prop](#icon-updates) mentioned above_
|
|
1365
|
+
|
|
1366
|
+
**Steps:**
|
|
1367
|
+
|
|
1368
|
+
1. Find all instances using regex: `<Icon\s+[^>]*\bbordered\b[^>]*>`
|
|
1369
|
+
2. Remove the `bordered` prop
|
|
1370
|
+
3. Wrap the Icon in a bordered Box
|
|
1371
|
+
|
|
1372
|
+
**Example:**
|
|
1373
|
+
|
|
1374
|
+
```tsx
|
|
1375
|
+
// ❌ Before
|
|
1376
|
+
<Icon name="info" bordered />
|
|
1377
|
+
|
|
1378
|
+
// ✅ After
|
|
1379
|
+
<Box bordered borderRadius={1000} borderColor="fgPrimary">
|
|
1380
|
+
<Icon name="info" />
|
|
1381
|
+
</Box>
|
|
1382
|
+
```
|
|
1383
|
+
|
|
1384
|
+
### Component Migration Instructions
|
|
1385
|
+
|
|
1386
|
+
_See [Component Updates](#component-updates) for overview_
|
|
1387
|
+
|
|
1388
|
+
#### Migrating NavigationIcon/NavigationIconButton
|
|
1389
|
+
|
|
1390
|
+
_Related to [Removed Components](#component-updates) mentioned above_
|
|
1391
|
+
|
|
1392
|
+
**Steps:**
|
|
1393
|
+
|
|
1394
|
+
1. Remove imports:
|
|
1395
|
+
```tsx
|
|
1396
|
+
import { NavigationIcon } from '@coinbase/cds-web/icons';
|
|
1397
|
+
import { NavigationIconButton } from '@coinbase/cds-web/buttons';
|
|
1398
|
+
```
|
|
1399
|
+
2. Replace with:
|
|
1400
|
+
```tsx
|
|
1401
|
+
import { Icon } from '@coinbase/cds-web/icons';
|
|
1402
|
+
import { IconButton } from '@coinbase/cds-web/buttons/IconButton';
|
|
1403
|
+
```
|
|
1404
|
+
3. Update component usage:
|
|
1405
|
+
|
|
1406
|
+
```tsx
|
|
1407
|
+
// ❌ Before
|
|
1408
|
+
<NavigationIcon name="home" />
|
|
1409
|
+
<NavigationIconButton name="settings" onClick={handleClick} />
|
|
1410
|
+
|
|
1411
|
+
// ✅ After
|
|
1412
|
+
<Icon name="home" />
|
|
1413
|
+
<IconButton name="settings" onClick={handleClick} />
|
|
1414
|
+
```
|
|
1415
|
+
|
|
1416
|
+
#### Migrating InteractableContent
|
|
1417
|
+
|
|
1418
|
+
_Related to [Removed Components](#component-updates) mentioned above_
|
|
1419
|
+
|
|
1420
|
+
**Steps:**
|
|
1421
|
+
|
|
1422
|
+
1. Remove import: `import { InteractableContent } from '@coinbase/cds-web/system';`
|
|
1423
|
+
2. Import Interactable: `import { Interactable } from '@coinbase/cds-web/system';`
|
|
1424
|
+
3. Replace all usage: `<InteractableContent>` → `<Interactable>`
|
|
1425
|
+
|
|
1426
|
+
#### Migrating Responsive Props
|
|
1427
|
+
|
|
1428
|
+
_Related to [Responsive Props](#component-updates) mentioned above_
|
|
1429
|
+
|
|
1430
|
+
The `responsiveConfig` prop migration is automated by the migration script, but here's the pattern:
|
|
1431
|
+
|
|
1432
|
+
```tsx
|
|
1433
|
+
// ❌ Before
|
|
1434
|
+
const responsiveConfig = { desktop: { gap: 2 }, tablet: { gap: 3 } };
|
|
1435
|
+
<Box responsiveConfig={responsiveConfig}>Content</Box>
|
|
1436
|
+
|
|
1437
|
+
// ✅ After
|
|
1438
|
+
<Box gap={{ desktop: 2, tablet: 3 }}>Content</Box>
|
|
1439
|
+
```
|
|
1440
|
+
|
|
1441
|
+
#### Migrating Breakpoints & Media Queries
|
|
1442
|
+
|
|
1443
|
+
_Related to [Breakpoints & Media Queries](#component-updates) mentioned above_
|
|
1444
|
+
|
|
1445
|
+
**Steps:**
|
|
1446
|
+
|
|
1447
|
+
1. Update import paths
|
|
1448
|
+
2. Update breakpoint values (note the changes)
|
|
1449
|
+
|
|
1450
|
+
```tsx
|
|
1451
|
+
// ❌ Before (v7)
|
|
1452
|
+
import { deviceBreakpoints, deviceMqs } from '@coinbase/cds-web/layout/breakpoints';
|
|
1453
|
+
|
|
1454
|
+
// ✅ After (v8)
|
|
1455
|
+
import { breakpoints, media } from '@coinbase/cds-web/styles/media';
|
|
1456
|
+
```
|
|
1457
|
+
|
|
1458
|
+
**Note:** Breakpoint values have changed. For example, `phone` now starts at `0` and `media.phone` is a `max-width` query.
|
|
1459
|
+
|
|
1460
|
+
#### Migrating overflowClassName
|
|
1461
|
+
|
|
1462
|
+
_Related to [Removed Utilities](#component-updates) mentioned above_
|
|
1463
|
+
|
|
1464
|
+
**Steps:**
|
|
1465
|
+
|
|
1466
|
+
1. Remove the import of `overflowClassName`
|
|
1467
|
+
2. Replace with equivalent CSS styles
|
|
1468
|
+
|
|
1469
|
+
```tsx
|
|
1470
|
+
// ❌ Before (v7)
|
|
1471
|
+
import { overflowClassName } from '@coinbase/cds-web/cells/Cell';
|
|
1472
|
+
|
|
1473
|
+
// ✅ After (v8)
|
|
1474
|
+
const overflowStyles = {
|
|
1475
|
+
overflow: 'auto',
|
|
1476
|
+
textOverflow: 'unset',
|
|
1477
|
+
whiteSpace: 'normal',
|
|
1478
|
+
};
|
|
1479
|
+
```
|
|
1480
|
+
|
|
1481
|
+
### Type Migration Instructions
|
|
1482
|
+
|
|
1483
|
+
_See [Type Updates](#type-updates) for overview_
|
|
1484
|
+
|
|
1485
|
+
#### Migrating Polymorphic Component Types
|
|
1486
|
+
|
|
1487
|
+
_Related to [Polymorphic Component Props](#type-updates) mentioned above_
|
|
1488
|
+
|
|
1489
|
+
**BoxElement:**
|
|
1490
|
+
|
|
1491
|
+
```tsx
|
|
1492
|
+
// ❌ Before (v7)
|
|
1493
|
+
import { BoxElement } from '@coinbase/cds-web/layout/Box';
|
|
1494
|
+
type MyProps = { as?: BoxElement };
|
|
1495
|
+
|
|
1496
|
+
// ✅ After (v8) - Option 1
|
|
1497
|
+
import { BoxDefaultElement } from '@coinbase/cds-web/layout/Box';
|
|
1498
|
+
type MyProps = VStackProps<BoxDefaultElement>;
|
|
1499
|
+
|
|
1500
|
+
// ✅ After (v8) - Option 2
|
|
1501
|
+
type MyProps = { as?: keyof JSX.IntrinsicElements };
|
|
1502
|
+
```
|
|
1503
|
+
|
|
1504
|
+
**TextProps:**
|
|
1505
|
+
|
|
1506
|
+
```tsx
|
|
1507
|
+
// ❌ Before (v7)
|
|
1508
|
+
import { TextProps } from '@coinbase/cds-web/typography/Text';
|
|
1509
|
+
|
|
1510
|
+
// ✅ After (v8)
|
|
1511
|
+
import { TextProps, TextDefaultElement } from '@coinbase/cds-web/typography/Text';
|
|
1512
|
+
|
|
1513
|
+
// Usage
|
|
1514
|
+
type MyProps = {
|
|
1515
|
+
textProps: TextProps<'h1'>; // specific element
|
|
1516
|
+
defaultTextProps: TextProps<TextDefaultElement>; // default element
|
|
1517
|
+
};
|
|
1518
|
+
```
|
|
1519
|
+
|
|
1520
|
+
**LinkTypography:**
|
|
1521
|
+
|
|
1522
|
+
```tsx
|
|
1523
|
+
// ❌ Before (v7)
|
|
1524
|
+
import { LinkTypography } from '@coinbase/cds-common/types/LinkBaseProps';
|
|
1525
|
+
type FontProp = LinkTypography;
|
|
1526
|
+
|
|
1527
|
+
// ✅ After (v8)
|
|
1528
|
+
import { LinkProps, LinkDefaultElement } from '@coinbase/cds-web/typography/Link';
|
|
1529
|
+
type FontProp = LinkProps<LinkDefaultElement>['font'];
|
|
1530
|
+
```
|
|
1531
|
+
|
|
1532
|
+
#### Migrating Removed Types
|
|
1533
|
+
|
|
1534
|
+
_Related to [Removed Types](#type-updates) mentioned above_
|
|
1535
|
+
|
|
1536
|
+
**HTMLNonHeadingTextTags:**
|
|
1537
|
+
|
|
1538
|
+
```tsx
|
|
1539
|
+
// ❌ Before (v7)
|
|
1540
|
+
import { HTMLNonHeadingTextTags } from '@coinbase/cds-web/typography';
|
|
1541
|
+
|
|
1542
|
+
// ✅ After (v8) - Define locally
|
|
1543
|
+
type HTMLNonHeadingTextTags = 'p' | 'span' | 'div' | 'label' | 'legend' | 'caption';
|
|
1544
|
+
```
|
|
1545
|
+
|
|
1546
|
+
**NoopFn:**
|
|
1547
|
+
|
|
1548
|
+
```tsx
|
|
1549
|
+
// ❌ Before (v7)
|
|
1550
|
+
import { NoopFn } from '@coinbase/cds-common/utils/mockUtils';
|
|
1551
|
+
|
|
1552
|
+
// ✅ After (v8)
|
|
1553
|
+
type NoopFn = () => void;
|
|
1554
|
+
```
|
|
1555
|
+
|
|
1556
|
+
**SetState:**
|
|
1557
|
+
|
|
1558
|
+
```tsx
|
|
1559
|
+
// ❌ Before (v7)
|
|
1560
|
+
import { SetState } from '@coinbase/cds-common/types';
|
|
1561
|
+
|
|
1562
|
+
// ✅ After (v8)
|
|
1563
|
+
type SetState<T> = React.Dispatch<React.SetStateAction<T>>;
|
|
1564
|
+
```
|
|
1565
|
+
|
|
1566
|
+
**Overflow:**
|
|
1567
|
+
|
|
1568
|
+
```tsx
|
|
1569
|
+
// ❌ Before (v7)
|
|
1570
|
+
import { Overflow } from '@coinbase/cds-web/types';
|
|
1571
|
+
|
|
1572
|
+
// ✅ After (v8)
|
|
1573
|
+
type Overflow = {
|
|
1574
|
+
overflow?: 'visible' | 'hidden' | 'scroll' | 'auto' | 'clip';
|
|
1575
|
+
};
|
|
1576
|
+
```
|
|
1577
|
+
|
|
1578
|
+
**IconPixelSize:**
|
|
1579
|
+
|
|
1580
|
+
```tsx
|
|
1581
|
+
// ❌ Before (v7)
|
|
1582
|
+
import { IconPixelSize } from '@coinbase/cds-common/types/IconSize';
|
|
1583
|
+
|
|
1584
|
+
// ✅ After (v8)
|
|
1585
|
+
type IconPixelSize = 8 | 12 | 16 | 24 | 32;
|
|
1586
|
+
```
|
|
1587
|
+
|
|
1588
|
+
**GapSpacing:**
|
|
1589
|
+
|
|
1590
|
+
```tsx
|
|
1591
|
+
// ❌ Before (v7)
|
|
1592
|
+
import { GapSpacing } from '@coinbase/cds-common/types/TooltipBaseProps';
|
|
1593
|
+
|
|
1594
|
+
// ✅ After (v8)
|
|
1595
|
+
import type { ThemeVars } from '@coinbase/cds-common/core/theme';
|
|
1596
|
+
type GapSpacing = ThemeVars.Space;
|
|
1597
|
+
```
|
|
1598
|
+
|
|
1599
|
+
### Hook Migration Instructions
|
|
1600
|
+
|
|
1601
|
+
_Cross-references to various sections above_
|
|
1602
|
+
|
|
1603
|
+
#### Migrating useAccessibleForeground
|
|
1604
|
+
|
|
1605
|
+
<Tag intent="promotional">Migration Script ✓</Tag>
|
|
1606
|
+
|
|
1607
|
+
_Related to color token changes in [Token Updates](#token-updates)_
|
|
1608
|
+
|
|
1609
|
+
```tsx
|
|
1610
|
+
// ❌ Before (v7)
|
|
1611
|
+
import { useAccessibleForeground } from '@coinbase/cds-web/color/useAccessibleForeground';
|
|
1612
|
+
|
|
1613
|
+
const MyComponent = () => {
|
|
1614
|
+
const backgroundColor = 'rgb(255, 0, 0)';
|
|
1615
|
+
const foregroundColor = useAccessibleForeground({
|
|
1616
|
+
background: backgroundColor,
|
|
1617
|
+
color: 'auto',
|
|
1618
|
+
usage: 'normalText',
|
|
1619
|
+
});
|
|
1620
|
+
|
|
1621
|
+
return <div style={{ backgroundColor, color: foregroundColor }}>Content</div>;
|
|
1622
|
+
};
|
|
1623
|
+
|
|
1624
|
+
// ✅ After (v8)
|
|
1625
|
+
import { getAccessibleColor } from '@coinbase/cds-common/utils/getAccessibleColor';
|
|
1626
|
+
|
|
1627
|
+
const MyComponent = () => {
|
|
1628
|
+
const backgroundColor = 'rgb(255, 0, 0)';
|
|
1629
|
+
const foregroundColor = getAccessibleColor({
|
|
1630
|
+
background: backgroundColor,
|
|
1631
|
+
foreground: 'auto', // Can only be 'auto' or undefined
|
|
1632
|
+
usage: 'normalText',
|
|
1633
|
+
});
|
|
1634
|
+
|
|
1635
|
+
return <div style={{ backgroundColor, color: foregroundColor }}>Content</div>;
|
|
1636
|
+
};
|
|
1637
|
+
```
|
|
1638
|
+
|
|
1639
|
+
#### Migrating useMergedRef
|
|
1640
|
+
|
|
1641
|
+
```tsx
|
|
1642
|
+
// ❌ Before (v7)
|
|
1643
|
+
import { useMergedRef } from '@coinbase/cds-common/hooks/useMergedRef';
|
|
1644
|
+
const mergedRef = useMergedRef(ref1, ref2);
|
|
1645
|
+
|
|
1646
|
+
// ✅ After (v8)
|
|
1647
|
+
import { useMergeRefs } from '@coinbase/cds-common/hooks/useMergeRefs';
|
|
1648
|
+
const mergedRef = useMergeRefs(ref1, ref2);
|
|
1649
|
+
```
|
|
1650
|
+
|
|
1651
|
+
#### Migrating useToggler
|
|
1652
|
+
|
|
1653
|
+
```tsx
|
|
1654
|
+
// ❌ Before (v7)
|
|
1655
|
+
import { useToggler } from '@coinbase/cds-common/hooks/useToggler';
|
|
1656
|
+
const [isOpen, toggleIsOpen] = useToggler(false);
|
|
1657
|
+
|
|
1658
|
+
// ✅ After (v8)
|
|
1659
|
+
import React from 'react';
|
|
1660
|
+
const [isOpen, setIsOpen] = React.useState(false);
|
|
1661
|
+
const toggleIsOpen = () => setIsOpen((prev) => !prev);
|
|
1662
|
+
```
|
|
1663
|
+
|
|
1664
|
+
#### Migrating useSpectrumConditional
|
|
1665
|
+
|
|
1666
|
+
_Related to theming changes in [Theming Updates](#theming-updates)_
|
|
1667
|
+
|
|
1668
|
+
```tsx
|
|
1669
|
+
// ❌ Before (v7)
|
|
1670
|
+
import { useSpectrumConditional } from '@coinbase/cds-common/hooks/useSpectrumConditional';
|
|
1671
|
+
const value = useSpectrumConditional(config);
|
|
1672
|
+
|
|
1673
|
+
// ✅ After (v8)
|
|
1674
|
+
import { useTheme } from '@coinbase/cds-web/hooks/useTheme';
|
|
1675
|
+
const theme = useTheme();
|
|
1676
|
+
const value = config(theme.activeColorScheme);
|
|
1677
|
+
```
|
|
1678
|
+
|
|
1679
|
+
#### Migrating useInteractableHeight
|
|
1680
|
+
|
|
1681
|
+
```tsx
|
|
1682
|
+
// ❌ Before (v7)
|
|
1683
|
+
import { useInteractableHeight } from '@coinbase/cds-common/hooks/useInteractableHeight';
|
|
1684
|
+
const height = useInteractableHeight(compact);
|
|
1685
|
+
|
|
1686
|
+
// ✅ After (v8)
|
|
1687
|
+
import { interactableHeight } from '@coinbase/cds-common/tokens/interactableHeight';
|
|
1688
|
+
const height = compact ? interactableHeight.compact : interactableHeight.regular;
|
|
1689
|
+
```
|
|
1690
|
+
|
|
1691
|
+
#### Migrating useIconSize
|
|
1692
|
+
|
|
1693
|
+
```tsx
|
|
1694
|
+
// ❌ Before (v7)
|
|
1695
|
+
import { useIconSize } from '@coinbase/cds-web/hooks/useIconSize';
|
|
1696
|
+
const { iconSize } = useIconSize(size);
|
|
1697
|
+
|
|
1698
|
+
// ✅ After (v8)
|
|
1699
|
+
import { useTheme } from '@coinbase/cds-web/hooks/useTheme';
|
|
1700
|
+
const theme = useTheme();
|
|
1701
|
+
const iconSize = theme.iconSize[size];
|
|
1702
|
+
```
|
|
1703
|
+
|
|
1704
|
+
#### Migrating useAvatarSize
|
|
1705
|
+
|
|
1706
|
+
```tsx
|
|
1707
|
+
// ❌ Before (v7)
|
|
1708
|
+
import { useAvatarSize } from '@coinbase/cds-mobile/hooks/useAvatarSize';
|
|
1709
|
+
const avatarSize = useAvatarSize(size);
|
|
1710
|
+
|
|
1711
|
+
// ✅ After (v8)
|
|
1712
|
+
import { useTheme } from '@coinbase/cds-mobile/hooks/useTheme';
|
|
1713
|
+
const theme = useTheme();
|
|
1714
|
+
const avatarSize = theme.avatarSize[size];
|
|
1715
|
+
```
|
|
1716
|
+
|
|
1717
|
+
#### Migrating Scale-Related Hooks (No Direct Replacement)
|
|
1718
|
+
|
|
1719
|
+
_Related to scale system removal in [Theming Updates](#scaledensity-system-removed)_
|
|
1720
|
+
|
|
1721
|
+
**useScale:**
|
|
1722
|
+
|
|
1723
|
+
```tsx
|
|
1724
|
+
// ❌ Before (v7) - Scale-based rendering
|
|
1725
|
+
const MyComponent = () => {
|
|
1726
|
+
const scale = useScale();
|
|
1727
|
+
if (scale === 'xSmall') {
|
|
1728
|
+
return <CompactLayout />;
|
|
1729
|
+
}
|
|
1730
|
+
return <NormalLayout />;
|
|
1731
|
+
};
|
|
1732
|
+
|
|
1733
|
+
// ✅ After (v8) - Direct component choice or user preference
|
|
1734
|
+
const MyComponent = ({ isCompact }: { isCompact?: boolean }) => {
|
|
1735
|
+
if (isCompact) {
|
|
1736
|
+
return <CompactLayout />;
|
|
1737
|
+
}
|
|
1738
|
+
return <NormalLayout />;
|
|
1739
|
+
};
|
|
1740
|
+
|
|
1741
|
+
// Or custom theme-based detection
|
|
1742
|
+
const useIsDenseTheme = () => {
|
|
1743
|
+
const theme = useTheme();
|
|
1744
|
+
return theme.id === 'dense-theme' || theme.space[2] < 16;
|
|
1745
|
+
};
|
|
1746
|
+
```
|
|
1747
|
+
|
|
1748
|
+
**useScaleConditional:**
|
|
1749
|
+
|
|
1750
|
+
```tsx
|
|
1751
|
+
// ❌ Before (v7)
|
|
1752
|
+
import { useScaleConditional } from '@coinbase/cds-common/scale/useScaleConditional';
|
|
1753
|
+
const size = useScaleConditional(mediaSize);
|
|
1754
|
+
|
|
1755
|
+
// ✅ After (v8)
|
|
1756
|
+
const size = mediaSize.normal; // Access values directly
|
|
1757
|
+
```
|
|
1758
|
+
|
|
1759
|
+
</MDXArticle>
|
|
1760
|
+
</MDXSection>
|
|
1761
|
+
|
|
1762
|
+
</VStack>
|