Conversation
…ith Tailwind styles
…t error state handling
* polish component states with hover, focus, and disabled styles * add useForm hook and FormContext for form state management * add Form wrapper component with submit handling * export Form, useForm, and FormContext from package * increase timeout for autoDismiss test stability * add PasswordInput component with visibility toggle and strength meter * add NumberInput component with increment buttons and formatting * add DatePicker component with calendar popup * add PhoneInput component with country code selection * feat: add FileInput component with drag-and-drop and preview * feat: add ColorPicker component with swatches and RGB/HSL inputs * feat: add Switch component with toggle states and customization * refactor: restrict public API to DynamicForm export only * refactor: restructure codebase to CHM architecture with core/, models/, fields/, and layout/ folders * chore: remove legacy code and consolidate to CHM architecture * feat(testing): add test suite achieving 80%+ coverage (192 tests) * docs: enhance JSDoc for FieldType and ConditionalOperator, add changeset * refactor: fix layer import rules and component default exports * style: add field components with improved styling * restore the checkbox field * restore the password field * feat: add PhoneField with country selector and countries.json data (240+ countries, flagcdn.com flags) * password field style adjustments * feat(FileField): add accept, maxFileSize, and multiple config options with client-side validation * adjust radio and checkbox fields styles * adjust szitch field styles * feat: add SliderField with range input, editable value sync, and min/max/step config options * feat: add RangeSliderField with dual-thumb slider and editable from/to inputs * feat: add OTPField with configurable length and Full paste support * feat: add TagsField with multi-tag input, paste support, and configurable limits * feat: add RatingField with star rating, half-star support, and keyboard navigation * feat: add TimeField with step interval * feat: add DateTimeField with combined date and time input * test: add comprehensive tests for new field components * fix: unify checkbox styles across components * feat: add MultiSelectField with search, tags, and keyboard navigation * fix: remove focus styles from rating field * feat: update SelectField to use custom dropdown with search matching MultiSelectField style * fix: update field and form tests * feat: update time, date and dateTime fields styles to have custom dropdowns and pickers * fix: adjust select and multi select fields styles * fix: update dropdowns and pickers positioning and style across components * feat: add responsive measures to form fields * feat: update OTP field styles to support mobile layout * feat(i18n): add internationalization with English and French locale support * feat(form): automatically scroll to first invalid field and focus it on submit * feat(ArrayField): refactor to reuse Field components via scoped context * feat: add translation content for Array field and optional params * refactor: remove unused config param * feat(layout): add grid-based layout system with sections and responsive columns * fix(ArrayField): enable per-field Zod validation and error display for nested fields * refactore and remove duplicate logic * address and fix the Sonar annotated findings * fix: formatting issues --------- Co-authored-by: Zaiidmo <zaiidmoumnii@gmail.com>
|
There was a problem hiding this comment.
Pull request overview
This PR evolves the repo from a template into the initial @ciscode/ui-form-kit package by adding the core form-kit architecture (core/models/hooks/components), i18n, Tailwind build output, and CI/quality gates for the first release.
Changes:
- Add core runtime modules (types, validation, conditional logic, grid helpers, i18n, errors) plus new models and hooks for form orchestration.
- Add many UI components (fields, layout primitives, wizard stepper) and expand the public API via
src/index.ts. - Introduce Vitest + Testing Library setup/coverage thresholds, Tailwind/PostCSS build output, and updated GitHub Actions workflows for release validation and publishing.
Reviewed changes
Copilot reviewed 114 out of 118 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| vitest.setup.ts | Adds Testing Library cleanup + jest-dom matchers for Vitest. |
| vitest.config.ts | Switches to jsdom, adds setup, includes tests, configures coverage/thresholds. |
| tsup.config.ts | Normalizes config style; exports a named config. |
| tsconfig.json | Adds Vitest/jest-dom global types for test typechecking. |
| tailwind.config.js | Adds Tailwind content scanning configuration. |
| src/vitest.d.ts | Adds vitest/jest-dom type references. |
| src/utils/noop.ts | Removes placeholder noop util. |
| src/utils/index.ts | Removes placeholder utils barrel. |
| src/styles.css | Adds Tailwind import and FormKit-specific utility/layout CSS. |
| src/models/ValidationRule.ts | Adds sync/async validation rule type contracts. |
| src/models/StepConfig.ts | Adds wizard step configuration type contract. |
| src/models/SectionConfig.ts | Adds section/grid layout contracts + runtime type guards. |
| src/models/index.ts | Adds models type exports barrel. |
| src/models/FormState.ts | Defines form/field state and context contracts. |
| src/models/FieldConfig.ts | Defines field configuration contract (incl. async validation + layout). |
| src/locales/index.ts | Adds locales barrel exports. |
| src/locales/fr.ts | Adds French translation dictionary. |
| src/locales/en.ts | Adds English translation dictionary. |
| src/index.ts | Defines the package’s primary public API surface (components/types/i18n/hooks). |
| src/hooks/useNoop.ts | Removes placeholder noop hook. |
| src/hooks/useI18n.ts | Adds i18n hook wrapper around I18nContext. |
| src/hooks/useFormStep.ts | Adds wizard step navigation + step-level validation. |
| src/hooks/useFormContext.ts | Adds public wrapper hook for accessing form context. |
| src/hooks/useFieldArray.ts | Adds array-field state helpers (append/insert/move/etc.). |
| src/hooks/useAsyncValidation.ts | Adds debounced async validation with AbortController cancellation. |
| src/hooks/index.ts | Replaces placeholder hooks barrel with real exports. |
| src/hooks/FormKitContext.ts | Adds form context + hook (layered under hooks). |
| src/hooks/tests/useFormContext.test.tsx | Adds tests for context hooks behavior and errors. |
| src/core/validator.ts | Adds Zod error mapping + sync validation helpers. |
| src/core/types.ts | Adds core field types, value types, validation modes, constants. |
| src/core/schema-helpers.ts | Adds helpers for creating/merging Zod schemas. |
| src/core/index.ts | Adds core barrel exports. |
| src/core/i18n.ts | Adds translation types + getTranslation() with interpolation. |
| src/core/grid.ts | Adds Tailwind grid class builders for columns/spans/gaps. |
| src/core/errors.ts | Adds custom error classes for consumers/internals. |
| src/core/conditional.ts | Adds conditional visibility evaluation logic. |
| src/core/tests/validator.test.ts | Adds unit tests for validator helpers. |
| src/core/tests/grid.test.ts | Adds unit tests for grid helpers. |
| src/components/NoopButton.tsx | Removes placeholder component. |
| src/components/layout/index.ts | Adds layout components barrel exports. |
| src/components/layout/FormSection.tsx | Adds section rendering (fieldset/legend + grid + colSpan). |
| src/components/layout/FormActions.tsx | Adds submit/reset/prev button group with i18n + loading state. |
| src/components/layout/FieldLabel.tsx | Adds standardized label/legend with required indicator and a11y label. |
| src/components/layout/FieldGroup.tsx | Adds fieldset grouping layout primitive. |
| src/components/layout/FieldError.tsx | Adds standardized error rendering with role=alert. |
| src/components/layout/tests/FormSection.test.tsx | Adds tests for section rendering and layout behavior. |
| src/components/layout/tests/FormActions.test.tsx | Adds tests for actions rendering + submitting state. |
| src/components/index.ts | Replaces placeholder components barrel with real exports. |
| src/components/form/index.ts | Adds form module barrel exports. |
| src/components/form/FormStepper.tsx | Adds wizard progress/stepper component with a11y. |
| src/components/form/DynamicFormStep.tsx | Adds per-step field rendering for wizard mode. |
| src/components/fields/TextField.tsx | Adds text/email/number input component with a11y + errors. |
| src/components/fields/TextareaField.tsx | Adds textarea component with a11y + errors. |
| src/components/fields/SwitchField.tsx | Adds switch (role=switch) component with a11y + errors. |
| src/components/fields/SliderField.tsx | Adds slider component with track fill, numeric input, clamping. |
| src/components/fields/RadioGroupField.tsx | Adds radio group component with fieldset/legend semantics. |
| src/components/fields/PasswordField.tsx | Adds password input with show/hide toggle and a11y labels. |
| src/components/fields/OTPField.tsx | Adds OTP input with auto-advance, paste, keyboard nav. |
| src/components/fields/index.ts | Adds fields barrel exports. |
| src/components/fields/FileField.tsx | Adds file upload input with type/size validation and i18n strings. |
| src/components/fields/Field.tsx | Adds field router for rendering the correct field by FieldType. |
| src/components/fields/CheckboxField.tsx | Adds checkbox with custom visuals and keyboard handling. |
| src/components/fields/tests/TimeField.test.tsx | Adds interaction/a11y tests for the time picker field. |
| src/components/fields/tests/TagsField.test.tsx | Adds tests for tags entry/removal/limits. |
| src/components/fields/tests/SliderField.test.tsx | Adds tests for slider behavior, sync, clamping. |
| src/components/fields/tests/RatingField.test.tsx | Adds tests for star rating interactions + keyboard behavior. |
| src/components/fields/tests/RangeSliderField.test.tsx | Adds tests for dual-slider range behavior and clamping. |
| src/components/fields/tests/PhoneField.test.tsx | Adds tests for phone field country selection and structure. |
| src/components/fields/tests/PasswordField.test.tsx | Adds tests for password field toggle and a11y attributes. |
| src/components/fields/tests/OTPField.test.tsx | Adds tests for OTP input behaviors (paste/nav/filtering). |
| src/components/fields/tests/DateTimeField.test.tsx | Adds tests for datetime picker behaviors and keyboard controls. |
| src/components/fields/tests/DateField.test.tsx | Adds tests for date picker behaviors and keyboard controls. |
| src/components/context/index.ts | Adds context module barrel exports. |
| src/components/context/I18nContext.tsx | Adds i18n provider/context with optional deep-merged overrides. |
| src/components/context/FormKitContext.tsx | Adds provider wrapper for the FormKitContext from hooks layer. |
| src/components/context/tests/I18nContext.test.tsx | Adds tests for locale selection, overrides, and getTranslation. |
| README.md | Rewrites README to document the published package and quality gates. |
| postcss.config.cjs | Adds PostCSS config (tailwindcss + autoprefixer). |
| package.json | Sets initial version, exports styles entry, adds Tailwind/test deps and scripts. |
| eslint.config.js | Updates ignores and rules; removes utils-layer import restriction block. |
| .prettierrc.json | Expands Prettier settings (tabs, EOL, spacing). |
| .github/workflows/release-check.yml | Adds release-check workflow for master PRs including SonarCloud. |
| .github/workflows/publish.yml | Adds publish workflow with tag/version validation and npm provenance. |
| .github/workflows/pr-validation.yml | Updates CI trigger and Node version for develop PRs. |
| .github/workflows/ci-release-check.yml | Removes old release-check workflow. |
| .github/workflows/cd-release.yml | Removes old publish workflow. |
| .github/instructions/sonarqube_mcp.instructions.md | Adds MCP usage guidelines file. |
| .github/instructions/bugfix.instructions.md | Adds bugfix process guidance documentation. |
| .github/dependabot.yml | Adds Dependabot configuration for npm updates. |
| .github/CODEOWNERS | Adds CODEOWNERS default ownership. |
| .changeset/first-release-v0-0-1.md | Adds changeset describing the first public release contents. |
| // Column span class | ||
| const colSpanClass = config.colSpan ? `col-span-${config.colSpan}` : ''; | ||
| const wrapperClass = `formkit-field ${colSpanClass} ${config.className ?? ''}`.trim(); |
There was a problem hiding this comment.
config.colSpan is typed as ColSpanValue (number OR responsive object). Interpolating it into col-span-${config.colSpan} will produce an invalid class like col-span-[object Object] for responsive configs, and layout already applies colSpan wrappers in DynamicForm/FormSection via getColSpanClass. Consider removing colSpan handling from Field entirely, or using getColSpanClass(config.colSpan) and ensuring it isn't applied twice.
| /** | ||
| * Type guard to check if an item is a SectionConfig | ||
| */ | ||
| export function isSection(item: FormLayoutItem): item is SectionConfig { | ||
| return Object.prototype.hasOwnProperty.call(item, 'type') && item.type === 'section'; | ||
| } |
There was a problem hiding this comment.
This file is documented as "Type Layer — contracts only, zero runtime logic" but it now exports runtime helpers (isSection/isField). That also conflicts with the coverage config comment that models have no runtime. To keep layering clear, move these type guards to src/core (or another runtime layer) and keep src/models type-only, or update both the file docs and coverage exclusions accordingly.
| 'dist/**', | ||
| // Type-only files (models have no runtime code) | ||
| 'src/models/**', | ||
| // Exclude wizard-mode components (not primary API, to be tested in Phase 3) |
There was a problem hiding this comment.
Coverage excludes src/models/** with the comment "models have no runtime code", but src/models/SectionConfig.ts now contains runtime exports (isSection/isField). That means these public runtime helpers won’t be counted toward coverage thresholds. Either move runtime helpers out of src/models, or adjust coverage exclusions so runtime code is measured.
| "scripts": { | ||
| "clean": "rimraf dist *.tsbuildinfo", | ||
| "build": "tsup", | ||
| "clean": "rimraf dist *.tsbuildinfo && rm -rf coverage", |
There was a problem hiding this comment.
clean script uses rm -rf coverage, which will fail on Windows shells (and the project already uses rimraf for cross-platform deletes). Consider switching this to rimraf coverage (or extending the existing rimraf call) to keep scripts portable.
| "clean": "rimraf dist *.tsbuildinfo && rm -rf coverage", | |
| "clean": "rimraf dist *.tsbuildinfo coverage", |
| {steps.map((step, index) => { | ||
| const state = getStepState(index, currentStep, onStepClick); | ||
|
|
||
| return ( | ||
| <li key={step.title} className={getStepItemClassName(state)}> | ||
| {/* Step number/icon */} |
There was a problem hiding this comment.
Using step.title as the React key can break rendering if two steps share the same title (React key collisions). Since StepConfig has no dedicated unique id, consider using the array index (or extending StepConfig with an id field and using that) to guarantee uniqueness.



Summary
Why
Checklist
npm run lintpassesnpm run typecheckpassesnpm testpassesnpm run buildpassesnpx changeset) if this affects consumersNotes