You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Evaluate available form libraries to determine the best fit for implementing dynamic task configuration forms. The selected library must support schema-driven form generation.
Motivation
To build a robust and maintainable dynamic form system for task configuration, we need to select a form library that aligns with our technical requirements and provides the flexibility needed to support all Open Workflow task types
Proposed Implementation
No response
Definition of Done
Implementation: Fully implemented according to the Open Workflow spec.
Unit Tests: Comprehensive unit tests are included and passing.
Integration Tests: Verified within the monorepo and target environments (Web/VS Code).
Documentation: Updated README.md, ADRs, or official docs.
Performance: No significant regression in editor responsiveness.
Accessibility: UI changes comply with accessibility standards.
Building on #337, we need a library to hold form state for the node-editing side panel - consuming the resolved schemas from filterSchemaByDefinition.ts and rendering through our existing src/components/ui/* components.
Option A: react-jsonschema-form (RJSF)
Main Pros
Generates a working form layout from JSON schemas with almost zero upfront code.
Handles open maps (additionalProperties) out of the box (add, rename, and remove actions).
Main Cons
Two options were evaluated to see if it would work with our existing shadcn components for the form:
@rjsf/shadcn:
RJSF site links to the @rjsf/shadcn theme package but it is unusable in our project because it ships un-prefixed Tailwind styles, whereas our application monorepo build exclusively targets dec: utility styles as it is embedded in host applications. It also vendors its own copy of 14 shadcn primitives so we would have 2 component sets in one app
withTheme()
Because @rjsf/shadcn is ruled out, it means we would have to use the generic withTheme() HOC API. Simple inputs map fine, but compound controls like Combobox do not against RJSF's flat value/onChange widget contract. The friction grows with every non-trivial control we add, and it lands hardest on the ones we need most.
Other reasons to not adopt:
We don't own the render cycle. RJSF holds the form state and decides which fields exist, in what order, and when they update - we fill slots it calls rather than deciding what to render.
Very limited when it comes to UX - UX customisation runs through RJSF's own contracts - uiSchema plus template overrides. Neither lets us change which fields render or how deep, and there is no collapsing support at all.
No out of the box dirty state so managing Save/Cancel UI triggers requires building a custom, manual deep-diffing engine
Option B: Uniforms
Ruled out:
No pre-built theme for shadcn/ui or Base UI, so we would design, code and maintain a wrapper for every primitive.
I used setTask as the baseline test, it cannot render the field that matters. Uniforms has no field type for open maps, so set - the Set task's only required property - gets a label and no control. We would need to build a workaround for this that would not be straightforward
Option C: React Hook Form (RHF) — RECOMMENDED
Main Pros
We own the render cycle. We retain complete architectural control over what renders, in what order, and how deep the form cascades
We can implement the UX we want - collapsing sections, progressive disclosure, conditional fields - in our own interaction logic rather than in schema syntax.
Native tracking for isDirty and dirtyFields is available out of the box
Fits our UI components directly with no intermediate theme abstraction layers, prefix mapping workarounds, or compound component layout friction as it is the recommended form library for shadcn
Client-side validation hooks into the SDK's existing Ajv engine, so the side panel and the canvas error badges cannot disagree.
No Zod needed. The shadcn docs use Zod in their examples, but it isn't required - the POC runs without it against the setTask output from the WIP filterSchemaByDefinition, and works well.
Less risk as we move forward - shadcn officially have it as an option on site.
Main Cons
We must write and maintain our own custom recursive field routing loop (This is the one layout element RJSF handles for free)
No open-map or array handling out of the box - we build those, RHF renders nothing by design, so this is true of every control, and it is not too much work to cater for.
Small POC to prove we can use react-hook-form to dynamically build a form without Zod, rendering the JSON the WIP filterSchemaByDefinition produces, without hardcoding fields:
NOTE: I just have all props render as a simple Input, and hardcoded the setTask JSON that was generated from the filter. You can view it in DynamicSchemaForm.stories and read the docs there.
I tested your PoC and it LGTM! It is definitely a good starting point.
I agree that option C is the way to go, mainly because shadcn officially has it and it aligns with our stack.
However, we are bringing a certain level of complexity to build a proper form on the editor side. That being said, we shall put in extra effort to not couple the form to the schema structure and its definitions, as it may change over time.
Agreed on both counts. That's the trade, and it's the main con, we write the field routing that RJSF would give us for free but get much more control and dont have to fight with UX and implement other functionality that comes out of the box with rhf. UX will be very important for us as well especially with the amount of nested objects
Just tested the POC, looks really good. I agree on going with option C - although being more complex, it seems like the pros outweigh the cons compared to the other options
We also have "ui:widget": "hidden" to hide some fields and support only specific fields for editing.
Regarding the CSS prefix, this does seem to be an issue, as I couldn't find any documented configuration for it.
Option B: Uniforms
+1 to prefer Option A over this one, as with Uniforms we would have to implement our own fields. This is not particularly complex, but RJSF seems to offer more out of the box.
From my previous experience with Uniforms in another project, we customised it to use a different UI library. The full customisation required 27 .tsx files, but they were neither long nor particularly complex.
Option C: React Hook Form (RHF)
IIUC, this means that initially we would support editing only a specific subset of fields, rather than all fields, while using the schema for validation. Is that correct?
What I like about this approach is that we go for "baby steps"
+1 also to @handreyrc's comment about avoiding too much complexity for this feature, at least at the beginning. Option C seems better aligned with this direction.
I still think this spike and the alternatives we evaluated are important to keep documented, in this spike, for future reference.
I can see that I overstated the ordering as a con. Ultimately RHF will give is more flexibility from a UX perspective and is more in line with our stack.
Agree on the baby steps as well, one issue at a time. Yes we start with a subset and grow it with validation coming from the sdk. +1 on keeping this documenting in spike for future
Looks like agreement with Option C anyway so we will go with that
+1 for React Hook Form as it seems like the best fit here since it gives us full control over rendering and UX while integrating cleanly with our existing components.
Activity
lornakelly commentedon Aug 26, 2026
Context
Building on #337, we need a library to hold form state for the node-editing side panel - consuming the resolved schemas from
filterSchemaByDefinition.tsand rendering through our existing src/components/ui/* components.Option A: react-jsonschema-form (RJSF)
Main Pros
Main Cons
Two options were evaluated to see if it would work with our existing shadcn components for the form:
@rjsf/shadcn:RJSF site links to the
@rjsf/shadcntheme package but it is unusable in our project because it ships un-prefixed Tailwind styles, whereas our application monorepo build exclusively targetsdec:utility styles as it is embedded in host applications. It also vendors its own copy of 14 shadcn primitives so we would have 2 component sets in one appwithTheme()@rjsf/shadcnis ruled out, it means we would have to use the genericwithTheme()HOC API. Simple inputs map fine, but compound controls like Combobox do not against RJSF's flat value/onChange widget contract. The friction grows with every non-trivial control we add, and it lands hardest on the ones we need most.Other reasons to not adopt:
Option B: Uniforms
Ruled out:
Option C: React Hook Form (RHF) — RECOMMENDED
Main Pros
isDirtyanddirtyFieldsis available out of the boxMain Cons
Small POC to prove we can use react-hook-form to dynamically build a form without Zod, rendering the JSON the WIP filterSchemaByDefinition produces, without hardcoding fields:
https://github.com/lornakelly/editor/tree/form-library-poc
NOTE: I just have all props render as a simple Input, and hardcoded the setTask JSON that was generated from the filter. You can view it in DynamicSchemaForm.stories and read the docs there.
handreyrc commentedon Aug 27, 2026
@lornakelly,
I tested your PoC and it LGTM! It is definitely a good starting point.
I agree that option C is the way to go, mainly because shadcn officially has it and it aligns with our stack.
However, we are bringing a certain level of complexity to build a proper form on the editor side. That being said, we shall put in extra effort to not couple the form to the schema structure and its definitions, as it may change over time.
Thanks for your analysis!
lornakelly commentedon Aug 27, 2026
Agreed on both counts. That's the trade, and it's the main con, we write the field routing that RJSF would give us for free but get much more control and dont have to fight with UX and implement other functionality that comes out of the box with rhf. UX will be very important for us as well especially with the amount of nested objects
Thanks @handreyrc
cheryl7114 commentedon Aug 27, 2026
Just tested the POC, looks really good. I agree on going with option C - although being more complex, it seems like the pros outweigh the cons compared to the other options
fantonangeli commentedon Aug 27, 2026
@lornakelly I can agree with Option C, but I have a few points to share.
I also tested your PoC and it LGTM
Option A: react-jsonschema-form (RJSF)
I see RJSF has UI options that let us control the order of the inputs:
https://rjsf-team.github.io/react-jsonschema-form/
There is an
ORDERINGexample on the left which uses:We also have
"ui:widget": "hidden"to hide some fields and support only specific fields for editing.Regarding the CSS prefix, this does seem to be an issue, as I couldn't find any documented configuration for it.
Option B: Uniforms
+1 to prefer Option A over this one, as with Uniforms we would have to implement our own fields. This is not particularly complex, but RJSF seems to offer more out of the box.
From my previous experience with Uniforms in another project, we customised it to use a different UI library. The full customisation required 27
.tsxfiles, but they were neither long nor particularly complex.Option C: React Hook Form (RHF)
IIUC, this means that initially we would support editing only a specific subset of fields, rather than all fields, while using the schema for validation. Is that correct?
What I like about this approach is that we go for "baby steps"
+1 also to @handreyrc's comment about avoiding too much complexity for this feature, at least at the beginning. Option C seems better aligned with this direction.
I still think this spike and the alternatives we evaluated are important to keep documented, in this spike, for future reference.
lornakelly commentedon Aug 27, 2026
Thanks @fantonangeli
I can see that I overstated the ordering as a con. Ultimately RHF will give is more flexibility from a UX perspective and is more in line with our stack.
Agree on the baby steps as well, one issue at a time. Yes we start with a subset and grow it with validation coming from the sdk. +1 on keeping this documenting in spike for future
Looks like agreement with Option C anyway so we will go with that
kumaradityaraj commentedon Aug 28, 2026
+1 for React Hook Form as it seems like the best fit here since it gives us full control over rendering and UX while integrating cleanly with our existing components.