mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-09-22 13:39:35 +00:00
feat(ui): implemented form control components
This commit is contained in:
@@ -0,0 +1,40 @@
|
|||||||
|
import type { Meta, StoryObj } from '@storybook/react';
|
||||||
|
|
||||||
|
// Be careful on dep cycle
|
||||||
|
import { Input } from '../Input/Input';
|
||||||
|
import { FormControl } from './FormControl';
|
||||||
|
|
||||||
|
const meta: Meta<typeof FormControl> = {
|
||||||
|
title: 'Components/FormControl',
|
||||||
|
component: FormControl,
|
||||||
|
tags: ['v2'],
|
||||||
|
argTypes: {}
|
||||||
|
};
|
||||||
|
|
||||||
|
export default meta;
|
||||||
|
type Story = StoryObj<typeof FormControl>;
|
||||||
|
|
||||||
|
// More on writing stories with args: https://storybook.js.org/docs/7.0/react/writing-stories/args
|
||||||
|
export const Basic: Story = {
|
||||||
|
args: {
|
||||||
|
children: <Input />,
|
||||||
|
label: 'Email',
|
||||||
|
id: 'email',
|
||||||
|
helperText: 'Type something..'
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const RequiredInput: Story = {
|
||||||
|
args: {
|
||||||
|
...Basic.args,
|
||||||
|
isRequired: true
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const ErrorInput: Story = {
|
||||||
|
args: {
|
||||||
|
...Basic.args,
|
||||||
|
errorText: 'Some random error',
|
||||||
|
isError: true
|
||||||
|
}
|
||||||
|
};
|
||||||
72
frontend/src/components/v2/FormControl/FormControl.tsx
Normal file
72
frontend/src/components/v2/FormControl/FormControl.tsx
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
import { cloneElement, ReactNode } from 'react';
|
||||||
|
import { faExclamationTriangle } from '@fortawesome/free-solid-svg-icons';
|
||||||
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
|
import * as Label from '@radix-ui/react-label';
|
||||||
|
import { twMerge } from 'tailwind-merge';
|
||||||
|
|
||||||
|
export type FormLabelProps = {
|
||||||
|
id?: string;
|
||||||
|
isRequired?: boolean;
|
||||||
|
label?: ReactNode;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const FormLabel = ({ id, label, isRequired }: FormLabelProps) => (
|
||||||
|
<Label.Root className="text-mineshaft-300 text-sm font-medium block mb-1 ml-0.5" htmlFor={id}>
|
||||||
|
{label}
|
||||||
|
{isRequired && <span className="text-red ml-1">*</span>}
|
||||||
|
</Label.Root>
|
||||||
|
);
|
||||||
|
|
||||||
|
export type FormHelperTextProps = {
|
||||||
|
isError?: boolean;
|
||||||
|
text?: ReactNode;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const FormHelperText = ({ isError, text }: FormHelperTextProps) => (
|
||||||
|
<div
|
||||||
|
className={twMerge(
|
||||||
|
'text-xs flex items-center opacity-90 text-mineshaft-300 mt-2',
|
||||||
|
isError && 'text-red-600'
|
||||||
|
)}
|
||||||
|
>
|
||||||
|
{isError && (
|
||||||
|
<span>
|
||||||
|
<FontAwesomeIcon icon={faExclamationTriangle} size="sm" className="mr-1" />
|
||||||
|
</span>
|
||||||
|
)}
|
||||||
|
<span>{text}</span>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
|
||||||
|
export type FormControlProps = {
|
||||||
|
id?: string;
|
||||||
|
isRequired?: boolean;
|
||||||
|
isError?: boolean;
|
||||||
|
label?: ReactNode;
|
||||||
|
helperText?: ReactNode;
|
||||||
|
errorText?: ReactNode;
|
||||||
|
children: JSX.Element;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const FormControl = ({
|
||||||
|
children,
|
||||||
|
isRequired,
|
||||||
|
label,
|
||||||
|
helperText,
|
||||||
|
errorText,
|
||||||
|
id,
|
||||||
|
isError
|
||||||
|
}: FormControlProps): JSX.Element => {
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{typeof label === 'string' ? (
|
||||||
|
<FormLabel label={label} isRequired={isRequired} id={id} />
|
||||||
|
) : (
|
||||||
|
label
|
||||||
|
)}
|
||||||
|
{cloneElement(children, { isRequired, 'data-required': isRequired, isError })}
|
||||||
|
{!isError && helperText && <FormHelperText isError={isError} text={helperText} />}
|
||||||
|
{isError && errorText && <FormHelperText isError={isError} text={errorText} />}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
2
frontend/src/components/v2/FormControl/index.tsx
Normal file
2
frontend/src/components/v2/FormControl/index.tsx
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
export type { FormControlProps, FormHelperTextProps, FormLabelProps } from './FormControl';
|
||||||
|
export { FormControl, FormHelperText, FormLabel } from './FormControl';
|
||||||
@@ -1 +1,3 @@
|
|||||||
export * from './Button';
|
export * from './Button';
|
||||||
|
export * from './FormControl';
|
||||||
|
export * from './Input';
|
||||||
|
|||||||
Reference in New Issue
Block a user