Skip to content

Conversation

@jthrilly
Copy link
Member

@jthrilly jthrilly commented Aug 12, 2025

This PR is a second attempt at a new form system to replace the old, redux-form, based approach.

  • <Form> component, supporting async onSubmit handler
  • <Field> component, which connects any standard or custom input to the form system. When rendered within <Form /> automatically handles registering/unregistering.
  • Supports nested field names
  • <FieldSet /> component, designed for grouping <Field /> components, and conditionally rendering them.
  • useForm, useField, and useFormValue hooks to enable clean composition patterns, and features such as conditional rendering
  • Validation using zod functions
  • Accessibility support with appropriate aria properties being added by custom hooks
  • useProtocolForm custom hook, which translates a protocol form definition to a renderable list of Field components.
  • Implementation of form field variants via cva beta 1.0.0
  • Make a plan for validation functions. Zod schemas are great, but what about localisation and compatibility with existing validation?

@vercel
Copy link

vercel bot commented Aug 12, 2025

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
fresco-sandbox Error Error Dec 27, 2025 11:09pm
fresco-storybook Error Error Dec 27, 2025 11:09pm
1 Skipped Deployment
Project Deployment Review Updated (UTC)
barf Ignored Ignored Dec 27, 2025 11:09pm

jthrilly and others added 3 commits December 26, 2025 10:39
## Field Component Architecture
- Refactor Field component with new type utilities for validation prop inference
- Add CreateFormFieldProps utility for cleaner field component prop definitions
- Implement ValidationPropsForValue to infer validation props based on value type
- Make InjectedFieldProps optional to support both Field-wrapped and standalone usage
- Extract ExtractValue utility for type-safe value extraction from components

## Form Field onChange Signature Standardization
- Update all form fields to use direct value onChange: (value: T) => void
- Affected components: InputField, SelectField, TextArea, and all field types
- Update consumers (DataTable, ApiTokenManagement, data-table-*) to new signature

## Select Field Reorganization
- Rename select/native.tsx → Select/Native.tsx (PascalCase)
- Rename select/styled.tsx → Select/Styled.tsx (PascalCase)
- Move Select.stories.tsx into Select/ directory
- Update all import paths to reflect new structure

## Component Import Updates
- Change Dialog import from named to default export
- Change FormStoreProvider import from named to default export
- Add useFormStore hook (separate from store provider)
- Update Button: rename variant prop to color for destructive style

## UI Component Fixes
- Add wrapperPaddingVariants to Button component
- Fix IconButton aspect-square styling with !important
- Revert CommandInput to use native cmdk input instead of InputField

## Interview Shell Simplification
- Remove DndStoreProvider wrapper (moved elsewhere or no longer needed)
- Remove DialogManager from InterviewShell

## Story Updates
- Update Form.stories.tsx with pattern errorMessage requirements
- Update ArrayField.stories.tsx for new onChange signatures
- Update various field stories for API changes

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…d APIs

Major changes to the form system architecture:

**Type reorganization**
- Move core form state types to lib/form/store/types.ts
- Move field component types to lib/form/components/Field/types.ts
- Delete lib/form/types.ts in favor of co-located type definitions
- Export FieldValue and ValidationPropsCatalogue from appropriate modules

**useField hook improvements**
- Add validateOnChange option with debounced validation for real-time feedback
- Add validateOnChangeDelay option (default 1000ms) for controlling debounce
- Disable fields automatically during form submission
- Inject disabled/readOnly props directly into field components
- Improve error display logic to work correctly with both blur and change validation

**Form store improvements**
- Initialize errors as empty object instead of null for consistent shape
- Add calculateFormValidity helper for consistent validity calculation
- Consider fields without validation as valid by default
- Clean up field errors when fields are unregistered
- Optimize validateAllFields with batched state updates

**Field component updates**
- Filter validation props before passing to child components
- Support validateOnChange and validateOnChangeDelay props
- Boolean field: use undefined instead of null for reset, styling improvements
- Move PasswordField to app/(blobs)/(setup)/_components/ (app-specific)

**File reorganization**
- Move test files from __tests__/ to their related directories
- Rename Input.stories.tsx to InputField.stories.tsx for consistency
- Update all field components to import from new type locations

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
## Tooltip Migration
- Replace @radix-ui/react-tooltip with @base-ui/react/tooltip
- Update tooltip.tsx to use MotionSurface for consistent styling with popover
- Add AnimatePresence for smooth enter/exit animations
- Include arrow by default via showArrow prop
- Update PassphrasePrompter.tsx to use base-ui tooltip API
- Add comprehensive Tooltip storybook stories

## Slider Components Migration
- Migrate VisualAnalogScale and LikertScale from @radix-ui/react-slider
  to @base-ui/react/slider
- Add shared slider variants to controlVariants.ts:
  - sliderRootVariants, sliderControlVariants, sliderTrackVariants
  - sliderThumbVariants with proper state handling (normal/disabled/readOnly/invalid)
  - sliderTickContainerStyles and sliderTickStyles
- Fix LikertScale tick alignment using absolute positioning with percentages
- Clean up unused tooltip state code from LikertScale

## Form Field Improvements
- Fix Boolean field: use CSS Grid for equal-width buttons with text wrapping
- Fix Checkbox: properly pass aria-invalid to getInputState
- Fix DatePicker: add padding for dropdown arrow, use w-fit for selects

## Storybook Updates
- Fix controls for Boolean, Checkbox, DatePicker, LikertScale,
  RichTextEditor, ToggleButtonGroup, and VisualAnalogScale stories
- Use args pattern with useEffect for proper state synchronization
- Ensure disabled, readOnly, and aria-invalid controls work correctly

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants