用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
直接命令不会经过审查 Prompt;运行前请先检查来源。
npx skills add https://github.com/coinbase/cds --skill dev-cds-mobile命令会保持在同一行。复制前请横向滚动并检查完整内容。
想先保存到本地?可下载 SkillsMP 当前能够提供的文件。
USE THIS when writing or reviewing Jetpack Compose / Kotlin code in packages/cds-android or apps/android-app - @Composable APIs, Modifier parameters, CompositionLocal, state hoisting, or naming. Not for React or React Native work.
Use this skill whenever working on CDS React components in any package.
Deprecates a CDS component, hook, or other exported symbol with consistent JSDoc, version tags, and docsite metadata across every public export path (web, mobile, common, visualization), not only the original package. Use whenever the user asks to deprecate a CDS component or API, mark something as deprecated, add @deprecated / @deprecationExpectedRemoval, or update deprecation warnings in apps/docs metadata under components or hooks (webMetadata.json / mobileMetadata.json / metadata.json). Also use when replacing a component or hook and sunsetting the old one. Always finish by running `yarn nx run <project>:lint` on modified packages so `internal/deprecated-jsdoc-has-removal-version` passes.
基于 SOC 职业分类
正在显示 SKILL.md
| name | dev.cds-mobile |
| description | USE THIS when asked to work on a new or existing (MOBILE) CDS React component in packages/mobile |
Mobile-specific patterns for @coinbase/cds-mobile.
Use this guidance when adding ComponentConfigProvider defaults for the specific component you are editing.
packages/mobile/src/core/componentConfig.ts using its *BaseProps:import type { MyComponentBaseProps } from '../category/MyComponent';
export type ComponentConfig = {
MyComponent?: ConfigResolver<MyComponentBaseProps>;
};
useComponentConfig in the component and destructure from merged props:import { useComponentConfig } from '../hooks/useComponentConfig';
export const MyComponent = memo((_props: MyComponentProps) => {
const mergedProps = useComponentConfig('MyComponent', _props);
const { style, ...props } = mergedProps;
return <Pressable style={style} {...props} />;
});
_props as the input variable and mergedProps as the configured output.*BaseProps (not full *Props).Use StyleSheet.create for static styles and useTheme() for dynamic values:
import { StyleSheet, type StyleProp, type ViewStyle } from 'react-native';
const styles = StyleSheet.create({
container: { position: 'relative', width: '100%' },
});
// Dynamic styles via theme hook
const theme = useTheme();
const dynamicStyle = {
backgroundColor: theme.color.bgPrimary,
padding: theme.space[2],
};
<View style={[styles.container, dynamicStyle, style]} />;
style and styles object props for overriding default styles.style and styles props should never be on the *BaseProps type.styles can be used for granular overrides on child elements within the component.useMemo in the correct order (default styles => style prop => styles[ELEMENT_NAME] prop).Example:
type ComponentProps = ComponentBaseProps & {
style?: StyleProp<ViewStyle>;
styles?: {
root?: StyleProp<ViewStyle>;
label?: StyleProp<TextStyle>;
};
};
const theme = useTheme();
const containerStyles = useMemo(
() => [
{ backgroundColor: theme.color.bgPrimary }, // default styles
style, // from props
styles.root, // from props
],
[theme.color.bgPrimary, animatedStyles, style]
);
// Apply to component
<Box style={containerStyles}>
import Animated, { useAnimatedStyle, useSharedValue, withTiming } from 'react-native-reanimated';
const opacity = useSharedValue(0);
const animatedStyle = useAnimatedStyle(() => ({
opacity: opacity.value,
transform: [{ translateY: withTiming(opacity.value * -8) }],
}));
<Animated.View style={animatedStyle} />;
We DO NOT use React-Spring anymore for animations on mobile.
Use react-native-gesture-handler:
import { Gesture, GestureDetector } from 'react-native-gesture-handler';
const panGesture = useMemo(
() =>
Gesture.Pan()
.onStart(() => {
/* ... */
})
.onUpdate(({ translationX }) => {
/* ... */
})
.onEnd(({ translationX, velocityX }) => {
/* ... */
})
.withTestId(testID)
.runOnJS(true),
[dependencies],
);
<GestureDetector gesture={panGesture}>
<Animated.View>{/* ... */}</Animated.View>
</GestureDetector>;
Use onLayout callback instead of ResizeObserver:
const [size, onLayout] = useLayout();
<View onLayout={onLayout} />
// Or inline
<View onLayout={(e) => setHeight(e.nativeEvent.layout.height)} />
Example: Use React Native accessibility props:
<View
accessible
accessibilityRole="adjustable"
accessibilityLabel="Product carousel"
accessibilityLiveRegion="polite"
>
<Pressable
accessibilityState={{ selected: isActive, disabled }}
accessibilityActions={[{ name: 'activate' }]}
onAccessibilityAction={handleAccessibilityAction}
/>
</View>
// Hide visual content from screen readers
<View accessibilityElementsHidden importantForAccessibility="no-hide-descendants">
{/* Animated/visual content */}
</View>
// Provide accessible alternative
<Text
importantForAccessibility="yes"
accessibilityLiveRegion="polite"
style={{ color: 'transparent', position: 'absolute' }}
>
{accessibleLabel}
</Text>