Files
modern-sk/CLAUDE.md
T
2026-05-31 16:47:52 +03:00

54 lines
3.7 KiB
Markdown

# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## What this is
`@modernsk/ui` — a tactile, dark-first React component library built on [Radix](https://www.radix-ui.com/) primitives. Distributed as a git-installable / publishable package; only `dist/` ships. Consumers get built ESM + CJS, `.d.ts` types, and a single `styles.css`.
## Commands
```bash
npm run dev # Rsbuild playground at http://localhost:3000 (renders src/App.tsx — every component on one page)
npm run build # build publishable package: tsup (JS/types) + build:css (bundled stylesheet) into dist/
npm run lint # rslint (rslint.config.ts)
npm run format # prettier --write .
```
No test suite exists. `npm run build` runs automatically on install via the `prepare` script — consumers build the package themselves.
The build is two steps that must both run (the `build` script chains them):
- `tsup` bundles `src/index.ts` → ESM/CJS + types. `react`/`react-dom` are externalized (peer deps); `radix-ui` + `@phosphor-icons/react` are bundled.
- `build:css` runs esbuild on `src/styles/index.css` with `--loader:.ttf=dataurl`, inlining the self-hosted Anta font so no asset hosting is needed.
## Architecture
Two parallel surfaces share the same source but never mix at publish time:
- **Library (shipped):** `src/index.ts` is the public entry. It re-exports everything from `src/components/ui.tsx`, plus `ThemeProvider`/`useTheme` from `src/components/theme.tsx`, and exposes `TooltipProvider` (Radix's `Tooltip.Provider`). The shipped stylesheet entry is `src/styles/index.css`.
- **Playground (dev-only, never published):** `src/index.tsx` mounts `src/App.tsx`, and uses `src/styles/global.css`. These are the Rsbuild dev target only.
`src/styles/index.css` (shipped) vs `src/styles/global.css` (dev) is a deliberate split: `index.css` imports only `tokens.css` + `components.css` and applies box-sizing at **zero specificity** via `:where([class^='msk-'])` so it never touches consumer elements. `global.css` adds a global reset and kitchen-sink layout helpers — those must stay out of the shipped bundle.
### Components (`src/components/ui.tsx`)
All components live in one file. Pattern: Radix provides logic/accessibility, every visual comes from CSS. Components are thin wrappers that attach `msk-*` classes and spread props. The `cx()` helper joins class names (no classnames dependency). Components forward refs where they wrap a DOM element. There is no inline styling and no CSS-in-JS — **all appearance is driven by `msk-*` classes resolving against CSS custom properties.**
### Styling system (`src/styles/`)
- `tokens.css` — single source of truth: color/type CSS custom properties, `@font-face`, Google Fonts import. Every component reads from here.
- `components.css` — the `msk-*` class definitions.
- Dark/light is driven by `data-theme` on `<html>`, set by `ThemeProvider` (persisted to `localStorage` under key `msk-theme`, default `dark`).
When adding or changing a component: add the wrapper in `ui.tsx`, define its `msk-*` styles in `components.css`, and pull any new color/spacing value from a token in `tokens.css` rather than hardcoding.
## Consumer contract
Consumers import `@modernsk/ui/styles.css` once at app root, wrap their tree in `ThemeProvider`, and wrap any tooltip-using subtree in `TooltipProvider`. Keep these provider requirements intact when refactoring exports.
## Conventions
- React 19, React Compiler is enabled (`babel-plugin-react-compiler` in the Rsbuild dev pipeline).
- TypeScript is `noEmit` + `verbatimModuleSyntax`: use `import type` for type-only imports. `noUnusedLocals`/`noUnusedParameters` are on.
- ESM-only package (`"type": "module"`).