Skip to content

Commit 2bc8ec3

Browse files
authored
Merge pull request #87 from lambda-curry/codegen-bot/medusa-cursor-rules-1748666401
2 parents bf5c98b + 8fa205b commit 2bc8ec3

File tree

5 files changed

+632
-14
lines changed

5 files changed

+632
-14
lines changed

.cursor/rules/form-component-patterns.mdc

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
---
22
type: Always
3-
description: Rules for form component integration patterns in the lambda-curry/forms repository
3+
description: Rules for form component integration patterns in the lambda-curry/forms repository (applies to Remix Hook Form components)
44
---
55

66
You are an expert in React Hook Form, Remix Hook Form, Zod validation, and form component architecture for the lambda-curry/forms monorepo.
77

8-
# Form Component Integration Patterns
8+
# Form Component Integration Patterns (Remix Hook Form)
9+
10+
**Note: These patterns apply to Remix Hook Form components in `packages/components/`. For Medusa Forms components using react-hook-form + @medusajs/ui, see the medusa-forms-patterns.mdc rules.**
911

1012
## Core Principles
1113
- All form components must integrate seamlessly with Remix Hook Form
@@ -215,4 +217,3 @@ export type { ComponentNameProps };
215217
- Test component composition and customization
216218

217219
Remember: Form components are the core of this library. Every form component should be intuitive, accessible, and integrate seamlessly with the Remix Hook Form + Zod validation pattern.
218-
Lines changed: 252 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,252 @@
1+
---
2+
type: Auto Attached
3+
description: Rules for Medusa Forms component development patterns using @medusajs/ui and react-hook-form
4+
globs: ["packages/medusa-forms/**/*.{ts,tsx}", "apps/docs/src/medusa-forms/**/*.{ts,tsx}"]
5+
---
6+
7+
You are an expert in React Hook Form, @medusajs/ui components, and Medusa design system integration for the lambda-curry/forms repository.
8+
9+
# Medusa Forms Component Patterns
10+
11+
## Core Architecture Principles
12+
- Medusa Forms use **react-hook-form** directly (not remix-hook-form)
13+
- All UI components are built on **@medusajs/ui** as the base design system
14+
- Follow the **controlled/** and **ui/** directory separation pattern
15+
- Use the **Controller** pattern for form integration
16+
- Maintain **FieldWrapper** consistency for all form fields
17+
18+
## Required Imports for Medusa Forms
19+
20+
### For Controlled Components
21+
```typescript
22+
import {
23+
Controller,
24+
type ControllerProps,
25+
type FieldValues,
26+
type Path,
27+
type RegisterOptions,
28+
useFormContext,
29+
} from 'react-hook-form';
30+
import { ComponentName, type Props as ComponentNameProps } from '../ui/ComponentName';
31+
```
32+
33+
### For UI Components
34+
```typescript
35+
import { ComponentName as MedusaComponentName } from '@medusajs/ui';
36+
import type * as React from 'react';
37+
import { FieldWrapper } from './FieldWrapper';
38+
import type { BasicFieldProps, MedusaComponentNameProps } from './types';
39+
```
40+
41+
## Directory Structure Convention
42+
```
43+
packages/medusa-forms/src/
44+
├── controlled/ # Form-aware wrapper components using Controller
45+
│ ├── ControlledInput.tsx
46+
│ ├── ControlledCheckbox.tsx
47+
│ ├── ControlledSelect.tsx
48+
│ └── index.ts
49+
└── ui/ # Base UI components using @medusajs/ui
50+
├── Input.tsx
51+
├── FieldCheckbox.tsx
52+
├── Select.tsx
53+
├── FieldWrapper.tsx
54+
└── types.d.ts
55+
```
56+
57+
## Controlled Component Pattern
58+
All controlled components must follow this exact pattern:
59+
60+
```typescript
61+
type Props<T extends FieldValues> = ComponentNameProps &
62+
Omit<ControllerProps, 'render'> & {
63+
name: Path<T>;
64+
rules?: Omit<RegisterOptions<T, Path<T>>, 'disabled' | 'valueAsNumber' | 'valueAsDate' | 'setValueAs'>;
65+
};
66+
67+
export const ControlledComponentName = <T extends FieldValues>({
68+
name,
69+
rules,
70+
onChange,
71+
...props
72+
}: Props<T>) => {
73+
const {
74+
control,
75+
formState: { errors },
76+
} = useFormContext<T>();
77+
78+
return (
79+
<Controller
80+
control={control}
81+
name={name}
82+
rules={rules as Omit<RegisterOptions<T, Path<T>>, 'disabled' | 'valueAsNumber' | 'valueAsDate' | 'setValueAs'>}
83+
render={({ field }) => (
84+
<ComponentName
85+
{...field}
86+
{...props}
87+
formErrors={errors}
88+
onChange={(value) => {
89+
if (onChange) onChange(value);
90+
field.onChange(value);
91+
}}
92+
/>
93+
)}
94+
/>
95+
);
96+
};
97+
```
98+
99+
## UI Component Pattern
100+
All UI components must use FieldWrapper and @medusajs/ui:
101+
102+
```typescript
103+
export type Props = MedusaComponentNameProps &
104+
BasicFieldProps & {
105+
ref?: React.Ref<HTMLInputElement>; // Adjust ref type based on component
106+
};
107+
108+
const Wrapper = FieldWrapper<Props>;
109+
110+
export const ComponentName: React.FC<Props> = ({ ref, ...props }) => (
111+
<Wrapper {...props}>
112+
{(inputProps) => <MedusaComponentName {...inputProps} ref={ref} />}
113+
</Wrapper>
114+
);
115+
```
116+
117+
## FieldWrapper Integration
118+
- **Always** use FieldWrapper for consistent label, error, and styling patterns
119+
- Pass `formErrors` prop to enable automatic error display
120+
- Use `labelClassName`, `wrapperClassName`, `errorClassName` for styling customization
121+
122+
```typescript
123+
<FieldWrapper<ComponentProps>
124+
wrapperClassName={wrapperClassName}
125+
errorClassName={errorClassName}
126+
formErrors={formErrors}
127+
{...props}
128+
>
129+
{(fieldProps) => (
130+
<MedusaComponent {...fieldProps} ref={ref} />
131+
)}
132+
</FieldWrapper>
133+
```
134+
135+
## @medusajs/ui Component Integration
136+
137+
### Input Components
138+
```typescript
139+
import { Input as MedusaInput } from '@medusajs/ui';
140+
// Use with FieldWrapper pattern
141+
```
142+
143+
### Checkbox Components
144+
```typescript
145+
import { Checkbox as MedusaCheckbox } from '@medusajs/ui';
146+
// Special handling for checked state and onCheckedChange
147+
```
148+
149+
### Select Components
150+
```typescript
151+
import { Select as MedusaSelect } from '@medusajs/ui';
152+
// Compound component pattern with Trigger, Content, Item
153+
```
154+
155+
### Currency Input Components
156+
```typescript
157+
import { CurrencyInput as MedusaCurrencyInput } from '@medusajs/ui';
158+
// Special props: symbol, code, currency
159+
```
160+
161+
### Date Picker Components
162+
```typescript
163+
import { DatePicker } from '@medusajs/ui';
164+
// Special props: dateFormat, minDate, maxDate, filterDate
165+
```
166+
167+
## Type Safety Requirements
168+
- Use generic types `<T extends FieldValues>` for all controlled components
169+
- Properly type `Path<T>` for name props
170+
- Extend `BasicFieldProps` for all UI components
171+
- Use proper ref types based on underlying HTML element
172+
173+
## Error Handling Pattern
174+
```typescript
175+
// In controlled components
176+
const {
177+
control,
178+
formState: { errors },
179+
} = useFormContext<T>();
180+
181+
// Pass errors to UI component
182+
<ComponentName
183+
{...field}
184+
{...props}
185+
formErrors={errors}
186+
/>
187+
```
188+
189+
## Validation Integration
190+
- Use `rules` prop for react-hook-form validation
191+
- Support both built-in and custom validation rules
192+
- Ensure error messages are user-friendly and specific
193+
194+
```typescript
195+
<ControlledInput
196+
name="email"
197+
label="Email Address"
198+
rules={{
199+
required: 'Email is required',
200+
pattern: {
201+
value: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i,
202+
message: 'Invalid email address'
203+
}
204+
}}
205+
/>
206+
```
207+
208+
## Accessibility Requirements
209+
- All form fields must have proper labels via FieldWrapper
210+
- Use ARIA attributes provided by @medusajs/ui components
211+
- Ensure keyboard navigation works correctly
212+
- Provide clear error announcements for screen readers
213+
214+
## Component Naming Conventions
215+
- Controlled components: `ControlledComponentName` (e.g., `ControlledInput`, `ControlledCheckbox`)
216+
- UI components: `ComponentName` (e.g., `Input`, `FieldCheckbox`)
217+
- Props interfaces: `ComponentNameProps`
218+
- File names: PascalCase matching component name
219+
220+
## Export Requirements
221+
Always export both the component and its props type:
222+
```typescript
223+
export { ControlledComponentName };
224+
export type { Props as ControlledComponentNameProps };
225+
```
226+
227+
## Performance Considerations
228+
- Use React.memo for expensive form components when needed
229+
- Avoid unnecessary re-renders by properly structuring form state
230+
- Consider field-level subscriptions for large forms
231+
232+
## Testing Integration
233+
- Components should work with existing Storybook patterns
234+
- Test both valid and invalid form states
235+
- Verify @medusajs/ui component integration
236+
- Test component composition and customization
237+
238+
## Common Patterns to Avoid
239+
- **Don't** use remix-hook-form patterns (use react-hook-form directly)
240+
- **Don't** create custom UI components when @medusajs/ui equivalents exist
241+
- **Don't** bypass FieldWrapper for form fields
242+
- **Don't** mix controlled and uncontrolled patterns
243+
- **Don't** forget to handle both onChange and field.onChange in controlled components
244+
245+
## Medusa Design System Compliance
246+
- Follow Medusa UI spacing and sizing conventions
247+
- Use Medusa color tokens and design patterns
248+
- Ensure components work with Medusa themes
249+
- Maintain consistency with Medusa component APIs
250+
251+
Remember: Medusa Forms are specifically designed to integrate with the Medusa ecosystem. Always prioritize @medusajs/ui component usage and follow Medusa design system principles while maintaining the react-hook-form integration patterns.
252+

0 commit comments

Comments
 (0)