Bin
2025-12-17 8c7632e4a973d7e005f6b070a7627205d869a344
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
---
description: React coding standards and best practices for the LabelStudio clientside application
globs: **/*.jsx,**/*.tsx
---
 
# React Best Practices
 
## Project Structure
- All frontend code lives in the `web` directory
- Main application code is in `web/apps/labelstudio`
- Shared libraries are in `web/libs`
- Follow the established directory structure:
  - `components/`: Reusable UI components
  - `pages/`: Top-level page components
  - `utils/`: Utility functions
  - `hooks/`: Custom React hooks
  - `atoms/`: Jotai atom state definitions
  - `providers/`: Context providers
  - `services/`: API and other services
  - `types/`: TypeScript type definitions
  - `assets/`: Static assets
 
## Component Structure
- Use functional components over class components
- Keep components small and focused
- Extract reusable logic into custom hooks
- Use composition over inheritance
- Implement proper prop types with TypeScript
- Split large components into smaller, focused ones
- Follow a consistent file organization pattern:
  ```
  component-name/
    component-name.tsx
    component-name.module.scss
    component-name.test.tsx
    index.ts
  ```
 
## Hooks
- Follow the Rules of Hooks
- Use custom hooks for reusable logic
- Keep hooks focused and simple
- Avoid useEffect unless absolutely required
- Use appropriate dependency arrays in useEffect
- Implement cleanup in useEffect when needed
- Avoid nested hooks
 
## State Management
- Use useState for local component state
- Use Jotai atoms and not the Context API for shared state
- Implement atomWithReducer for complex state logic
- Implement atomWithQuery for any API requests for data
- Keep state as close to where it's used as possible
- Avoid prop drilling through proper state management
- Only use Jotai as the single source of truth of global state management
 
## Performance
- Implement proper memoization (useMemo, useCallback)
- Use React.memo for expensive components
- Avoid unnecessary re-renders
- Implement proper lazy loading
- Use proper key props in lists
- Profile and optimize render performance
 
## Tooling
- Use Biome for code linting and formatting
- Follow CSS/SCSS linting rules defined in .stylelintrc.json
- Use TypeScript for type safety
- Keep bundle size in check by monitoring imports
 
## Forms
- Use controlled components for form inputs
- Implement proper form validation
- Handle form submission states properly
- Show appropriate loading and error states
- Use form libraries for complex forms
- Implement proper accessibility for forms
 
## Error Handling
- Implement Error Boundaries
- Handle async errors properly
- Show user-friendly error messages
- Implement proper fallback UI
- Log errors appropriately
- Handle edge cases gracefully
 
## Testing
- Write unit tests for components
- Implement integration tests for complex flows
- Use React Testing Library
- Test user interactions
- Test error scenarios
- Implement proper mock data
 
## Accessibility
- Ensure components meet WCAG 2.1 AA standards
- Use semantic HTML elements
- Implement proper ARIA attributes
- Ensure keyboard navigation
- Test with screen readers
- Handle focus management
- Provide proper alt text for images
 
## Code Organization
- Use proper file naming conventions which is kebab-case ie. ListItem -> `list-item.tsx`
- Prefer one component per folder, but group related components together when necessary, and ensure there is only one component per file.
- Component folders should have a SCSS `.module.scss` with the name of the component kebab-case ie. ListItem -> `list-item.module.scss`
- Implement proper directory structure
- UI components live within `web/libs/ui`
- Application components that are shared across applications such as certain page-level blocks live within `web/libs/app-common`
- Code in `web/apps` can only import code from `web/libs` and `web/libs` cannot import from `web/apps`
- Code in `web/libs/app-common` can only import code from other `web/libs` or `web/apps`. No other `web/libs` can import from `web/libs/app-common`
- Keep atoms in a global atoms folder with the name of the file matching the entity or intent of state
- Add all components and their states to Storybook by co-locating the story file next to the component file ie. `list-item.stories.tsx`
- Use the `@humansignal/ui` package for UI components
- Use the `@humansignal/icons` package for icons
- Use the `@humansignal/core` package for core utilities/functions
- Use the `@humansignal/app-common` package for application components
 
## Best Practices
- No cyclic imports
- Use proper imports/exports
- Follow established import ordering
- Compose components rather than extending them
- Keep components focused on a single responsibility
- Document complex logic with clear comments
- Follow the project's folder structure and naming conventions
- Prefer controlled components over uncontrolled ones