UI & Testing Standards
UI Implementation Standards
Our UI architecture focuses on consistency, reusability, and type safety. We utilize a component-driven development approach, where Claude Code is trained to prioritize our local design system over generic libraries.
Core Component Patterns
All UI components should reside in the src/components directory and follow a modular structure. When creating new UI elements, adhere to these requirements:
- Functional Components: Use TypeScript functional components (
FC) with explicit prop interfaces. - Composition Over Inheritance: Build complex layouts by nesting smaller, atomic components.
- Style Isolation: Use our standardized styling solution (as defined in
.claude/skills/core-components/SKILL.md) to ensure visual consistency.
interface ButtonProps {
label: string;
variant: 'primary' | 'secondary';
onClick: () => void;
isLoading?: boolean;
}
export const Button: React.FC<ButtonProps> = ({ label, variant, onClick, isLoading }) => {
return (
<button className={`btn-${variant}`} onClick={onClick} disabled={isLoading}>
{isLoading ? <Spinner /> : label}
</button>
);
};
Form Handling with Formik
We use Formik as our primary library for managing form state and validation. This ensures a predictable data flow for complex user inputs.
- Validation Schemas: Always pair Formik with Yup or Zod for schema-based validation.
- Custom Inputs: Use the
useFieldhook to create custom inputs that integrate seamlessly with the Formik context. - Submission Handling: Keep submission logic decoupled from the UI by passing
onSubmithandlers as props.
import { Formik, Form, Field } from 'formik';
import * as Yup from 'yup';
const SignupSchema = Yup.object().shape({
email: Yup.string().email('Invalid email').required('Required'),
});
export const RegistrationForm = () => (
<Formik
initialValues={{ email: '' }}
validationSchema={SignupSchema}
onSubmit={(values) => submitToApi(values)}
>
{({ errors, touched }) => (
<Form>
<Field name="email" />
{errors.email && touched.email ? <div>{errors.email}</div> : null}
<button type="submit">Submit</button>
</Form>
)}
</Formik>
);
Standardized Testing Strategy
Testing is not an afterthought; it is integrated into the development lifecycle via automated quality gates and Claude Code "skills."
Test Levels
| Level | Tooling | Focus | | :--- | :--- | :--- | | Unit | Jest / Vitest | Business logic, utility functions, and pure components. | | Integration | React Testing Library | Component interactions and hook behaviors. | | End-to-End | Maestro / Playwright | Critical user journeys and cross-module workflows. |
Testing Patterns
To maintain a high-quality codebase, all test files must follow these patterns:
- Placement: Tests should be located in a
__tests__directory adjacent to the file being tested or use the.test.tsxsuffix. - Mocking: Use standard mock patterns for API calls (MSW is preferred) and external dependencies.
- Accessibility: Favor testing via accessibility roles (e.g.,
screen.getByRole('button')) rather than implementation details or IDs.
Automated Quality Gates
Claude Code monitors the testing environment through several hooks defined in .claude/settings.json:
- Pre-commit Validation: Runs TypeScript type-checking and ESLint checks.
- Reactive Testing: When a file in
src/is modified, Claude is configured to suggest updates to the corresponding test file or run the relevant test suite automatically. - PR Review Agent: Our automated reviewer checks for test coverage and ensures that new features include appropriate unit and integration tests before allowing a merge.
# Manual execution of the test suite
npm test
# Running specific skill-based testing checks via Claude
/ask Claude "Run the testing-patterns skill on my recent changes"
Mobile E2E with Maestro
For mobile-specific UI flows, we utilize Maestro. Flows are defined in .maestro/ and are automatically triggered by our GitHub Actions workflows to ensure UI regressions are caught early in the development cycle.