From 0742118156b016e304e90248de3e76bc79f3a021 Mon Sep 17 00:00:00 2001 From: Jaap-Hein Wester Date: Wed, 6 Nov 2024 17:13:01 +0100 Subject: [PATCH] FormFieldTextbox with Lux components --- .../form-field-textbox/FormFieldTextbox.tsx | 123 +++++++++++++++++- .../components-react/src/textbox/Textbox.tsx | 2 +- ...{FormTextbox.spec.tsx => Textbox.spec.tsx} | 0 .../form-field-textbox.stories.tsx | 47 +++---- 4 files changed, 142 insertions(+), 30 deletions(-) rename packages/components-react/src/textbox/test/{FormTextbox.spec.tsx => Textbox.spec.tsx} (100%) diff --git a/packages/components-react/src/form-field-textbox/FormFieldTextbox.tsx b/packages/components-react/src/form-field-textbox/FormFieldTextbox.tsx index 999c43bd..aa160091 100644 --- a/packages/components-react/src/form-field-textbox/FormFieldTextbox.tsx +++ b/packages/components-react/src/form-field-textbox/FormFieldTextbox.tsx @@ -1,9 +1,120 @@ +import { TextboxTypes } from '@utrecht/component-library-react/dist/Textbox'; +import { FormFieldTextboxProps as UtrechtFormFieldTextboxProps } from '@utrecht/component-library-react/dist/css-module'; +import clsx from 'clsx'; +import { useId } from 'react'; +import { LuxFormField } from '../form-field/FormField'; import { - FormFieldTextbox as UtrechtFormFieldTextbox, - FormFieldTextboxProps as UtrechtFormFieldTextboxProps, -} from '@utrecht/component-library-react/dist/css-module'; + LuxFormFieldDescription, + type LuxFormFieldDescriptionAppearance, +} from '../form-field-description/FormFieldDescription'; +import { LuxFormFieldErrorMessage } from '../form-field-error-message/FormFieldErrorMessage'; +import { LuxFormFieldLabel } from '../form-field-label/FormFieldLabel'; +import { type Direction, LuxTextbox } from '../textbox/Textbox'; -UtrechtFormFieldTextbox.displayName = 'LuxFormFieldTextbox'; +export type LuxFormFieldTextboxProps = UtrechtFormFieldTextboxProps & { + appearance?: LuxFormFieldDescriptionAppearance; + distanced?: boolean; + inputDir?: Direction; +}; -export const LuxFormFieldTextbox = UtrechtFormFieldTextbox; -export type LuxFormFieldTextboxProps = UtrechtFormFieldTextboxProps; +export const LuxFormFieldTextbox = ({ + label, + type, + description, + errorMessage, + disabled, + invalid, + appearance, + distanced, + className, + inputRef, + inputDir, + ...restProps +}: LuxFormFieldTextboxProps) => { + const inputId = useId(); + const descriptionId = useId(); + const errorMessageId = useId(); + + const labelNode = + typeof label === 'string' ? ( + + {label} + + ) : ( + label + ); + const descriptionNode = + typeof description === 'string' ? ( + + {description} + + ) : ( + description + ); + const errorMessageNode = + typeof errorMessage === 'string' ? ( + + {errorMessage} + + ) : ( + errorMessage + ); + + // TODO: naar utils + function pick(obj: T, paths: Array): Pick { + const ret = Object.create(null); + for (const k of paths) { + ret[k] = obj[k]; + } + return ret; + } + + const textBoxAttrs = pick(restProps, [ + 'autoComplete', + 'min', + 'max', + 'minLength', + 'maxLength', + 'pattern', + 'placeholder', + 'readOnly', + 'required', + 'inputRequired', + 'value', + 'defaultValue', + 'list', + 'size', + 'step', + 'onFocus', + 'onBlur', + 'onInput', + 'onChange', + ]); + + return ( + + } + className={className} + {...restProps} + /> + ); +}; diff --git a/packages/components-react/src/textbox/Textbox.tsx b/packages/components-react/src/textbox/Textbox.tsx index 42985eae..0bc82551 100644 --- a/packages/components-react/src/textbox/Textbox.tsx +++ b/packages/components-react/src/textbox/Textbox.tsx @@ -27,7 +27,7 @@ export const INPUT_TYPES = { } as const; export type InputType = (typeof INPUT_TYPES)[keyof typeof INPUT_TYPES]; -type Direction = 'ltr' | 'rtl' | 'auto'; +export type Direction = 'ltr' | 'rtl' | 'auto'; export interface LuxTextboxProps extends Omit, 'type'> { type?: InputType; diff --git a/packages/components-react/src/textbox/test/FormTextbox.spec.tsx b/packages/components-react/src/textbox/test/Textbox.spec.tsx similarity index 100% rename from packages/components-react/src/textbox/test/FormTextbox.spec.tsx rename to packages/components-react/src/textbox/test/Textbox.spec.tsx diff --git a/packages/storybook/src/react-components/form-field-textbox/form-field-textbox.stories.tsx b/packages/storybook/src/react-components/form-field-textbox/form-field-textbox.stories.tsx index ac4eb5e4..47b26387 100644 --- a/packages/storybook/src/react-components/form-field-textbox/form-field-textbox.stories.tsx +++ b/packages/storybook/src/react-components/form-field-textbox/form-field-textbox.stories.tsx @@ -1,8 +1,9 @@ -import { LuxFormFieldTextbox } from '@lux-design-system/components-react'; +import { LuxFormFieldTextbox, type LuxFormFieldTextboxProps } from '@lux-design-system/components-react'; import tokens from '@lux-design-system/design-tokens/dist/index.json'; import type { Meta, StoryObj } from '@storybook/react'; -// import { forwardRef, InputHTMLAttributes, PropsWithChildren } from 'react'; import { BADGES } from '../../../config/preview'; +import FormFieldDescriptionMeta from '../form-field-description/form-field-description.stories'; +import FormFieldErrorMessageMeta from '../form-field-error-message/form-field-error-message.stories'; import TextboxMeta from '../textbox/textbox.stories'; const meta = { @@ -12,22 +13,27 @@ const meta = { parameters: { badges: [BADGES.WIP, BADGES.CANARY], tokens, - tokensPrefix: 'react-form-field', + tokensPrefix: 'utrecht-form-field-textbox', }, argTypes: { ...TextboxMeta.argTypes, - // type: { - // control: 'select', - // options: ['text', 'checkbox', 'radio'], - // description: 'The type of the form field', - // }, - // invalid: { - // control: 'boolean', - // description: 'Whether the field is in an invalid state', - // defaultValue: false, - // }, + appearance: { + ...FormFieldDescriptionMeta.argTypes.appearance, + }, + distanced: { + ...FormFieldErrorMessageMeta.argTypes.distanced, + }, + disabled: { + type: 'boolean', + }, + errorMessage: { + if: { + arg: 'invalid', + truthy: true, + }, + }, }, -} satisfies Meta; +} satisfies Meta; export default meta; type Story = StoryObj; @@ -35,16 +41,11 @@ type Story = StoryObj; export const Playground: Story = { name: 'Playground', args: { - label: 'test', - description: '', // ReactNode; - errorMessage: '', // ReactNode; - inputDir: undefined, //TextboxProps['dir']; - inputRef: undefined, // Ref; + label: 'Form Field Textbox', + description: 'Textbox in een FormField', + errorMessage: 'Zo kan het ook een ErrorMessage hebben', invalid: false, - status: '', // ReactNode; - // appearance: undefined, - // children: - // 'Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Dolor ante id varius, aenean eu faucibus vitae malesuada. Viverra malesuada aliquam et placerat justo porta ipsum parturient. Cursus nostra varius efficitur lobortis aliquam lectus bibendum.', + appearance: undefined, }, parameters: { docs: {