From b65123e15fa80f319f1de83b5cfa4af45fdde91d Mon Sep 17 00:00:00 2001 From: Jan Librowski Date: Fri, 21 Aug 2026 10:59:40 +0200 Subject: [PATCH 1/4] feat(ui)!: rebuild the form fields and add NumberField Fields take an explicit state - default, critical, success or read-only - in place of the error boolean, and sizes are letter-scaled. Hover, focus and filled stay visual states rather than props. Read-only keeps the field focusable and copyable through the native attribute, while disabled stays out of the tab order. Icons arrive as prefix and suffix slots with an optional clear affordance. Heights, padding, gap, radius and the label roles come from the design component set, and every surface, border and text colour binds to its field token. NumberField is new: an input with an always-visible stepper that honours min, max and step from both the buttons and the arrow keys. --- .changeset/form-fields-redesign.md | 6 + apps/docs/scripts/ui-components.mjs | 1 + .../docs/src/components/ui-examples/input.tsx | 27 ++- .../components/ui-examples/number-field.tsx | 14 ++ .../src/components/ui-examples/text-area.tsx | 18 +- .../docs/ui-library/ui-components/index.mdx | 3 +- .../docs/ui-library/ui-components/input.mdx | 19 +- .../ui-library/ui-components/number-field.mdx | 35 ++++ .../ui-library/ui-components/text-area.mdx | 14 +- .../text-area-control/text-area-control.tsx | 2 +- .../controls/text-control/text-control.tsx | 2 +- .../dynamic-typed-input.tsx | 15 +- .../variable-form/variable-form.tsx | 6 +- packages/ui/src/components/input/index.ts | 1 + .../components/input/input-root.module.css | 74 ++++++-- .../ui/src/components/input/input.module.css | 11 +- packages/ui/src/components/input/input.tsx | 56 +++--- packages/ui/src/components/input/types.ts | 29 +-- .../ui/src/components/input/variables.css | 18 +- .../ui/src/components/number-field/index.ts | 3 + .../number-field/number-field.module.css | 170 ++++++++++++++++++ .../number-field/number-field.spec.tsx | 85 +++++++++ .../components/number-field/number-field.tsx | 96 ++++++++++ .../ui/src/components/number-field/types.ts | 18 ++ .../src/components/number-field/variables.css | 21 +++ packages/ui/src/components/text-area/index.ts | 1 + .../components/text-area/text-area.module.css | 120 ++++++++++--- .../ui/src/components/text-area/text-area.tsx | 148 +++++---------- packages/ui/src/index.ts | 2 + .../shared/styles/input-font-size.module.css | 10 ++ .../src/shared/styles/input-size.module.css | 48 +++++ packages/ui/src/shared/types/field.ts | 23 +++ packages/ui/vite.config.mts | 1 + 33 files changed, 881 insertions(+), 216 deletions(-) create mode 100644 .changeset/form-fields-redesign.md create mode 100644 apps/docs/src/components/ui-examples/number-field.tsx create mode 100644 apps/docs/src/content/docs/ui-library/ui-components/number-field.mdx create mode 100644 packages/ui/src/components/number-field/index.ts create mode 100644 packages/ui/src/components/number-field/number-field.module.css create mode 100644 packages/ui/src/components/number-field/number-field.spec.tsx create mode 100644 packages/ui/src/components/number-field/number-field.tsx create mode 100644 packages/ui/src/components/number-field/types.ts create mode 100644 packages/ui/src/components/number-field/variables.css create mode 100644 packages/ui/src/shared/types/field.ts diff --git a/.changeset/form-fields-redesign.md b/.changeset/form-fields-redesign.md new file mode 100644 index 000000000..ce765e23e --- /dev/null +++ b/.changeset/form-fields-redesign.md @@ -0,0 +1,6 @@ +--- +'@workflowbuilder/ui': major +'@workflowbuilder/sdk': minor +--- + +Input and TextArea now take a `state` enum instead of `error`, use letter sizes, and support prefix, suffix, and clear icon slots. Read-only fields remain focusable and copyable, and the new NumberField adds bounded keyboard and stepper controls. diff --git a/apps/docs/scripts/ui-components.mjs b/apps/docs/scripts/ui-components.mjs index 8abe83075..12f3b050d 100644 --- a/apps/docs/scripts/ui-components.mjs +++ b/apps/docs/scripts/ui-components.mjs @@ -21,6 +21,7 @@ export const COMPONENTS = [ { slug: 'input', name: 'Input', propsType: 'InputProps', dir: 'input' }, { slug: 'menu', name: 'Menu', propsType: 'MenuProps', dir: 'menu' }, { slug: 'modal', name: 'Modal', propsType: 'ModalProps', dir: 'modal' }, + { slug: 'number-field', name: 'NumberField', propsType: 'NumberFieldProps', dir: 'number-field' }, { slug: 'nav-button', name: 'NavButton', diff --git a/apps/docs/src/components/ui-examples/input.tsx b/apps/docs/src/components/ui-examples/input.tsx index f1d4cc4b2..394871cfa 100644 --- a/apps/docs/src/components/ui-examples/input.tsx +++ b/apps/docs/src/components/ui-examples/input.tsx @@ -1,3 +1,4 @@ +import { MagnifyingGlass } from '@phosphor-icons/react'; import { Input } from '@workflowbuilder/ui'; import { useState } from 'react'; @@ -8,7 +9,31 @@ export function InputExample() { return ( - setValue(event.target.value)} /> +
+ } + placeholder="Large input" + value={value} + onChange={(event) => setValue(event.target.value)} + onClear={() => setValue('')} + /> + setValue(event.target.value)} + /> + setValue(event.target.value)} + /> + +
); } diff --git a/apps/docs/src/components/ui-examples/number-field.tsx b/apps/docs/src/components/ui-examples/number-field.tsx new file mode 100644 index 000000000..85a780b0e --- /dev/null +++ b/apps/docs/src/components/ui-examples/number-field.tsx @@ -0,0 +1,14 @@ +import { NumberField } from '@workflowbuilder/ui'; +import { useState } from 'react'; + +import { ComponentPreview } from './component-preview'; + +export function NumberFieldExample() { + const [value, setValue] = useState(3); + + return ( + + + + ); +} diff --git a/apps/docs/src/components/ui-examples/text-area.tsx b/apps/docs/src/components/ui-examples/text-area.tsx index d0d45749d..3425ac537 100644 --- a/apps/docs/src/components/ui-examples/text-area.tsx +++ b/apps/docs/src/components/ui-examples/text-area.tsx @@ -8,7 +8,23 @@ export function TextAreaExample() { return ( -