|
| 1 | +# ReQore AI Coding Agent Instructions |
| 2 | + |
| 3 | +## Project Overview |
| 4 | + |
| 5 | +ReQore is a **themeable React component library** for the Qorus platform. It provides 40+ UI components (Button, Table, Modal, Drawer, etc.) that share a unified design system with consistent theming, sizing, and effect systems. |
| 6 | + |
| 7 | +**Key Facts:** |
| 8 | + |
| 9 | +- **Framework:** React 18 + TypeScript (strict mode) |
| 10 | +- **Build:** TypeScript compilation to `/dist`, exports both `.js` and `.d.ts` |
| 11 | +- **Styling:** styled-components with theme-driven values (no CSS modules) |
| 12 | +- **State Management:** zustand + React Context (use-context-selector) |
| 13 | +- **Testing:** Jest + React Testing Library (tests in `__tests__/`) |
| 14 | +- **Documentation:** Storybook (dev stories in `src/stories/`) + Docusaurus (docs site) |
| 15 | + |
| 16 | +## Architecture Essentials |
| 17 | + |
| 18 | +### General Development Practices |
| 19 | + |
| 20 | +# General |
| 21 | + |
| 22 | +- Focus is first on user experience and performance, complexity and tech debt secondary |
| 23 | +- Follow existing code patterns for new components; refer to similar components for guidance |
| 24 | +- Check if a helper or utility already exists before writing a new one |
| 25 | + |
| 26 | +# TypeScript |
| 27 | + |
| 28 | +- Use TypeScript with strict typing; define prop interfaces for each component with `I` prefix for interfaces and `T` prefix for types |
| 29 | + |
| 30 | +# UI / UX |
| 31 | + |
| 32 | +- Always make sure to create reusable components |
| 33 | +- Always use named exports for React components |
| 34 | +- There can be multiple React components in one file if it makes sense |
| 35 | +- Use styled-components for styling; define style interfaces for styled components |
| 36 | +- Always componentize styles with styled-components; avoid inline styles except for dynamic cases |
| 37 | +- Use functional components with React hooks |
| 38 | +- For React, always wrap components in `memo()` unless there's a specific reason not to |
| 39 | +- For React, always wrap callbacks in `useCallback()` unless there's a specific reason not to |
| 40 | +- For React, always memoize computed values in `useMemo()` unless there's a specific reason not to |
| 41 | + |
| 42 | +# Testing |
| 43 | + |
| 44 | +- Run tests after changes, run `yarn precheck` after feature completions |
| 45 | +- Write a unit test if it makes sense for the change you have made, but Storybook tests will always have higher priority |
| 46 | + |
| 47 | +### Component Structure |
| 48 | + |
| 49 | +- **Folder:** `src/components/{ComponentName}/` contains only `index.tsx` (and occasionally `backdrop.tsx` for overlay components) |
| 50 | +- **Pattern:** Each component is a `memo()` wrapped functional component with TypeScript interfaces |
| 51 | +- **Exports:** Named exports (e.g., `export const ReqoreButton`) from component files; re-exported in `src/index.tsx` |
| 52 | + |
| 53 | +### Theme System (`src/constants/theme.ts` + hooks) |
| 54 | + |
| 55 | +- **Global theming:** `useReqoreTheme()` hook provides `IReqoreTheme` (colors, text, main background, intents) |
| 56 | +- **Dynamic theming:** Components read theme via hooks, enabling runtime theme switching |
| 57 | +- **Intents:** Type-safe intent system (e.g., `'primary' | 'secondary' | 'success' | 'danger'`) maps to theme colors |
| 58 | +- **Custom themes:** Merge with `DEFAULT_THEME`; see `ThemeProvider.tsx` |
| 59 | + |
| 60 | +### Sizing System (`src/constants/sizes.ts`) |
| 61 | + |
| 62 | +- **Size types:** `'micro' | 'tiny' | 'small' | 'normal' | 'big' | 'huge' | 'massive'` |
| 63 | +- **Pattern:** Maps like `SIZE_TO_PX`, `SIZE_TO_NUMBER`, `CONTROL_TEXT_FROM_SIZE` convert size enums to pixel/CSS values |
| 64 | +- **Usage:** Most interactive components accept `size?: TSizes` prop; pass through to nested styled components |
| 65 | + |
| 66 | +### Effect System (`src/components/Effect/`) |
| 67 | + |
| 68 | +- **Purpose:** Provides gradient, blur, shadow effects applied via `StyledTextEffect` |
| 69 | +- **Props:** `IWithReqoreEffect` mixin (gradient, blur, shadow, opacity) on interactive components |
| 70 | +- **Color types:** `TReqoreHexColor`, `TReqoreRgbaColor`, `TReqoreMultiTypeColor` used consistently |
| 71 | + |
| 72 | +### Global Context (`src/context/ReqoreContext.tsx` + `ReqoreProvider.tsx`) |
| 73 | + |
| 74 | +- **Manages:** Modals, notifications, z-index stack, mobile breakpoints, animations toggle, tooltips |
| 75 | +- **Methods:** `addModal()`, `removeModal()`, `addNotification()`, `confirmAction()` (confirmation dialog) |
| 76 | +- **Mobile detection:** `isMobile`, `isTablet`, `isMobileOrTablet` flags from `useMedia()` hook |
| 77 | +- **ESC handling:** Modals/popovers close on ESC via `escClosableModals` stack; `closeModalsOnEscPress` toggle |
| 78 | + |
| 79 | +## Development Workflows |
| 80 | + |
| 81 | +### Quick Start |
| 82 | + |
| 83 | +```bash |
| 84 | +yarn install |
| 85 | +yarn storybook # Dev mode on http://localhost:6007 |
| 86 | +yarn docs:dev # Docusaurus dev server |
| 87 | +yarn test:watch # Jest watch mode |
| 88 | +yarn lint # ESLint check |
| 89 | +yarn build # TypeScript compilation |
| 90 | +``` |
| 91 | + |
| 92 | +### Pre-commit Checks |
| 93 | + |
| 94 | +- `yarn precheck` runs: lint → test → build (production) |
| 95 | +- `pre-push` hook enforces same checks before push (see `package.json`) |
| 96 | +- Line length: 100 characters (enforced by eslint) |
| 97 | + |
| 98 | +### Testing Patterns |
| 99 | + |
| 100 | +- **Setup:** `__tests__/setup.js` disables console debug/info/error |
| 101 | +- **Wrapper:** Always wrap tests with `<ReqoreUIProvider><ReqoreLayoutContent><ReqoreContent>...</ReqoreContent></ReqoreLayoutContent></ReqoreUIProvider>` |
| 102 | +- **Selectors:** Use CSS classes like `.reqore-button`, `.reqore-icon` (added via `className` prop) |
| 103 | +- **Example:** See [button.test.tsx](__tests__/button.test.tsx) |
| 104 | + |
| 105 | +### Storybook Stories |
| 106 | + |
| 107 | +- **Location:** `src/stories/` (e.g., `Collection.stories.tsx`) |
| 108 | +- **Pattern:** ArgTypes for props, canvas controls, visual testing via Chromatic |
| 109 | +- **Command:** `yarn build-storybook` builds static site |
| 110 | + |
| 111 | +## Code Patterns & Conventions |
| 112 | + |
| 113 | +### Component Prop Interfaces |
| 114 | + |
| 115 | +- **Extend mixins:** `IWithReqoreSize`, `IWithReqoreEffect`, `IWithReqoreLoading`, `IWithReqoreReadOnly` |
| 116 | +- **Naming:** Props interface is `IReqore{ComponentName}Props`; style interface is `IReqore{ComponentName}Style` |
| 117 | +- **Optional theme:** Style interfaces accept `theme: IReqoreTheme` for styled-components access |
| 118 | +- **Readonly context:** Use `readonly` keyword on context properties (immutability) |
| 119 | + |
| 120 | +### Styled Components Pattern |
| 121 | + |
| 122 | +```tsx |
| 123 | +const StyledButton = styled.button<IReqoreButtonStyle>` |
| 124 | + // Use props.theme from ReqoreTheme |
| 125 | + background: ${({ theme, intent }) => theme.intents?.[intent]?.color}; |
| 126 | + color: ${({ theme }) => getReadableColor(theme)}; |
| 127 | + // Conditional styles via css helper |
| 128 | + ${({ disabled }) => |
| 129 | + disabled && |
| 130 | + css` |
| 131 | + opacity: 0.5; |
| 132 | + `} |
| 133 | +`; |
| 134 | +``` |
| 135 | + |
| 136 | +### Hooks Usage |
| 137 | + |
| 138 | +- **Theme:** `useReqoreTheme()` returns `IReqoreTheme` |
| 139 | +- **Context props:** `useReqoreProperty('propertyName')` for context values (avoids consuming entire context) |
| 140 | +- **Local refs:** `useCombinedRefs()` for forwarding + internal refs; `useOutsideClick()` for popover clicks |
| 141 | +- **Auto-focus:** `useAutoFocus()` for modal/drawer focus management |
| 142 | + |
| 143 | +### Color Helpers (`src/helpers/colors.ts`) |
| 144 | + |
| 145 | +- **Text contrast:** `getReadableColor(theme)` returns light or dark based on theme.main |
| 146 | +- **Gradients:** `getGradientMix()` blends multiple colors for effect gradients |
| 147 | +- **Hex↔RGBA:** `hexAToRGBA()`, `getRGBAFromHex()` for color space conversions |
| 148 | +- **Lightness:** `changeLightness()`, `changeDarkness()` for theme-aware color adjustments |
| 149 | + |
| 150 | +### Animation Config |
| 151 | + |
| 152 | +- **Spring:** `SPRING_CONFIG` for bounce/smooth animations (via `@react-spring/web`) |
| 153 | +- **Disabled:** `SPRING_CONFIG_NO_ANIMATIONS` when `animations.buttons: false` |
| 154 | +- **Usage:** Wrap animated components with `<animated>` from react-spring |
| 155 | + |
| 156 | +## Key Integration Points |
| 157 | + |
| 158 | +### Modal & Notification Flow |
| 159 | + |
| 160 | +1. **Add modal:** `context.addModal(modalElement, id?)` returns modal ID |
| 161 | +2. **Close:** `context.removeModal(id)` + optional confirmation dialog |
| 162 | +3. **Notifications:** `context.addNotification({...})` queues toast; auto-removes after `duration` |
| 163 | +4. **Portal:** All modals/notifications render via `customPortalId` or default DOM portal |
| 164 | + |
| 165 | +### Responsive Breakpoints |
| 166 | + |
| 167 | +- **Mobile:** `isMobile` (width ≤ 480px) |
| 168 | +- **Tablet:** `isTablet` (width ≤ 1024px) |
| 169 | +- **Usage:** Conditional rendering in components; affects dropdown/menu positioning |
| 170 | + |
| 171 | +### Icon System (`src/types/icons.ts`) |
| 172 | + |
| 173 | +- **Type:** `IReqoreIconName` (string literal of all icon names) |
| 174 | +- **Render:** `<ReqoreIcon name="iconNameHere" />` or component prop `icon="iconNameHere"` |
| 175 | +- **Sizing:** Icon size auto-scales with component size via `ICON_FROM_SIZE` |
| 176 | + |
| 177 | +### Collections & Paging |
| 178 | + |
| 179 | +- **Collection:** Renders arrays with optional sorting/filtering; used in Table, MultiSelect |
| 180 | +- **Paging:** `useReqorePaging()` hook handles offset/limit; `<ReqorePaging>` component for controls |
| 181 | +- **Pattern:** See [Collection.tsx](src/components/Collection/) and [Paging.tsx](src/containers/Paging.tsx) |
| 182 | + |
| 183 | +## Common Pitfalls & Solutions |
| 184 | + |
| 185 | +| Issue | Solution | |
| 186 | +| -------------------------------------- | -------------------------------------------------------------------------------------------- | |
| 187 | +| Styled component props not typed | Add `<IComponentStyle>` generic; ensure mixin interfaces extend properly | |
| 188 | +| Theme not applying | Verify `ReqoreUIProvider` wraps component tree; check `useReqoreTheme()` call | |
| 189 | +| ESC key ignored in modal | Ensure `closeModalsOnEscPress: true` in provider; modal must be in `escClosableModals` stack | |
| 190 | +| Icon not rendering | Verify icon name in `IReqoreIconName`; check icon imports in `Icon/` component | |
| 191 | +| Tests fail with "React is not defined" | Verify `setup.js` is loaded; jsx: "react-jsx" in tsconfig.json | |
| 192 | +| Animation janky on slow devices | Offer `animations.buttons: false` toggle in theme/context; use `SPRING_CONFIG_NO_ANIMATIONS` | |
| 193 | + |
| 194 | +## File Reference |
| 195 | + |
| 196 | +| Path | Purpose | |
| 197 | +| ----------------- | --------------------------------------------------------------- | |
| 198 | +| `src/index.tsx` | Main export barrel; re-exports all public components | |
| 199 | +| `src/constants/` | Global enums, size maps, theme defaults, animation configs | |
| 200 | +| `src/helpers/` | Color math, utility functions (no React) | |
| 201 | +| `src/hooks/` | Custom React hooks (theme, context, DOM utilities) | |
| 202 | +| `src/containers/` | Provider components (ReqoreProvider, ThemeProvider, UIProvider) | |
| 203 | +| `src/context/` | Context definitions (ReqoreContext, ThemeContext) | |
| 204 | +| `src/types/` | Global TypeScript interfaces (icons, global prop mixins) | |
| 205 | +| `__tests__/` | Jest tests; mirrors `src/` structure | |
| 206 | +| `src/stories/` | Storybook stories for visual development | |
| 207 | + |
| 208 | +## When Adding New Components |
| 209 | + |
| 210 | +1. **Create folder:** `src/components/{ComponentName}/index.tsx` |
| 211 | +2. **Define interfaces:** `IReqore{ComponentName}Props` + `IReqore{ComponentName}Style` |
| 212 | +3. **Use mixins:** Extend `IWithReqoreEffect`, `IWithReqoreSize` as needed |
| 213 | +4. **Apply theme:** Use `useReqoreTheme()` and styled-components `theme` prop |
| 214 | +5. **Export:** Add named export to `src/index.tsx` |
| 215 | +6. **Test:** Add test file in `__tests__/{ComponentName}.test.tsx` with UIProvider wrapper |
| 216 | +7. **Story:** Create `src/stories/{ComponentName}.stories.tsx` with argTypes |
| 217 | + |
| 218 | +## Documentation |
| 219 | + |
| 220 | +- **Storybook:** Run `yarn storybook` for interactive component playground |
| 221 | +- **Docusaurus:** Run `yarn docs:dev` for user guides + API docs |
| 222 | +- **TypeDoc:** `yarn docs:api` generates API reference from JSDoc comments |
| 223 | +- **Inline:** Use JSDoc comments on public props/methods for IDE tooltips |
0 commit comments