name: f0-code-review description: Code review checklist for the F0 React component library. Use when reviewing PRs, auditing component code quality, or checking compliance with F0 conventions before merging. Covers component structure, TypeScript strictness, testing standards, styling, accessibility, and Storybook requirements.
F0 Code Review
Review F0 React components against the conventions in packages/react/AGENTS.md. This skill adds review-specific guidance on top of those standards.
Review Workflow
- Read
packages/react/AGENTS.mdfor full component conventions - For components with interactive or animated elements, also load the
a11yskill (vendor/skills/a11y/) for detailed WCAG patterns - Check each item below — flag violations with severity
- Classify issues as blocking (must fix) or suggestion (nice to have)
Blocking Issues
Flag these as blocking — they must be fixed before merge:
TypeScript
anyoras anyusage anywhereimport * as Reactinstead of named imports- Default exports on components
- Circular imports
Component Structure
- Missing
displayNameonforwardRefcomponents - Direct Radix/third-party primitive import (must use
@/ui/wrappers) - New component name missing
F0prefix - New component placed in
experimental/instead ofcomponents/(useexperimentalComponentfrom@/lib/experimental.ts) - Internal components or
internal-types.tsexported publicly - New component not exported in
exports.ts
Testing
- Missing test file for new/changed components
- Test files named
.spec.tsinstead of.test.tsx - Using
renderfrom@testing-library/reactinstead ofzeroRenderfrom@/testing/test-utils.tsx - Using
jest.fn()instead ofvi.fn() - Snapshot testing (use explicit assertions only)
Storybook
- Missing
Snapshotstory withwithSnapshot({})for Chromatic
Security
dangerouslySetInnerHTMLwithout explicit justification
Suggestions (Non-blocking)
Flag these as suggestions:
Code Quality
- Comments describing "what" instead of "why"
- Missing
React.memo/useMemo/useCallbackwhere beneficial - Missing cleanup in
useEffect classNameexposed on public component API (should be a private prop)- Union type props not using const array pattern
Testing
- Using
fireEventwhereuserEventwould be more appropriate - Coverage appears below 80%
- Missing helper functions for repeated multi-step interactions
Accessibility
- Missing
useReducedMotion()check in animated components - Missing
aria-live="polite"on loading/skeleton states - Missing
sr-onlylabel on icon-only buttons - Focusable element missing
focusRing() - Interactive div missing keyboard handler (
onKeyDownfor Enter/Space) ortabIndex={0}+role
i18n
- Hardcoded user-facing strings (should use
useI18n()) - Missing fallback for translation keys
Styling
- CSS modules or CSS-in-JS usage (should use Tailwind)
- CVA imported from
"class-variance-authority"instead of"cva" - Inline
stylefor values expressible as Tailwind classes
Storybook Review
Verify stories follow these F0-specific patterns:
- Meta uses
satisfies Meta<typeof Component>(notas Meta) - Tags include
["autodocs", "stable"]or["autodocs", "experimental"] - ArgTypes for union props reference the component's const array directly
- Union types without const arrays use
table.type.summary - Snapshot story renders all meaningful variants in a flex layout
// Required Snapshot pattern
export const Snapshot: Story = {
parameters: withSnapshot({}),
render: () => (
<div className="flex w-fit flex-col gap-2">
{/* All meaningful variants */}
</div>
),
}
Props Review Checklist
- Names are functional and clear (
only-iconnothide-icon+hide-label) - Union types use exported const arrays:
export const colors = ["a", "b", "c"] as const export type Color = (typeof colors)[number] - Public interfaces are exported, internal types stay in
internal-types.ts - Default prop values set inline during destructuring (not
defaultProps) DataAttributesfrom@/global.typesused fordata-*prop support where needed