|
| 1 | +# CLAUDE.md |
| 2 | + |
| 3 | +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. |
| 4 | + |
| 5 | +## Commands |
| 6 | + |
| 7 | +All `npm` commands must be run inside Docker containers. Use `node_shell` for most tasks, `playwright` for visual tests. |
| 8 | + |
| 9 | +```bash |
| 10 | +# Enter node_shell container |
| 11 | +docker compose run --rm node_shell |
| 12 | + |
| 13 | +# Enter playwright container (for visual tests) |
| 14 | +docker compose run --rm --service-ports playwright |
| 15 | +``` |
| 16 | + |
| 17 | +**Within `node_shell`:** |
| 18 | + |
| 19 | +```bash |
| 20 | +npm run lint # All linters (ESLint + Stylelint + Markdownlint) |
| 21 | +npm run eslint # JS + TS linting |
| 22 | +npm run stylelint # SCSS linting |
| 23 | +npm run test:jest # All Jest unit tests |
| 24 | +npm run test:jest:ts -- <file> # Single TypeScript test file |
| 25 | +npm run test:jest:js -- <file> # Single JavaScript test file |
| 26 | +``` |
| 27 | + |
| 28 | +**Within `playwright`:** |
| 29 | + |
| 30 | +```bash |
| 31 | +npm run test:playwright-ct:all # All component tests |
| 32 | +npm run test:playwright-ct:all-with-update # Update snapshots |
| 33 | +npm run test:playwright-ct:all -- -- src/components/Button # Tests for one component |
| 34 | +npm run test:playwright-ct:show-report # Serve test report at localhost:9323 |
| 35 | +``` |
| 36 | + |
| 37 | +Playwright snapshots must always be generated inside the Docker container — snapshots differ between operating systems. |
| 38 | + |
| 39 | +## Architecture |
| 40 | + |
| 41 | +React UI is a themeable React component library. It is distributed in two ways: |
| 42 | + |
| 43 | +- **UMD bundle** with separate CSS — ready to use out of the box |
| 44 | +- **ESM** — users are responsible for their own SASS pipeline to compile the styles |
| 45 | + |
| 46 | +### Component structure |
| 47 | + |
| 48 | +Each component lives in `src/components/<ComponentName>/` and follows this layout: |
| 49 | + |
| 50 | +``` |
| 51 | +Button/ |
| 52 | + Button.jsx # Component implementation (React.forwardRef + withGlobalProps) |
| 53 | + Button.module.scss # CSS Modules styles |
| 54 | + index.js # Re-exports default (withGlobalProps-wrapped) as named export |
| 55 | + _settings.scss # Component-level SCSS variables |
| 56 | + _theme.scss # CSS custom properties (design tokens) |
| 57 | + _tools.scss # SCSS mixins |
| 58 | + README.md # Docoff/MkDocs documentation with live previews |
| 59 | + helpers/ # Component-specific helper functions |
| 60 | + __tests__/ |
| 61 | + Button.spec.tsx # Playwright visual + functional tests |
| 62 | + Button.story.tsx # Story components used as test fixtures |
| 63 | + _propTests/ # Reusable prop test generators (arrays of test cases) |
| 64 | +``` |
| 65 | + |
| 66 | +### Component implementation pattern |
| 67 | + |
| 68 | +Components are `.jsx` files (not `.tsx`) using PropTypes. They: |
| 69 | +1. Use `React.forwardRef` to forward refs to the root HTML element |
| 70 | +2. Are wrapped with `withGlobalProps(Component, 'ComponentName')` for global prop injection; the wrapped version is the default export |
| 71 | +3. Use `useContext` to detect layout/group contexts (`FormLayoutContext`, `ButtonGroupContext`, `InputGroupContext`) and apply CSS class variants accordingly |
| 72 | +4. Use `classNames()` helper to conditionally combine CSS Module class names |
| 73 | +5. Use `transferProps()` to pass through non-React HTML attributes to the root element |
| 74 | + |
| 75 | +### Styling |
| 76 | + |
| 77 | +- CSS Modules (`.module.scss`) with camelCase class names |
| 78 | +- Class naming convention: `root` for the root element; modifiers follow `isRootXxx` (state), `hasRootXxx` (has feature), `isRootInXxx` (context), `isRootLayoutXxx` (layout variant) |
| 79 | +- `src/styles/` contains the global theming system: settings (variables), tools (mixins), and a large set of CSS custom properties for theming |
| 80 | +- Component SCSS files `@use` their own `settings`, `theme`, `tools` partials plus shared styles from `src/styles/` |
| 81 | + |
| 82 | +### Testing patterns |
| 83 | + |
| 84 | +**Playwright component tests** (`.spec.tsx`) use a table-driven pattern: |
| 85 | +- Import arrays of test cases from `_propTests/` directories and from shared `tests/playwright/propTests/` |
| 86 | +- Each test case is `{ name, props, onBeforeTest?, onBeforeSnapshot? }`; custom field tests add `customFieldLayoutProps`, `customFieldProps`, etc. |
| 87 | +- `mixPropTests([...arrays])` generates the cartesian product of multiple prop arrays |
| 88 | +- `propTests` from `tests/playwright/` provides standard reusable test sets (e.g. `layoutPropTest`, `sizePropTest`, `disabledPropTest`) |
| 89 | +- Snapshot images are stored alongside the spec file in `<ComponentName>.spec.tsx-snapshots/` |
| 90 | + |
| 91 | +**Story components** (`.story.tsx`) wrap the real component in a minimal fixture (sometimes inside a context provider) and are imported only by `.spec.tsx` files. Naming convention: `<ComponentName>ForTest`, `<ComponentName>ForRefTest`, `<ComponentName>ForFormLayoutTests` — FormLayout story component is always last. |
| 92 | + |
| 93 | +**Test describe structure:** `test.describe('ComponentName')` → `test.describe('base')` (if present) → `visual` / `non-visual` / `functionality`; `formLayout` describe is always the last block at the same level as `base`. |
| 94 | + |
| 95 | +### Git workflow |
| 96 | + |
| 97 | +Branch naming: `bc/*`, `feature/*`, `bugfix/*`, `refactoring/*`, `docs/*`, `maintenance/*` |
| 98 | + |
| 99 | +Commit messages: imperative English, component names in backticks (e.g. `` Add `FormLayout` context awareness to `Button` ``). No `Co-Authored-By` lines. |
| 100 | + |
| 101 | +PR names follow the same rules as commit messages and are used directly in the changelog. Only PRs into `master` appear in the changelog. |
0 commit comments