Skip to content

Commit

Permalink
FormFieldTextbox with Lux components
Browse files Browse the repository at this point in the history
  • Loading branch information
Jaap-Hein Wester committed Nov 6, 2024
1 parent 032f945 commit 0742118
Show file tree
Hide file tree
Showing 4 changed files with 142 additions and 30 deletions.
123 changes: 117 additions & 6 deletions packages/components-react/src/form-field-textbox/FormFieldTextbox.tsx
Original file line number Diff line number Diff line change
@@ -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' ? (
<LuxFormFieldLabel disabled={disabled} htmlFor={inputId}>
{label}
</LuxFormFieldLabel>
) : (
label
);
const descriptionNode =
typeof description === 'string' ? (
<LuxFormFieldDescription appearance={invalid ? 'invalid' : appearance} id={descriptionId}>
{description}
</LuxFormFieldDescription>
) : (
description
);
const errorMessageNode =
typeof errorMessage === 'string' ? (
<LuxFormFieldErrorMessage distanced={distanced} id={errorMessageId}>
{errorMessage}
</LuxFormFieldErrorMessage>
) : (
errorMessage
);

// TODO: naar utils
function pick<T extends object, U extends keyof T>(obj: T, paths: Array<U>): Pick<T, U> {
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 (
<LuxFormField
label={labelNode}
description={descriptionNode}
errorMessage={errorMessageNode}
input={
<LuxTextbox
ref={inputRef}
id={inputId}
type={(type as TextboxTypes) || 'text'}
invalid={invalid}
disabled={disabled}
dir={inputDir || 'auto'}
aria-describedby={
clsx({
[descriptionId]: description,
[errorMessageId]: invalid,
}) || undefined
}
{...textBoxAttrs}
/>
}
className={className}
{...restProps}
/>
);
};
2 changes: 1 addition & 1 deletion packages/components-react/src/textbox/Textbox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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<InputHTMLAttributes<HTMLInputElement>, 'type'> {
type?: InputType;
Expand Down
Original file line number Diff line number Diff line change
@@ -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 = {
Expand All @@ -12,39 +13,39 @@ 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<typeof LuxFormFieldTextbox>;
} satisfies Meta<LuxFormFieldTextboxProps>;

export default meta;
type Story = StoryObj<typeof meta>;

export const Playground: Story = {
name: 'Playground',
args: {
label: 'test',
description: '', // ReactNode;
errorMessage: '', // ReactNode;
inputDir: undefined, //TextboxProps['dir'];
inputRef: undefined, // Ref<HTMLInputElement>;
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: {
Expand Down

0 comments on commit 0742118

Please sign in to comment.