mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-09-22 13:39:35 +00:00
feat(ui): added textarea component
This commit is contained in:
48
frontend/src/components/v2/TextArea/TextArea.stories.tsx
Normal file
48
frontend/src/components/v2/TextArea/TextArea.stories.tsx
Normal file
@@ -0,0 +1,48 @@
|
||||
import type { Meta, StoryObj } from '@storybook/react';
|
||||
|
||||
import { TextArea } from './TextArea';
|
||||
|
||||
const meta: Meta<typeof TextArea> = {
|
||||
title: 'Components/TextArea',
|
||||
component: TextArea,
|
||||
tags: ['v2'],
|
||||
argTypes: {
|
||||
placeholder: {
|
||||
defaultValue: 'Type anything',
|
||||
type: 'string'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default meta;
|
||||
type Story = StoryObj<typeof TextArea>;
|
||||
|
||||
// More on writing stories with args: https://storybook.js.org/docs/7.0/react/writing-stories/args
|
||||
export const Filled: Story = {
|
||||
args: {}
|
||||
};
|
||||
|
||||
export const Outline: Story = {
|
||||
args: {
|
||||
variant: 'outline'
|
||||
}
|
||||
};
|
||||
|
||||
export const Plain: Story = {
|
||||
args: {
|
||||
variant: 'plain'
|
||||
}
|
||||
};
|
||||
|
||||
export const Error: Story = {
|
||||
args: {
|
||||
isError: true
|
||||
}
|
||||
};
|
||||
|
||||
export const AutoWidth: Story = {
|
||||
args: {
|
||||
isFullWidth: false,
|
||||
className: 'w-auto'
|
||||
}
|
||||
};
|
||||
74
frontend/src/components/v2/TextArea/TextArea.tsx
Normal file
74
frontend/src/components/v2/TextArea/TextArea.tsx
Normal file
@@ -0,0 +1,74 @@
|
||||
import { forwardRef, TextareaHTMLAttributes } from 'react';
|
||||
import { cva, VariantProps } from 'cva';
|
||||
import { twMerge } from 'tailwind-merge';
|
||||
|
||||
type Props = {
|
||||
placeholder?: string;
|
||||
isFullWidth?: boolean;
|
||||
isRequired?: boolean;
|
||||
reSize?: 'none' | 'both' | 'vertical' | 'horizontal';
|
||||
};
|
||||
|
||||
const textAreaVariants = cva(
|
||||
'textarea w-full p-2 border border-solid text-gray-400 placeholder-gray-500 placeholder-opacity-50',
|
||||
{
|
||||
variants: {
|
||||
size: {
|
||||
xs: ['text-xs'],
|
||||
sm: ['text-sm'],
|
||||
md: ['text-md'],
|
||||
lg: ['text-lg']
|
||||
},
|
||||
isRounded: {
|
||||
true: ['rounded-md'],
|
||||
false: ''
|
||||
},
|
||||
variant: {
|
||||
filled: ['bg-bunker-800', 'text-gray-400'],
|
||||
outline: ['bg-transparent'],
|
||||
plain: 'bg-transparent outline-none'
|
||||
},
|
||||
isError: {
|
||||
true: 'focus:ring-red/50 placeholder-red-300 border-red',
|
||||
false: 'focus:ring-primary/50 border-mineshaft-400'
|
||||
}
|
||||
},
|
||||
compoundVariants: [
|
||||
{
|
||||
variant: 'plain',
|
||||
isError: [true, false],
|
||||
className: 'border-none'
|
||||
}
|
||||
]
|
||||
}
|
||||
);
|
||||
|
||||
export type TextAreaProps = Omit<TextareaHTMLAttributes<HTMLTextAreaElement>, 'size'> &
|
||||
VariantProps<typeof textAreaVariants> &
|
||||
Props;
|
||||
|
||||
export const TextArea = forwardRef<HTMLTextAreaElement, TextAreaProps>(
|
||||
(
|
||||
{
|
||||
className,
|
||||
isRounded = true,
|
||||
isError = false,
|
||||
isRequired,
|
||||
variant = 'filled',
|
||||
size = 'md',
|
||||
reSize = 'both',
|
||||
...props
|
||||
},
|
||||
ref
|
||||
): JSX.Element => (
|
||||
<textarea
|
||||
{...props}
|
||||
style={{ resize: reSize }}
|
||||
required={isRequired}
|
||||
ref={ref}
|
||||
className={twMerge(textAreaVariants({ className, isError, size, isRounded, variant }))}
|
||||
/>
|
||||
)
|
||||
);
|
||||
|
||||
TextArea.displayName = 'TextArea';
|
||||
2
frontend/src/components/v2/TextArea/index.tsx
Normal file
2
frontend/src/components/v2/TextArea/index.tsx
Normal file
@@ -0,0 +1,2 @@
|
||||
export type { TextAreaProps } from './TextArea';
|
||||
export { TextArea } from './TextArea';
|
||||
@@ -6,3 +6,4 @@ export * from './Input';
|
||||
export * from './Menu';
|
||||
export * from './Modal';
|
||||
export * from './Select';
|
||||
export * from './TextArea';
|
||||
|
||||
Reference in New Issue
Block a user