packages/ui: add textarea

fix element container position
apps/web: add webkit scroll style
move comment element to end of form
use textarea element for comment
This commit is contained in:
vchikalkin 2023-11-22 15:36:08 +03:00
parent c3b6e8b046
commit a8684087cf
7 changed files with 76 additions and 7 deletions

View File

@ -1,7 +1,7 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
export type MetaObject = {
disabled: boolean;
fieldType: 'CHECKBOX' | 'DECIMAL' | 'INT' | 'STRING';
fieldType: 'CHECKBOX' | 'DECIMAL' | 'INT' | 'STRING' | 'TEXTAREA';
label: string;
max: number;
min: number;

View File

@ -18,3 +18,24 @@
body {
background-color: var(--color-background);
}
/* Scroll bar stylings */
::-webkit-scrollbar {
width: 6px;
height: 6px;
}
/* Track */
::-webkit-scrollbar-track {
}
/* Handle */
::-webkit-scrollbar-thumb {
background: rgba(0, 0, 0, 0.3);
border-radius: 2px;
}
/* Handle on hover */
::-webkit-scrollbar-thumb:hover {
background: rgba(0, 0, 0, 0.4);
}

View File

@ -4,6 +4,13 @@ import { useFormStore } from '@/store/ius/form';
import { useEffect } from 'react';
import { ElementContainer } from 'ui';
function compatMetadata(metaData: Props['metaData']) {
const { comment, ...meta } = metaData;
comment.fieldType = 'TEXTAREA';
return { ...meta, comment };
}
export function Elements({ data, metaData }: Props) {
const { init, setValue, validation, values } = useFormStore();
@ -13,7 +20,7 @@ export function Elements({ data, metaData }: Props) {
return (
<div className="mt-2 grid auto-rows-auto grid-cols-1 gap-2 gap-x-4 md:grid-cols-2 lg:grid-cols-3">
{Object.keys(metaData).map((name) => {
{Object.keys(compatMetadata(metaData)).map((name) => {
const { fieldType, label, max, min = 0, visible, ...props } = metaData[name];
if (!visible) return false;
@ -22,6 +29,7 @@ export function Elements({ data, metaData }: Props) {
return (
<ElementContainer
classNameParent={fieldType === 'TEXTAREA' ? 'col-[span_3]' : undefined}
intent={validation[name] ? 'danger' : 'default'}
message={validation[name]?.message}
key={name}

View File

@ -1,5 +1,5 @@
import type { MetaObject } from '@/api/ius/types';
import { Checkbox, Input, InputNumber } from 'ui';
import { Checkbox, Input, InputNumber, Textarea } from 'ui';
function wrapMap<C, T extends Record<MetaObject['fieldType'], C>>(arg: T) {
return arg;
@ -10,4 +10,5 @@ export const mapFieldTypeElement = wrapMap({
DECIMAL: InputNumber,
INT: InputNumber,
STRING: Input,
TEXTAREA: Textarea,
});

View File

@ -5,7 +5,9 @@ import { forwardRef, type HTMLAttributes, type PropsWithChildren } from 'react';
export type ContainerProps = HTMLAttributes<HTMLDivElement> & PropsWithChildren;
const variants = cva('flex h-9 items-center', {
const parentVariants = cva('flex flex-col justify-center');
const variants = cva('min-h-[36px] flex items-center', {
defaultVariants: {
intent: 'default',
},
@ -18,11 +20,28 @@ const variants = cva('flex h-9 items-center', {
});
export type WrapperProps = HTMLAttributes<HTMLDivElement> &
VariantProps<typeof variants> & { readonly message?: string };
VariantProps<typeof variants> & { readonly classNameParent?: string; readonly message?: string };
export const ElementContainer = forwardRef<HTMLDivElement, WrapperProps>(
({ children, className, id, intent, message = 'Некорректные данные', title, ...props }, ref) => (
<div {...props} className="flex flex-col justify-center" ref={ref} {...props}>
(
{
children,
className,
classNameParent,
id,
intent,
message = 'Некорректные данные',
title,
...props
},
ref
) => (
<div
{...props}
className={cn(parentVariants({ className: classNameParent }))}
ref={ref}
{...props}
>
<label
htmlFor={id}
className="mb-1 block overflow-hidden overflow-ellipsis whitespace-nowrap text-sm font-medium text-black text-opacity-90"

View File

@ -12,3 +12,4 @@ export * from './http-error';
export * from './icons';
export * from './input';
export * from './select';
export * from './textarea';

19
packages/ui/textarea.tsx Normal file
View File

@ -0,0 +1,19 @@
import { cn } from './utils';
import type { VariantProps } from 'class-variance-authority';
import { cva } from 'class-variance-authority';
import { forwardRef } from 'react';
const variants = cva(
'focus:ring-0 h-auto hover:border-primary-500 focus:border-primary-500 w-full resize-none rounded-sm border disabled:hover:border-gray-300 border-gray-300 p-2 px-3 text-sm text-gray-900 outline-none transition-all ease-in-out disabled:cursor-not-allowed disabled:text-opacity-30'
);
export type TextAreaProps = React.TextareaHTMLAttributes<HTMLTextAreaElement> &
VariantProps<typeof variants> & { readonly loading?: boolean };
export const Textarea = forwardRef<HTMLTextAreaElement, TextAreaProps>(
({ className, loading, ...props }, ref) => {
if (loading) return <div className="h-[98px] w-full animate-pulse rounded bg-gray-100" />;
return <textarea rows={4} ref={ref} className={cn(variants({ className }))} {...props} />;
}
);