feat: enhance TextEditor and Input components with improved styling and error handling

This commit is contained in:
Ardeman
2025-03-06 03:53:15 +08:00
parent 9117a99cc3
commit 894698c5d6
6 changed files with 97 additions and 23 deletions
@@ -121,7 +121,7 @@ export const EditorMenuBar = (properties: TProperties) => {
return (
<>
<div className="flex items-start justify-between gap-4 rounded-[5px_5px_0_0] border-x border-t border-[#D2D2D2] px-4 py-3">
<div className="flex items-start justify-between gap-4 rounded-[5px_5px_0_0] px-4 py-3">
<div className="flex divide-x">
<div className="flex max-w-[150px] flex-wrap items-start gap-1 px-1">
<EditorButton
+18 -20
View File
@@ -1,3 +1,4 @@
import { Field, Label } from '@headlessui/react'
import { Color } from '@tiptap/extension-color'
import Highlight from '@tiptap/extension-highlight'
import Image from '@tiptap/extension-image'
@@ -9,6 +10,7 @@ import StarterKit from '@tiptap/starter-kit'
import { useEffect, useId, useState } from 'react'
import {
get,
type FieldError,
type FieldValues,
type Path,
type RegisterOptions,
@@ -27,6 +29,7 @@ type TProperties<TFormValues extends FieldValues> = {
labelClassName?: string
className?: string
inputClassName?: string
containerClassName?: string
rules?: RegisterOptions
disabled?: boolean
isRequired?: boolean
@@ -41,11 +44,11 @@ export const TextEditor = <TFormValues extends Record<string, unknown>>(
label,
name,
labelClassName,
isRequired,
className,
inputClassName,
category,
disabled = false,
containerClassName,
} = properties
const [isPlainHTML, setIsPlainHTML] = useState(false)
@@ -60,7 +63,7 @@ export const TextEditor = <TFormValues extends Record<string, unknown>>(
} = useRemixFormContext()
const watchContent = watch(name)
const error = get(errors, name)
const error: FieldError = get(errors, name)
const editor = useEditor({
editable: !disabled,
@@ -100,15 +103,16 @@ export const TextEditor = <TFormValues extends Record<string, unknown>>(
}, [watchContent])
return (
<div className={twMerge('', className)}>
<Field
className={twMerge('relative', containerClassName)}
disabled={disabled}
id={id}
>
{label && (
<label
htmlFor={id ?? generatedId}
className={twMerge('mb-2 block text-sm font-bold', labelClassName)}
>
{label}
{isRequired && <sup className="text-[#DF0000]">*</sup>}
</label>
<Label className={twMerge('mb-1 block text-gray-700', labelClassName)}>
{label}{' '}
{error && <span className="text-red-500">{error.message}</span>}
</Label>
)}
{isPlainHTML ? (
@@ -118,7 +122,7 @@ export const TextEditor = <TFormValues extends Record<string, unknown>>(
disabled={disabled}
/>
) : (
<>
<div className={twMerge('', className)}>
<EditorMenuBar
disabled={disabled}
category={category}
@@ -132,20 +136,14 @@ export const TextEditor = <TFormValues extends Record<string, unknown>>(
editor={editor}
id={id ?? generatedId}
className={twMerge(
'prose mb-1 max-h-96 max-w-none cursor-text overflow-y-auto rounded-[0_0_5px_5px] border border-[#D2D2D2] px-4 py-1',
'prose-invert max-h-96 max-w-none cursor-text overflow-y-auto rounded-[0_0_5px_5px] border border-[#D2D2D2] p-2',
darkMode ? 'bg-[#00000055]' : '',
inputClassName,
)}
onClick={() => editor?.commands.focus()}
/>
</>
</div>
)}
{error && (
<p className="text-xs text-[#DF0000] italic">
{error?.message?.toString()}
</p>
)}
</div>
</Field>
)
}