Agent Capability Analysis
The gluestack-ui-v4:variants skill by bogajoss is an open-source community AI agent skill for Claude Code and other IDE workflows, helping agents execute tasks with better context, repeatability, and domain-specific guidance.
Ideal Agent Persona
Ideal for Frontend Agents requiring customizable UI component styling with type safety
Core Value
Empowers agents to create custom variants for existing gluestack-ui v4 components, maintaining consistency and type safety through project-specific styling patterns, utilizing className patterns and brand-specific design elements like button styles and card types
↓ Capabilities Granted for gluestack-ui-v4:variants
! Prerequisites & Limits
- Requires gluestack-ui v4 components
- Limited to project-specific styling patterns
Browser Sandbox Environment
⚡️ Ready to unleash?
Experience this Agent in a zero-setup browser environment powered by WebContainers. No installation required.
gluestack-ui-v4:variants
Install gluestack-ui-v4:variants, an AI agent skill for AI agent workflows and automation. Works with Claude Code, Cursor, and Windsurf with one-command...
Gluestack UI v4 - Creating Component Variants
This sub-skill focuses on creating custom variants for existing gluestack-ui v4 components, allowing you to extend the design system with project-specific styling patterns while maintaining consistency and type safety.
When to Create a Variant
Create a new variant when:
- Repeating the same style combination - Multiple places use the same className pattern
- Project-specific design patterns - Brand-specific button styles, card types, etc.
- Conditional styling - Component appearance changes based on props
- Extending existing components - Adding new visual styles to Gluestack components
- Theme-specific variations - Different appearances for specific contexts
Don't create variants for:
- One-off custom styles (use className instead)
- Simple modifications (use existing props + className)
- Styles that should be in the global design system
Variant Creation Workflow
Step 1: Analyze the Component
Before creating a variant, understand:
- What's the base component? - Button, Card, Badge, etc.
- What visual states are needed? - Colors, sizes, borders, shadows
- Are there sub-components? - ButtonText, CardHeader, etc.
- What props should control variants? - variant, size, state props
- Should variants affect children? - Parent variants for sub-components
Step 2: Plan Variant Structure
Define your variant system:
tsx1// Example: Planning a Badge component with variants 2{ 3 variant: ['default', 'success', 'warning', 'error', 'info'] 4 size: ['sm', 'md', 'lg'] 5 shape: ['rounded', 'pill', 'square'] 6}
Step 3: Implement with tva
Use tva (Tailwind Variant Authority) to create type-safe, composable variants.
Creating Simple Variants
Template: Adding Variants to a Custom Component
tsx1import React from 'react'; 2import { tva } from '@gluestack-ui/utils/nativewind-utils'; 3import { Box } from '@/components/ui/box'; 4import { Text } from '@/components/ui/text'; 5 6interface BadgeProps { 7 readonly variant?: 'default' | 'success' | 'warning' | 'error' | 'info'; 8 readonly size?: 'sm' | 'md' | 'lg'; 9 readonly shape?: 'rounded' | 'pill' | 'square'; 10 readonly className?: string; 11 readonly children: React.ReactNode; 12} 13 14// Define variant styles 15const badgeStyles = tva({ 16 base: 'inline-flex items-center justify-center font-medium', 17 variants: { 18 variant: { 19 default: 'bg-muted text-muted-foreground', 20 success: 'bg-primary/10 text-primary border border-primary/20', 21 warning: 'bg-accent/10 text-accent-foreground border border-accent/20', 22 error: 'bg-destructive/10 text-destructive border border-destructive/20', 23 info: 'bg-secondary/10 text-secondary-foreground border border-secondary/20', 24 }, 25 size: { 26 sm: 'px-2 py-0.5 text-xs', 27 md: 'px-3 py-1 text-sm', 28 lg: 'px-4 py-1.5 text-base', 29 }, 30 shape: { 31 rounded: 'rounded-md', 32 pill: 'rounded-full', 33 square: 'rounded-none', 34 }, 35 }, 36 defaultVariants: { 37 variant: 'default', 38 size: 'md', 39 shape: 'rounded', 40 }, 41}); 42 43export const Badge = ({ 44 variant, 45 size, 46 shape, 47 className, 48 children 49}: BadgeProps) => { 50 return ( 51 <Box className={badgeStyles({ variant, size, shape, class: className })}> 52 <Text>{children}</Text> 53 </Box> 54 ); 55}; 56 57// Usage: 58// <Badge variant="success" size="lg" shape="pill">Active</Badge> 59// <Badge variant="error" size="sm">Error</Badge>
Key Points:
- ✅ Uses
tvafor variant management - ✅ Base styles apply to all variants
- ✅ Multiple variant dimensions (variant, size, shape)
- ✅ Default variants specified
- ✅ className override support with
classparameter - ✅ TypeScript types for variant options
Extending Existing Gluestack Components
Template: Adding Custom Variants to Button
tsx1import React from 'react'; 2import { tva } from '@gluestack-ui/utils/nativewind-utils'; 3import { Button as GluestackButton, ButtonText } from '@/components/ui/button'; 4 5// Define additional variant styles 6const customButtonStyles = tva({ 7 base: '', 8 variants: { 9 variant: { 10 // Extend existing variants with new ones 11 gradient: 'bg-gradient-to-r from-primary to-accent', 12 glass: 'bg-background/20 backdrop-blur-lg border border-border/50', 13 neon: 'bg-transparent border-2 border-primary shadow-[0_0_15px_rgba(59,130,246,0.5)]', 14 }, 15 size: { 16 // Add custom sizes 17 xs: 'px-2 py-1', 18 xl: 'px-8 py-4', 19 }, 20 }, 21}); 22 23interface CustomButtonProps { 24 readonly variant?: 'default' | 'destructive' | 'outline' | 'secondary' | 'ghost' | 'link' | 'gradient' | 'glass' | 'neon'; 25 readonly size?: 'default' | 'sm' | 'lg' | 'icon' | 'xs' | 'xl'; 26 readonly className?: string; 27 readonly onPress?: () => void; 28 readonly isDisabled?: boolean; 29 readonly children: React.ReactNode; 30} 31 32export const CustomButton = ({ 33 variant = 'default', 34 size = 'default', 35 className, 36 onPress, 37 isDisabled, 38 children, 39}: CustomButtonProps) => { 40 // Use Gluestack Button for built-in variants 41 if (['default', 'destructive', 'outline', 'secondary', 'ghost', 'link'].includes(variant)) { 42 return ( 43 <GluestackButton 44 variant={variant as any} 45 size={['default', 'sm', 'lg', 'icon'].includes(size) ? size as any : 'default'} 46 onPress={onPress} 47 isDisabled={isDisabled} 48 className={className} 49 > 50 {children} 51 </GluestackButton> 52 ); 53 } 54 55 // Use custom variants 56 return ( 57 <GluestackButton 58 onPress={onPress} 59 isDisabled={isDisabled} 60 className={customButtonStyles({ variant: variant as any, size: size as any, class: className })} 61 > 62 {children} 63 </GluestackButton> 64 ); 65}; 66 67// Usage: 68// <CustomButton variant="gradient" size="xl"> 69// <ButtonText>Gradient Button</ButtonText> 70// </CustomButton> 71// 72// <CustomButton variant="neon" size="lg"> 73// <ButtonText>Neon Button</ButtonText> 74// </CustomButton>
Key Points:
- ✅ Extends existing component
- ✅ Preserves original variants
- ✅ Adds new custom variants
- ✅ Maintains compound component pattern
- ✅ Type-safe variant options
Parent-Child Variant Relationships
When creating components with sub-components, use parentVariants to style children based on parent state.
Template: Card with Variant-Aware Children
tsx1import React from 'react'; 2import { tva } from '@gluestack-ui/utils/nativewind-utils'; 3import { Box } from '@/components/ui/box'; 4import { Heading } from '@/components/ui/heading'; 5import { Text } from '@/components/ui/text'; 6 7interface CardProps { 8 readonly variant?: 'default' | 'elevated' | 'outlined' | 'ghost'; 9 readonly colorScheme?: 'neutral' | 'primary' | 'success' | 'error'; 10 readonly className?: string; 11 readonly children: React.ReactNode; 12} 13 14interface CardHeaderProps { 15 readonly className?: string; 16 readonly children: React.ReactNode; 17} 18 19interface CardBodyProps { 20 readonly className?: string; 21 readonly children: React.ReactNode; 22} 23 24// Parent card styles 25const cardStyles = tva({ 26 base: 'rounded-lg overflow-hidden', 27 variants: { 28 variant: { 29 default: 'border border-border bg-card', 30 elevated: 'shadow-hard-2 bg-card', 31 outlined: 'border-2 border-border bg-transparent', 32 ghost: 'bg-transparent', 33 }, 34 colorScheme: { 35 neutral: '', 36 primary: 'border-primary/20', 37 success: 'border-primary/20', 38 error: 'border-destructive/20', 39 }, 40 }, 41 compoundVariants: [ 42 { 43 variant: 'default', 44 colorScheme: 'primary', 45 class: 'bg-primary/5', 46 }, 47 { 48 variant: 'default', 49 colorScheme: 'success', 50 class: 'bg-primary/5', 51 }, 52 { 53 variant: 'default', 54 colorScheme: 'error', 55 class: 'bg-destructive/5', 56 }, 57 ], 58 defaultVariants: { 59 variant: 'default', 60 colorScheme: 'neutral', 61 }, 62}); 63 64// Child styles that respond to parent variants 65const cardHeaderStyles = tva({ 66 base: 'p-4 border-b', 67 parentVariants: { 68 variant: { 69 default: 'border-border', 70 elevated: 'border-border/50', 71 outlined: 'border-border', 72 ghost: 'border-transparent', 73 }, 74 colorScheme: { 75 neutral: '', 76 primary: 'border-primary/20 bg-primary/5', 77 success: 'border-primary/20 bg-primary/5', 78 error: 'border-destructive/20 bg-destructive/5', 79 }, 80 }, 81}); 82 83const cardBodyStyles = tva({ 84 base: 'p-4', 85 parentVariants: { 86 colorScheme: { 87 neutral: '', 88 primary: '', 89 success: '', 90 error: '', 91 }, 92 }, 93}); 94 95// Context to share variant state with children 96const CardContext = React.createContext<Pick<CardProps, 'variant' | 'colorScheme'>>({ 97 variant: 'default', 98 colorScheme: 'neutral', 99}); 100 101export const Card = ({ 102 variant = 'default', 103 colorScheme = 'neutral', 104 className, 105 children 106}: CardProps) => { 107 return ( 108 <CardContext.Provider value={{ variant, colorScheme }}> 109 <Box className={cardStyles({ variant, colorScheme, class: className })}> 110 {children} 111 </Box> 112 </CardContext.Provider> 113 ); 114}; 115 116export const CardHeader = ({ className, children }: CardHeaderProps) => { 117 const { variant, colorScheme } = React.useContext(CardContext); 118 return ( 119 <Box className={cardHeaderStyles({ parentVariants: { variant, colorScheme }, class: className })}> 120 {children} 121 </Box> 122 ); 123}; 124 125export const CardBody = ({ className, children }: CardBodyProps) => { 126 const { variant, colorScheme } = React.useContext(CardContext); 127 return ( 128 <Box className={cardBodyStyles({ parentVariants: { colorScheme }, class: className })}> 129 {children} 130 </Box> 131 ); 132}; 133 134// Usage: 135// <Card variant="elevated" colorScheme="primary"> 136// <CardHeader> 137// <Heading size="lg">Success Card</Heading> 138// </CardHeader> 139// <CardBody> 140// <Text>This card responds to parent variants</Text> 141// </CardBody> 142// </Card>
Key Points:
- ✅ Parent context shares variant state
- ✅ Children use
parentVariantsto style based on parent - ✅ Compound variants for complex combinations
- ✅ Type-safe context usage
- ✅ Flexible composition
Compound Variants
Use compound variants when combinations of variant options need special styling.
Template: Button with Compound Variants
tsx1import React from 'react'; 2import { tva } from '@gluestack-ui/utils/nativewind-utils'; 3import { Button, ButtonText, ButtonIcon } from '@/components/ui/button'; 4import { Loader2Icon } from '@/components/ui/icon'; 5 6interface ActionButtonProps { 7 readonly variant?: 'solid' | 'outline' | 'ghost'; 8 readonly colorScheme?: 'primary' | 'secondary' | 'destructive'; 9 readonly size?: 'sm' | 'md' | 'lg'; 10 readonly isLoading?: boolean; 11 readonly isDisabled?: boolean; 12 readonly className?: string; 13 readonly onPress?: () => void; 14 readonly children: React.ReactNode; 15} 16 17const actionButtonStyles = tva({ 18 base: 'rounded-md font-medium transition-colors', 19 variants: { 20 variant: { 21 solid: '', 22 outline: 'border-2 bg-transparent', 23 ghost: 'bg-transparent', 24 }, 25 colorScheme: { 26 primary: '', 27 secondary: '', 28 destructive: '', 29 }, 30 size: { 31 sm: 'px-3 py-1.5 text-sm', 32 md: 'px-4 py-2 text-base', 33 lg: 'px-6 py-3 text-lg', 34 }, 35 }, 36 compoundVariants: [ 37 // Solid + Primary 38 { 39 variant: 'solid', 40 colorScheme: 'primary', 41 class: 'bg-primary text-primary-foreground data-[hover=true]:bg-primary/90', 42 }, 43 // Solid + Destructive 44 { 45 variant: 'solid', 46 colorScheme: 'destructive', 47 class: 'bg-destructive text-white data-[hover=true]:bg-destructive/90', 48 }, 49 // Outline + Primary 50 { 51 variant: 'outline', 52 colorScheme: 'primary', 53 class: 'border-primary text-primary data-[hover=true]:bg-primary/10', 54 }, 55 // Outline + Destructive 56 { 57 variant: 'outline', 58 colorScheme: 'destructive', 59 class: 'border-destructive text-destructive data-[hover=true]:bg-destructive/10', 60 }, 61 // Ghost + Primary 62 { 63 variant: 'ghost', 64 colorScheme: 'primary', 65 class: 'text-primary data-[hover=true]:bg-primary/10', 66 }, 67 // Ghost + Destructive 68 { 69 variant: 'ghost', 70 colorScheme: 'destructive', 71 class: 'text-destructive data-[hover=true]:bg-destructive/10', 72 }, 73 ], 74 defaultVariants: { 75 variant: 'solid', 76 colorScheme: 'primary', 77 size: 'md', 78 }, 79}); 80 81export const ActionButton = ({ 82 variant, 83 colorScheme, 84 size, 85 isLoading = false, 86 isDisabled = false, 87 className, 88 onPress, 89 children, 90}: ActionButtonProps) => { 91 return ( 92 <Button 93 onPress={onPress} 94 isDisabled={isDisabled || isLoading} 95 className={actionButtonStyles({ variant, colorScheme, size, class: className })} 96 > 97 {isLoading && <ButtonIcon as={Loader2Icon} className="animate-spin" />} 98 {children} 99 </Button> 100 ); 101}; 102 103// Usage: 104// <ActionButton variant="solid" colorScheme="primary" size="lg"> 105// <ButtonText>Primary Action</ButtonText> 106// </ActionButton> 107// 108// <ActionButton variant="outline" colorScheme="destructive" isLoading> 109// <ButtonText>Delete</ButtonText> 110// </ActionButton>
Key Points:
- ✅ Compound variants handle specific combinations
- ✅ Base variants provide defaults
- ✅ Hover states with data attributes
- ✅ Loading state integration
- ✅ Flexible variant combinations
Common Variant Patterns
Pattern 1: Status Badges
tsx1const statusBadgeStyles = tva({ 2 base: 'inline-flex items-center rounded-full px-2.5 py-0.5 text-xs font-semibold', 3 variants: { 4 status: { 5 active: 'bg-primary/10 text-primary', 6 inactive: 'bg-muted text-muted-foreground', 7 pending: 'bg-accent/10 text-accent-foreground', 8 completed: 'bg-primary/10 text-primary', 9 failed: 'bg-destructive/10 text-destructive', 10 }, 11 }, 12 defaultVariants: { 13 status: 'inactive', 14 }, 15}); 16 17// Usage: 18// <Box className={statusBadgeStyles({ status: 'active' })}> 19// <Text>Active</Text> 20// </Box>
Pattern 2: Alert Variants
tsx1const alertStyles = tva({ 2 base: 'rounded-lg border p-4', 3 variants: { 4 severity: { 5 info: 'bg-secondary/10 border-secondary/20 text-secondary-foreground', 6 success: 'bg-primary/10 border-primary/20 text-primary', 7 warning: 'bg-accent/10 border-accent/20 text-accent-foreground', 8 error: 'bg-destructive/10 border-destructive/20 text-destructive', 9 }, 10 }, 11 defaultVariants: { 12 severity: 'info', 13 }, 14}); 15 16// Usage: 17// <Box className={alertStyles({ severity: 'error' })}> 18// <Text>Error message</Text> 19// </Box>
Pattern 3: Interactive Card States
tsx1const interactiveCardStyles = tva({ 2 base: 'rounded-lg border border-border p-4 transition-all cursor-pointer', 3 variants: { 4 state: { 5 default: 'bg-card data-[hover=true]:bg-muted/50', 6 selected: 'bg-primary/10 border-primary', 7 disabled: 'bg-muted opacity-60 cursor-not-allowed', 8 }, 9 }, 10 defaultVariants: { 11 state: 'default', 12 }, 13}); 14 15// Usage: 16// <Pressable> 17// <Box className={interactiveCardStyles({ state: 'selected' })}> 18// <Text>Selected Card</Text> 19// </Box> 20// </Pressable>
Pattern 4: Size Variants with Consistent Ratios
tsx1const avatarStyles = tva({ 2 base: 'rounded-full overflow-hidden', 3 variants: { 4 size: { 5 xs: 'w-6 h-6', 6 sm: 'w-8 h-8', 7 md: 'w-12 h-12', 8 lg: 'w-16 h-16', 9 xl: 'w-20 h-20', 10 '2xl': 'w-24 h-24', 11 }, 12 }, 13 defaultVariants: { 14 size: 'md', 15 }, 16}); 17 18// Usage: 19// <Image className={avatarStyles({ size: 'lg' })} source={{ uri: avatarUrl }} />
Best Practices for Variants
✅ Do's
-
Use semantic variant names
tsx1// ✅ GOOD: Semantic names 2variant: 'primary' | 'secondary' | 'destructive' 3 4// ❌ BAD: Generic names 5variant: 'blue' | 'red' | 'green' -
Provide default variants
tsx1// ✅ GOOD: Always specify defaults 2defaultVariants: { 3 variant: 'default', 4 size: 'md', 5} -
Use compound variants for combinations
tsx1// ✅ GOOD: Handle specific combinations 2compoundVariants: [ 3 { 4 variant: 'outline', 5 colorScheme: 'primary', 6 class: 'border-primary text-primary', 7 }, 8] -
Keep variant dimensions focused
tsx1// ✅ GOOD: Clear separation 2variants: { 3 variant: { ... }, // Visual style 4 size: { ... }, // Size 5 state: { ... }, // Interactive state 6} -
Use ONLY semantic tokens in variant styles - NO EXCEPTIONS
tsx1// ✅ CORRECT: Semantic tokens with alpha values 2success: 'bg-primary/10 text-primary border-primary/20' 3error: 'bg-destructive/10 text-destructive border-destructive/20' 4muted: 'bg-muted text-muted-foreground border-border' 5 6// ❌ PROHIBITED: Numbered color tokens 7success: 'bg-green-100 text-green-800 border-green-200' 8error: 'bg-red-100 text-red-800 border-red-200' 9 10// ❌ PROHIBITED: Generic tokens 11muted: 'bg-neutral-100 text-neutral-600 border-neutral-300' 12muted: 'bg-gray-100 text-gray-600 border-gray-300' 13 14// ❌ PROHIBITED: Typography tokens 15text: 'text-typography-900'
❌ Don'ts
-
Don't create too many variant dimensions
tsx1// ❌ BAD: Too many dimensions 2variants: { 3 variant: { ... }, 4 size: { ... }, 5 color: { ... }, 6 border: { ... }, 7 shadow: { ... }, 8 rounded: { ... }, 9} 10 11// ✅ GOOD: Focused dimensions 12variants: { 13 variant: { ... }, 14 size: { ... }, 15} -
Don't mix concerns in variant names
tsx1// ❌ BAD: Mixing visual and semantic 2variant: 'primary' | 'large-primary' | 'small-secondary' 3 4// ✅ GOOD: Separate dimensions 5variant: 'primary' | 'secondary' 6size: 'sm' | 'md' | 'lg' -
Don't duplicate existing component props
tsx1// ❌ BAD: Duplicating Button's variant prop 2const CustomButton = ({ variant, ... }: { variant: 'new1' | 'new2' }) 3 4// ✅ GOOD: Extend existing variants 5const CustomButton = ({ variant, ... }: { 6 variant: 'default' | 'outline' | 'new1' | 'new2' 7})
CRITICAL: Semantic Tokens in Variants
ALL variant styles MUST use ONLY semantic tokens. This is NON-NEGOTIABLE.
Correct Variant Token Usage
tsx1// ✅ CORRECT: All colors are semantic tokens 2const badgeStyles = tva({ 3 base: 'inline-flex items-center rounded-full px-3 py-1', 4 variants: { 5 variant: { 6 default: 'bg-muted text-muted-foreground', 7 primary: 'bg-primary/10 text-primary border border-primary/20', 8 success: 'bg-primary/10 text-primary border border-primary/20', 9 error: 'bg-destructive/10 text-destructive border border-destructive/20', 10 warning: 'bg-accent/10 text-accent-foreground border border-accent/20', 11 }, 12 }, 13});
Prohibited Variant Token Usage
tsx1// ❌ PROHIBITED: Using numbered color tokens 2const badgeStyles = tva({ 3 variants: { 4 variant: { 5 success: 'bg-green-100 text-green-800 border-green-200', // ❌ NO 6 error: 'bg-red-100 text-red-800 border-red-200', // ❌ NO 7 warning: 'bg-yellow-100 text-yellow-800', // ❌ NO 8 }, 9 }, 10}); 11 12// ❌ PROHIBITED: Using generic tokens 13const badgeStyles = tva({ 14 variants: { 15 variant: { 16 default: 'bg-neutral-100 text-neutral-700', // ❌ NO 17 muted: 'bg-gray-100 text-gray-600', // ❌ NO 18 }, 19 }, 20}); 21 22// ❌ PROHIBITED: Using typography tokens 23const textStyles = tva({ 24 variants: { 25 variant: { 26 heading: 'text-typography-900', // ❌ NO 27 body: 'text-typography-700', // ❌ NO 28 }, 29 }, 30});
Token Replacement Guide for Variants
| Prohibited Pattern | Use Instead |
|---|---|
bg-green-100 text-green-800 | bg-primary/10 text-primary |
bg-red-100 text-red-800 | bg-destructive/10 text-destructive |
bg-yellow-100 text-yellow-800 | bg-accent/10 text-accent-foreground |
bg-blue-100 text-blue-800 | bg-primary/10 text-primary |
bg-neutral-100 text-neutral-700 | bg-muted text-muted-foreground |
bg-gray-100 text-gray-900 | bg-muted text-foreground |
text-typography-900 | text-foreground |
text-typography-600 | text-muted-foreground |
border-gray-300 | border-border |
Validation Checklist for Variants
When creating variants, verify:
- CRITICAL: NO prohibited tokens - No
typography-*,neutral-*,gray-*,slate-*, numbered colors - All colors are semantic tokens - Every color uses semantic tokens from the approved list
- Alpha values instead of opacity - Uses
/70,/90instead ofopacity-*utilities - Variant names are semantic (not color names)
- Default variants specified
- Spacing uses scale values (no arbitrary values)
- TypeScript types match variant options
- className override supported with
classparameter - Parent variants used for child components (if applicable)
- Compound variants for complex combinations (if needed)
- Data attributes for interactive states
- Tested with dark mode (semantic tokens ensure compatibility)
- Documentation/comments for non-obvious variants
Recipe: Converting Repeated Styles to Variants
Before: Repeated className Patterns
tsx1// ❌ Repeated patterns across codebase 2<Box className="bg-primary/10 border border-primary/20 rounded-full px-3 py-1"> 3 <Text className="text-xs text-primary font-semibold">Active</Text> 4</Box> 5 6<Box className="bg-destructive/10 border border-destructive/20 rounded-full px-3 py-1"> 7 <Text className="text-xs text-destructive font-semibold">Error</Text> 8</Box> 9 10<Box className="bg-accent/10 border border-accent/20 rounded-full px-3 py-1"> 11 <Text className="text-xs text-accent-foreground font-semibold">Pending</Text> 12</Box>
After: Variant-Based Component
tsx1// ✅ GOOD: Single component with variants 2const StatusPill = ({ status, children }: StatusPillProps) => { 3 const pillStyles = tva({ 4 base: 'inline-flex items-center rounded-full px-3 py-1', 5 variants: { 6 status: { 7 active: 'bg-primary/10 border border-primary/20', 8 error: 'bg-destructive/10 border border-destructive/20', 9 pending: 'bg-accent/10 border border-accent/20', 10 }, 11 }, 12 }); 13 14 const textStyles = tva({ 15 base: 'text-xs font-semibold', 16 parentVariants: { 17 status: { 18 active: 'text-primary', 19 error: 'text-destructive', 20 pending: 'text-accent-foreground', 21 }, 22 }, 23 }); 24 25 return ( 26 <Box className={pillStyles({ status })}> 27 <Text className={textStyles({ parentVariants: { status } })}>{children}</Text> 28 </Box> 29 ); 30}; 31 32// Usage: 33<StatusPill status="active">Active</StatusPill> 34<StatusPill status="error">Error</StatusPill> 35<StatusPill status="pending">Pending</StatusPill>
Troubleshooting
Issue: Variants Not Applying
Problem: Variant classes not showing up
Solution:
- Check Tailwind config includes tva patterns
- Verify className merge order
- Ensure no conflicting inline styles
Issue: Parent Variants Not Working
Problem: Child components don't respond to parent variants
Solution:
- Use context to share parent state
- Pass parentVariants object correctly
- Verify context provider wraps children
Issue: Type Errors with Variants
Problem: TypeScript errors with variant options
Solution:
- Define variant types in interface
- Use literal types for variant values
- Ensure defaultVariants match types
Reference
- tva Documentation: https://www.tailwind-variants.org/
- Gluestack v4 Docs: https://v4.gluestack.io/ui/docs
- Component Examples:
https://v4.gluestack.io/ui/docs/components/${componentName}/
FAQ & Installation Steps
These questions and steps mirror the structured data on this page for better search understanding.
? Frequently Asked Questions
What is gluestack-ui-v4:variants?
Ideal for Frontend Agents requiring customizable UI component styling with type safety gluestack-ui-v4:variants is a sub-skill for creating custom variants of gluestack-ui v4 components, extending the design system with project-specific styling patterns.
How do I install gluestack-ui-v4:variants?
Run the command: npx killer-skills add bogajoss/native_threads. It works with Cursor, Windsurf, VS Code, Claude Code, and 19+ other IDEs.
What are the use cases for gluestack-ui-v4:variants?
Key use cases include: Creating project-specific button styles with custom variants, Extending the design system with reusable card type components, Maintaining consistency across multiple UI components with custom className patterns.
Which IDEs are compatible with gluestack-ui-v4:variants?
This skill is compatible with Cursor, Windsurf, VS Code, Trae, Claude Code, OpenClaw, Aider, Codex, OpenCode, Goose, Cline, Roo Code, Kiro, Augment Code, Continue, GitHub Copilot, Sourcegraph Cody, and Amazon Q Developer. Use the Killer-Skills CLI for universal one-command installation.
Are there any limitations for gluestack-ui-v4:variants?
Requires gluestack-ui v4 components. Limited to project-specific styling patterns.
↓ How To Install
-
1. Open your terminal
Open the terminal or command line in your project directory.
-
2. Run the install command
Run: npx killer-skills add bogajoss/native_threads. The CLI will automatically detect your IDE or AI agent and configure the skill.
-
3. Start using the skill
The skill is now active. Your AI agent can use gluestack-ui-v4:variants immediately in the current project.