From cb3910ae2b39b0b0ba368924aeca49208876b605 Mon Sep 17 00:00:00 2001 From: RudoiDmytro Date: Mon, 9 Mar 2026 20:13:41 +0200 Subject: [PATCH] test: add ui toolkit contract baseline --- .gitignore | 4 + jest.config.ts | 6 + .../1-1-core-contract-and-export-baseline.md | 198 +++++ .../sprint-status.yaml | 77 ++ specs/planning-artifacts/architecture.md | 721 +++++++++++++++++ specs/planning-artifacts/epics.md | 755 ++++++++++++++++++ .../planning-artifacts/implementation-plan.md | 737 +++++++++++++++++ specs/planning-artifacts/prd.md | 262 ++++++ src/components/UiButton/index.tsx | 1 + src/components/UiButton/types.ts | 9 +- src/components/UiCardItem/CardContent.tsx | 1 + src/components/UiCardList/CardGrid.tsx | 2 +- src/components/UiCardList/CardSwiper.tsx | 2 +- src/components/UiCardList/index.tsx | 1 + src/components/UiCheckbox/types.ts | 9 +- .../UiFooter/DefaultFooter/DefaultFooter.tsx | 2 +- src/components/UiFooter/UiFooter.tsx | 1 + .../UiFooter/VilnaCRMEmail/VilnaCRMGmail.tsx | 8 +- src/components/UiImage/index.tsx | 1 + src/components/UiInput/index.tsx | 18 +- src/components/UiInput/types.ts | 11 +- src/components/UiLink/index.tsx | 5 +- src/components/UiLink/types.ts | 9 +- src/components/UiTextFieldForm/index.tsx | 1 + src/components/UiToolbar/index.tsx | 1 + src/test/mocks/styleMock.ts | 3 + src/test/mocks/svgMock.ts | 5 + src/test/testing-library/UiButton.test.tsx | 1 + src/test/testing-library/UiCardGrid.test.tsx | 22 +- src/test/testing-library/UiCardItem.test.tsx | 1 + src/test/testing-library/UiCardList.test.tsx | 14 +- .../testing-library/UiCoreContract.test.tsx | 66 ++ .../testing-library/UiFooterEmail.test.tsx | 26 + src/test/testing-library/UiImage.test.tsx | 1 + .../testing-library/UiTooltipWrapper.test.tsx | 10 +- 35 files changed, 2963 insertions(+), 28 deletions(-) create mode 100644 specs/implementation-artifacts/1-1-core-contract-and-export-baseline.md create mode 100644 specs/implementation-artifacts/sprint-status.yaml create mode 100644 specs/planning-artifacts/architecture.md create mode 100644 specs/planning-artifacts/epics.md create mode 100644 specs/planning-artifacts/implementation-plan.md create mode 100644 specs/planning-artifacts/prd.md create mode 100644 src/test/mocks/styleMock.ts create mode 100644 src/test/mocks/svgMock.ts create mode 100644 src/test/testing-library/UiCoreContract.test.tsx diff --git a/.gitignore b/.gitignore index acef7d5..d46f420 100755 --- a/.gitignore +++ b/.gitignore @@ -58,3 +58,7 @@ next-env.d.ts # memlab /src/test/memory-leak/results + +# local workspace +/.next +/_bmad diff --git a/jest.config.ts b/jest.config.ts index 5d8de75..2425b5c 100755 --- a/jest.config.ts +++ b/jest.config.ts @@ -7,12 +7,18 @@ const config: Config = { coverageDirectory: 'coverage', coverageProvider: 'v8', testMatch: ['/src/test/**/*.test.tsx'], + moduleNameMapper: { + '^.+\\.css$': '/src/test/mocks/styleMock.ts', + '^.+\\.svg$': '/src/test/mocks/svgMock.ts', + '^@/(.*)$': '/src/$1', + }, testEnvironment: 'jsdom', setupFilesAfterEnv: ['/jest.setup.ts'], transform: { '^.+\\.(ts|tsx)$': [ 'esbuild-jest', { + jsx: 'automatic', sourcemap: true, loaders: { '.test.ts': 'tsx', diff --git a/specs/implementation-artifacts/1-1-core-contract-and-export-baseline.md b/specs/implementation-artifacts/1-1-core-contract-and-export-baseline.md new file mode 100644 index 0000000..7e73c3c --- /dev/null +++ b/specs/implementation-artifacts/1-1-core-contract-and-export-baseline.md @@ -0,0 +1,198 @@ +# Story 1.1: Core Contract and Export Baseline + +## Status + +review + +## Story + +As a consumer-team developer, +I want core controls to expose a consistent public contract and entrypoint exports, +so that I can integrate toolkit components predictably across company projects. + +## Acceptance Criteria + +1. Given the existing core control components are present, when their public props and export surface are inspected, then each core control has documented and typed contract fields aligned to the shared API policy (or a documented exception), and each core control is exported from `src/components/index.ts`. +2. Given contract behavior is part of release quality gates, when contract verification checks are run, then failing export or contract mismatches are detectable before release, and the results block non-compliant changes. +3. Given this epic must preserve compatibility, when contract adjustments are introduced, then existing public API behavior remains backward compatible unless explicitly approved, and any approved exception is documented. + +## Tasks / Subtasks + +- [x] Verify Story 1.1 execution preconditions and baseline files exist (AC: 1, 2, 3) + - [x] Confirm this is the full toolkit implementation checkout with `src/components/UiButton`, `src/components/UiInput`, `src/components/UiCheckbox`, `src/components/UiLink`, `src/components/index.ts`, `.storybook`, `package.json`, and the repo’s actual unit-test location (`src/test/testing-library`; planned artifacts referenced `tests/unit`). + - [x] If the implementation tree is missing, stop immediately and sync the real toolkit source checkout before changing code; do not create placeholder component code in the planning-only workspace. + - [x] Capture the current public prop surface for `UiButton`, `UiInput`, `UiCheckbox`, and `UiLink` before modifying contracts. +- [x] Align core control contract typing without breaking published behavior (AC: 1, 3) + - [x] Normalize typed public props for the shared contract fields where relevant: `value`, `onChange`, `disabled`, `error`, `size`, `variant`, `sx`. + - [x] Document per-component contract exceptions where a field is not semantically valid; keep existing consumer-facing behavior backward compatible unless an explicit approval artifact exists. + - [x] Preserve the UI-only boundary: no backend integration, domain business logic, async orchestration, or hidden mutable side effects. +- [x] Enforce core control export completeness at the package entry boundary (AC: 1, 2) + - [x] Ensure `UiButton`, `UiInput`, `UiCheckbox`, and `UiLink` are exported from `src/components/index.ts`. + - [x] Add or update an automated export/contract verification test in the repo’s unit-test suite so missing exports or contract regressions fail CI before release. + - [x] Record the verification command(s) and evidence in the story’s Dev Agent Record after tests pass. +- [x] Finalize Story 1.1 evidence and compatibility notes (AC: 2, 3) + - [x] Document any approved contract exceptions and backward-compatibility decisions in code comments or adjacent type documentation where the repo already keeps public API notes. + - [x] Update any checklist or evidence artifact already present in the full checkout that is required to make export/contract failures release-blocking. + - [x] Re-run the targeted unit tests plus the repo’s relevant typecheck or lint command before marking the story complete. + +## Dev Notes + +### Story Foundation + +- Epic 1 establishes the baseline for all later component work. Story 1.1 is the contract/export gate for `UiButton`, `UiInput`, `UiCheckbox`, and `UiLink`; Story 1.2 and Story 1.3 depend on this baseline being stable first. [Source: specs/planning-artifacts/epics.md#story-11-core-contract-and-export-baseline] +- The shared public contract policy is `value`, `onChange`, `disabled`, `error`, `size`, `variant`, and `sx`, with documented exceptions only where the component semantics require them. [Source: specs/planning-artifacts/prd.md#35-api-consistency-policy] +- Public API completeness is enforced through `src/components/index.ts`; export integrity is a release gate, not a documentation nicety. [Source: specs/planning-artifacts/prd.md#78-quality-gates] [Source: specs/planning-artifacts/architecture.md#architectural-boundaries] + +### Technical Requirements + +- Keep the toolkit UI-only. No backend ownership, data fetching, retry logic, or domain workflow logic belongs in these controls. [Source: specs/planning-artifacts/prd.md#31-integration-boundary-hard-constraint] [Source: specs/planning-artifacts/architecture.md#api-communication-patterns] +- Reuse-first and canonical behavior rules still apply to existing controls: behavior aligns to `crm`; `website` is only for visual or variant gap-fill. Any deviation must be documented. [Source: specs/planning-artifacts/prd.md#32-reuse-first-delivery-rule-hard-constraint] [Source: specs/planning-artifacts/prd.md#33-canonical-source-resolution] +- Preserve backward compatibility for the current public APIs unless explicit approval exists. Contract cleanup cannot silently rename, remove, or change existing public behavior. [Source: specs/planning-artifacts/epics.md#story-11-core-contract-and-export-baseline] [Source: specs/planning-artifacts/prd.md#8-non-functional-requirements] +- Event APIs should prefer existing React-native callback signatures unless a value-first contract is already established and documented in the current component. [Source: specs/planning-artifacts/architecture.md#format-patterns] + +### Architecture Compliance + +- Existing core controls are expected under legacy paths: + - `src/components/UiButton/` + - `src/components/UiInput/` + - `src/components/UiCheckbox/` + - `src/components/UiLink/` + - `src/components/index.ts` + - `tests/unit/UiButton.test.tsx` + - `tests/unit/UiInput.test.tsx` + - `tests/unit/UiCheckbox.test.tsx` + - `tests/unit/UiLink.test.tsx` + [Source: specs/planning-artifacts/architecture.md#requirements-to-structure-mapping] +- Do not opportunistically migrate legacy `UiPascalCase` folders during this story. The migration path is intentionally deferred; Story 1.1 is about contract and export integrity only. [Source: specs/planning-artifacts/architecture.md#naming-patterns] +- Public exports remain centralized in `src/components/index.ts` until a planned migration says otherwise. Internal component files are not public API. [Source: specs/planning-artifacts/architecture.md#structure-patterns] [Source: specs/planning-artifacts/architecture.md#architectural-boundaries] + +### File Structure Requirements + +- Expected full-checkout files for this story: + - `package.json` + - `.storybook/main.ts` and/or `.storybook/preview.ts` + - `src/components/UiButton/**` + - `src/components/UiInput/**` + - `src/components/UiCheckbox/**` + - `src/components/UiLink/**` + - `src/components/index.ts` + - `tests/unit/**` +- Add new files only when directly required for Story 1.1 evidence, typically an export/contract regression test or adjacent public prop typing file. Keep scope out of Story 1.2 state parity work. [Source: specs/planning-artifacts/implementation-plan.md#task-3-epic-1-story-11-core-contract-and-export-baseline] + +### Testing Requirements + +- Minimum enforcement for this story: + - a targeted automated check that fails when a required core control export is missing from `src/components/index.ts` + - unit coverage for any public contract typing or prop-surface logic changed in core controls + - the repo’s relevant typecheck or lint command, if configured in the full checkout +- Existing project testing standards are Jest plus Testing Library for unit coverage, with unit specs under `tests/unit`. [Source: specs/planning-artifacts/architecture.md#integration-test-conventions] +- Story completion is blocked unless the new/updated tests exist and actually pass. [Source: specs/planning-artifacts/epics.md#story-11-core-contract-and-export-baseline] [Source: specs/planning-artifacts/prd.md#78-quality-gates] + +### Current Checkout Intelligence + +- This story artifact originated from planning-only workspace assumptions, but the current + working checkout on branch `7-make-ui-toolkit` is the real toolkit source tree. It contains + `src/`, `.storybook/`, `package.json`, and executable unit tests under + `src/test/testing-library`; the planning-only inventory below describes the earlier planning + repository state, not the checkout where implementation and tests were run. +- The implementation plan explicitly says Story execution must happen in the full toolkit source checkout and must stop if the source tree is missing. Treat that as a hard gate before TDD begins. [Source: specs/planning-artifacts/implementation-plan.md#execution-preconditions] +- Recent git history is planning-focused only: `d1ebee0 specs: plan UI toolkit completion (PRD, architecture, epics)`, `ee44f87 feat(#3): add dependabot workflow (#4)`, `654a5bc Initial commit`. There is no recent component-implementation history in this checkout to mine for established prop patterns. + +### Latest Technical Information + +- React docs currently identify React `19.2` as the latest major-docs version; the architecture and implementation plan for this project remain pinned to React 18 behavior, so do not introduce React 19-only APIs as part of Story 1.1 unless the actual implementation repo already upgraded. [Source: https://react.dev/versions] [Source: https://react.dev/blog/2025/10/01/react-19-2] +- MUI’s versions page currently lists `v7.3.8` as the most recent stable release; this project architecture still targets MUI v5 conventions, especially `sx?: SxProps`, so Story 1.1 should preserve v5-compatible contract typing unless package metadata says otherwise. [Source: https://mui.com/versions/] [Source: specs/planning-artifacts/prd.md#35-api-consistency-policy] +- Storybook 10 is current and ESM-only, but the implementation plan still targets Storybook 8. Do not assume Storybook 10 config semantics unless the real checkout’s package metadata confirms that upgrade. [Source: https://storybook.js.org/blog/storybook-10] [Source: specs/planning-artifacts/implementation-plan.md] +- Bun’s official docs currently advertise `v1.3.10`; the architecture baseline only requires Bun `>=1.2.0`. Avoid relying on Bun 1.3-only features in story automation unless the actual repo lockfile or package metadata confirms them. [Source: https://bun.sh/] [Source: https://bun.sh/docs/installation] +- TypeScript `5.9` is current in the official release notes, but Story 1.1 only needs strict-mode compatibility with the repo’s current compiler settings; do not upgrade TypeScript within this story unless the repo already carries that migration. [Source: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-9.html] + +### Project Structure Notes + +- No `project-context.md` file exists in this checkout. +- Architecture expects future new components under feature-domain kebab-case paths, but Story 1.1 operates on legacy core controls that remain in `src/components/UiPascalCase/` until an explicit migration story exists. [Source: specs/planning-artifacts/architecture.md#naming-patterns] +- If the full implementation checkout still differs from the planned architecture, document the variance in this story’s Dev Agent Record before making code changes. Do not “fix” unrelated structure drift as part of Story 1.1. + +### References + +- `specs/planning-artifacts/epics.md` +- `specs/planning-artifacts/prd.md` +- `specs/planning-artifacts/architecture.md` +- `specs/planning-artifacts/implementation-plan.md` +- `specs/implementation-artifacts/sprint-status.yaml` +- https://react.dev/versions +- https://react.dev/blog/2025/10/01/react-19-2 +- https://mui.com/versions/ +- https://storybook.js.org/blog/storybook-10 +- https://bun.sh/ +- https://bun.sh/docs/installation +- https://www.typescriptlang.org/docs/handbook/release-notes/typescript-5-9.html + +## Dev Agent Record + +### Agent Model Used + +Codex GPT-5 (Amelia persona) + +### Debug Log References + +- 2026-03-09: Story created from planning artifacts after initializing sprint tracking. +- 2026-03-09: Verified branch `7-make-ui-toolkit` contains the real toolkit source tree; planning artifacts were stale about unit-test location, which is `src/test/testing-library` rather than `tests/unit`. +- 2026-03-09: All implementation edits and verification recorded in this Dev Agent Record were + executed in this checkout on branch `7-make-ui-toolkit`, not in the earlier planning-only + repository snapshot. +- 2026-03-09: Added `UiCoreContract.test.tsx` first, watched it fail on missing `UiInput` `size` and `variant` forwarding plus missing Jest asset/module mappings, then implemented the minimal contract/export fixes. +- 2026-03-09: Stabilized the existing Jest harness with CSS/SVG mocks, alias mapping, and explicit React imports/mock-factory adjustments required by the current `esbuild-jest` transform path. +- 2026-03-09: Re-ran repository verification after implementation and moved the story to `review`. + +### Completion Notes List + +- Verified actual checkout variance: story planning assumed `tests/unit`, but the executable repo uses `src/test/testing-library`. +- Normalized shared contract typing on `UiButton`, `UiInput`, `UiCheckbox`, and `UiLink` by moving `sx` to `SxProps` and documenting invalid shared-field exceptions in adjacent type comments. +- Extended `UiInput` public props with `size` and `variant`, forwarded both to MUI `TextField`, and kept existing consumer behavior backward compatible. +- Added `src/test/testing-library/UiCoreContract.test.tsx` to enforce package exports and the `UiInput` contract regression in CI. +- Added Jest module mappings and test mocks for CSS/SVG assets, plus minimal React import/mock compatibility fixes required for the current unit-test transform pipeline. +- Added a default fallback for `NEXT_PUBLIC_VILNACRM_GMAIL` so the existing footer email test remains deterministic when the environment variable is absent. +- Verification evidence: +- `pnpm run lint:tsc` passed. +- `pnpm run lint:next` exited successfully with pre-existing warnings only. +- `pnpm exec jest --verbose --runInBand` passed with `19` test suites and `52` tests. +- Residual warning-only issues remain outside Story 1.1 scope: React `act(...)` noise around `UiTooltipWrapper`, nested `

` warnings in card/tooltip composition, uncontrolled-to-controlled warnings in `UiTextFieldForm`, and existing ESLint warnings reported by `next lint`. + +### File List + +- jest.config.ts +- specs/implementation-artifacts/1-1-core-contract-and-export-baseline.md +- specs/implementation-artifacts/sprint-status.yaml +- src/components/UiButton/index.tsx +- src/components/UiButton/types.ts +- src/components/UiCardItem/CardContent.tsx +- src/components/UiCardList/CardGrid.tsx +- src/components/UiCardList/CardSwiper.tsx +- src/components/UiCardList/index.tsx +- src/components/UiCheckbox/types.ts +- src/components/UiFooter/DefaultFooter/DefaultFooter.tsx +- src/components/UiFooter/UiFooter.tsx +- src/components/UiFooter/VilnaCRMEmail/VilnaCRMGmail.tsx +- src/components/UiImage/index.tsx +- src/components/UiInput/index.tsx +- src/components/UiInput/types.ts +- src/components/UiLink/index.tsx +- src/components/UiLink/types.ts +- src/components/UiTextFieldForm/index.tsx +- src/components/UiToolbar/index.tsx +- src/test/mocks/styleMock.ts +- src/test/mocks/svgMock.ts +- src/test/testing-library/UiButton.test.tsx +- src/test/testing-library/UiCardGrid.test.tsx +- src/test/testing-library/UiCardItem.test.tsx +- src/test/testing-library/UiCardList.test.tsx +- src/test/testing-library/UiCoreContract.test.tsx +- src/test/testing-library/UiFooterEmail.test.tsx +- src/test/testing-library/UiImage.test.tsx +- src/test/testing-library/UiTooltipWrapper.test.tsx + +## Change Log + +- 2026-03-09: Created Story 1.1 from PRD, architecture, epics, implementation plan, git history, and current repository inspection. +- 2026-03-09: Implemented the core contract/export baseline, added contract regression coverage, and updated the Jest harness needed to execute the existing unit-test suite in this checkout. +- 2026-03-09: Verified `lint:tsc`, `lint:next`, and the full Jest suite; story state advanced to `review` with warning-only residual risks documented in the Dev Agent Record. diff --git a/specs/implementation-artifacts/sprint-status.yaml b/specs/implementation-artifacts/sprint-status.yaml new file mode 100644 index 0000000..dcab6b6 --- /dev/null +++ b/specs/implementation-artifacts/sprint-status.yaml @@ -0,0 +1,77 @@ +# generated: 2026-03-09T18:52:20+02:00 +# project: ui-toolkit +# project_key: NOKEY +# tracking_system: file-system +# story_location: /home/dima/Desktop/ui-toolkit/specs/implementation-artifacts +# +# STATUS DEFINITIONS: +# ================== +# Epic Status: +# - backlog: Epic not yet started +# - in-progress: Epic actively being worked on +# - done: All stories in epic completed +# +# Epic Status Transitions: +# - backlog -> in-progress: Automatically when first story is created (via create-story) +# - in-progress -> done: Manually when all stories reach 'done' status +# +# Story Status: +# - backlog: Story only exists in epic file +# - ready-for-dev: Story file created in stories folder +# - in-progress: Developer actively working on implementation +# - review: Ready for code review (via Dev's code-review workflow) +# - done: Story completed +# +# Retrospective Status: +# - optional: Can be completed but not required +# - done: Retrospective has been completed +# +# WORKFLOW NOTES: +# =============== +# - Epic transitions to 'in-progress' automatically when first story is created +# - Stories can be worked in parallel if team capacity allows +# - SM typically creates next story after previous one is 'done' to incorporate learnings +# - Dev moves story to 'review', then runs code-review (fresh context, different LLM recommended) + +generated: 2026-03-09T18:52:20+02:00 +project: ui-toolkit +project_key: NOKEY +tracking_system: file-system +story_location: /home/dima/Desktop/ui-toolkit/specs/implementation-artifacts + +development_status: + epic-1: in-progress + 1-1-core-contract-and-export-baseline: review + 1-2-core-control-state-parity-completion: backlog + 1-3-accessibility-and-interaction-consistency-hardening: backlog + 1-4-epic-1-quality-gate-closure: backlog + epic-1-retrospective: optional + epic-2: backlog + 2-1-search-and-select-foundation: backlog + 2-2-multi-select-interaction-workflow: backlog + 2-3-calendar-multi-select-variant: backlog + 2-4-radio-group-input-workflow: backlog + 2-4a-file-upload-input-workflows: backlog + 2-5-pagination-workflow-component-delivery: backlog + 2-6-epic-2-quality-gate-closure: backlog + epic-2-retrospective: optional + epic-3: backlog + 3-1-item-row-and-list-data-presentation: backlog + 3-2-task-card-workflow: backlog + 3-3-profile-select-card-workflow: backlog + 3-4-integration-card-workflow: backlog + 3-5-board-a-micro-components-delivery: backlog + 3-6-epic-3-quality-gate-closure: backlog + epic-3-retrospective: optional + epic-4: backlog + 4-1-crm-skeleton-baseline-and-provenance-lock: backlog + 4-2-skeleton-primitive-variants: backlog + 4-3-composed-skeleton-layout-variants: backlog + 4-4-skeleton-parity-and-quality-gate-closure: backlog + epic-4-retrospective: optional + epic-5: backlog + 5-1-board-coverage-closure-and-traceability: backlog + 5-2-reuse-canonical-compliance-and-provenance-completion: backlog + 5-3-export-contract-and-entry-point-integrity: backlog + 5-4-internal-release-readiness-governance-report: backlog + epic-5-retrospective: optional diff --git a/specs/planning-artifacts/architecture.md b/specs/planning-artifacts/architecture.md new file mode 100644 index 0000000..69b95b6 --- /dev/null +++ b/specs/planning-artifacts/architecture.md @@ -0,0 +1,721 @@ +--- +stepsCompleted: + - 1 + - 2 + - 3 + - 4 + - 5 + - 6 + - 7 + - 8 +inputDocuments: + - specs/planning-artifacts/prd.md + - specs/planning-artifacts/implementation-plan.md +workflowType: 'architecture' +lastStep: 8 +status: 'complete' +completedAt: '2026-02-20T18:15:15+02:00' +project_name: 'ui-toolkit' +user_name: 'platform-team' +date: '2026-02-20T15:10:14+02:00' +--- + +# Architecture Decision Document + +_This document builds collaboratively through step-by-step discovery. Sections are appended as we work through each architectural decision together._ + +## Project Context Analysis + +### Requirements Overview + +**Functional Requirements:** +The PRD defines 8 functional requirement groups that drive architecture: + +- FR-01 Board Coverage Completeness: every board element must map to a delivered component/enhancement and be tracked by checklist. +- FR-02 Reuse-First Compliance: implementations must prioritize existing assets from `crm` and `website`. +- FR-03 Canonical Behavior Alignment: behavior must align to `crm`; `website` is for visual/variant gap-fill. +- FR-04 State Parity for Existing Controls: `UiButton`, `UiInput`, `UiCheckbox`, `UiLink` must satisfy required state matrices. +- FR-05 Missing Module Delivery: broad module set including form controls, cards, micro-components, and skeleton suite. +- FR-06 Skeleton Parity: CRM skeleton baseline and exact animation parity are mandatory and release-blocking. +- FR-07 API Contract Consistency: unified prop model with documented exceptions. +- FR-08 Quality Gates: full GitHub CI parity with `website`/`crm` (lint, typecheck, unit, integration, e2e, visual, memory-leak, Storybook build, export completeness, and publish checks). + +Architecturally, this means we need a consistent component behavior model, source provenance tracking, and enforcement mechanisms for parity, CI completeness, and export completeness. + +**Non-Functional Requirements:** +Key non-functional drivers from PRD and constraints: + +- Backward compatibility for existing public APIs unless explicitly approved. +- Naming consistency under `Ui*` conventions. +- Keyboard accessibility and consistent disabled behavior across interactive controls. +- Maintainability/composability for future expansion. +- Release exit criteria requiring complete board coverage, test/story/documentation completeness, TS health, and skeleton parity verification. + +**Scale & Complexity:** +This is a large-surface frontend architecture effort with strict consistency controls. + +- Primary domain: web frontend component toolkit +- Complexity level: high +- Estimated architectural components: ~24 (new modules, existing parity updates, and shared governance/verification mechanisms) + +Complexity drivers include breadth of UI patterns, strict cross-repo reuse policy, and release-blocking parity requirements. Complexity is reduced by the explicit UI-only boundary (no backend/data ownership). + +### Technical Constraints & Dependencies + +- UI-layer boundary only: no backend integration ownership, no domain business logic. +- Reuse-first dependency on existing implementations in `crm` and `website`. +- Canonical source rule: `crm` behavior first; `website` fills visual/variant gaps. +- Skeleton dependency: CRM skeleton source is required baseline with exact animation parity. +- Tooling baseline from implementation context: Bun runtime/package manager (target `>=1.2.0`), Dockerized local/CI runtime, React 18, TypeScript strict mode, MUI v5, Storybook 8, Jest + Testing Library, Playwright, and CRM/website-aligned rebuild/toolchain dependencies. +- Single-release boundary for all board coverage increases need for strict definition-of-done and traceability. + +### Cross-Cutting Concerns Identified + +- UI component interface consistency across all modules and state variants (without backend API-contract scope). +- Source provenance and drift control between toolkit and upstream `crm`/`website`. +- Uniform state semantics (rest/hover/active/disabled/error) across component families. +- Accessibility consistency (keyboard interaction, disabled semantics). +- Verification strategy standardization against `website`/`crm` CI checks (lint, typecheck, unit, integration, e2e, visual, memory-leak, Storybook/build, and publish gates). +- Release traceability via board-to-component coverage checklist and explicit exit criteria. + +## Starter Template Evaluation + +### Primary Technology Domain + +Web frontend component library within an existing React + TypeScript workspace. + +### Starter Options Considered + +1. Existing repository baseline (no re-bootstrap) +- Best fit for current project state and minimizes migration risk. +- Preserves current contracts, test suites, Storybook setup, and release cadence. + +2. `create-tsdown` React starter (greenfield library-first) +- Good option for a brand-new component library. +- Modern library bundling defaults and templates. +- Not selected due to migration overhead for this already-established codebase. + +3. Bun + Storybook + Bulletproof React structure adaptation +- Strong option for a library-first workflow with Bun package/runtime consistency. +- Not selected as a re-bootstrap path because this workstream extends an existing repository baseline. + +### Selected Starter: Existing Repository Baseline (No Re-bootstrap) + +**Rationale for Selection:** +Current architecture already matches project constraints and quality gates. Rebootstrapping would add unnecessary churn without improving delivery of board coverage, parity, and reuse-first goals. + +**Initialization Command:** + +```bash +bun install +bun run storybook-start +``` + +**Architectural Decisions Provided by Starter:** + +**Language & Runtime:** +TypeScript strict mode, React 18, Bun runtime/package manager baseline, with Docker-first execution for local parity and CI. + +**Styling Solution:** +MUI v5 + Emotion-based component styling model. + +**Build Tooling:** +Library-focused build/export pipeline integrated in repository scripts (no Next.js runtime dependency). + +**Testing Framework:** +Jest + Testing Library for unit tests; Playwright for E2E/visual checks. + +**Code Organization:** +Bulletproof React-inspired organization with clear `src/features`, `src/shared`, and app boundary separation, while preserving a centralized package export boundary. + +**Development Experience:** +Established lint/test/storybook command surface and team-familiar workflows. + +**Note:** No new starter generation story is needed. First implementation story should begin directly with component-source reuse mapping (`crm` then `website`) and coverage checklist enforcement. + +## Core Architectural Decisions + +### Decision Priority Analysis + +**Critical Decisions (Block Implementation):** +- Data Architecture: no persistent data layer; UI-library-only runtime model. +- Component Interface Model: props + callbacks only for UI component interaction; no backend API-contract layer. +- Distribution Model: public npm registry as the official package distribution path. +- Runtime/Tooling Model: Bun + Docker as the default execution baseline. +- Security/Auth Scope: UI-library scoped only; no auth system architecture in this project. +- Contract Enforcement: mandatory per-component checklist (exports, state matrix, accessibility, Storybook/tests, provenance note). + +**Important Decisions (Shape Architecture):** +- Reuse governance from PRD remains active: `crm` canonical behavior, `website` visual/variant gap-fill. +- Existing repository baseline retained (no re-bootstrap). + +**Deferred Decisions (Post-MVP):** +- Any adapter/hook integration abstractions for app-specific backend coupling. +- Any internal metadata service beyond file-based governance artifacts. + +### Data Architecture + +- Decision: No persistent data layer. +- Version/Technology: N/A (no DB, migrations, or caching tier). +- Rationale: Aligns with UI-only library boundary and avoids non-essential infrastructure. +- Affects: component props contracts, Storybook fixtures, unit test fixtures. +- Provided by Starter: Aligned with current frontend-only baseline. + +### Authentication & Security + +- Decision: Security/auth considerations limited to UI-library surface. +- Scope Includes: + - Safe prop handling and rendering behavior. + - Accessibility and interaction safety (disabled/focus/keyboard consistency). + - Consumer-facing API clarity to prevent misuse. +- Scope Excludes: + - Identity provider design. + - Token/session lifecycle. + - Backend authorization models. +- Rationale: Keeps architecture aligned to product outcome and prevents scope creep. + +### API & Communication Patterns + +- Decision: Props + callbacks only. +- Pattern: + - Controlled/uncontrolled component interfaces where relevant. + - Standard callback surfaces such as `onChange`, `onClick`, selection events. + - No event-bus or global context orchestration as a default library pattern. +- Evidence: + - Existing components already follow this model (`UiInput`, `UiButton`, `UiCheckbox`, `UiTextFieldForm`). +- Rationale: Consistency with current codebase and predictable integration for internal consumers. + +### Frontend Architecture + +- Decision Set: + - Keep existing React + TypeScript strict + MUI-based architecture baseline. + - Enforce unified UI component interface policy from PRD. + - Follow Bulletproof React structure boundaries for new organization (`src/features`, `src/shared`, `src/app`). +- Quality Architecture: + - Enforce full GitHub CI check matrix aligned with `website`/`crm`: lint, typecheck, unit, integration, e2e, visual regression, memory-leak, Storybook build, package build, and publish checks. + - Storybook coverage and test evidence required for each new/enhanced component. + - Export surface managed centrally through the package entry boundary. +- Rationale: Maximizes delivery speed while preserving consistency and maintainability. + +### Infrastructure & Deployment + +- Decision: Public npm package registry for distribution. +- Release Policy Direction: + - Semver-managed versioning. + - CI publish gate on full CI matrix completion and checklist closure. + - Consumer compatibility policy for internal and external consumers. +- Rationale: Standardized consumption path, clear upgrade flow, and governance-ready distribution. + +### Decision Impact Analysis + +**Implementation Sequence:** +1. Define and enforce quality checklist as definition-of-done. +2. Implement/upgrade components using reuse-first policy. +3. Validate state matrix, tests, stories, exports per component. +4. Package and publish through public npm registry with versioned release gates. + +**Cross-Component Dependencies:** +- Contract checklist influences every component implementation and release eligibility. +- API communication model constrains prop design across all modules. +- Distribution model constrains versioning, changelog discipline, and CI release behavior. +- UI-only data/security scope keeps architecture focused and reduces accidental backend coupling. + +## Implementation Patterns & Consistency Rules + +### Pattern Categories Defined + +**Critical Conflict Points Identified:** +5 major areas where AI agents could diverge: naming, prop contracts, file placement, state/error semantics, and provenance tracking. + +### Naming Patterns + +**Code Naming Conventions:** +- Component folders/files use kebab-case. +- Component exported symbol names remain `UiPascalCase`. +- Variables/functions use camelCase. +- Type/interface names use PascalCase. + +**Examples:** +- Folder: `src/components/ui-button/` +- File: `src/components/ui-button/index.tsx` +- Export: `export default function UiButton(...)` + +**Transition Rule (Required due to current repo state):** +- Existing `UiPascalCase` folders remain valid until migration tasks are explicitly planned. +- New components follow kebab-case from this point forward. +- Do not rename legacy folders opportunistically inside feature tasks. + +### Structure Patterns + +**Project Organization:** +- Follow Bulletproof React structure boundaries for new work: + - `src/app/providers` for Storybook/dev-harness provider composition only + - `src/features//components` for domain-driven components + - `src/shared/ui` for reusable cross-domain UI primitives +- Stories are co-located with component implementation files. +- Unit tests are centralized in root-level `tests/unit`. +- Integration tests are centralized in root-level `tests/integration`. +- Public exports remain centralized in the package entry boundary (`src/components/index.ts` until migration is complete). + +**File Structure Patterns (per new component):** +- `src/features//components//index.tsx` +- `src/features//components//types.ts` +- `src/features//components//.stories.tsx` +- `tests/unit/.test.tsx` + +### Integration Test Conventions + +- Framework/library: Jest runner with React Testing Library is used for integration tests in this repository. +- Naming/location: `tests/integration/**/*.integration.test.ts(x)`. +- Scope definitions: + - Unit tests (`tests/unit`): single-module behavior and pure logic in isolation. + - Integration tests (`tests/integration`): behavior spanning multiple toolkit modules and/or external resource boundaries (mocked/stubbed where needed). +- CI enforcement: all integration specs are executed by the CI matrix gate named `integration`. + +### Format Patterns + +**Public Component Contract:** +- Shared base props for interactive components where relevant: + - `value` + - `onChange` + - `disabled` + - `error` + - `size` + - `variant` + - `sx` +- Exceptions must be documented in component-level notes and reflected in stories/tests. + +**Data Exchange Formats:** +- Props/events use TypeScript-typed shapes. +- Event callback payloads should favor native React event signatures unless a value-first API is explicitly chosen and documented. +- No backend transport payload formats are defined in this library architecture. + +### Communication Patterns + +**Component Communication:** +- Props + callbacks only. +- No global event bus pattern in library architecture. +- No hidden cross-component side effects through shared mutable state. + +**State Management Pattern:** +- Components are async-stateless. +- Consumer applications own loading, retry, and async error flows. +- Library exposes visual/control props (`loading`, `error`, `disabled`) when needed. + +### Process Patterns + +**Error Handling Patterns:** +- Library components render deterministic error visuals from props. +- No internal domain error mapping logic. +- Accessibility and disabled behavior consistency are mandatory across components. + +**Loading State Patterns:** +- Loading UI is visual-only and externally driven by consumers. +- Components must not start network calls or retry loops internally. + +### Provenance & Governance Patterns + +**Source Provenance Tracking:** +- Maintain a central registry: + - `specs/planning-artifacts/component-provenance.md` +- For each component, record: + - `source`: `crm` | `website` | `new` + - rationale + - notes on behavior/visual alignment decisions + +**Quality Enforcement Checklist (Mandatory per component):** +- Export present in `src/components/index.ts` +- Required state matrix covered +- Accessibility baseline checks included +- Storybook coverage present +- Unit tests present in `tests/unit` +- Provenance entry exists in central registry + +### Enforcement Guidelines + +**All AI Agents MUST:** +- Follow naming and structure patterns exactly for new components. +- Apply shared prop contract policy and document exceptions. +- Complete quality checklist before considering a component done. +- Update provenance registry for each delivered/enhanced component. + +**Pattern Enforcement:** +- Enforce via PR checklist + CI gates (tests/type checks/export checks). +- Pattern violations are documented in the relevant implementation artifact and corrected before release tagging. + +### Pattern Examples + +**Good Examples:** +- New component created under kebab-case path with co-located story and centralized test. +- Component exposes standardized `disabled/error/variant/size/sx` and documents any exception. +- Provenance updated with `crm` canonical behavior and `website` visual gap-fill note. + +**Anti-Patterns:** +- Introducing a global event bus for component interactions. +- Embedding async fetch/retry in library UI components. +- Shipping component changes without export update, checklist completion, or provenance entry. + +## Project Structure & Boundaries + +### Complete Project Directory Structure + +```text +ui-toolkit/ +├── package.json +├── bun.lock +├── tsconfig.json +├── tsconfig.paths.json +├── jest.config.ts +├── playwright.config.ts +├── build.config.mjs +├── .eslintrc.js +├── tests/ +│ ├── unit/ # Jest + Testing Library; `*.test.ts(x)` for single-module logic +│ ├── integration/ # Jest + React Testing Library; `*.integration.test.ts(x)` for multi-module/external-resource interactions +│ ├── e2e/ +│ ├── visual/ +│ └── memory-leak/ +├── .storybook/ +│ ├── main.ts +│ └── preview.ts +├── .github/ +│ └── workflows/ +│ ├── static-testing.yml +│ ├── unit-testing.yml +│ ├── visual-testing.yml +│ ├── e2e-testing.yml +│ ├── autorelease.yml +│ └── autoprerelease.yml +├── scripts/ +│ ├── localizationGenerator.js +│ └── test/ +│ └── unit/ +│ └── localizationGenerator.spec.js +├── specs/ +│ ├── planning-artifacts/ +│ │ ├── prd.md +│ │ ├── epics.md +│ │ ├── implementation-plan.md +│ │ ├── architecture.md +│ │ └── component-provenance.md # to create +│ └── implementation-artifacts/ +├── src/ +│ ├── app/ +│ │ └── providers/ # Storybook/dev-harness provider wrappers only +│ ├── features/ +│ │ ├── core-controls/ +│ │ │ ├── components/ +│ │ │ │ ├── ui-button/ +│ │ │ │ ├── ui-checkbox/ +│ │ │ │ ├── ui-input/ +│ │ │ │ └── ui-link/ +│ │ │ ├── hooks/ +│ │ │ ├── types/ +│ │ │ └── index.ts +│ │ ├── selection-input/ +│ │ │ ├── components/ +│ │ │ │ ├── ui-pagination/ +│ │ │ │ ├── ui-search-input/ +│ │ │ │ ├── ui-select-with-search/ +│ │ │ │ ├── ui-multi-select/ +│ │ │ │ ├── ui-calendar-multi-select/ +│ │ │ │ ├── ui-radio-group/ +│ │ │ │ └── ui-file-upload-input/ +│ │ │ ├── hooks/ +│ │ │ ├── types/ +│ │ │ └── index.ts +│ │ ├── data-cards/ +│ │ │ ├── components/ +│ │ │ │ ├── ui-item-row/ +│ │ │ │ ├── ui-items-list/ +│ │ │ │ ├── ui-task-card/ +│ │ │ │ ├── ui-profile-select-card/ +│ │ │ │ └── ui-integration-card/ +│ │ │ ├── hooks/ +│ │ │ ├── types/ +│ │ │ └── index.ts +│ │ ├── micro-components/ +│ │ │ ├── components/ +│ │ │ │ ├── ui-filter-chip/ +│ │ │ │ ├── ui-pin-input/ +│ │ │ │ ├── ui-payment-option-card/ +│ │ │ │ ├── ui-action-icon-bar/ +│ │ │ │ ├── ui-status-badge/ +│ │ │ │ └── ui-notification-badge/ +│ │ │ ├── hooks/ +│ │ │ ├── types/ +│ │ │ └── index.ts +│ │ └── skeleton/ +│ │ ├── components/ +│ │ │ ├── ui-skeleton/ +│ │ │ └── ui-skeleton-composed/ +│ │ ├── hooks/ +│ │ ├── types/ +│ │ └── index.ts +│ ├── shared/ +│ │ ├── ui/ # shared primitives and legacy bridges +│ │ ├── hooks/ +│ │ ├── lib/ +│ │ ├── types/ +│ │ └── utils/ +│ ├── components/ +│ │ └── index.ts # package public API boundary (transitional) +│ ├── assets/ +│ └── utils/ +└── docs/ +``` + +**Lockfile Policy (Bun v1.2+):** +- Required lockfile format is text-based `bun.lock` (legacy `bun.lockb` is not allowed on active branches). +- Migration command: + +```bash +bun install --save-text-lockfile --frozen-lockfile --lockfile-only +``` + +**`src/app` Scope Constraint:** +- `src/app/providers` is limited to provider wrappers used by Storybook/dev harnesses (for example `ThemeProvider` composition). +- Do not add app-level `routes/` or `stores/` to this library architecture. +- `src/app` must not contain async orchestration, backend coupling, or product application logic. + +### Architectural Boundaries + +**API Boundaries:** +- Public component API is exported only through `src/components/index.ts`. +- Internal component files are non-public implementation details. +- No backend API surface is owned by this repository. + +**Component Boundaries:** +- Component communication is props + callbacks only. +- No global event-bus architecture. +- Async orchestration (fetch/retry/session) stays in consumer apps (`crm`, `website`). + +**Service Boundaries:** +- No application service layer in toolkit scope. +- Integration logic belongs to consuming applications, not library components. + +**Data Boundaries:** +- No persistent data layer (no DB schema/migrations/caching tier). +- Data contracts exist as TypeScript props and test/story fixtures only. + +### Requirements to Structure Mapping + +**FR-01 Board Coverage Completeness** +- Component implementation: `src/features/*`, `src/shared/ui/*`, and exported entry boundary +- Coverage governance artifacts: `specs/planning-artifacts/*` +- Validation surfaces: stories in component folders + tests in `tests/unit` + +**FR-02 Reuse-First Compliance** +- Provenance registry: `specs/planning-artifacts/component-provenance.md` +- Source alignment notes per component entry (`crm`/`website`/`new`) + +**FR-03 Canonical Behavior Alignment** +- Behavioral baseline encoded in component implementations and tests: + - `src/features/*`, `src/shared/ui/*` + - `tests/unit/*` + +**FR-04 Existing Control State Parity** +- Existing controls: + - `src/components/UiButton/` + - `src/components/UiInput/` + - `src/components/UiCheckbox/` + - `src/components/UiLink/` +- State tests: + - `tests/unit/UiButton.test.tsx` + - `tests/unit/UiInput.test.tsx` + - `tests/unit/UiCheckbox.test.tsx` + - `tests/unit/UiLink.test.tsx` + +**FR-05 Missing Module Delivery** +- New modules under Bulletproof feature/shared paths with kebab-case naming +- Matching tests in `tests/unit/` + +**FR-06 Skeleton Parity** +- Skeleton implementation: + - `src/features/skeleton/components/ui-skeleton/` + - `src/features/skeleton/components/ui-skeleton-composed/` +- Parity verification tests in `tests/unit/` + +**FR-07 API Contract Consistency** +- Prop/type definitions in each component `types.ts` (UI component interfaces only) +- Public export discipline in `src/components/index.ts` + +**FR-08 Quality Gates** +- Stories co-located in component folders +- Unit tests centralized under `tests/unit/` +- CI gates in `.github/workflows/` aligned to `website`/`crm` matrices + +### Integration Points + +**Internal Communication:** +- Props down, callbacks up, typed event payloads. +- Shared UI patterns through MUI theme/config and common prop contract rules. + +**External Integrations:** +- Distribution via public npm registry. +- Consumer projects (`crm`, `website`, others) and external adopters import published package surface. + +**Data Flow:** +- Consumer app state drives component props. +- Components emit interaction callbacks to consumer handlers. +- No repository-owned external data fetch lifecycle. + +### Compatibility Matrix (Build vs Consumer Runtime) + +#### Dev/build requirements + +- Purpose: local development, test execution, package build, and publish automation for this repository. +- Bun: `>=1.2.0` (enforced via `bun.lock` text lockfile policy). +- Toolchain baseline: TypeScript strict mode, Jest + Testing Library, Playwright, Storybook 8, and Docker-based CI parity. +- Build/publish responsibility: maintainers and CI only. + +#### Consumer runtime requirements + +- Bun is **not required** to consume the published npm package. +- Supported Node.js LTS range for consumer build/SSR environments: `20.x` and `22.x`. +- Browser target matrix for rendered components: + - Chromium browsers (Chrome/Edge): latest stable and previous stable. + - Firefox: latest stable and ESR. + - Safari (macOS/iOS): latest major and previous major. +- Peer dependency expectations for downstream consumers (`crm`, `website`, external adopters): + - `react`: `^18.2.0` + - `react-dom`: `^18.2.0` + - `@mui/material`: `^5.15.0` + - `@emotion/react`: `^11.11.0` + - `@emotion/styled`: `^11.11.0` + +### File Organization Patterns + +**Configuration Files:** +- Root-level build/lint/test config files remain authoritative. + +**Source Organization:** +- Bulletproof React boundaries are primary (`src/features`, `src/shared`, `src/app`). +- `src/components` remains as package export boundary during migration. +- Legacy `UiPascalCase` remains until explicit migration. +- New components use kebab-case folders/files. + +**Test Organization:** +- Unit tests centralized in root `tests/unit`. +- Integration, E2E, visual, and memory-leak checks are mapped under root `tests/*`. + +**Asset Organization:** +- Static visual assets in `src/assets`. +- Component-local style/type/theme files stay near implementation. + +### Development Workflow Integration + +**Development Server Structure:** +- Storybook and local dev scripts operate against Bulletproof domains (`src/features`, `src/shared`) and shared config. + +**Build Process Structure:** +- Bun-driven build scripts and TypeScript/Jest/Playwright pipelines validate exported library surface and the full CI matrix. + +**Deployment Structure:** +- CI workflow publishes versioned package to public npm registry after full quality gates pass. + +## Architecture Validation Results + +### Coherence Validation ✅ + +**Decision Compatibility:** +All major decisions align: UI-only scope, no persistent data layer, props/callback communication, full CI quality checklist, Bun+Docker dev/build baseline, and public npm distribution. No blocking contradictions detected. + +**Pattern Consistency:** +Patterns are internally consistent with one managed tension: new kebab-case component folders vs legacy `UiPascalCase` folders. This is resolved by explicit transition rule (legacy untouched unless dedicated migration task). + +**Structure Alignment:** +Project structure supports all decisions: Bulletproof React boundaries, central export boundary, root-level test matrix, co-located stories, governance artifacts under `specs/planning-artifacts`, and clear consumer/app boundary. + +### Requirements Coverage Validation ✅ + +**Feature Coverage:** +All PRD feature groups are represented in architecture sections (existing parity, missing modules, skeleton parity, governance/checklists). + +**Functional Requirements Coverage:** +FR-01..FR-08 are explicitly mapped to implementation locations and validation surfaces. + +**Non-Functional Requirements Coverage:** +Compatibility, accessibility consistency, maintainability, and release-gate discipline are all addressed through patterns and checklist enforcement. + +### Implementation Readiness Validation ✅ + +**Decision Completeness:** +Critical decisions are documented and actionable for implementation sequencing. + +**Structure Completeness:** +Complete project tree and boundary map are defined with specific directories/files. + +**Pattern Completeness:** +Naming, structure, contract, communication, and process patterns are specified with anti-patterns and enforcement rules. + +### Gap Analysis Results + +**Critical Gaps:** +- None. + +**Important Gaps:** +- `specs/planning-artifacts/component-provenance.md` is defined but not yet created. +- Compatibility matrix is now defined in this document and must be mirrored in release-gate automation (validation + documentation checks) before publish. +- CI publish gate is defined conceptually but requires concrete workflow-level checklist. + +**Nice-to-Have Gaps:** +- Add a migration playbook for eventual legacy `UiPascalCase` → kebab-case folder convergence. + +### Validation Issues Addressed + +- Naming convention conflict resolved by transition rule: + - legacy folders remain valid; + - all new components use kebab-case; + - no opportunistic renames during feature implementation. + +### Architecture Completeness Checklist + +**✅ Requirements Analysis** +- [x] Project context thoroughly analyzed +- [x] Scale and complexity assessed +- [x] Technical constraints identified +- [x] Cross-cutting concerns mapped + +**✅ Architectural Decisions** +- [x] Critical decisions documented +- [x] Technology stack baseline specified +- [x] Integration patterns defined +- [x] Security scope boundaries defined + +**✅ Implementation Patterns** +- [x] Naming conventions established +- [x] Structure patterns defined +- [x] Communication patterns specified +- [x] Process patterns documented + +**✅ Project Structure** +- [x] Complete directory structure defined +- [x] Component boundaries established +- [x] Integration points mapped +- [x] Requirements-to-structure mapping complete + +### Architecture Readiness Assessment + +**Overall Status:** READY FOR IMPLEMENTATION +**Confidence Level:** High + +**Key Strengths:** +- Strong scope discipline for a shared internal UI library. +- Clear cross-repo reuse governance (`crm` canonical behavior). +- Practical enforcement model (tests, stories, exports, provenance). + +**Areas for Future Enhancement:** +- Planned legacy folder naming migration path. + +### Implementation Handoff + +**AI Agent Guidelines:** +- Follow architectural decisions and patterns exactly. +- Treat checklist completion as definition-of-done. +- Keep component behavior deterministic and async-stateless. + +**First Implementation Priority:** +Create governance artifact + bootstrap enforcement: +1. Create `specs/planning-artifacts/component-provenance.md` +2. Implement export/checklist scaffolding for first new component slice. diff --git a/specs/planning-artifacts/epics.md b/specs/planning-artifacts/epics.md new file mode 100644 index 0000000..b17869d --- /dev/null +++ b/specs/planning-artifacts/epics.md @@ -0,0 +1,755 @@ +--- +stepsCompleted: + - 1 + - 2 + - 3 +inputDocuments: + - specs/planning-artifacts/prd.md + - specs/planning-artifacts/architecture.md +workflowType: 'epics-and-stories' +project_name: 'ui-toolkit' +user_name: 'platform-team' +date: '2026-02-20T18:26:30+02:00' +--- + +# ui-toolkit - Epic Breakdown + +## Overview + +This document provides the complete epic and story breakdown for ui-toolkit, decomposing the requirements from the PRD, UX Design if it exists, and Architecture requirements into implementable stories. + +## Requirements Inventory + +### Functional Requirements + +FR1: Ensure complete board coverage by mapping every board element to a delivered component or documented enhancement. +FR2: Enforce reuse-first implementation by prioritizing existing `crm` and `website` assets before creating new modules. +FR3: Align behavior canonically to `crm` for equivalent components, using `website` only for visual/variant gap-fill. +FR4: Achieve required state parity for existing controls (`UiButton`, `UiInput`, `UiCheckbox`, `UiLink`). +FR5: Deliver missing reusable modules: `ui-pagination`, `ui-search-input`, `ui-select-with-search`, `ui-multi-select`, `ui-calendar-multi-select`, `ui-radio-group`, `ui-file-upload-input`, `ui-item-row`, `ui-items-list`, `ui-task-card`, `ui-profile-select-card`, `ui-integration-card`, `ui-filter-chip`, `ui-pin-input`, `ui-payment-option-card`, `ui-action-icon-bar`, `ui-status-badge`, `ui-notification-badge`, `ui-skeleton` (primitives + composed variants). +FR6: Implement skeletons from `crm` baseline with exact animation parity as a release blocker. +FR7: Apply unified component API contract (`value`, `onChange`, `disabled`, `error`, `size`, `variant`, `sx`) with documented exceptions. +FR8: Satisfy quality gates for all delivered/enhanced modules: Storybook coverage, unit tests, strict TypeScript checks, and complete public exports. + +### NonFunctional Requirements + +NFR1: Preserve backward compatibility for existing public component APIs unless explicitly approved. +NFR2: Maintain naming and API conventions aligned with `Ui*` public component standards. +NFR3: Ensure keyboard accessibility and consistent disabled/error interaction behavior. +NFR4: Keep implementation maintainable and composable for future board expansion. +NFR5: Keep architecture scoped strictly to UI-layer concerns (no backend ownership, no domain business logic). +NFR6: Maintain deterministic, async-stateless component behavior with consumer-owned orchestration. + +### Additional Requirements + +- Existing repository baseline is retained; no starter re-bootstrap is required. +- Public API boundary is enforced via `src/components/index.ts` exports. +- New component folders/files follow kebab-case naming; existing legacy `UiPascalCase` folders remain until explicit migration. +- Stories are co-located with components; unit tests remain centralized in `src/test/testing-library`. +- Source provenance must be tracked centrally at `specs/planning-artifacts/component-provenance.md` with `crm|website|new` source labels and rationale. +- Distribution path is public npm package registry with semver-governed releases. +- Public npm promotion requires a blocking Epic 5 licensing/IP governance gate before release approval. +- CI publish gating depends on contract checklist completion (exports, state matrix, accessibility checks, Storybook/tests). +- PRD, architecture, and implementation constraints must remain aligned with `crm` canonical behavior policy. + +### Governance Roles + +- **Release Manager:** owns release checklist execution, evidence collection, and go/no-go recommendation packaging. +- **Governance Board:** cross-functional approvers (Engineering Lead, QA Lead, and Legal/OSS Compliance representative) with authority to approve or block public npm promotion. +- **Role distinction:** the Release Manager prepares and presents validation artifacts; the Governance Board provides final release authorization. + +### FR Coverage Map + +FR1: Epic 5 - Production Adoption Readiness ensures complete board-to-component coverage tracking and closure. +FR2: Epics 2-4 delivery stories record reuse-first provenance details via the shared Definition of Done checklist; Epic 5 validates and closes cross-epic compliance. +FR3: Epics 2-4 delivery stories record canonical behavior/source decisions via the shared Definition of Done checklist; Epic 5 validates and closes cross-epic alignment. +FR4: Epic 1 - Core Controls and Contract Foundation delivers required state parity for existing controls. +FR5: Epic 2, Epic 3, Epic 4 - Missing module delivery is split by user workflow domain (input/select, data/cards, skeletons). +FR6: Epic 4 - Skeleton Loading Experience Parity delivers CRM baseline reuse and animation parity. +FR7: Epic 1, Epic 2, Epic 3 - Unified API contract is applied across foundational and new interactive components. +FR8: Epic 1, Epic 2, Epic 3, Epic 4, Epic 5 - Quality gates are enforced across all delivery domains and release readiness. + +### NFR Coverage Map + +NFR1: Epic 1 (Stories 1.1-1.4) preserves public API compatibility; Epic 5: Production Readiness (Stories 5.3-5.4) performs backward-compatibility/contract/export review and closes quality-gate evidence before release approval. +NFR2: Epic 1 (Stories 1.1-1.4), Epic 2 (Stories 2.1-2.6 including Story 2.4A), Epic 3 (Stories 3.1-3.6), and Epic 4: Skeleton Loading (ui-skeleton) (Stories 4.1-4.4) enforce naming and API convention alignment. +NFR3: Epic 1 Story 1.3 establishes accessibility baseline controls; Epic 2 Story 2.6, Epic 3 Story 3.6, and Epic 4: Skeleton Loading (ui-skeleton) Story 4.4 enforce keyboard accessibility plus disabled/error checks where applicable; Epic 5: Production Readiness validates closure evidence. +NFR4: Epic 2 (Stories 2.1-2.6 including Story 2.4A), Epic 3 (Stories 3.1-3.6), and Epic 4: Skeleton Loading (ui-skeleton) ensure maintainable composability from primitive to composed variants; Epic 5: Production Readiness consolidates cross-epic traceability for sustained maintainability. +NFR5: Epic 1 Story 1.1 plus Epic 2/3 quality-gate stories enforce UI-layer-only boundaries. +NFR6: Epic 2 and Epic 3 delivery stories enforce deterministic component behavior with consumer-owned orchestration. + +### Shared Definition of Done Checklist + +All delivery stories in Epic 2 (Stories 2.1-2.4, Story 2.4A, and Story 2.5) and Epic 3 (Stories 3.1-3.5) carry an implicit provenance obligation. +Each delivery story must record source, reuse rationale, and reference IDs in PR/issue metadata using the shared Definition of Done checklist at `specs/implementation-artifacts/story-dod-template.md`. + +## Epic List + +### Epic 1: Core Controls and Contract Foundation +Deliver stable, production-ready foundational controls and consistent contracts so product teams can build interactive UI without custom rework. +**FRs covered:** FR4, FR7, FR8 + +### Epic 2: Selection, Search, and Input Workflows +Enable users to search, select, and submit values through reusable input-selection components that support company app workflows. +**FRs covered:** FR5, FR7, FR8 + +### Epic 3: Data Presentation and Cards +Enable users to understand and act on structured information via reusable item rows, lists, and card patterns. +**FRs covered:** FR5, FR7, FR8 + +### Epic 4: Skeleton Loading Experience Parity +Provide trusted loading experiences by delivering skeleton primitives and composed variants with exact CRM animation parity. +**FRs covered:** FR5, FR6, FR8 + +### Epic 5: Production Adoption Readiness +Make the toolkit safely adoptable across company projects by closing coverage, provenance, export, and release-gate governance. +**FRs covered:** FR1, FR2, FR3, FR8 (plus consolidated traceability references for FR4, FR5, FR6, and FR7 delivered in Epics 1-4) + +## Epic 1: Core Controls and Contract Foundation + +Deliver stable, production-ready foundational controls and consistent contracts so product teams can build interactive UI without custom rework. + +### Story 1.1: Core Contract and Export Baseline + +As a consumer-team developer, +I want core controls to expose a consistent public contract and entrypoint exports, +So that I can integrate toolkit components predictably across company projects. + +**Acceptance Criteria:** + +**Given** the existing core control components are present +**When** I inspect their public props and export surface +**Then** each core control has documented and typed contract fields aligned to the shared API policy (or documented exception) +**And** each core control is exported from `src/components/index.ts`. + +**Given** contract behavior is part of release quality gates +**When** contract verification checks are run +**Then** failing export/contract mismatches are detectable before release +**And** results are reported in a way that blocks non-compliant changes. + +**Given** this epic must preserve compatibility +**When** contract adjustments are introduced +**Then** existing public API behavior remains backward compatible unless explicitly approved +**And** any approved exception is documented. + +### Story 1.2: Core Control State Parity Completion + +As a product-team developer, +I want the existing core controls to implement all required state variants, +So that users get consistent behavior and visuals across company applications. + +**Acceptance Criteria:** + +**Given** the core controls in scope are `UiButton`, `UiInput`, `UiCheckbox`, and `UiLink` +**When** state behavior is reviewed against the PRD and board requirements +**Then** each control supports required states for its role (rest, hover, active, disabled, plus error where applicable) +**And** state behavior is consistent with canonical `crm` behavior where equivalent. + +**Given** visual/interaction parity can drift during implementation +**When** updates are delivered for these controls +**Then** state semantics remain backward compatible for existing consumers +**And** any unavoidable deviation is explicitly documented with rationale. + +**Given** this story must be independently verifiable +**When** QA validation is executed for this story +**Then** required state coverage is demonstrable for all four controls +**And** unresolved parity gaps are tracked as blocking issues for this epic. + +### Story 1.3: Accessibility and Interaction Consistency Hardening + +As an end user, +I want core controls to behave consistently for keyboard and disabled/error interactions, +So that I can use company products reliably and accessibly. + +**Acceptance Criteria:** + +**Given** core controls are used in keyboard and assistive-technology flows +**When** I navigate and interact without a mouse +**Then** focus behavior is visible and consistent across controls +**And** keyboard interactions follow expected patterns for each control type. + +**Given** controls can be set to disabled or error states +**When** those states are active +**Then** interaction behavior is predictable and non-conflicting +**And** disabled/error semantics are consistently represented in component behavior and styling. + +**Given** accessibility is part of release quality gates +**When** Epic 1 accessibility checks are executed +**Then** core interaction and accessibility requirements are validated for all four controls +**And** any failures are treated as blocking issues for Epic 1 completion. + +### Story 1.4: Epic 1 Quality Gate Closure + +As a release owner, +I want Storybook coverage and unit-test validation finalized for Epic 1 controls, +So that this foundation can be confidently consumed by company projects. + +**Acceptance Criteria:** + +**Given** Epic 1 controls are implemented and updated +**When** I review Storybook coverage for these controls +**Then** each control has stories that represent required states and core usage +**And** story artifacts are ready for board-parity and interaction review. + +**Given** Epic 1 quality requires test-backed behavior +**When** unit tests are executed for Epic 1 controls +**Then** render and critical interaction behavior are validated +**And** failing tests block Epic 1 completion. + +**Given** release readiness depends on contract and export integrity +**When** Epic 1 checks are run end-to-end +**Then** export surface, state coverage, and quality evidence are complete for Epic 1 +**And** Epic 1 is marked ready to enable subsequent epics without unresolved blockers. + +**Given** Epic 1 closure requires traceable completion evidence +**When** Epic 1 is finalized +**Then** a Definition of Done artifact and test/story/export evidence references are captured in implementation artifacts +**And** those references are available for Epic 5 governance validation. + +## Epic 2: Selection, Search, and Input Workflows + +Enable users to search, select, and submit values through reusable input-selection components that support company app workflows. + +### Story 2.1: Search and Select Foundation + +As a product-team user, +I want search-capable input and select controls, +So that I can quickly find and choose values in complex forms. + +**Acceptance Criteria:** + +**Given** search/select workflows are required across company apps +**When** I use `ui-search-input` and `ui-select-with-search` +**Then** I can input search text and receive appropriate selectable options behavior +**And** controls support shared API contract fields where relevant (`value`, `onChange`, `disabled`, `error`, `size`, `variant`, `sx`). + +**Given** canonical behavior must align with `crm` where equivalent +**When** these components are implemented +**Then** behavior patterns follow reuse/canonical governance rules +**And** visual/variant gaps are filled without violating canonical behavior. + +**Given** these components are foundational for later stories in this epic +**When** Story 2.1 is complete +**Then** it is independently usable and testable +**And** subsequent Epic 2 stories can build on it without requiring future-story dependencies. + +### Story 2.2: Multi-Select Interaction Workflow + +As a product-team user, +I want to select multiple values and manage selected chips clearly, +So that I can complete multi-value form tasks efficiently. + +**Acceptance Criteria:** + +**Given** multi-value selection is required in board workflows +**When** I interact with `ui-multi-select` +**Then** I can select multiple options and see clear selected-chip/tag representations +**And** I can remove or update selections through consistent interaction patterns. + +**Given** this component must remain contract-consistent +**When** `ui-multi-select` is used in forms +**Then** it supports shared contract expectations where relevant (`value`, `onChange`, `disabled`, `error`, `size`, `variant`, `sx`) +**And** any contract exceptions are explicitly documented. + +**Given** quality and usability are mandatory +**When** disabled or error states are applied +**Then** interactions are correctly constrained and visually clear +**And** behavior remains independently testable as a standalone story outcome. + +### Story 2.3: Calendar Multi-Select Variant + +As a product-team user, +I want a calendar-style multi-select control, +So that I can choose date-based values with a UI pattern consistent with toolkit standards. + +**Acceptance Criteria:** + +**Given** date-oriented multi-selection is required in board scope +**When** I use `ui-calendar-multi-select` +**Then** I can select and manage date-oriented values using a calendar-style interaction +**And** the component behavior is consistent with shared selection-control semantics. + +**Given** this story extends selection capabilities from earlier stories +**When** Story 2.3 is implemented +**Then** it reuses established contract and interaction patterns from Epic 2 where relevant +**And** it does not introduce dependencies on future stories in this epic. + +**Given** accessibility and quality gates apply to all interactive controls +**When** this component is validated +**Then** keyboard/disabled/error behavior is consistent and testable +**And** component behavior is documented with Storybook scenarios and unit-test coverage expectations. + +### Story 2.4: Radio Group Input Workflow + +As a product-team user, +I want a reusable radio-group control, +So that I can complete single-choice tasks consistently across apps. + +**Acceptance Criteria:** + +**Given** board scope includes single-choice radio interactions +**When** I use `ui-radio-group` +**Then** I can select one option with clear focus and selection-state behavior +**And** interaction behavior is consistent with toolkit control patterns. + +**Given** this control is used in form contexts +**When** disabled/error and callback behaviors are exercised +**Then** `ui-radio-group` follows shared contract expectations where relevant +**And** any component-specific contract exceptions are documented. + +**Given** this story should remain independently completable +**When** Story 2.4 is delivered +**Then** `ui-radio-group` is usable and verifiable without relying on future Epic 2 stories +**And** quality expectations for Storybook scenarios and unit validation are defined. + +### Story 2.4A: File Upload Input Workflows + +As a product-team user, +I want a reusable file-upload input control, +So that I can complete file-submission tasks consistently across apps. + +**Acceptance Criteria:** + +**Given** board scope includes file-upload interactions +**When** I use `ui-file-upload-input` +**Then** async upload states (`idle`, `uploading`, `success`, `error`) are represented clearly +**And** progress reporting is available for long-running uploads. + +**Given** upload inputs must handle validation and failure paths +**When** files violate type/size rules or upload requests fail +**Then** validation and upload error states are surfaced with actionable messages +**And** file type/size constraints are testable and documented. + +**Given** drag-and-drop and keyboard/assistive-technology access are required +**When** files are provided via drag-and-drop or non-pointer interaction +**Then** the component supports drag-and-drop behaviors and keyboard-operable upload actions +**And** screen-reader announcements communicate selection/progress/error outcomes. + +**Given** this story should remain independently completable +**When** Story 2.4A is delivered +**Then** Storybook scenarios cover async, progress, validation, error, and drag-and-drop cases +**And** unit tests validate render plus core upload interaction behavior. + +### Story 2.5: Pagination Workflow Component Delivery + +As a product-team user, +I want a reusable pagination control, +So that I can navigate long result sets with consistent toolkit behavior. + +**Acceptance Criteria:** + +**Given** board scope requires paginated list navigation +**When** I use `ui-pagination` +**Then** I can navigate pages with clear current/next/previous semantics +**And** component interactions follow shared contract expectations where relevant. + +**Given** this component must be reusable across company apps +**When** `ui-pagination` is delivered +**Then** Storybook scenarios document key states and usage patterns +**And** unit tests validate render and core interaction behavior. + +**Given** Epic 2 outcomes require export and governance traceability +**When** Story 2.5 is complete +**Then** `ui-pagination` is exported from `src/components/index.ts` +**And** provenance/source decisions are recorded using the shared Definition of Done checklist at `specs/implementation-artifacts/story-dod-template.md` (source, reuse rationale, and reference IDs in PR/issue metadata). + +### Story 2.6: Epic 2 Quality Gate Closure + +As a release owner, +I want Epic 2 components to pass contract, coverage, and quality gates, +So that selection and input workflows are safe for production adoption. + +**Acceptance Criteria:** + +**Given** Epic 2 components are implemented (`ui-search-input`, `ui-select-with-search`, `ui-multi-select`, `ui-calendar-multi-select`, `ui-radio-group`, `ui-file-upload-input`, `ui-pagination`) +**When** release-quality checks are executed +**Then** each component has Storybook coverage for relevant states and usage flows +**And** each component has unit-test validation for render and core interactions. + +**Given** export and contract consistency are required +**When** Epic 2 deliverables are reviewed +**Then** Epic 2 components are correctly exported from toolkit entrypoint +**And** contract consistency and documented exceptions are complete. + +**Given** Epic 2 must satisfy the Story 1.3 accessibility baseline and NFR3 +**When** Epic 2 accessibility checks are executed +**Then** keyboard navigation (`Tab`/`Shift+Tab`), logical focus order, visible focus indicators, keyboard-operable controls, and disabled/error behavior are validated across Epic 2 components +**And** accessibility failures are treated as blocking issues for Epic 2 completion. + +**Given** Epic 2 must enable future epics cleanly +**When** Epic 2 is marked complete +**Then** no unresolved blocking issues remain for downstream epics +**And** evidence for FR7/FR8 coverage is captured for this epic. + +**Given** Epic 2 closure requires traceable completion evidence +**When** Epic 2 is finalized +**Then** a Definition of Done artifact and test/story/export evidence references are captured in implementation artifacts +**And** those references are available for Epic 5 governance validation. + +## Epic 3: Data Presentation and Cards + +Enable users to understand and act on structured information via reusable item rows, lists, and card patterns. + +### Story 3.1: Item Row and List Data Presentation + +As a product-team user, +I want reusable item-row and list components for structured data, +So that I can view and act on list-based records consistently. + +**Acceptance Criteria:** + +**Given** board requirements include row/list data presentation patterns +**When** I use `ui-item-row` and `ui-items-list` +**Then** rows and list containers render structured data with clear semantics +**And** state and interaction behavior remains consistent with toolkit conventions. + +**Given** method/status semantics are part of required board behavior +**When** row variants are displayed +**Then** method/status visual distinctions are supported +**And** row interaction patterns are predictable and testable. + +**Given** this story must be independently completable +**When** Story 3.1 is delivered +**Then** `ui-item-row` and `ui-items-list` are usable without future-story dependencies +**And** component contracts and usage examples are ready for downstream card stories. + +### Story 3.2: Task Card Workflow + +As a product-team user, +I want a reusable task/person card component, +So that I can view card-based information with consistent interaction states. + +**Acceptance Criteria:** + +**Given** card-based task/person presentation is required +**When** I use `ui-task-card` +**Then** key card content and state behavior are supported consistently with board expectations +**And** interaction semantics are clear for rest/active/disabled usage contexts. + +**Given** this component is part of a reusable library +**When** `ui-task-card` is integrated in consuming applications +**Then** its API aligns with shared toolkit contract principles where relevant +**And** contract exceptions are documented when needed. + +**Given** Epic 3 stories must remain sequential and independent +**When** Story 3.2 is completed +**Then** `ui-task-card` is independently usable and testable +**And** no future-story dependency is required for core behavior. + +### Story 3.3: Profile Select Card Workflow + +As a product-team user, +I want a profile-select card with menu interactions, +So that I can choose profile-related options through a consistent card UI pattern. + +**Acceptance Criteria:** + +**Given** profile card selection/menu behavior is required by board scope +**When** I use `ui-profile-select-card` +**Then** profile information and selection/menu interaction states are supported +**And** behavior is consistent with established card and control patterns. + +**Given** this card may include selectable and dropdown-like interactions +**When** interaction states are exercised +**Then** the component handles active/disabled/error-relevant behavior predictably +**And** callback and contract behavior is clearly defined. + +**Given** this story must stand on its own +**When** Story 3.3 is complete +**Then** `ui-profile-select-card` is independently usable and testable +**And** it does not depend on any future Epic 3 story to function. + +### Story 3.4: Integration Card Workflow + +As a product-team user, +I want an integration/brand selection card component, +So that I can select integration options through a consistent card interaction model. + +**Acceptance Criteria:** + +**Given** integration/brand card selection is required by board scope +**When** I use `ui-integration-card` +**Then** selection behavior and state feedback are clear and consistent +**And** card behavior aligns with toolkit interaction and contract standards. + +**Given** this component is used in configurable selection flows +**When** selected/unselected and disabled states are exercised +**Then** state transitions are predictable and testable +**And** callback semantics are well-defined for consuming applications. + +**Given** this story must be independently completable +**When** Story 3.4 is delivered +**Then** `ui-integration-card` is usable and testable without future-story dependency +**And** its behavior is ready for inclusion in Epic 3 quality closure. + +### Story 3.5: Board A Micro-Components Delivery + +As a product-team developer, +I want reusable micro-components from Board A, +So that I can compose common interaction patterns without custom one-off implementations. + +**Acceptance Criteria:** + +**Given** Board A requires multiple supporting micro-components +**When** Epic 3 micro-components are delivered +**Then** the following reusable components exist with defined contracts and interaction behavior: +`ui-filter-chip`, `ui-pin-input`, `ui-payment-option-card`, `ui-action-icon-bar`, `ui-status-badge`, `ui-notification-badge` +**And** each component follows shared styling/contract conventions where relevant. + +**Given** these micro-components are often used compositionally +**When** they are integrated in consuming UIs +**Then** they behave consistently and predictably with disabled/error/state semantics where applicable +**And** documented exceptions are captured where shared contract fields are not applicable. + +**Given** this story should remain independently completable +**When** Story 3.5 is complete +**Then** each listed micro-component is individually usable and testable +**And** no future Epic 3 story is required for baseline functionality. + +### Story 3.6: Epic 3 Quality Gate Closure + +As a release owner, +I want all Epic 3 components to meet export, test, and Storybook quality requirements, +So that data-presentation and card workflows are production-ready for company adoption. + +**Acceptance Criteria:** + +**Given** Epic 3 components are implemented (`ui-item-row`, `ui-items-list`, `ui-task-card`, `ui-profile-select-card`, `ui-integration-card`, `ui-filter-chip`, `ui-pin-input`, `ui-payment-option-card`, `ui-action-icon-bar`, `ui-status-badge`, `ui-notification-badge`) +**When** Epic 3 quality validation is executed +**Then** each component has Storybook coverage for required usage and state behavior +**And** each component has unit-test validation for render and core interactions. + +**Given** public API integrity is mandatory +**When** Epic 3 output is reviewed +**Then** all Epic 3 components are exported correctly from toolkit entrypoint +**And** contract consistency plus documented exceptions are complete. + +**Given** Epic 3 must satisfy the Story 1.3 accessibility baseline and NFR3 +**When** Epic 3 accessibility checks are executed +**Then** keyboard navigation (`Tab`/`Shift+Tab`), logical focus order, visible focus indicators, keyboard-operable controls, and disabled/error behavior are validated across Epic 3 components +**And** accessibility failures are treated as blocking issues for Epic 3 completion. + +**Given** Epic 3 should enable subsequent epics cleanly +**When** Epic 3 is marked complete +**Then** there are no unresolved blockers for downstream epic execution +**And** FR7/FR8 quality evidence for Epic 3 is captured and traceable. + +**Given** Epic 3 closure requires traceable completion evidence +**When** Epic 3 is finalized +**Then** a Definition of Done artifact and test/story/export evidence references are captured in implementation artifacts +**And** those references are available for Epic 5 governance validation. + +## Epic 4: Skeleton Loading Experience Parity + +Provide trusted loading experiences by delivering skeleton primitives and composed variants with exact CRM animation parity. + +### Story 4.1: CRM Skeleton Baseline and Provenance Lock + +As a release owner, +I want the toolkit skeleton foundation to be sourced from CRM baseline, +So that loading experiences remain behaviorally consistent across company products. + +**Acceptance Criteria:** + +**Given** skeleton parity is a release blocker +**When** skeleton implementation work starts +**Then** CRM skeleton source is identified and reused as baseline +**And** provenance/source details are recorded with the shared Definition of Done checklist at `specs/implementation-artifacts/story-dod-template.md` (source, reuse rationale, and reference IDs in PR/issue metadata). + +**Given** canonical animation behavior is mandatory +**When** baseline skeleton code is integrated +**Then** key animation characteristics (timing/easing/keyframe behavior) are preserved +**And** no redesign of animation behavior is introduced in this story. + +**Given** this story must be independently completable +**When** Story 4.1 is complete +**Then** a verified baseline exists for further skeleton variant/composition stories +**And** no future-story dependency is required to validate baseline provenance/parity setup. + +### Story 4.2: Skeleton Primitive Variants + +As an end user, +I want consistent primitive loading placeholders, +So that content-loading states are understandable and visually stable. + +**Acceptance Criteria:** + +**Given** primitive skeleton variants are required by board scope +**When** `ui-skeleton` primitive variants are implemented +**Then** required primitive patterns are available (`image`, `text one-line`, `text many-lines`, `block`) +**And** variant APIs and behavior are consistent with toolkit component standards. + +**Given** animation parity is mandatory +**When** primitive variants render loading states +**Then** they use the established CRM-derived animation system +**And** no variant introduces incompatible animation behavior. + +**Given** this story must be independently completable +**When** Story 4.2 is finished +**Then** primitive skeleton variants are usable/testable on their own +**And** they provide a stable base for composed skeleton layouts without future-story dependency. + +### Story 4.3: Composed Skeleton Layout Variants + +As an end user, +I want realistic composed loading layouts, +So that complex screens communicate structure while data is loading. + +**Acceptance Criteria:** + +**Given** board scope includes composed skeleton layouts +**When** composed skeleton variants are implemented +**Then** required composed patterns are available (widget small/medium, menu, tab bar, button, list, input, checkbox+text, radio+text, table) +**And** composed variants are built from primitive skeleton foundations with consistent behavior. + +**Given** animation and interaction consistency are required +**When** composed variants are rendered +**Then** they preserve CRM-aligned animation behavior inherited from baseline/primitives +**And** no composed variant introduces conflicting animation or state semantics. + +**Given** this story should be independently completable +**When** Story 4.3 is delivered +**Then** composed skeleton variants are independently usable/testable +**And** completion does not require any future Epic 4 story to enable their baseline functionality. + +### Story 4.4: Skeleton Parity and Quality Gate Closure + +As a release owner, +I want full skeleton parity and quality evidence validated, +So that loading-state components are safe for production adoption. + +**Acceptance Criteria:** + +**Given** Epic 4 baseline, primitive, and composed variants are implemented +**When** parity validation is executed +**Then** CRM alignment for skeleton animation behavior is verified for the delivered scope +**And** any parity deviation is treated as a blocking issue for Epic 4 completion. + +**Given** release-quality requirements apply to skeleton components +**When** Epic 4 quality checks are run +**Then** skeleton components have Storybook coverage for relevant variants +**And** unit-test validation exists for render and key behavior expectations. + +**Given** provenance and export integrity are required for release readiness +**When** Epic 4 is reviewed for completion +**Then** source provenance is documented, `ui-skeleton` (primitive + composed) delivery artifacts are recorded with origin details, and export surface is complete +**And** Epic 4 exits with traceable FR5/FR6/FR8 evidence and no unresolved blockers. + +**Given** Epic 5 governance reporting consolidates FR evidence across epics +**When** Story 4.4 closure artifacts are finalized +**Then** the provenance/export checklist and traceability matrix include explicit links to the delivered `ui-skeleton` artifact and its source +**And** those links are ready for direct consolidation in subsequent Epic 5 governance validation/reporting. + +**Given** Epic 4 closure requires traceable completion evidence +**When** Epic 4 is finalized +**Then** a Definition of Done artifact and test/story/export/parity evidence references are captured in implementation artifacts +**And** those references are available for Epic 5 governance validation. + +## Epic 5: Production Adoption Readiness + +Make the toolkit safely adoptable across company projects by closing coverage, provenance, export, and release-gate governance. + +**Cross-Epic Dependency Note:** Epic 5 validates and consolidates outputs from Epics 1-4. It does not block execution start of Epics 1-4. + +### Story 5.1: Board Coverage Closure and Traceability + +As a release owner, +I want board-to-component coverage fully tracked and closed, +So that no required UI scope is omitted before production adoption. + +**Acceptance Criteria:** + +**Given** all boards define required component and state scope +**When** coverage mapping is finalized +**Then** each required board element is mapped to a delivered component or documented non-goal +**And** unresolved items are visible and treated as blockers. + +**Given** traceability is required for implementation confidence +**When** coverage documentation is reviewed +**Then** mappings are clear enough to verify completion objectively +**And** board-level completion status is explicit and auditable. + +**Given** this story must be independently completable +**When** Story 5.1 is done +**Then** board coverage status is complete and actionable +**And** downstream readiness stories do not depend on future untracked scope decisions. + +### Story 5.2: Reuse/Canonical Compliance and Provenance Completion + +As a release owner, +I want source provenance and canonical behavior compliance documented for all delivered components, +So that company teams can trust consistency with CRM/website governance rules. + +**Acceptance Criteria:** + +**Given** reuse-first and canonical policies are mandatory +**When** provenance documentation is completed +**Then** each delivered/enhanced component is marked with `source` (`crm`, `website`, `new`) and rationale +**And** canonical behavior alignment decisions are clearly documented using the shared Definition of Done checklist at `specs/implementation-artifacts/story-dod-template.md` (source, reuse rationale, and reference IDs in PR/issue metadata). + +**Given** deviations may be necessary in limited cases +**When** a component diverges from canonical expectations +**Then** the deviation is explicitly justified and recorded +**And** the decision is visible for release review. + +**Given** this story must be independently completable +**When** Story 5.2 is complete +**Then** provenance/compliance artifacts are production-review ready +**And** future stories do not need to redefine component source governance. + +### Story 5.3: Export Contract and Entry Point Integrity + +As a consumer-team developer, +I want all delivered components to be correctly exported from the toolkit entry point, +So that application teams can adopt components without import-surface inconsistencies. + +**Acceptance Criteria:** + +**Given** delivered components must be publicly consumable +**When** export integrity checks are executed +**Then** all in-scope components are available from `src/components/index.ts` +**And** missing or broken exports are treated as blocking issues. + +**Given** API contract consistency is required for adoption +**When** export and contract verification is reviewed +**Then** exported components align with expected public contract definitions +**And** contract exceptions are documented and traceable. + +**Given** this story must be independently completable +**When** Story 5.3 is complete +**Then** entrypoint/export integrity evidence is ready for release review +**And** no future Epic 5 story is needed to establish export correctness baseline. + +### Story 5.4: Internal Release-Readiness Governance Report + +As a release owner, +I want a consolidated readiness report covering coverage, provenance, quality, and compatibility checks, +So that internal package publication is a controlled and auditable decision. + +**Acceptance Criteria:** + +**Given** release depends on multiple governance gates +**When** release-readiness evidence is consolidated +**Then** board coverage closure, provenance compliance, export integrity, and quality-gate status are summarized in one report +**And** blocking vs non-blocking issues are explicitly identified. + +**Given** internal consumers rely on predictable compatibility +**When** readiness is finalized +**Then** compatibility expectations for internal consumers are documented (consumer scope, baseline runtime/dependency constraints) +**And** release-go/no-go decision criteria are explicit. + +**Given** public npm publication requires licensing/IP clearance +**When** pre-publish compliance checks are executed in CI +**Then** a valid `LICENSE` file and SPDX identifier are present, automated OSS license/IP scanning reports no critical findings, and repository checks confirm no proprietary code, internal-only URLs, or secrets are exposed +**And** Legal/OSS Compliance sign-off is recorded before public npm promotion, with release pipeline failure enforced if any licensing/IP gate check fails. + +**Given** this is the final Epic 5 story +**When** Story 5.4 is completed +**Then** Epic 5 can be marked complete with traceable evidence for FR1/FR2/FR3/FR8 and consolidated traceability references for FR4/FR5/FR6/FR7 delivered in Epics 1-4 +**And** the Release Manager performs a checklist-driven final validation review across epic and implementation artifacts. + +**Given** final governance sign-off requires auditable closure +**When** the Release Manager and Governance Board (see Governance Roles) complete final validation +**Then** the canonical output artifact is a signed `specs/implementation-artifacts/final-validation-certificate.md` containing sign-off fields (`reviewer`, `date`, `decision`, `blocking-issues`, `follow-ups`) plus linked Definition of Done evidence references +**And** if `specs/planning-artifacts/epics.md` is additionally annotated, the annotation must include a canonical pointer to `specs/implementation-artifacts/final-validation-certificate.md` plus `certificate-version` and `certificate-timestamp` metadata +**And** the canonical certificate is stored under `specs/implementation-artifacts/` before Epic 5 can be marked complete and release go/no-go is approved. diff --git a/specs/planning-artifacts/implementation-plan.md b/specs/planning-artifacts/implementation-plan.md new file mode 100644 index 0000000..13ebef3 --- /dev/null +++ b/specs/planning-artifacts/implementation-plan.md @@ -0,0 +1,737 @@ +# UI Toolkit Completion Implementation Plan (Re-scoped) + +**Goal:** Deliver a production-ready internal UI library for company projects (including `crm` and `website`) with complete Board A-D scope coverage, reuse-first delivery, canonical behavior consistency, and release-gate evidence. + +**Architecture:** Execute in epic order with governance-first setup, then deliver components by domain: core controls, selection/input workflows, data/cards, and skeletons. Reuse already implemented components from `crm` and `website` before creating new modules. Keep `crm` as canonical behavior source and use `website` only for visual and variant gap-fill. + +**Tech Stack:** React 18, TypeScript strict, MUI v5, Storybook 8, Jest + Testing Library, public npm registry publishing. + +**Plan Date:** 2026-02-23 +**Input Artifacts:** `specs/planning-artifacts/prd.md`, `specs/planning-artifacts/architecture.md`, `specs/planning-artifacts/epics.md` + +## Hard Constraints + +1. Reuse-first is mandatory: use already implemented components from `crm` and `website` first. +2. Canonical behavior is `crm`; `website` is only for visual/variant gap-fill. +3. Skeleton baseline must be copied from `crm` and keep exact animation behavior. +4. Toolkit remains UI-layer only: no backend ownership, no domain business logic. +5. Shared contract fields are required where relevant: `value`, `onChange`, `disabled`, `error`, `size`, `variant`, `sx`. +6. New component folders are kebab-case; existing legacy `UiPascalCase` folders stay unchanged unless explicitly migrated. +7. Every story exits only when Storybook coverage, unit tests, export completeness, and provenance updates are complete. + +## Current Repository Snapshot + +1. This workspace snapshot currently contains planning artifacts and not the full implementation tree (`src/components`, tests, Storybook files). +2. Known existing components from architecture baseline: + - `UiButton`, `UiInput`, `UiCheckbox`, `UiLink` + - `UiTypography`, `UiImage`, `UiToolbar`, `UiTooltip` + - `UiTextFieldForm`, `UiCardItem`, `UiCardList` + - `UiFooter`, `UiBreakpoints`, `UiColorTheme` +3. Present local coverage artifacts currently include only: + - `coverage/lcov-report/ui-toolkit/src/components/UiBreakpoints` + - `coverage/lcov-report/ui-toolkit/src/components/UiCardList` + +## Execution Preconditions + +1. Execute this plan in the full toolkit source checkout containing: + - `src/components` + - `tests/unit` + - `tests/integration` + - `.storybook` + - `package.json` +2. Ensure local source repos for reuse are available and readable: + - `crm` + - `website` +3. If source tree is missing, sync the implementation repository first and restart at Task 1. + +### Task 1: Bootstrap Governance Artifacts + +**Files:** +- Create: `specs/planning-artifacts/component-provenance.md` +- Create: `specs/planning-artifacts/board-coverage-checklist.md` +- Create: `specs/implementation-artifacts/release-readiness-report.md` +- Create: `specs/implementation-artifacts/story-dod-template.md` + +**Step 1: Create provenance registry skeleton** + +Add table columns: +- `component` +- `board` +- `source (crm|website|new)` +- `behavior-source` +- `visual-source` +- `notes` + +**Step 2: Create board coverage checklist** + +Add every scope item from Boards A-D with status fields: +- `implemented` +- `story-id` +- `storybook` +- `tests` +- `exports` +- `provenance` + +**Step 3: Create release-readiness report template** + +Add sections for: +- Epic closure status +- FR/NFR evidence links +- Blocking issues +- Go/No-Go decision + +**Step 4: Create story DoD template** + +Capture: +- changed files +- tests run +- stories added/updated +- export changes +- provenance updates + +**Step 5: Commit** + +```bash +git add specs/planning-artifacts/component-provenance.md \ + specs/planning-artifacts/board-coverage-checklist.md \ + specs/implementation-artifacts/release-readiness-report.md \ + specs/implementation-artifacts/story-dod-template.md +git commit -m "chore: bootstrap governance artifacts for ui-toolkit completion" +``` + +### Task 2: Inventory Existing Components and Map Reuse Sources + +**Files:** +- Modify: `specs/planning-artifacts/component-provenance.md` +- Modify: `specs/planning-artifacts/board-coverage-checklist.md` + +**Step 1: Inventory current toolkit components** + +Run and capture output: + +```bash +ls -1 src/components +rg -n "export \\{\\s*default\\s+as\\s+Ui" src/components/index.ts +rg -n "export \\{\\s*[^}]*Ui" src/components/index.ts +rg -n "export \\* from" src/components/index.ts +``` + +**Step 2: Inventory reusable candidates from `crm` and `website`** + +Run equivalent component listings in both repositories and map candidates to required components. + +**Step 3: Decide source per component** + +For each required component: +- pick `crm` for behavior baseline whenever available +- use `website` only for missing visual variants +- mark `new` only when neither source has viable implementation + +**Step 4: Update governance artifacts** + +Record all decisions in provenance and set checklist status to `mapped`. + +**Step 5: Commit** + +```bash +git add specs/planning-artifacts/component-provenance.md \ + specs/planning-artifacts/board-coverage-checklist.md +git commit -m "docs: map board scope to crm/website/new provenance sources" +``` + +### Task 3: Epic 1 Story 1.1 - Core Contract and Export Baseline + +**Files:** +- Modify: `src/components/UiButton/**` +- Modify: `src/components/UiInput/**` +- Modify: `src/components/UiCheckbox/**` +- Modify: `src/components/UiLink/**` +- Modify: `src/components/index.ts` +- Create/Modify: `tests/unit/ui-exports-coverage.test.tsx` + +**Step 1: Add/normalize shared contract typing where relevant** + +Apply typed fields and document exceptions per component semantics. + +**Step 2: Ensure export completeness** + +Verify core controls are exported from `src/components/index.ts`. + +**Step 3: Add export contract test coverage** + +Validate that expected exports exist and fail on missing exports. + +**Step 4: Verify** + +```bash +bunx jest tests/unit/ui-exports-coverage.test.tsx --verbose +``` + +**Step 5: Commit** + +```bash +git add src/components/UiButton src/components/UiInput src/components/UiCheckbox \ + src/components/UiLink src/components/index.ts \ + tests/unit/ui-exports-coverage.test.tsx +git commit -m "feat: align core control contracts and export baseline" +``` + +### Task 4: Epic 1 Stories 1.2 and 1.3 - State Parity + Accessibility Consistency + +**Files:** +- Modify: `src/components/UiButton/**` +- Modify: `src/components/UiInput/**` +- Modify: `src/components/UiCheckbox/**` +- Modify: `src/components/UiLink/**` +- Modify: `tests/unit/ui-button.test.tsx` +- Modify: `tests/unit/ui-input.test.tsx` +- Modify: `tests/unit/ui-checkbox.test.tsx` +- Modify: `tests/unit/ui-link.test.tsx` + +**Step 1: Implement missing state parity** + +Cover required states: +- button: rest, hover, active, disabled +- input: rest, hover, active, disabled, error +- checkbox: rest/checked/disabled combinations +- link: rest, hover, active, disabled when applicable + +**Step 2: Harden accessibility behavior** + +Ensure keyboard focus visibility and disabled/error interaction consistency. + +**Step 3: Align behavior with `crm`** + +Use `crm` behavior as source of truth; record any justified deviations in provenance notes. + +**Step 4: Verify** + +```bash +bunx jest tests/unit/ui-button.test.tsx --verbose +bunx jest tests/unit/ui-input.test.tsx --verbose +bunx jest tests/unit/ui-checkbox.test.tsx --verbose +bunx jest tests/unit/ui-link.test.tsx --verbose +``` + +**Step 5: Commit** + +```bash +git add src/components/UiButton src/components/UiInput src/components/UiCheckbox \ + src/components/UiLink tests/unit/ui-button.test.tsx \ + tests/unit/ui-input.test.tsx \ + tests/unit/ui-checkbox.test.tsx \ + tests/unit/ui-link.test.tsx \ + specs/planning-artifacts/component-provenance.md +git commit -m "feat: complete core state parity and accessibility consistency" +``` + +### Task 5: Epic 1 Story 1.4 - Quality Gate Closure + +**Files:** +- Modify: `src/components/UiButton/*.stories.tsx` +- Modify: `src/components/UiInput/*.stories.tsx` +- Modify: `src/components/UiCheckbox/*.stories.tsx` +- Modify: `src/components/UiLink/*.stories.tsx` +- Create: `specs/implementation-artifacts/epic-1-dod.md` + +**Step 1: Add/normalize stories for required states** + +Represent required interactive states and edge behaviors. + +**Step 2: Validate story and tests coverage for Epic 1** + +Run story build and core control tests. + +**Step 3: Update board checklist and DoD artifact** + +Mark Epic 1 rows and link evidence. + +**Step 4: Verify** + +```bash +bun run storybook-build +bunx jest tests/unit/ui-button.test.tsx \ + tests/unit/ui-input.test.tsx \ + tests/unit/ui-checkbox.test.tsx \ + tests/unit/ui-link.test.tsx --verbose +``` + +**Step 5: Commit** + +```bash +git add src/components/UiButton src/components/UiInput src/components/UiCheckbox \ + src/components/UiLink specs/planning-artifacts/board-coverage-checklist.md \ + specs/implementation-artifacts/epic-1-dod.md +git commit -m "test: close epic 1 quality gates with story and test evidence" +``` + +### Task 6: Epic 2 Stories 2.1 and 2.2 - Search/Select Foundation + Multi-Select + +**Canonical module locations for Tasks 6-11:** `src/features//components/` + +**Files:** +- Create: `src/features/selection-input/components/ui-search-input/index.tsx` +- Create: `src/features/selection-input/components/ui-search-input/types.ts` +- Create: `src/features/selection-input/components/ui-search-input/UiSearchInput.stories.tsx` +- Create: `src/features/selection-input/components/ui-select-with-search/index.tsx` +- Create: `src/features/selection-input/components/ui-select-with-search/types.ts` +- Create: `src/features/selection-input/components/ui-select-with-search/UiSelectWithSearch.stories.tsx` +- Create: `src/features/selection-input/components/ui-multi-select/index.tsx` +- Create: `src/features/selection-input/components/ui-multi-select/types.ts` +- Create: `src/features/selection-input/components/ui-multi-select/UiMultiSelect.stories.tsx` +- Create: `tests/unit/ui-search-input.test.tsx` +- Create: `tests/unit/ui-select-with-search.test.tsx` +- Create: `tests/unit/ui-multi-select.test.tsx` +- Modify: `src/features/selection-input/index.ts` +- Modify: `src/components/index.ts` (re-export via feature domain entry) + +**Step 1: Reuse implementations from `crm` and `website`** + +Start from existing source modules and adapt into toolkit contract patterns. + +**Step 2: Implement shared contract and disabled/error handling** + +Ensure consistent callback signatures and value handling. + +**Step 3: Add stories and tests** + +Cover render, selection/search interaction, and disabled/error behavior. + +**Step 4: Verify** + +```bash +bunx jest tests/unit/ui-search-input.test.tsx --verbose +bunx jest tests/unit/ui-select-with-search.test.tsx --verbose +bunx jest tests/unit/ui-multi-select.test.tsx --verbose +``` + +**Step 5: Commit** + +```bash +git add src/features/selection-input/components/ui-search-input \ + src/features/selection-input/components/ui-select-with-search \ + src/features/selection-input/components/ui-multi-select \ + src/features/selection-input/index.ts src/components/index.ts \ + tests/unit/ui-search-input.test.tsx \ + tests/unit/ui-select-with-search.test.tsx \ + tests/unit/ui-multi-select.test.tsx \ + specs/planning-artifacts/component-provenance.md +git commit -m "feat: deliver epic 2 search/select foundation and multi-select" +``` + +### Task 7: Epic 2 Stories 2.3, 2.4, and 2.4A - Calendar Multi-Select + Radio/File Upload + +**Files:** +- Create: `src/features/selection-input/components/ui-calendar-multi-select/index.tsx` +- Create: `src/features/selection-input/components/ui-calendar-multi-select/types.ts` +- Create: `src/features/selection-input/components/ui-calendar-multi-select/UiCalendarMultiSelect.stories.tsx` +- Create: `src/features/selection-input/components/ui-radio-group/index.tsx` +- Create: `src/features/selection-input/components/ui-radio-group/types.ts` +- Create: `src/features/selection-input/components/ui-radio-group/UiRadioGroup.stories.tsx` +- Create: `src/features/selection-input/components/ui-file-upload-input/index.tsx` +- Create: `src/features/selection-input/components/ui-file-upload-input/types.ts` +- Create: `src/features/selection-input/components/ui-file-upload-input/UiFileUploadInput.stories.tsx` +- Create: `tests/unit/ui-calendar-multi-select.test.tsx` +- Create: `tests/unit/ui-radio-group.test.tsx` +- Create: `tests/unit/ui-file-upload-input.test.tsx` +- Modify: `src/features/selection-input/index.ts` +- Modify: `src/components/index.ts` (re-export via feature domain entry) + +**Step 1: Implement components with reuse-first policy** + +Start from `crm` and `website` implementations when available. + +**Step 2: Standardize contract and interaction semantics** + +Align disabled/error behavior and callback contracts. + +**Step 3: Add story and test coverage** + +Include keyboard behavior for calendar and radio where relevant. + +**Step 4: Verify** + +```bash +bunx jest tests/unit/ui-calendar-multi-select.test.tsx --verbose +bunx jest tests/unit/ui-radio-group.test.tsx --verbose +bunx jest tests/unit/ui-file-upload-input.test.tsx --verbose +``` + +**Step 5: Commit** + +```bash +git add src/features/selection-input/components/ui-calendar-multi-select \ + src/features/selection-input/components/ui-radio-group \ + src/features/selection-input/components/ui-file-upload-input \ + src/features/selection-input/index.ts src/components/index.ts \ + tests/unit/ui-calendar-multi-select.test.tsx \ + tests/unit/ui-radio-group.test.tsx \ + tests/unit/ui-file-upload-input.test.tsx \ + specs/planning-artifacts/component-provenance.md +git commit -m "feat: complete epic 2 calendar, radio, and file-upload workflows" +``` + +### Task 7.5: Epic 2 Story 2.5 - Pagination Delivery + +**Files:** +- Create: `src/features/selection-input/components/ui-pagination/index.tsx` +- Create: `src/features/selection-input/components/ui-pagination/types.ts` +- Create: `src/features/selection-input/components/ui-pagination/UiPagination.stories.tsx` +- Create: `tests/unit/ui-pagination.test.tsx` +- Modify: `src/features/selection-input/index.ts` +- Modify: `src/components/index.ts` (re-export via feature domain entry) +- Modify: `specs/planning-artifacts/component-provenance.md` + +**Step 1: Implement `UiPagination` with reuse-first policy** + +Adapt from `crm`/`website` implementation patterns where viable and keep canonical behavior alignment. + +**Step 2: Add story and unit coverage** + +Document primary pagination states and test core interactions and disabled behavior. + +**Step 3: Verify** + +```bash +bunx jest tests/unit/ui-pagination.test.tsx --verbose +``` + +**Step 4: Commit** + +```bash +git add src/features/selection-input/components/ui-pagination \ + src/features/selection-input/index.ts src/components/index.ts \ + tests/unit/ui-pagination.test.tsx \ + specs/planning-artifacts/component-provenance.md +git commit -m "feat: deliver epic 2 pagination module" +``` + +### Task 8: Epic 2 Story 2.6 - Quality Gate Closure + +**Files:** +- Modify: `specs/planning-artifacts/board-coverage-checklist.md` +- Create: `specs/implementation-artifacts/epic-2-dod.md` + +**Step 1: Validate Epic 2 stories and tests** + +Ensure all Epic 2 components have stories and tests linked, including `UiPagination`. + +**Step 2: Validate export completeness** + +Confirm all Epic 2 components are available from `src/features/selection-input/index.ts` +and re-exported from `src/components/index.ts`. + +**Step 3: Record evidence** + +Capture test command output references and checklist row completion. + +**Step 4: Commit** + +```bash +git add specs/planning-artifacts/board-coverage-checklist.md \ + specs/implementation-artifacts/epic-2-dod.md +git commit -m "docs: close epic 2 quality gates and evidence tracking" +``` + +### Task 9: Epic 3 Stories 3.1 to 3.4 - Data Rows and Card Workflows + +**Files:** +- Create: `src/features/data-cards/components/ui-item-row/**` +- Create: `src/features/data-cards/components/ui-items-list/**` +- Create: `src/features/data-cards/components/ui-task-card/**` +- Create: `src/features/data-cards/components/ui-profile-select-card/**` +- Create: `src/features/data-cards/components/ui-integration-card/**` +- Create: `tests/unit/ui-item-row.test.tsx` +- Create: `tests/unit/ui-items-list.test.tsx` +- Create: `tests/unit/ui-task-card.test.tsx` +- Create: `tests/unit/ui-profile-select-card.test.tsx` +- Create: `tests/unit/ui-integration-card.test.tsx` +- Modify: `src/features/data-cards/index.ts` +- Modify: `src/components/index.ts` (re-export via feature domain entry) + +**Step 1: Reuse existing components from `crm`/`website`** + +Import behavior from `crm` and fill visual gaps from `website`. + +**Step 2: Implement module contracts and state semantics** + +Keep deterministic behavior and clear interaction callbacks. + +**Step 3: Add stories and tests** + +Cover method/status variants, selectable states, disabled behavior. + +**Step 4: Verify** + +```bash +bunx jest tests/unit/ui-item-row.test.tsx --verbose +bunx jest tests/unit/ui-items-list.test.tsx --verbose +bunx jest tests/unit/ui-task-card.test.tsx --verbose +bunx jest tests/unit/ui-profile-select-card.test.tsx --verbose +bunx jest tests/unit/ui-integration-card.test.tsx --verbose +``` + +**Step 5: Commit** + +```bash +git add src/features/data-cards/components/ui-item-row \ + src/features/data-cards/components/ui-items-list \ + src/features/data-cards/components/ui-task-card \ + src/features/data-cards/components/ui-profile-select-card \ + src/features/data-cards/components/ui-integration-card \ + src/features/data-cards/index.ts src/components/index.ts \ + tests/unit/ui-item-row.test.tsx \ + tests/unit/ui-items-list.test.tsx tests/unit/ui-task-card.test.tsx \ + tests/unit/ui-profile-select-card.test.tsx \ + tests/unit/ui-integration-card.test.tsx \ + specs/planning-artifacts/component-provenance.md +git commit -m "feat: deliver epic 3 data rows and card workflows" +``` + +### Task 10: Epic 3 Stories 3.5 and 3.6 - Micro-Components + Quality Closure + +**Files:** +- Create: `src/features/micro-components/components/ui-filter-chip/**` +- Create: `src/features/micro-components/components/ui-pin-input/**` +- Create: `src/features/micro-components/components/ui-payment-option-card/**` +- Create: `src/features/micro-components/components/ui-action-icon-bar/**` +- Create: `src/features/micro-components/components/ui-status-badge/**` +- Create: `src/features/micro-components/components/ui-notification-badge/**` +- Create: `tests/unit/ui-filter-chip.test.tsx` +- Create: `tests/unit/ui-pin-input.test.tsx` +- Create: `tests/unit/ui-payment-option-card.test.tsx` +- Create: `tests/unit/ui-action-icon-bar.test.tsx` +- Create: `tests/unit/ui-status-badge.test.tsx` +- Create: `tests/unit/ui-notification-badge.test.tsx` +- Modify: `src/features/micro-components/index.ts` +- Modify: `src/components/index.ts` (re-export via feature domain entry) +- Create: `specs/implementation-artifacts/epic-3-dod.md` + +**Step 1: Implement micro-components with shared conventions** + +Apply contract fields only where semantically relevant and document exceptions. + +**Step 2: Add story/test coverage for all micro-components** + +Cover render + one core interaction assertion per component. + +**Step 3: Validate exports and governance records** + +Ensure all components are exported and provenance entries are complete. + +**Step 4: Verify** + +```bash +bunx jest tests/unit/ui-filter-chip.test.tsx --verbose +bunx jest tests/unit/ui-pin-input.test.tsx --verbose +bunx jest tests/unit/ui-payment-option-card.test.tsx --verbose +bunx jest tests/unit/ui-action-icon-bar.test.tsx --verbose +bunx jest tests/unit/ui-status-badge.test.tsx --verbose +bunx jest tests/unit/ui-notification-badge.test.tsx --verbose +``` + +**Step 5: Commit** + +```bash +git add src/features/micro-components/components/ui-filter-chip \ + src/features/micro-components/components/ui-pin-input \ + src/features/micro-components/components/ui-payment-option-card \ + src/features/micro-components/components/ui-action-icon-bar \ + src/features/micro-components/components/ui-status-badge \ + src/features/micro-components/components/ui-notification-badge \ + src/features/micro-components/index.ts src/components/index.ts \ + tests/unit/ui-filter-chip.test.tsx \ + tests/unit/ui-pin-input.test.tsx \ + tests/unit/ui-payment-option-card.test.tsx \ + tests/unit/ui-action-icon-bar.test.tsx \ + tests/unit/ui-status-badge.test.tsx \ + tests/unit/ui-notification-badge.test.tsx \ + specs/planning-artifacts/component-provenance.md \ + specs/implementation-artifacts/epic-3-dod.md +git commit -m "feat: complete epic 3 micro-components and quality closure" +``` + +### Task 11: Epic 4 Stories 4.1 to 4.3 - Skeleton Baseline, Primitive, and Composed Variants + +**Files:** +- Create/Modify: `src/features/skeleton/components/ui-skeleton/**` +- Create/Modify: `src/features/skeleton/components/ui-skeleton-composed/**` +- Create: `tests/unit/ui-skeleton.test.tsx` +- Create: `tests/unit/ui-skeleton-composed.test.tsx` +- Modify: `src/features/skeleton/index.ts` +- Modify: `src/components/index.ts` (re-export via feature domain entry) +- Modify: `specs/planning-artifacts/component-provenance.md` + +**Step 1: Copy skeleton baseline from `crm`** + +Reuse existing skeleton implementation and preserve animation behavior exactly. + +**Step 2: Add primitive variants** + +Implement image/text/block primitive placeholders. + +**Step 3: Add composed variants** + +Implement required composed layouts (widgets, menu, tab bar, controls, table). + +**Step 4: Verify parity + behavior** + +```bash +bunx jest tests/unit/ui-skeleton.test.tsx --verbose +bunx jest tests/unit/ui-skeleton-composed.test.tsx --verbose +``` + +**Step 5: Commit** + +```bash +git add src/features/skeleton/components/ui-skeleton \ + src/features/skeleton/components/ui-skeleton-composed \ + src/features/skeleton/index.ts src/components/index.ts \ + tests/unit/ui-skeleton.test.tsx \ + tests/unit/ui-skeleton-composed.test.tsx \ + specs/planning-artifacts/component-provenance.md +git commit -m "feat: deliver epic 4 skeleton baseline and variants with crm parity" +``` + +### Task 12: Epic 4 Story 4.4 - Skeleton Quality Gate Closure + +**Files:** +- Modify: `specs/planning-artifacts/board-coverage-checklist.md` +- Create: `specs/implementation-artifacts/epic-4-dod.md` + +**Step 1: Verify parity evidence** + +Capture proof that animation behavior remains aligned to `crm` baseline. + +**Step 2: Verify story/test/export completeness** + +Ensure skeleton components are fully documented and exported. + +**Step 3: Commit** + +```bash +git add specs/planning-artifacts/board-coverage-checklist.md \ + specs/implementation-artifacts/epic-4-dod.md +git commit -m "docs: close epic 4 skeleton parity and quality gates" +``` + +### Task 13: Epic 5 Stories 5.1 to 5.4 - Adoption Readiness and Governance Closure + +**Files:** +- Modify: `specs/planning-artifacts/board-coverage-checklist.md` +- Modify: `specs/planning-artifacts/component-provenance.md` +- Modify: `src/components/index.ts` (if missing exports remain) +- Modify: `specs/implementation-artifacts/release-readiness-report.md` +- Create: `specs/implementation-artifacts/epic-5-dod.md` + +**Step 1: Close board coverage mapping** + +Each Board A-D item must be `done` or explicitly documented as non-goal. + +**Step 2: Finalize provenance and canonical compliance** + +All components must have source + rationale + behavior alignment notes. + +**Step 3: Finalize export integrity** + +No required component missing from entrypoint exports. + +**Step 4: Complete governance report** + +Summarize: +- coverage closure +- provenance compliance +- export integrity +- quality-gate evidence +- compatibility notes for internal consumers (`crm`, `website`, others) + +**Step 5: Commit** + +```bash +git add specs/planning-artifacts/board-coverage-checklist.md \ + specs/planning-artifacts/component-provenance.md \ + src/components/index.ts \ + specs/implementation-artifacts/release-readiness-report.md \ + specs/implementation-artifacts/epic-5-dod.md +git commit -m "docs: finalize epic 5 adoption readiness governance" +``` + +### Task 14: Final Verification and Release Gate + +**Files:** +- Modify: `specs/implementation-artifacts/release-readiness-report.md` +- Modify: `package.json` +- Modify: `CHANGELOG.md` (and/or `.changeset/**`, `bun.lock`) during version management + +**Step 1: Run full verification suite** + +```bash +bun run lint +bun run typecheck +bunx jest --verbose +bun run storybook-build +bun run build +``` + +**Step 1b: Perform version management (Changesets preferred)** + +Preferred Changesets flow: + +```bash +bunx changeset +bunx changeset version +git add .changeset package.json bun.lock CHANGELOG.md +git commit -m "chore: version ui-toolkit for release" +``` + +Fallback flow if Changesets are unavailable: + +```bash +npm version --no-git-tag-version +git add package.json bun.lock CHANGELOG.md +git commit -m "chore: bump ui-toolkit version to " +``` + +**Step 2: Confirm release exit criteria** + +Checklist must be true: +- board coverage fully closed +- stories exist for new/enhanced components +- unit tests pass +- strict TS checks pass +- library build succeeds +- skeleton parity verified +- export surface complete +- version bump PR includes updated `CHANGELOG.md` and package metadata +- `ci:publish` script is present in `package.json` and points to the public npm registry URL (`${NPM_REGISTRY_URL:-https://registry.npmjs.org}`) + +**Step 3: Record final evidence and release decision** + +Set `release-readiness-report.md` to `GO` or `NO-GO` with blocking items, and include links to verification output and the version-bump PR. + +**Step 4: Commit** + +```bash +git add specs/implementation-artifacts/release-readiness-report.md +git commit -m "chore: publish final release-readiness gate decision" +``` + +**Step 5: Publish from CI after version-bump PR merge** + +Ensure `package.json` contains: + +```json +{ + "scripts": { + "ci:publish": "bun publish --registry ${NPM_REGISTRY_URL:-https://registry.npmjs.org}" + } +} +``` + +After the version-bump PR is merged to the release branch, run publish in CI: + +```bash +bun run ci:publish +``` + +Archive publish logs/artifact links in `specs/implementation-artifacts/release-readiness-report.md`. diff --git a/specs/planning-artifacts/prd.md b/specs/planning-artifacts/prd.md new file mode 100644 index 0000000..55f32c4 --- /dev/null +++ b/specs/planning-artifacts/prd.md @@ -0,0 +1,262 @@ +# UI Toolkit Completion PRD (Re-scoped) + +**Date:** February 20, 2026 +**Owner:** UI Toolkit Team +**Status:** Approved +**Target Release Version:** `ui-toolkit` `v1.0.0` +**Planned Release Window:** March 16, 2026 - March 27, 2026 (Sprint `2026-S06`) +**Milestone Target:** `UITK-SR1` + +## 1. Product Outcome + +Deliver a production-ready `ui-toolkit` release that fully covers all component modules and state variants represented in: + +1. Board A +2. Board B +3. Board C +4. Board D + +This release must remove the need for product teams to implement ad hoc UI controls outside the toolkit for covered surfaces. + +## 2. Release Boundary + +Single release scope: full coverage of all four boards in one versioned delivery. + +## 3. Operating Principles and Constraints + +### 3.1 Integration Boundary (Hard Constraint) + +Toolkit remains strictly UI-layer: + +1. Presentation and interaction contracts only. +2. No backend integrations or data-fetching ownership. +3. No domain business logic. +4. Styling override entrypoint is the shared `sx` contract defined in §3.5 and constrained by §8. + +### 3.2 Reuse-First Delivery Rule (Hard Constraint) + +Before creating new implementations, teams must reuse already implemented components from: + +1. `crm` +2. `website` + +### 3.3 Canonical Source Resolution + +When both sources contain similar components: + +1. `crm` is canonical for behavior and interaction patterns. +2. `website` is used to fill visual and variant gaps. +3. Any divergence from this policy requires explicit note in implementation artifacts. + +### 3.4 Skeleton Policy (Release Blocker) + +1. Skeleton implementation is copied/reused from `crm` as baseline. +2. Animation parity is mandatory: keyframes, easing, timing, shimmer/pulse behavior. +3. No animation redesign in this release. + +### 3.5 API Consistency Policy + +New components follow a strict unified contract where relevant: + +1. `value` +2. `onChange` +3. `disabled` +4. `error` +5. `size` +6. `variant` +7. `sx` + +Documented exceptions are allowed only where control semantics require it. +`sx` is the MUI-style system prop and must accept `SxProps` semantics (theme-aware object/array/function). +Reference signature: `sx?: SxProps`. +Vendor-coupling guardrail: if a consumer cannot pass MUI `SxProps`, provide an adapter layer that maps to `className`/`style` while preserving theme-token behavior; this requirement is mandatory under FR-07 Acceptance Criterion 3 and release-gated by §9 Criterion 7. + +## 4. Scope Coverage by Board + +### 4.1 Board A + +1. Button states: rest, hover, active, disabled. +2. Secondary/outlined button states. +3. Link states. +4. Checkbox states in row context. +5. Select with search. +6. Radio group. +7. File upload input. +8. Supporting micro-components: + - Filter chip (removable) + - PIN/OTP input + - Payment option card + - Action icon bar + - Status badge + - Notification badge/counter + +### 4.2 Board B + +1. Input states: rest, hover, active, disabled, error. +2. Item row/list with method/status semantics. +3. Pagination states. +4. Search states with suggestion dropdown. +5. Multiselect states with selected chips. +6. Calendar-style multiselect variant. + +### 4.3 Board C + +1. Task/person cards and states. +2. Profile select card with menu states. +3. Integration/brand selection card behavior and states. + +### 4.4 Board D + +1. Skeleton primitives: + - Round image + - Block image + - One-line text + - Multi-line text + - Generic block placeholder +2. Skeleton composed layouts: + - Widget small + - Widget medium + - Menu + - Tab bar + - Button + - List + - Input + - Checkbox + text + - Radio + text + - Table + +## 5. In Scope + +1. Missing modules from all boards. +2. Missing state parity for existing modules. +3. Storybook story coverage for each delivered/enhanced module. +4. Unit tests for each delivered/enhanced module. +5. Export coverage via `src/components/index.ts`. +6. Coverage checklist maintained as Markdown at `specs/planning-artifacts/board-coverage-checklist.md` ("coverage checklist"), owned by the Component Lead / Frontend Team, with checklist rows mapping `board element -> component -> implementation status -> src/components/index.ts export link -> Storybook coverage (URL / status) -> Unit test coverage (coverage report link / status)`; the Component Lead / Frontend Team must populate every column for every row so FR-08 acceptance and §9 exit criteria items 2-3 can be verified from this single source of truth. + +## 6. Out of Scope + +1. Backend/API integrations (search backends, upload storage, etc.). +2. Product-specific business workflows. +3. Token redesign or global visual language refresh. +4. Visual regression program setup beyond this release’s targeted checks. + +## 7. Functional Requirements + +### FR-01 Board Coverage Completeness + +Every board section listed in Scope Coverage must map to a delivered toolkit component or documented enhancement. + +Acceptance: + +1. The canonical coverage checklist at `specs/planning-artifacts/board-coverage-checklist.md` exists, is complete, and is maintained by the Component Lead / Frontend Team. +2. No unresolved board element remains without explicit non-goal decision. + +### FR-02 Reuse-First Compliance + +Implementations must prioritize existing `crm` and `website` assets before creating new modules. + +Acceptance: + +1. Component implementation notes include source origin. +2. New from-scratch modules only when no viable source exists. + +### FR-03 Canonical Behavior Alignment + +Interaction behavior follows `crm` when both systems have equivalent components. + +Acceptance: + +1. Behavior and interaction semantics match `crm`. +2. Visual gap-fill from `website` does not break canonical behavior. + +### FR-04 State Parity for Existing Controls + +Existing controls must support board-required states defined in §4.1 and §4.2. + +Acceptance: + +1. `UiButton` implements `rest`, `hover`, `active`, `focus-visible`, and `disabled` states (plus `error/invalid` where used by form-validation contexts). +2. `UiInput` renders `rest`, `hover`, `active`, `focus-visible`, `disabled`, `error`, and `invalid` states. +3. `UiCheckbox` provides `unchecked`, `checked`, `hover`, `active`, `focus-visible`, `disabled`, `error`, and `invalid` states where applicable. +4. `UiLink` exposes `rest`, `hover`, `active`, `focus-visible`, and `disabled` states; `focus-visible` is mandatory and must be visibly distinct for keyboard operability per WCAG 2.1 AA, while `error/invalid` remains optional unless explicitly introduced by product usage. + +### FR-05 Missing Module Delivery + +Deliver reusable components: + +1. `ui-pagination` +2. `ui-search-input` +3. `ui-select-with-search` +4. `ui-multi-select` +5. `ui-calendar-multi-select` +6. `ui-radio-group` +7. `ui-file-upload-input` +8. `ui-item-row` +9. `ui-items-list` +10. `ui-task-card` +11. `ui-profile-select-card` +12. `ui-integration-card` +13. `ui-filter-chip` +14. `ui-pin-input` +15. `ui-payment-option-card` +16. `ui-action-icon-bar` +17. `ui-status-badge` +18. `ui-notification-badge` +19. `ui-skeleton` primitives and composed variants + +### FR-06 Skeleton Parity (Release Blocker) + +Acceptance: + +1. `crm` skeleton baseline is copied before extension. +2. Animation parity is preserved exactly. +3. Added variants reuse the same animation system. + +### FR-07 API Contract Consistency + +Acceptance: + +1. Unified API fields are used where relevant. +2. Exceptions are documented with rationale. +3. A documented and tested adapter that maps `SxProps` to `className`/`style` while preserving theme-token behavior is delivered and passes integration tests. + +### FR-08 Quality Gates + +Acceptance: + +1. Every delivered component has Storybook coverage. +2. Every delivered component has unit tests with at least render + one core interaction assertion. +3. TypeScript strict checks pass. +4. Components are exported and importable via `src/components/index.ts`. + +## 8. Non-Functional Requirements + +1. Preserve backward compatibility for existing public component APIs unless explicitly approved. +2. Keep naming aligned to existing `Ui*` conventions. +3. Maintain keyboard accessibility meeting WCAG 2.1 AA with explicit checks: `Tab`/`Shift+Tab` navigation, logical focus order, visible focus indicator, keyboard-operable controls, appropriate ARIA roles/states, and consistent disabled/error behavior. +4. Keep implementation maintainable and composable for future board expansion. +5. Keep `sx` usage compatible with MUI `SxProps` and provide a documented fallback mapping strategy for non-MUI consumers, enforced by FR-07 Acceptance Criterion 3 and §9 Criterion 7. + +## 9. Release Exit Criteria + +Release is complete only when all are true: + +1. The canonical coverage checklist at `specs/planning-artifacts/board-coverage-checklist.md` is fully closed and current under Component Lead / Frontend Team ownership. +2. Storybook coverage exists for all new/enhanced components. +3. Unit tests pass for new/enhanced components. +4. TypeScript checks pass. +5. Skeleton parity requirements are verified. +6. Exports are complete from toolkit entry point. +7. Adapter implementation, documentation, and automated integration tests are present and passing. + +## 10. Risks and Mitigations + +1. Risk: Scope pressure from single-release mandate. + - Mitigation: enforce board checklist and strict definition of done per component. +2. Risk: Behavior drift between source systems. + - Mitigation: enforce `crm` canonical behavior policy. +3. Risk: Visual inconsistency while blending sources. + - Mitigation: use website only for visual/variant gap-fill after behavior alignment. +4. Risk: Skeleton parity regressions. + - Mitigation: treat animation parity as release blocker and verify before sign-off. diff --git a/src/components/UiButton/index.tsx b/src/components/UiButton/index.tsx index ffb957c..a2332c7 100755 --- a/src/components/UiButton/index.tsx +++ b/src/components/UiButton/index.tsx @@ -1,4 +1,5 @@ import { Button, ThemeProvider } from '@mui/material'; +import React from 'react'; import { theme } from './theme'; import { UiButtonProps } from './types'; diff --git a/src/components/UiButton/types.ts b/src/components/UiButton/types.ts index 0f472a2..f01ae6c 100755 --- a/src/components/UiButton/types.ts +++ b/src/components/UiButton/types.ts @@ -1,3 +1,10 @@ +import { SxProps, Theme } from '@mui/material'; + +/** + * Shared contract support: + * - supported: disabled, size, variant, sx + * - exceptions: value, onChange, error + */ export interface UiButtonProps { variant?: 'outlined' | 'contained'; size?: 'small' | 'medium' | 'large'; @@ -6,6 +13,6 @@ export interface UiButtonProps { onClick?: () => void; type?: 'button' | 'submit' | 'reset'; children?: React.ReactNode | string; - sx?: React.CSSProperties; + sx?: SxProps; name?: string; } diff --git a/src/components/UiCardItem/CardContent.tsx b/src/components/UiCardItem/CardContent.tsx index 021059e..21bb8de 100755 --- a/src/components/UiCardItem/CardContent.tsx +++ b/src/components/UiCardItem/CardContent.tsx @@ -1,3 +1,4 @@ +import React from 'react'; import { Trans } from 'react-i18next'; import UiTooltip from '../UiTooltip'; diff --git a/src/components/UiCardList/CardGrid.tsx b/src/components/UiCardList/CardGrid.tsx index 0d60042..383f9a0 100755 --- a/src/components/UiCardList/CardGrid.tsx +++ b/src/components/UiCardList/CardGrid.tsx @@ -1,5 +1,5 @@ import { Grid } from '@mui/material'; -import { CSSProperties } from 'react'; +import React, { CSSProperties } from 'react'; import UiCardItem from '../UiCardItem'; diff --git a/src/components/UiCardList/CardSwiper.tsx b/src/components/UiCardList/CardSwiper.tsx index 7af1fd4..8cac2fa 100755 --- a/src/components/UiCardList/CardSwiper.tsx +++ b/src/components/UiCardList/CardSwiper.tsx @@ -1,5 +1,5 @@ import { Grid } from '@mui/material'; -import { CSSProperties, useEffect, useRef } from 'react'; +import React, { CSSProperties, useEffect, useRef } from 'react'; import { Pagination } from 'swiper/modules'; import { Swiper, SwiperSlide } from 'swiper/react'; diff --git a/src/components/UiCardList/index.tsx b/src/components/UiCardList/index.tsx index f21c771..2f6c42d 100755 --- a/src/components/UiCardList/index.tsx +++ b/src/components/UiCardList/index.tsx @@ -1,4 +1,5 @@ import { Box } from '@mui/material'; +import React from 'react'; import CardGrid from './CardGrid'; import CardSwiper from './CardSwiper'; diff --git a/src/components/UiCheckbox/types.ts b/src/components/UiCheckbox/types.ts index b648d9f..284fa97 100755 --- a/src/components/UiCheckbox/types.ts +++ b/src/components/UiCheckbox/types.ts @@ -1,7 +1,14 @@ +import { SxProps, Theme } from '@mui/material'; + +/** + * Shared contract support: + * - supported: onChange, disabled, error, sx + * - exceptions: value, size, variant + */ export interface UiCheckboxProps { onChange: (event: React.ChangeEvent) => void; label: string | React.ReactNode; disabled?: boolean; - sx?: React.CSSProperties; + sx?: SxProps; error?: boolean; } diff --git a/src/components/UiFooter/DefaultFooter/DefaultFooter.tsx b/src/components/UiFooter/DefaultFooter/DefaultFooter.tsx index f6e1864..8383ad6 100755 --- a/src/components/UiFooter/DefaultFooter/DefaultFooter.tsx +++ b/src/components/UiFooter/DefaultFooter/DefaultFooter.tsx @@ -1,5 +1,5 @@ import { Box, Stack } from '@mui/material'; -import { useMemo } from 'react'; +import React, { useMemo } from 'react'; import { useTranslation } from 'react-i18next'; import Logo from '@/assets/svg/Logo.svg'; diff --git a/src/components/UiFooter/UiFooter.tsx b/src/components/UiFooter/UiFooter.tsx index 2a479ed..0f98659 100755 --- a/src/components/UiFooter/UiFooter.tsx +++ b/src/components/UiFooter/UiFooter.tsx @@ -1,4 +1,5 @@ import { Box } from '@mui/material'; +import React from 'react'; import { socialLinks } from './constants'; import { DefaultFooter } from './DefaultFooter'; diff --git a/src/components/UiFooter/VilnaCRMEmail/VilnaCRMGmail.tsx b/src/components/UiFooter/VilnaCRMEmail/VilnaCRMGmail.tsx index 888221e..1110ca3 100755 --- a/src/components/UiFooter/VilnaCRMEmail/VilnaCRMGmail.tsx +++ b/src/components/UiFooter/VilnaCRMEmail/VilnaCRMGmail.tsx @@ -5,12 +5,16 @@ import { UiTypography } from '@/components/'; import styles from './styles'; +const defaultEmailAddress: string = 'info@vilnacrm.com'; + function VilnaCRMEmail(): React.ReactElement { + const email: string = process.env.NEXT_PUBLIC_VILNACRM_GMAIL ?? defaultEmailAddress; + return ( - - {process.env.NEXT_PUBLIC_VILNACRM_GMAIL} + + {email} diff --git a/src/components/UiImage/index.tsx b/src/components/UiImage/index.tsx index aa4b0d5..b0fcc98 100755 --- a/src/components/UiImage/index.tsx +++ b/src/components/UiImage/index.tsx @@ -1,4 +1,5 @@ import { Box } from '@mui/material'; +import React from 'react'; import styles from './styles'; import { UiImageProps } from './types'; diff --git a/src/components/UiInput/index.tsx b/src/components/UiInput/index.tsx index 867e682..456661f 100755 --- a/src/components/UiInput/index.tsx +++ b/src/components/UiInput/index.tsx @@ -10,7 +10,21 @@ const UiInput: React.ForwardRefExoticComponent< UiInputProps & React.RefAttributes > = React.forwardRef( ( - { sx, placeholder, error, onBlur, type, fullWidth, value, onChange, disabled, onInput, id }, + { + sx, + placeholder, + error, + size, + variant, + onBlur, + type, + fullWidth, + value, + onChange, + disabled, + onInput, + id, + }, ref ) => ( @@ -19,6 +33,8 @@ const UiInput: React.ForwardRefExoticComponent< placeholder={placeholder} inputRef={ref} error={error} + size={size} + variant={variant} type={type} onChange={onChange} onBlur={onBlur} diff --git a/src/components/UiInput/types.ts b/src/components/UiInput/types.ts index 5b11c13..451a042 100755 --- a/src/components/UiInput/types.ts +++ b/src/components/UiInput/types.ts @@ -1,10 +1,19 @@ +import { SxProps, TextFieldProps, Theme } from '@mui/material'; + +/** + * Shared contract support: + * - supported: value, onChange, disabled, error, size, variant, sx + * - exceptions: none for Story 1.1 baseline + */ export interface UiInputProps { - sx?: React.CSSProperties; + sx?: SxProps; placeholder?: string; value?: string; onChange?: (event: React.ChangeEvent) => void; ref?: React.ForwardedRef; error?: boolean; + size?: TextFieldProps['size']; + variant?: TextFieldProps['variant']; onBlur?: (event: React.FocusEvent) => void; type?: string; fullWidth?: boolean; diff --git a/src/components/UiLink/index.tsx b/src/components/UiLink/index.tsx index a5e8cb6..ea13c95 100755 --- a/src/components/UiLink/index.tsx +++ b/src/components/UiLink/index.tsx @@ -1,12 +1,13 @@ import { Link, ThemeProvider } from '@mui/material'; +import React from 'react'; import { theme } from './theme'; import { UiLinkProps } from './types'; -function UiLink({ children, href, target }: UiLinkProps): React.ReactElement { +function UiLink({ children, href, target, sx }: UiLinkProps): React.ReactElement { return ( - + {children} diff --git a/src/components/UiLink/types.ts b/src/components/UiLink/types.ts index 48f7a2f..449fcf3 100755 --- a/src/components/UiLink/types.ts +++ b/src/components/UiLink/types.ts @@ -1,6 +1,13 @@ +import { SxProps, Theme } from '@mui/material'; + +/** + * Shared contract support: + * - supported: sx + * - exceptions: value, onChange, disabled, error, size, variant + */ export interface UiLinkProps { children: React.ReactNode; href: string; target?: string; - sx?: React.CSSProperties; + sx?: SxProps; } diff --git a/src/components/UiTextFieldForm/index.tsx b/src/components/UiTextFieldForm/index.tsx index f7dfbd2..0b0ce57 100755 --- a/src/components/UiTextFieldForm/index.tsx +++ b/src/components/UiTextFieldForm/index.tsx @@ -1,3 +1,4 @@ +import React from 'react'; import { Controller, FieldValues } from 'react-hook-form'; import UiInput from '../UiInput'; diff --git a/src/components/UiToolbar/index.tsx b/src/components/UiToolbar/index.tsx index 829a338..7f4edf0 100755 --- a/src/components/UiToolbar/index.tsx +++ b/src/components/UiToolbar/index.tsx @@ -1,4 +1,5 @@ import { Toolbar, ThemeProvider } from '@mui/material'; +import React from 'react'; import { theme } from './theme'; diff --git a/src/test/mocks/styleMock.ts b/src/test/mocks/styleMock.ts new file mode 100644 index 0000000..9741db8 --- /dev/null +++ b/src/test/mocks/styleMock.ts @@ -0,0 +1,3 @@ +const styleMock: Record = {}; + +export default styleMock; diff --git a/src/test/mocks/svgMock.ts b/src/test/mocks/svgMock.ts new file mode 100644 index 0000000..c97d128 --- /dev/null +++ b/src/test/mocks/svgMock.ts @@ -0,0 +1,5 @@ +const svgMock: { src: string } = { + src: 'svg-mock', +}; + +export default svgMock; diff --git a/src/test/testing-library/UiButton.test.tsx b/src/test/testing-library/UiButton.test.tsx index 02b3440..cae47c8 100644 --- a/src/test/testing-library/UiButton.test.tsx +++ b/src/test/testing-library/UiButton.test.tsx @@ -1,4 +1,5 @@ import { render, fireEvent } from '@testing-library/react'; +import React from 'react'; import { UiButton } from '../../components'; diff --git a/src/test/testing-library/UiCardGrid.test.tsx b/src/test/testing-library/UiCardGrid.test.tsx index e0cb06b..57a446b 100644 --- a/src/test/testing-library/UiCardGrid.test.tsx +++ b/src/test/testing-library/UiCardGrid.test.tsx @@ -5,21 +5,29 @@ import CardGrid from '../../components/UiCardList/CardGrid'; import { cardList, largeCardList, smallCardList } from './constants'; -jest.mock('../../components/UiCardItem', () => ({ - __esModule: true, - default: jest.fn(() =>

), -})); +jest.mock('../../components/UiCardItem', () => { + const mockReact: typeof import('react') = jest.requireActual('react'); + + return { + __esModule: true, + default: jest.fn(() => + mockReact.createElement('div', { + 'data-testid': 'mock-ui-card-item', + }) + ), + }; +}); describe('CardGrid component', () => { it('renders with correct props', () => { - const { getByTestId } = render(); + const { getByTestId } = render(React.createElement(CardGrid, { cardList })); const cardGrid: HTMLElement = getByTestId('mock-ui-card-item'); expect(cardGrid).toBeInTheDocument(); }); it('renders with smallGrid style when cardList[0].type is smallCard', () => { - const { container } = render(); + const { container } = render(React.createElement(CardGrid, { cardList: smallCardList })); const gridElement: ChildNode | null = container.firstChild; const computedStyles: CSSStyleDeclaration = window.getComputedStyle(gridElement as Element); @@ -28,7 +36,7 @@ describe('CardGrid component', () => { }); it('renders with largeGrid style when cardList[0].type is largeGrid', () => { - const { container } = render(); + const { container } = render(React.createElement(CardGrid, { cardList: largeCardList })); const gridElement: ChildNode | null = container.firstChild; const computedStyles: CSSStyleDeclaration = window.getComputedStyle(gridElement as Element); diff --git a/src/test/testing-library/UiCardItem.test.tsx b/src/test/testing-library/UiCardItem.test.tsx index f2034c8..c84cee2 100644 --- a/src/test/testing-library/UiCardItem.test.tsx +++ b/src/test/testing-library/UiCardItem.test.tsx @@ -1,4 +1,5 @@ import { render } from '@testing-library/react'; +import React from 'react'; import UiCardItem from '../../components/UiCardItem'; import CardContent from '../../components/UiCardItem/CardContent'; diff --git a/src/test/testing-library/UiCardList.test.tsx b/src/test/testing-library/UiCardList.test.tsx index 3d3998e..524a401 100644 --- a/src/test/testing-library/UiCardList.test.tsx +++ b/src/test/testing-library/UiCardList.test.tsx @@ -5,13 +5,19 @@ import UiCardList from '../../components/UiCardList'; import { cardList } from './constants'; -jest.mock('../../components/UiCardList/CardSwiper', () => - jest.fn(() =>
) -); +jest.mock('../../components/UiCardList/CardSwiper', () => { + const mockReact: typeof import('react') = jest.requireActual('react'); + + return jest.fn(() => + mockReact.createElement('div', { + 'data-testid': 'card-swiper', + }) + ); +}); describe('UiCardList component', () => { it('renders CardSwiper with correct props', () => { - const { getByTestId } = render(); + const { getByTestId } = render(React.createElement(UiCardList, { cardList })); const cardSwiper: HTMLElement = getByTestId('card-swiper'); expect(cardSwiper).toBeInTheDocument(); diff --git a/src/test/testing-library/UiCoreContract.test.tsx b/src/test/testing-library/UiCoreContract.test.tsx new file mode 100644 index 0000000..b84b675 --- /dev/null +++ b/src/test/testing-library/UiCoreContract.test.tsx @@ -0,0 +1,66 @@ +import type { Theme, SxProps } from '@mui/material'; +import { render } from '@testing-library/react'; +import React from 'react'; + +import { UiButton, UiCheckbox, UiInput, UiLink } from '../../components'; +import type { UiButtonProps } from '../../components/UiButton/types'; +import type { UiCheckboxProps } from '../../components/UiCheckbox/types'; +import type { UiInputProps } from '../../components/UiInput/types'; +import type { UiLinkProps } from '../../components/UiLink/types'; + +const sharedSxFn: (theme: Theme) => { color: string } = (theme: Theme): { color: string } => ({ + color: theme.palette.primary.main, +}); + +const buttonSxContract: UiButtonProps['sx'] = sharedSxFn; +const checkboxSxContract: UiCheckboxProps['sx'] = sharedSxFn; +const inputSxContract: UiInputProps['sx'] = sharedSxFn; +const linkSxContract: UiLinkProps['sx'] = sharedSxFn; + +const inputSharedContractProps: Pick = { + size: 'small', + variant: 'filled', +}; + +type AssertAssignable> = T; + +const assertMuiSxContract: >( + value: T +) => AssertAssignable = >(value: T): AssertAssignable => value; + +const assertedButtonSx: NonNullable = assertMuiSxContract< + NonNullable +>(buttonSxContract); +const assertedCheckboxSx: NonNullable = assertMuiSxContract< + NonNullable +>(checkboxSxContract); +const assertedInputSx: NonNullable = assertMuiSxContract< + NonNullable +>(inputSxContract); +const assertedLinkSx: NonNullable = assertMuiSxContract< + NonNullable +>(linkSxContract); + +describe('Ui core contract', () => { + it('exports the four core controls from the package entrypoint', () => { + expect(UiButton).toBeDefined(); + expect(UiCheckbox).toBeDefined(); + expect(UiInput).toBeDefined(); + expect(UiLink).toBeDefined(); + expect(assertedButtonSx).toBeDefined(); + expect(assertedCheckboxSx).toBeDefined(); + expect(assertedInputSx).toBeDefined(); + expect(assertedLinkSx).toBeDefined(); + expect(inputSharedContractProps).toEqual({ + size: 'small', + variant: 'filled', + }); + }); + + it('forwards size and variant to UiInput', () => { + const { container } = render(); + + expect(container.querySelector('.MuiFilledInput-root')).toBeInTheDocument(); + expect(container.querySelector('.MuiInputBase-sizeSmall')).toBeInTheDocument(); + }); +}); diff --git a/src/test/testing-library/UiFooterEmail.test.tsx b/src/test/testing-library/UiFooterEmail.test.tsx index 22ed1d5..c7cb2be 100644 --- a/src/test/testing-library/UiFooterEmail.test.tsx +++ b/src/test/testing-library/UiFooterEmail.test.tsx @@ -1,14 +1,40 @@ import { render } from '@testing-library/react'; +import React from 'react'; import { VilnaCRMEmail } from '../../components/UiFooter/VilnaCRMEmail'; import { mockEmail } from './constants'; describe('VilnaCRMEmail component', () => { + const originalEmail: string | undefined = process.env.NEXT_PUBLIC_VILNACRM_GMAIL; + + afterEach(() => { + if (originalEmail === undefined) { + delete process.env.NEXT_PUBLIC_VILNACRM_GMAIL; + return; + } + + process.env.NEXT_PUBLIC_VILNACRM_GMAIL = originalEmail; + }); + it('renders email address correctly', () => { + delete process.env.NEXT_PUBLIC_VILNACRM_GMAIL; + const { getByText } = render(); const emailLink: HTMLElement = getByText(mockEmail); expect(emailLink).toBeInTheDocument(); }); + + it('uses the configured email for both text and mailto href', () => { + const configuredEmail: string = 'support@example.com'; + process.env.NEXT_PUBLIC_VILNACRM_GMAIL = configuredEmail; + + const { getByRole } = render(); + + expect(getByRole('link', { name: configuredEmail })).toHaveAttribute( + 'href', + `mailto:${configuredEmail}` + ); + }); }); diff --git a/src/test/testing-library/UiImage.test.tsx b/src/test/testing-library/UiImage.test.tsx index a9aeb55..81c8095 100644 --- a/src/test/testing-library/UiImage.test.tsx +++ b/src/test/testing-library/UiImage.test.tsx @@ -1,4 +1,5 @@ import { render } from '@testing-library/react'; +import React from 'react'; import { UiImage } from '../../components'; diff --git a/src/test/testing-library/UiTooltipWrapper.test.tsx b/src/test/testing-library/UiTooltipWrapper.test.tsx index 32a9a5d..3ae9112 100644 --- a/src/test/testing-library/UiTooltipWrapper.test.tsx +++ b/src/test/testing-library/UiTooltipWrapper.test.tsx @@ -1,9 +1,8 @@ import { render, screen, fireEvent, waitFor } from '@testing-library/react'; -import userEvent, { UserEvent } from '@testing-library/user-event'; -import React from 'react'; +import userEvent from '@testing-library/user-event'; +import * as React from 'react'; import WrapperUiTooltip from '../../components/UiTooltip/TooltipWrapper'; -import { UiTooltipProps } from '../../components/UiTooltip/types'; const triggerText: string = 'Trigger'; const tooltipContent: string = 'Tooltip Text'; @@ -15,8 +14,9 @@ jest.mock('@mui/material', () => ({ })); describe('WrapperUiTooltip', () => { - const setup: (props?: UiTooltipProps) => void = () => + const setup: () => void = () => { render({triggerText}); + }; afterEach(() => { jest.clearAllMocks(); @@ -45,7 +45,7 @@ describe('WrapperUiTooltip', () => { }); it('open and clone tooltip', async () => { - const user: UserEvent = userEvent.setup(); + const user: { click: (element: Element) => Promise } = userEvent.setup(); setup(); const trigger: HTMLElement = screen.getByText(triggerText);