{"_id":"@ahmed.tawfik.galal/prep-design-system","name":"@ahmed.tawfik.galal/prep-design-system","dist-tags":{"latest":"0.1.0"},"versions":{"0.1.0":{"name":"@ahmed.tawfik.galal/prep-design-system","version":"0.1.0","type":"module","main":"./dist/index.cjs.js","module":"./dist/index.es.js","types":"./dist/index.d.ts","sideEffects":["**/*.css"],"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.es.js","require":"./dist/index.cjs.js"},"./style.css":"./dist/prep-design-system.css"},"scripts":{"dev":"vite","build":"tsc -b && vite build","lint":"eslint .","preview":"vite preview","test":"vitest","storybook":"storybook dev -p 6006","build-storybook":"storybook build","tokens:build":"node style-dictionary.config.mjs","size":"size-limit","build:lib":"vite build --config vite.lib.config.ts","prepublishOnly":"npm run build:lib"},"peerDependencies":{"react":"^19.0.0","react-dom":"^19.0.0"},"dependencies":{"react":"^19.2.8","react-dom":"^19.2.8"},"devDependencies":{"@chromatic-com/storybook":"latest","@eslint/js":"^10.0.1","@size-limit/preset-small-lib":"^13.0.3","@storybook/addon-a11y":"^10.6.0","@storybook/addon-docs":"^10.6.0","@storybook/addon-mcp":"^10.6.0","@storybook/addon-vitest":"^10.6.0","@storybook/react-vite":"^10.6.0","@testing-library/jest-dom":"^7.0.1","@testing-library/react":"^16.3.3","@types/node":"^24.13.3","@types/react":"^19.2.18","@types/react-dom":"^19.2.4","@vitejs/plugin-react":"^6.1.0","@vitest/browser-playwright":"5.0.0","@vitest/coverage-v8":"5.0.0","eslint":"^10.9.0","eslint-plugin-react-hooks":"^7.1.1","eslint-plugin-react-refresh":"^0.5.4","eslint-plugin-storybook":"^10.6.0","globals":"^17.11.0","jsdom":"^29.1.1","playwright":"latest","size-limit":"^13.0.3","storybook":"^10.6.0","style-dictionary":"^5.5.3","typescript":"~6.0.2","typescript-eslint":"^8.67.0","vite":"^8.2.2","vite-plugin-dts":"^5.1.0","vitest":"^5.0.0"},"_id":"@ahmed.tawfik.galal/prep-design-system@0.1.0","gitHead":"1b7e38bf888d3201018f6b9e65a87936d492cb21","description":"![CI](https://github.com/ahmedtawfikgalal/prep-design-system/actions/workflows/ci.yml/badge.svg)","_nodeVersion":"24.9.0","_npmVersion":"11.6.0","dist":{"integrity":"sha512-TeBMZv6ID8nIy0faOM1Gmiok2pLWsaFuTjQ2B73EdDoJRhmyuzQKep93mP2SwnH/PzrKJVwGNVGYLE8UVCTQKw==","shasum":"4af0e2877231b7ca780ef4672808390dfbe62d2f","tarball":"https://registry.npmjs.org/@ahmed.tawfik.galal/prep-design-system/-/prep-design-system-0.1.0.tgz","fileCount":12,"unpackedSize":33582,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCICBNmF0EYWb1Bg3LhTuiDAftrQF7W0qyRJGNFCjS0fdlAiEArpe+K8lc5Tc1/hIDI0i5e4hq7zmtigRjrZXj2zNXshA="}]},"_npmUser":{"name":"ahmed.tawfik.galal","email":"ahmed.tawfik.galal@gmail.com"},"directories":{},"maintainers":[{"name":"ahmed.tawfik.galal","email":"ahmed.tawfik.galal@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/prep-design-system_0.1.0_1788804742283_0.9888776072016494"},"_hasShrinkwrap":false}},"time":{"created":"2026-09-07T18:12:22.105Z","0.1.0":"2026-09-07T18:12:22.414Z","modified":"2026-09-07T18:12:22.663Z"},"maintainers":[{"name":"ahmed.tawfik.galal","email":"ahmed.tawfik.galal@gmail.com"}],"description":"![CI](https://github.com/ahmedtawfikgalal/prep-design-system/actions/workflows/ci.yml/badge.svg)","readme":"# prep-design-system\n\n![CI](https://github.com/ahmedtawfikgalal/prep-design-system/actions/workflows/ci.yml/badge.svg)\n\nA token-driven React + TypeScript component library, built with accessibility and a single source of truth for design values as first-class requirements — not afterthoughts.\n\n## Components\n\n| Component | What it does |\n|---|---|\n| **Button** | Primary/secondary variants, disabled state, safe `type=\"button\"` default |\n| **Input** | Token-driven, forwards native props and refs, supports invalid state |\n| **Modal** | Accessible dialog — overlay/Escape/close-button dismiss, `role=\"dialog\"` + `aria-modal` |\n| **Toast** | Info/success/error variants, optional auto-dismiss, correct `alert`/`status` roles |\n| **DataTable** | Generic, supports custom cell rendering, handles empty state |\n| **FormField** | Automatically wires label, hint, and error message to its control — zero manual ARIA wiring required |\n\nEvery component ships with a co-located `.css` file (tokens only, no hardcoded values), Storybook stories covering realistic states, and a behavioral test suite (not just render checks).\n\n## Quick example — FormField's automatic accessibility wiring\n\n```tsx\nimport { FormField } from './components/FormField/FormField';\nimport { Input } from './components/Input/Input';\n\n<FormField label=\"Email\" error=\"This field is required\">\n  <Input />\n</FormField>\n```\n\nThat's it — no manual `aria-describedby`, no manual `id` matching, no manual `aria-invalid`. FormField generates a stable id, links the label via `htmlFor`, and injects the correct ARIA attributes onto its child automatically. See [ADR 0003](docs/adr/0003-accessible-composition-via-clone-element.md) for why this is built this way, and what it requires of any control used inside FormField.\n\n## Design tokens\n\nDesign values (colors, spacing, typography, and effects like radius/shadow/z-index) are **not** hand-written in multiple places. They live as JSON under `design-system/tokens/`, and are compiled into `src/tokens/tokens.css` (CSS custom properties) via [Style Dictionary](https://styledictionary.com/).\n\n**To add or change a token:**\n1. Edit the relevant JSON file under `design-system/tokens/`\n2. Regenerate the CSS: npm run tokens:build\n3. Commit the JSON change and the regenerated `src/tokens/tokens.css` together\n\nNever edit `src/tokens/tokens.css` directly — it's a generated file (see the header comment in the file itself). See [ADR 0002](docs/adr/0002-style-dictionary-single-source-of-truth.md) for the reasoning.\n\n## Development\n\n```bash\nnpm install --legacy-peer-deps\nnpm run tokens:build      # generate tokens.css from JSON — required before first run\nnpm run dev                # run the app\nnpm run storybook          # component playground at http://localhost:6006\nnpx vitest run             # unit + Storybook interaction tests\nnpm run lint\nnpm run build\n```\n\n> `--legacy-peer-deps` is currently required due to a version mismatch between `@storybook/addon-vitest` and `vitest@5.x`. Safe to remove once Storybook publishes a compatible release.\n\n## Architecture decisions\n\nSignificant design decisions are documented as ADRs in [`docs/adr/`](docs/adr/):\n\n- [0001 — Styling approach: inline styles vs. CSS](docs/adr/0001-styling-approach-inline-styles-vs-css.md)\n- [0002 — Style Dictionary as the tokens single source of truth](docs/adr/0002-style-dictionary-single-source-of-truth.md)\n- [0003 — Accessible composition via `cloneElement`](docs/adr/0003-accessible-composition-via-clone-element.md)\n\n## CI\n\nEvery push to `main` runs lint, token generation, the full test suite (unit + Storybook browser tests via Playwright), and both app and Storybook production builds. See [`.github/workflows/ci.yml`](.github/workflows/ci.yml).","readmeFilename":"README.md","_rev":"1-677c9397d6db5405d51be1d0105d5bb2"}