gluestack-nativewind
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseGluestack NativeWind Design Patterns
Gluestack NativeWind 设计模式
This skill enforces constrained, opinionated styling patterns that reduce decision fatigue, improve performance, enable consistent theming, and limit the solution space to canonical patterns.
本技能强制执行受限的、约定式的样式模式,以减少决策疲劳、提升性能、实现一致的主题化,并将解决方案范围限定为标准模式。
Core Principles
核心原则
- Gluestack components over React Native primitives - Gluestack wraps RN with theming, accessibility, and cross-platform consistency
- Semantic tokens over arbitrary values - Tokens encode intent, not just appearance
- className over inline styles - Inline styles bypass optimization and consistency
- Spacing scale over pixel values - Arbitrary values create unsustainable exceptions
- Remove dead code - Unused patterns mislead AI and increase cognitive load
- 优先使用Gluestack组件而非React Native原生组件 - Gluestack为RN组件封装了主题化、无障碍支持和跨平台一致性特性
- 优先使用语义化令牌而非任意值 - 令牌编码的是设计意图,而非单纯的外观
- 优先使用className而非内联样式 - 内联样式会绕过优化机制,破坏一致性
- 优先使用间距刻度而非像素值 - 任意值会导致难以维护的例外情况
- 移除无用代码 - 未使用的模式会误导AI,增加认知负担
When to Use This Skill
何时使用本技能
- Creating new components with styling
- Reviewing existing component styles
- Refactoring styles to follow the design system
- Fixing styling inconsistencies
- Adding dark mode support
- Theming components
- 创建带样式的新组件
- 评审现有组件的样式
- 重构样式以遵循设计系统
- 修复样式不一致问题
- 添加深色模式支持
- 为组件配置主题
Rule 1: Gluestack Components Over React Native Primitives
规则1:优先使用Gluestack组件而非React Native原生组件
Always use Gluestack components instead of direct React Native imports:
| React Native | Gluestack Equivalent |
|---|---|
| |
| |
| |
| |
| |
| |
| |
始终使用Gluestack组件,而非直接导入React Native组件:
| React Native | Gluestack 等效组件 |
|---|---|
| |
| |
| |
| |
| |
| |
| |
Correct Pattern
正确示例
tsx
import { Box } from "@/components/ui/box";
import { Text } from "@/components/ui/text";
import { Pressable } from "@/components/ui/pressable";
const Component = () => (
<Box className="p-4">
<Text className="text-typography-900">Hello</Text>
<Pressable onPress={handlePress}>
<Text>Press Me</Text>
</Pressable>
</Box>
);tsx
import { Box } from "@/components/ui/box";
import { Text } from "@/components/ui/text";
import { Pressable } from "@/components/ui/pressable";
const Component = () => (
<Box className="p-4">
<Text className="text-typography-900">Hello</Text>
<Pressable onPress={handlePress}>
<Text>Press Me</Text>
</Pressable>
</Box>
);Incorrect Pattern
错误示例
tsx
import { View, Text, TouchableOpacity } from "react-native";
const Component = () => (
<View style={{ padding: 16 }}>
<Text style={{ color: "#333" }}>Hello</Text>
<TouchableOpacity onPress={handlePress}>
<Text>Press Me</Text>
</TouchableOpacity>
</View>
);tsx
import { View, Text, TouchableOpacity } from "react-native";
const Component = () => (
<View style={{ padding: 16 }}>
<Text style={{ color: "#333" }}>Hello</Text>
<TouchableOpacity onPress={handlePress}>
<Text>Press Me</Text>
</TouchableOpacity>
</View>
);Exceptions
例外情况
- Platform-specific code where RN primitives are explicitly required
- Deep integration with native modules
- Performance-critical paths where wrapper overhead matters (rare, must document)
- 明确需要使用RN原生组件的平台特定代码
- 与原生模块深度集成的场景
- 对性能要求极高的路径(罕见情况,必须添加文档说明)
Rule 2: Semantic Color Tokens Over Raw Values
规则2:优先使用语义化颜色令牌而非原始值
Use Gluestack semantic tokens instead of raw Tailwind colors:
| Instead of | Use |
|---|---|
| |
| |
| |
| |
| |
| |
| |
| |
使用Gluestack语义化令牌,而非原始Tailwind颜色:
| 避免使用 | 推荐使用 |
|---|---|
| |
| |
| |
| |
| |
| |
| |
| |
Available Semantic Token Categories
可用的语义化令牌类别
| Token | Purpose | Scale |
|---|---|---|
| Brand identity, key interactive elements | 0-950 |
| Secondary actions, supporting elements | 0-950 |
| Tertiary accents | 0-950 |
| Validation errors, destructive actions | 0-950 |
| Positive feedback, completions | 0-950 |
| Alerts, attention-required states | 0-950 |
| Informational content | 0-950 |
| Text colors | 0-950 |
| Border colors | 0-950 |
| Background colors | 0-950 |
| 令牌 | 用途 | 范围 |
|---|---|---|
| 品牌标识、核心交互元素 | 0-950 |
| 次要操作、辅助元素 | 0-950 |
| 三级强调色 | 0-950 |
| 验证错误、破坏性操作 | 0-950 |
| 正向反馈、完成状态 | 0-950 |
| 警告、需要关注的状态 | 0-950 |
| 信息类内容 | 0-950 |
| 文本颜色 | 0-950 |
| 边框颜色 | 0-950 |
| 背景颜色 | 0-950 |
Special Background Tokens
特殊背景令牌
Use state-based background tokens:
- - Error state backgrounds
bg-background-error - - Warning state backgrounds
bg-background-warning - - Success state backgrounds
bg-background-success - - Muted/disabled backgrounds
bg-background-muted - - Informational backgrounds
bg-background-info
使用基于状态的背景令牌:
- - 错误状态背景
bg-background-error - - 警告状态背景
bg-background-warning - - 成功状态背景
bg-background-success - - 弱化/禁用状态背景
bg-background-muted - - 信息类背景
bg-background-info
Correct Pattern
正确示例
tsx
<Box className="bg-error-500">
<Text className="text-typography-0">Error message</Text>
</Box>
<Box className="border border-outline-300 bg-background-50">
<Text className="text-success-600">Success!</Text>
</Box>tsx
<Box className="bg-error-500">
<Text className="text-typography-0">Error message</Text>
</Box>
<Box className="border border-outline-300 bg-background-50">
<Text className="text-success-600">Success!</Text>
</Box>Incorrect Pattern
错误示例
tsx
<Box className="bg-red-500">
<Text className="text-white">Error message</Text>
</Box>
<Box style={{ backgroundColor: '#DC2626' }}>
<Text style={{ color: 'green' }}>Success!</Text>
</Box>For complete token reference, see .
references/color-tokens.mdtsx
<Box className="bg-red-500">
<Text className="text-white">Error message</Text>
</Box>
<Box style={{ backgroundColor: '#DC2626' }}>
<Text style={{ color: 'green' }}>Success!</Text>
</Box>完整的令牌参考请查看 。
references/color-tokens.mdRule 3: No Inline Styles
规则3:禁止使用内联样式
Avoid inline props when className can achieve the same result.
style当可以通过className实现相同效果时,避免使用内联属性。
styleResolution Hierarchy (in order of preference)
解决方案优先级(从高到低)
- className utilities - Use existing Tailwind/NativeWind classes
- Gluestack component variants - Use built-in component variants
- tva (Tailwind Variant Authority) - Create reusable variant patterns
- NativeWind interop - Enable className on third-party components
- Inline styles - Only as absolute last resort with documented justification
- className工具类 - 使用现有的Tailwind/NativeWind类
- Gluestack组件变体 - 使用内置的组件变体
- tva(Tailwind Variant Authority) - 创建可复用的变体模式
- NativeWind互操作 - 为第三方组件启用className支持
- 内联样式 - 仅作为最后的手段,且必须添加文档说明理由
Correct Pattern
正确示例
tsx
<Box className="w-20 h-20 rounded-full bg-background-100" />
<Text className="text-lg font-bold text-typography-900" />tsx
<Box className="w-20 h-20 rounded-full bg-background-100" />
<Text className="text-lg font-bold text-typography-900" />Incorrect Pattern
错误示例
tsx
<Box
style={{
width: 80,
height: 80,
borderRadius: 40,
backgroundColor: "rgba(255, 255, 255, 0.1)",
}}
/>tsx
<Box
style={{
width: 80,
height: 80,
borderRadius: 40,
backgroundColor: "rgba(255, 255, 255, 0.1)",
}}
/>Acceptable Exceptions
可接受的例外情况
Inline styles are acceptable for:
- Dynamic values - Values computed at runtime (e.g., animation values, safe area insets)
- Third-party component requirements - Components that don't support className
- Platform-specific overrides - When Platform.select is needed
tsx
// Acceptable: dynamic value from hook
<Box style={{ paddingBottom: bottomInset }} />
// Acceptable: animation value
<Animated.View style={{ transform: [{ translateX: animatedValue }] }} />内联样式可用于以下场景:
- 动态值 - 运行时计算的值(如动画值、安全区域内边距)
- 第三方组件要求 - 不支持className的第三方组件
- 平台特定覆盖 - 需要使用Platform.select的场景
tsx
// 可接受:来自hook的动态值
<Box style={{ paddingBottom: bottomInset }} />
// 可接受:动画值
<Animated.View style={{ transform: [{ translateX: animatedValue }] }} />Rule 4: Spacing Scale Adherence
规则4:遵循间距刻度
Use only values from the standard spacing scale. Arbitrary values create maintenance burden.
仅使用标准间距刻度中的值。任意值会增加维护负担。
Allowed Spacing Values
允许的间距值
| Class | Size |
|---|---|
| 0px |
| 2px |
| 4px |
| 6px |
| 8px |
| 10px |
| 12px |
| 14px |
| 16px |
| 20px |
| 24px |
| 28px |
| 32px |
| 36px |
| 40px |
| 44px |
| 48px |
| 56px |
| 64px |
| 80px |
| 96px |
| 112px |
| 128px |
| 144px |
| 160px |
| 176px |
| 192px |
| 208px |
| 224px |
| 240px |
| 256px |
| 288px |
| 320px |
| 384px |
| 类名 | 像素值 |
|---|---|
| 0px |
| 2px |
| 4px |
| 6px |
| 8px |
| 10px |
| 12px |
| 14px |
| 16px |
| 20px |
| 24px |
| 28px |
| 32px |
| 36px |
| 40px |
| 44px |
| 48px |
| 56px |
| 64px |
| 80px |
| 96px |
| 112px |
| 128px |
| 144px |
| 160px |
| 176px |
| 192px |
| 208px |
| 224px |
| 240px |
| 256px |
| 288px |
| 320px |
| 384px |
Prohibited Patterns
禁止的模式
- Arbitrary values: ,
p-[13px],m-[27px]gap-[15px] - Non-scale decimals: ,
p-2.7m-4.3
- 任意值:,
p-[13px],m-[27px]gap-[15px] - 非刻度内的小数:,
p-2.7m-4.3
Correct Pattern
正确示例
tsx
<Box className="p-4 m-2 gap-3" />
<Box className="px-6 py-4 mt-8" />tsx
<Box className="p-4 m-2 gap-3" />
<Box className="px-6 py-4 mt-8" />Incorrect Pattern
错误示例
tsx
<Box className="p-[13px] m-[27px]" />
<Box style={{ padding: 13, margin: 27 }} />For complete spacing reference, see .
references/spacing-scale.mdtsx
<Box className="p-[13px] m-[27px]" />
<Box style={{ padding: 13, margin: 27 }} />完整的间距参考请查看 。
references/spacing-scale.mdRule 5: Dark Mode Using CSS Variables
规则5:使用CSS变量实现深色模式
Use the CSS variables approach with prefix for dark mode support.
dark:使用带前缀的CSS变量方式来支持深色模式。
dark:Correct Pattern
正确示例
tsx
<Box className="bg-background-0 dark:bg-background-950" />
<Text className="text-typography-900 dark:text-typography-0" />tsx
<Box className="bg-background-0 dark:bg-background-950" />
<Text className="text-typography-900 dark:text-typography-0" />Component-Level Dark Mode
组件级深色模式
tsx
const CardView = ({ isDark }: { readonly isDark: boolean }) => (
<Box className={isDark ? "bg-background-950" : "bg-background-0"}>
<Text className={isDark ? "text-typography-0" : "text-typography-900"}>
Content
</Text>
</Box>
);tsx
const CardView = ({ isDark }: { readonly isDark: boolean }) => (
<Box className={isDark ? "bg-background-950" : "bg-background-0"}>
<Text className={isDark ? "text-typography-0" : "text-typography-900"}>
Content
</Text>
</Box>
);Rule 6: Gluestack Sub-Component Pattern
规则6:Gluestack子组件模式
Use Gluestack's composable sub-component pattern for complex components.
对于复杂组件,使用Gluestack的可组合子组件模式。
Correct Pattern
正确示例
tsx
<Button action="primary" size="md">
<ButtonText>Click Me</ButtonText>
<ButtonIcon as={ChevronRightIcon} />
</Button>
<Input variant="outline" size="md">
<InputField placeholder="Enter text" />
<InputSlot>
<InputIcon as={SearchIcon} />
</InputSlot>
</Input>
<Select>
<SelectTrigger>
<SelectInput placeholder="Select option" />
<SelectIcon as={ChevronDownIcon} />
</SelectTrigger>
<SelectPortal>
<SelectBackdrop />
<SelectContent>
<SelectItem label="Option 1" value="1" />
<SelectItem label="Option 2" value="2" />
</SelectContent>
</SelectPortal>
</Select>tsx
<Button action="primary" size="md">
<ButtonText>Click Me</ButtonText>
<ButtonIcon as={ChevronRightIcon} />
</Button>
<Input variant="outline" size="md">
<InputField placeholder="Enter text" />
<InputSlot>
<InputIcon as={SearchIcon} />
</InputSlot>
</Input>
<Select>
<SelectTrigger>
<SelectInput placeholder="Select option" />
<SelectIcon as={ChevronDownIcon} />
</SelectTrigger>
<SelectPortal>
<SelectBackdrop />
<SelectContent>
<SelectItem label="Option 1" value="1" />
<SelectItem label="Option 2" value="2" />
</SelectContent>
</SelectPortal>
</Select>Incorrect Pattern
错误示例
tsx
// Missing sub-components
<Button>Click Me</Button>
// Text must be wrapped in ButtonText
<Button>
Click Me {/* Will not render correctly */}
</Button>tsx
// 缺少子组件
<Button>Click Me</Button>
// 文本必须包裹在ButtonText中
<Button>
Click Me {/* 无法正确渲染 */}
</Button>Rule 7: Variant-Based Styling with tva
规则7:使用tva实现基于变体的样式
For components with multiple style variants, use (Tailwind Variant Authority).
tva对于有多组样式变体的组件,使用(Tailwind Variant Authority)。
tvaCorrect Pattern
正确示例
tsx
import { tva } from "@gluestack-ui/nativewind-utils/tva";
const cardStyles = tva({
base: "rounded-lg p-4",
variants: {
variant: {
elevated: "bg-background-0 shadow-hard-2",
outlined: "bg-transparent border border-outline-200",
filled: "bg-background-50",
},
size: {
sm: "p-2",
md: "p-4",
lg: "p-6",
},
},
defaultVariants: {
variant: "elevated",
size: "md",
},
});
const Card = ({ variant, size, className }: CardProps) => (
<Box className={cardStyles({ variant, size, className })} />
);tsx
import { tva } from "@gluestack-ui/nativewind-utils/tva";
const cardStyles = tva({
base: "rounded-lg p-4",
variants: {
variant: {
elevated: "bg-background-0 shadow-hard-2",
outlined: "bg-transparent border border-outline-200",
filled: "bg-background-50",
},
size: {
sm: "p-2",
md: "p-4",
lg: "p-6",
},
},
defaultVariants: {
variant: "elevated",
size: "md",
},
});
const Card = ({ variant, size, className }: CardProps) => (
<Box className={cardStyles({ variant, size, className })} />
);Rule 8: className Merging for Custom Components
规则8:自定义组件的className合并
Allow className override in custom components using string concatenation.
通过字符串拼接允许自定义组件的className覆盖。
Correct Pattern
正确示例
tsx
interface BoxCardProps {
readonly className?: string;
readonly children: React.ReactNode;
}
const BoxCard = ({ className, children }: BoxCardProps) => (
<Box className={`rounded-lg bg-background-0 p-4 ${className ?? ""}`}>
{children}
</Box>
);tsx
interface BoxCardProps {
readonly className?: string;
readonly children: React.ReactNode;
}
const BoxCard = ({ className, children }: BoxCardProps) => (
<Box className={`rounded-lg bg-background-0 p-4 ${className ?? ""}`}>
{children}
</Box>
);Validation
验证
To validate styling compliance, run:
bash
python3 .claude/skills/gluestack-nativewind/scripts/validate_styling.py [path]The script detects:
- Direct React Native component imports with Gluestack equivalents
- Raw color values without semantic tokens
- Inline style objects where className could be used
- Arbitrary bracket notation values
- Non-scale spacing values
要验证样式合规性,运行以下命令:
bash
python3 .claude/skills/gluestack-nativewind/scripts/validate_styling.py [path]该脚本会检测:
- 直接导入存在Gluestack等效组件的React Native组件
- 未使用语义化令牌的原始颜色值
- 可使用className实现却使用了内联样式的情况
- 任意括号表示法的值
- 非刻度内的间距值
Escalation Guidance
升级指导
When a design request cannot be satisfied with existing patterns:
- Push back early - Explain performance and maintenance implications
- Propose alternatives - Map to existing tokens or suggest new semantic tokens
- Add to design system - If truly needed, add token to tailwind.config.js
- Document exception - If inline style is unavoidable, add JSDoc explaining why
当设计需求无法通过现有模式满足时:
- 尽早反馈 - 说明性能和维护方面的影响
- 提出替代方案 - 映射到现有令牌,或建议新增语义化令牌
- 添加到设计系统 - 如果确实需要,将令牌添加到tailwind.config.js
- 记录例外情况 - 如果必须使用内联样式,添加JSDoc说明理由
Reference Documentation
参考文档
For detailed mappings and complete token lists:
- - Gluestack equivalents for React Native primitives
references/component-mapping.md - - Complete semantic color token reference
references/color-tokens.md - - Allowed spacing values with pixel equivalents
references/spacing-scale.md
如需详细的映射关系和完整的令牌列表:
- - React Native原生组件对应的Gluestack等效组件
references/component-mapping.md - - 完整的语义化颜色令牌参考
references/color-tokens.md - - 允许的间距值及对应的像素等效值
references/spacing-scale.md