Agent skill
react-components
React component patterns and style guide for the Commons monorepo. Use when creating React components, working with GraphQL in components, or implementing internationalization with MessageFormat.
Install this agent skill to your Project
npx add-skill https://github.com/jakewaldrip/.dotfiles/tree/main/.config/opencode/skill/react-component-writing
SKILL.md
React Components
Component Guidelines
- Named exports only:
export const MyComponent = ...(no default exports) - Plain arrow functions: Don't type with
React.FC - No spread props in GraphQL wrappers: List all props individually for type safety
interface MyComponentProps {
title: MessageFormat;
onSubmit: () => void;
}
export const MyComponent = ({ title, onSubmit }: MyComponentProps) => {
// ...
};
UI Components (no GraphQL)
Simple structure—see example: commons-packages/frontend/shared/example-ui-component/
interface ExampleUiComponentProps {
description?: MessageFormat;
onSubmitClick: () => void;
title: MessageFormat;
}
export const ExampleUiComponent = ({ description, onSubmitClick, title }: ExampleUiComponentProps) => {
// Component implementation
};
GraphQL Components
Separate into two components:
- UI sub-component (
MyComponentUI): Renders UI, receives data as props - GraphQL wrapper (
MyComponent): Fetches data, passes to UI
See example: commons-packages/frontend/shared/example-graphql-component/
// UI sub-component
interface MyComponentUIProps extends MyComponentBaseProps {
error?: ApolloError;
isLoading?: boolean;
data?: GetDataQuery['data'];
}
export const MyComponentUI = ({ error, isLoading, data }: MyComponentUIProps) => {
if (isLoading) return <Spinner />;
if (error) return <ErrorComponent error={error} />;
return (/* render UI */);
};
// GraphQL wrapper
export const MyComponent = ({ id }: MyComponentProps) => {
const { data, loading, error } = useGetDataQuery({ variables: { id } });
return (
<MyComponentUI
isLoading={loading}
error={error}
data={data?.data}
/>
);
};
Custom Hooks
- Prefix with
use:useMyHook - Return typed objects or tuples
- Place in
hooks/directory or co-locate with component
interface UseMyHookResult {
value: string;
setValue: (v: string) => void;
isLoading: boolean;
}
export const useMyHook = (initialValue: string): UseMyHookResult => {
// ...
};
Internationalization
Use MessageFormat for text. Render with useFormatMessage from Commonplace (not useIntl from react-intl):
import { Text, useFormatMessage } from '@commons/frontend/shared/commonplace';
const Component = ({ pageNumber }: { pageNumber: number }) => {
const formatMessage = useFormatMessage();
const nextText = formatMessage({ id: 'shared.next' });
return <Text text={`${nextText}: ${pageNumber}`} />;
};
Testing
Import from test-utils
import { render } from '@commons/frontend/rtlTests/test-utils';
This wraps components with necessary providers (IntlProvider, MockedProvider, AppStateProvider, Router).
Two Approaches for GraphQL Components
-
Test UI sub-component directly — pass props without mocks:
tsxrender(<MyComponentUI data={mockData} isLoading={false} />); -
Use GraphQL mocks — test full wrapper:
tsxrender(<MyComponent id="123" />, { customMocks: [myMock] });
See examples: commons-packages/frontend/shared/example-graphql-component/__tests__/
File Structure
Co-locate related files:
my-component/
├── my-component.tsx
├── my-component.graphql
├── my-component.css (or .module.css)
└── __tests__/
└── my-component.spec.tsx
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
react-component-writing
React component patterns and style guide for the Commons monorepo. Use when creating React components, working with GraphQL in components, or implementing internationalization with MessageFormat.
graphite-cli
Use Graphite CLI (gt) for stacked PRs and branch management. Use when creating branches, committing changes, submitting PRs, syncing with trunk, or managing stacked pull requests.
test-running
Run Jest tests in the Commons monorepo. Use when testing code changes, validating implementations, debugging test failures, or when the user mentions running tests.
document-type-adding
Add new document types to the DocuSign integration in the Commons monorepo. Use when the user wants to add a patient document, consent form, or agreement to the DocuSign workflow.
dataloader-dual-mode-migration
Migrate dataloaders to dual-mode pattern supporting both patientId and enrollmentId for Member Model 2.0. Use when converting a patient-based dataloader to support the MemberModelV2Switch.
feature-flag-create-or-remove
Create or remove feature flags in the Commons application. Use when the user wants to add a new feature flag, delete a feature flag, or asks about feature flag naming conventions.
Didn't find tool you were looking for?