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

3.7 KiB

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 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

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").