---
description:
globs: *.tsx
alwaysApply: false
---
# JSX Best Practices
This guide outlines our conventions for writing clean, maintainable JSX in React applications.
## Utility Functions
### Class Name Management
When merging complex classes, always use the `cn` utility from `clsx`/`tailwind-merge`:
```tsx
import { cn } from '@kit/ui/utils';
// Simple usage
// Conditional classes
Content
// Array syntax for dynamic classes
{label}
```
Why use `cn`:
- Handles merging tailwind classes correctly
- Automatically removes duplicate classes
- Resolves conflicting classes by keeping the last one
- Provides type-safety with TypeScript
## Common Patterns
### Conditional Rendering with `If`
Prefer the `If` component to complex ternary operators in JSX:
```tsx
import { If } from '@kit/ui/if';
// Basic usage
// With fallback
}>
// With callback function for condition match
{(userData) => }
```
Benefits:
- Improves readability compared to ternary operators
- Type-safe with TypeScript
- Reduces nesting and complexity in JSX
### List Rendering
Consistently use these patterns for list rendering:
```tsx
// Empty state handling, avoid ternaries
{items.length > 0 ? (
{items.map((item) => (
{item.name}
))}
) : (
)}
// Even better with If component
0} fallback={
}>
{items.map((item) => (
{item.name}
))}
```
### Using Translations
All user-facing text should use the `Trans` component unless specified otherwise:
```tsx
import { Trans } from '@kit/ui/trans';
// Basic usage
// With variables
// With HTML elements
,
PrivacyLink:
}}
defaults="I agree to the Terms and Privacy Policy."
/>
// Pluralization
```
Important rules:
- Always provide a `defaults` prop with the English text as fallback
- Ensure the key exists in the appropriate translation file
- Keep HTML elements minimal in translations
## Error and Loading States
Use consistent patterns for handling loading and error states:
```tsx
// Loading state
// Error state that infer the type of the condition. The type of the variable "err" is now inferred
// Always use this pattern when the value of the condition is used within the body
{(err) => (
{err.message}
)}
// Empty state
```
## Testing Attributes
Add consistent data attributes for testing:
```tsx