mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-06-02 12:05:54 +00:00
fix(web): prevent plugin config form overflow
This commit is contained in:
@@ -126,13 +126,13 @@ function WebhookUrlField({
|
||||
};
|
||||
|
||||
return (
|
||||
<FormItem>
|
||||
<FormLabel>{label}</FormLabel>
|
||||
<div className="flex items-center gap-2">
|
||||
<FormItem className="min-w-0">
|
||||
<FormLabel className="break-words">{label}</FormLabel>
|
||||
<div className="flex min-w-0 items-center gap-2">
|
||||
<Input
|
||||
value={url}
|
||||
readOnly
|
||||
className="flex-1 bg-muted"
|
||||
className="min-w-0 flex-1 bg-muted"
|
||||
onClick={(e) => (e.target as HTMLInputElement).select()}
|
||||
/>
|
||||
<Button
|
||||
@@ -149,11 +149,11 @@ function WebhookUrlField({
|
||||
</Button>
|
||||
</div>
|
||||
{extraUrl && (
|
||||
<div className="flex items-center gap-2 mt-2">
|
||||
<div className="mt-2 flex min-w-0 items-center gap-2">
|
||||
<Input
|
||||
value={extraUrl}
|
||||
readOnly
|
||||
className="flex-1 bg-muted"
|
||||
className="min-w-0 flex-1 bg-muted"
|
||||
onClick={(e) => (e.target as HTMLInputElement).select()}
|
||||
/>
|
||||
<Button
|
||||
@@ -171,12 +171,14 @@ function WebhookUrlField({
|
||||
</div>
|
||||
)}
|
||||
{description && (
|
||||
<p className="text-sm text-muted-foreground">{description}</p>
|
||||
<p className="text-sm break-words text-muted-foreground">
|
||||
{description}
|
||||
</p>
|
||||
)}
|
||||
{systemInfo.edition === 'community' && (
|
||||
<div className="flex items-start gap-2.5 rounded-md border border-border/60 bg-muted/40 px-3 py-2.5 mt-1 max-w-2xl">
|
||||
<div className="mt-1 flex max-w-full min-w-0 items-start gap-2.5 rounded-md border border-border/60 bg-muted/40 px-3 py-2.5">
|
||||
<Globe className="h-4 w-4 text-muted-foreground shrink-0 mt-0.5" />
|
||||
<p className="text-sm text-muted-foreground leading-relaxed">
|
||||
<p className="text-sm leading-relaxed break-words text-muted-foreground">
|
||||
{t('bots.webhookSaasHint')}{' '}
|
||||
<a
|
||||
href="https://space.langbot.app/cloud?utm_source=local_webui&utm_medium=webhook_alert&utm_campaign=saas_conversion"
|
||||
@@ -442,7 +444,7 @@ export default function DynamicFormComponent({
|
||||
|
||||
return (
|
||||
<Form {...form}>
|
||||
<div className="space-y-4">
|
||||
<div className="min-w-0 max-w-full space-y-4 overflow-x-hidden">
|
||||
{itemConfigList.map((config) => {
|
||||
if (config.show_if) {
|
||||
const dependValue = resolveShowIfValue(
|
||||
@@ -582,20 +584,20 @@ export default function DynamicFormComponent({
|
||||
control={form.control}
|
||||
name={config.name as keyof FormValues}
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormItem className="min-w-0">
|
||||
<div
|
||||
className={cn(
|
||||
'flex flex-row items-center justify-between rounded-lg border p-4 max-w-2xl',
|
||||
'flex w-full min-w-0 max-w-full flex-row items-center justify-between rounded-lg border p-4',
|
||||
isFieldDisabled && 'pointer-events-none opacity-60',
|
||||
)}
|
||||
>
|
||||
<div className="space-y-0.5">
|
||||
<FormLabel className="text-base flex items-center gap-1.5">
|
||||
<div className="min-w-0 space-y-0.5">
|
||||
<FormLabel className="flex min-w-0 items-center gap-1.5 text-base">
|
||||
{extractI18nObject(config.label)}
|
||||
{renderDisabledTooltipIcon()}
|
||||
</FormLabel>
|
||||
{config.description && (
|
||||
<p className="text-sm text-muted-foreground">
|
||||
<p className="text-sm break-words text-muted-foreground">
|
||||
{extractI18nObject(config.description)}
|
||||
</p>
|
||||
)}
|
||||
@@ -621,9 +623,9 @@ export default function DynamicFormComponent({
|
||||
control={form.control}
|
||||
name={config.name as keyof FormValues}
|
||||
render={({ field }) => (
|
||||
<FormItem>
|
||||
<FormLabel className="flex items-center gap-1.5">
|
||||
<span>
|
||||
<FormItem className="min-w-0">
|
||||
<FormLabel className="flex min-w-0 items-center gap-1.5">
|
||||
<span className="min-w-0 break-words">
|
||||
{extractI18nObject(config.label)}{' '}
|
||||
{config.required && (
|
||||
<span className="text-red-500">*</span>
|
||||
@@ -633,9 +635,10 @@ export default function DynamicFormComponent({
|
||||
</FormLabel>
|
||||
<FormControl>
|
||||
<div
|
||||
className={
|
||||
isFieldDisabled ? 'pointer-events-none opacity-60' : ''
|
||||
}
|
||||
className={cn(
|
||||
'min-w-0 max-w-full overflow-x-hidden',
|
||||
isFieldDisabled && 'pointer-events-none opacity-60',
|
||||
)}
|
||||
>
|
||||
<DynamicFormItemComponent
|
||||
config={config}
|
||||
@@ -645,7 +648,7 @@ export default function DynamicFormComponent({
|
||||
</div>
|
||||
</FormControl>
|
||||
{config.description && (
|
||||
<p className="text-sm text-muted-foreground">
|
||||
<p className="text-sm break-words text-muted-foreground">
|
||||
{extractI18nObject(config.description)}
|
||||
</p>
|
||||
)}
|
||||
|
||||
@@ -69,7 +69,6 @@ export default function DynamicFormItemComponent({
|
||||
onFileUploaded,
|
||||
}: {
|
||||
config: IDynamicFormItemSchema;
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
field: ControllerRenderProps<any, any>;
|
||||
onFileUploaded?: (fileKey: string) => void;
|
||||
}) {
|
||||
@@ -251,7 +250,7 @@ export default function DynamicFormItemComponent({
|
||||
return (
|
||||
<Input
|
||||
type="number"
|
||||
className="max-w-xs"
|
||||
className="w-full max-w-xs"
|
||||
{...field}
|
||||
onChange={(e) => field.onChange(Number(e.target.value))}
|
||||
/>
|
||||
@@ -260,8 +259,8 @@ export default function DynamicFormItemComponent({
|
||||
case DynamicFormItemType.STRING:
|
||||
if (config.options && config.options.length > 0) {
|
||||
return (
|
||||
<div className="flex items-center gap-1.5 max-w-md">
|
||||
<Input className="flex-1" {...field} />
|
||||
<div className="flex w-full max-w-md min-w-0 items-center gap-1.5">
|
||||
<Input className="min-w-0 flex-1" {...field} />
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button
|
||||
@@ -292,21 +291,26 @@ export default function DynamicFormItemComponent({
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return <Input className="max-w-md" {...field} />;
|
||||
return <Input className="w-full max-w-md" {...field} />;
|
||||
|
||||
case DynamicFormItemType.TEXT:
|
||||
return <Textarea {...field} className="min-h-[120px] max-w-2xl" />;
|
||||
return (
|
||||
<Textarea
|
||||
{...field}
|
||||
className="min-h-[120px] w-full max-w-full resize-y overflow-x-hidden break-all"
|
||||
/>
|
||||
);
|
||||
|
||||
case DynamicFormItemType.BOOLEAN:
|
||||
return <Switch checked={field.value} onCheckedChange={field.onChange} />;
|
||||
|
||||
case DynamicFormItemType.STRING_ARRAY:
|
||||
return (
|
||||
<div className="space-y-2 max-w-md">
|
||||
<div className="w-full max-w-md min-w-0 space-y-2">
|
||||
{field.value.map((item: string, index: number) => (
|
||||
<div key={index} className="flex gap-1.5 items-center">
|
||||
<div key={index} className="flex min-w-0 items-center gap-1.5">
|
||||
<Input
|
||||
className="flex-1"
|
||||
className="min-w-0 flex-1"
|
||||
value={item}
|
||||
onChange={(e) => {
|
||||
const newValue = [...field.value];
|
||||
@@ -347,7 +351,7 @@ export default function DynamicFormItemComponent({
|
||||
case DynamicFormItemType.SELECT:
|
||||
return (
|
||||
<Select value={field.value} onValueChange={field.onChange}>
|
||||
<SelectTrigger className="max-w-md bg-[#ffffff] dark:bg-[#2a2a2e]">
|
||||
<SelectTrigger className="w-full max-w-md bg-[#ffffff] dark:bg-[#2a2a2e]">
|
||||
<SelectValue placeholder={t('common.select')} />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
@@ -409,10 +413,10 @@ export default function DynamicFormItemComponent({
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="max-w-md flex items-center gap-1.5">
|
||||
<div className="flex-1">
|
||||
<div className="flex w-full max-w-md min-w-0 items-center gap-1.5">
|
||||
<div className="min-w-0 flex-1">
|
||||
<Select value={field.value} onValueChange={field.onChange}>
|
||||
<SelectTrigger className="bg-[#ffffff] dark:bg-[#2a2a2e]">
|
||||
<SelectTrigger className="min-w-0 bg-[#ffffff] dark:bg-[#2a2a2e]">
|
||||
<SelectValue placeholder={t('models.selectModel')} />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
@@ -577,9 +581,9 @@ export default function DynamicFormItemComponent({
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="max-w-md">
|
||||
<div className="w-full max-w-md min-w-0">
|
||||
<Select value={field.value} onValueChange={field.onChange}>
|
||||
<SelectTrigger className="bg-[#ffffff] dark:bg-[#2a2a2e]">
|
||||
<SelectTrigger className="min-w-0 bg-[#ffffff] dark:bg-[#2a2a2e]">
|
||||
<SelectValue placeholder={t('knowledge.selectEmbeddingModel')} />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
@@ -612,12 +616,12 @@ export default function DynamicFormItemComponent({
|
||||
);
|
||||
|
||||
return (
|
||||
<div className="max-w-md">
|
||||
<div className="w-full max-w-md min-w-0">
|
||||
<Select
|
||||
value={field.value || '__none__'}
|
||||
onValueChange={(v) => field.onChange(v === '__none__' ? '' : v)}
|
||||
>
|
||||
<SelectTrigger className="bg-[#ffffff] dark:bg-[#2a2a2e]">
|
||||
<SelectTrigger className="min-w-0 bg-[#ffffff] dark:bg-[#2a2a2e]">
|
||||
<SelectValue placeholder={t('models.rerank')} />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
@@ -713,7 +717,7 @@ export default function DynamicFormItemComponent({
|
||||
placeholder: string,
|
||||
) => (
|
||||
<Select value={value} onValueChange={onChange}>
|
||||
<SelectTrigger className="bg-[#ffffff] dark:bg-[#2a2a2e]">
|
||||
<SelectTrigger className="min-w-0 bg-[#ffffff] dark:bg-[#2a2a2e]">
|
||||
<SelectValue placeholder={placeholder} />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
@@ -879,14 +883,14 @@ export default function DynamicFormItemComponent({
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="space-y-3">
|
||||
<div className="w-full min-w-0 space-y-3">
|
||||
{/* Primary model selector */}
|
||||
<div>
|
||||
<p className="text-xs text-muted-foreground mb-1">
|
||||
{t('models.fallback.primary')}
|
||||
</p>
|
||||
<div className="flex items-center gap-1.5">
|
||||
<div className="flex-1">
|
||||
<div className="flex min-w-0 items-center gap-1.5">
|
||||
<div className="min-w-0 flex-1">
|
||||
{renderModelSelect(
|
||||
modelValue.primary,
|
||||
(val) => updateValue({ primary: val }),
|
||||
@@ -918,16 +922,16 @@ export default function DynamicFormItemComponent({
|
||||
|
||||
{/* Fallback models */}
|
||||
{modelValue.fallbacks.length > 0 && (
|
||||
<div className="space-y-2">
|
||||
<div className="min-w-0 space-y-2">
|
||||
<p className="text-xs text-muted-foreground">
|
||||
{t('models.fallback.fallbackList')}
|
||||
</p>
|
||||
{modelValue.fallbacks.map((fbUuid: string, index: number) => (
|
||||
<div key={index} className="flex items-center gap-2">
|
||||
<div key={index} className="flex min-w-0 items-center gap-2">
|
||||
<span className="text-xs text-muted-foreground w-4 shrink-0">
|
||||
{index + 1}.
|
||||
</span>
|
||||
<div className="flex-1">
|
||||
<div className="min-w-0 flex-1">
|
||||
{renderModelSelect(
|
||||
fbUuid,
|
||||
(val) => updateFallbackModel(index, val),
|
||||
@@ -1003,20 +1007,22 @@ export default function DynamicFormItemComponent({
|
||||
|
||||
return (
|
||||
<Select value={field.value} onValueChange={field.onChange}>
|
||||
<SelectTrigger className="bg-[#ffffff] dark:bg-[#2a2a2e]">
|
||||
<SelectTrigger className="min-w-0 bg-[#ffffff] dark:bg-[#2a2a2e]">
|
||||
{field.value && field.value !== '__none__' ? (
|
||||
(() => {
|
||||
const selectedKb = knowledgeBases.find(
|
||||
(kb) => kb.uuid === field.value,
|
||||
);
|
||||
return (
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="flex min-w-0 items-center gap-2">
|
||||
{selectedKb?.emoji && (
|
||||
<span className="text-sm shrink-0">
|
||||
{selectedKb.emoji}
|
||||
</span>
|
||||
)}
|
||||
<span>{selectedKb?.name ?? field.value}</span>
|
||||
<span className="truncate">
|
||||
{selectedKb?.name ?? field.value}
|
||||
</span>
|
||||
</div>
|
||||
);
|
||||
})()
|
||||
@@ -1066,9 +1072,9 @@ export default function DynamicFormItemComponent({
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="space-y-2">
|
||||
<div className="min-w-0 space-y-2">
|
||||
{field.value && field.value.length > 0 ? (
|
||||
<div className="space-y-2">
|
||||
<div className="min-w-0 space-y-2">
|
||||
{field.value.map((kbId: string) => {
|
||||
const currentKb = knowledgeBases.find(
|
||||
(base) => base.uuid === kbId,
|
||||
@@ -1078,17 +1084,17 @@ export default function DynamicFormItemComponent({
|
||||
return (
|
||||
<div
|
||||
key={kbId}
|
||||
className="flex items-center justify-between rounded-lg border p-3 hover:bg-accent"
|
||||
className="flex min-w-0 items-center justify-between rounded-lg border p-3 hover:bg-accent"
|
||||
>
|
||||
<div className="flex items-center gap-2 flex-1">
|
||||
<div className="flex min-w-0 flex-1 items-center gap-2">
|
||||
<div className="flex-1 min-w-0">
|
||||
<div className="font-medium flex items-center gap-2">
|
||||
<div className="flex min-w-0 items-center gap-2 font-medium">
|
||||
{currentKb.emoji && (
|
||||
<span className="text-sm shrink-0">
|
||||
{currentKb.emoji}
|
||||
</span>
|
||||
)}
|
||||
{currentKb.name}
|
||||
<span className="truncate">{currentKb.name}</span>
|
||||
{currentKb.knowledge_engine?.name && (
|
||||
<span className="text-xs px-2 py-0.5 rounded-full bg-purple-100 text-purple-700 dark:bg-purple-900 dark:text-purple-300">
|
||||
{extractI18nObject(
|
||||
@@ -1098,7 +1104,7 @@ export default function DynamicFormItemComponent({
|
||||
)}
|
||||
</div>
|
||||
{currentKb.description && (
|
||||
<div className="text-sm text-muted-foreground">
|
||||
<div className="text-sm break-words text-muted-foreground">
|
||||
{currentKb.description}
|
||||
</div>
|
||||
)}
|
||||
@@ -1221,7 +1227,7 @@ export default function DynamicFormItemComponent({
|
||||
case DynamicFormItemType.BOT_SELECTOR:
|
||||
return (
|
||||
<Select value={field.value} onValueChange={field.onChange}>
|
||||
<SelectTrigger className="bg-[#ffffff] dark:bg-[#2a2a2e]">
|
||||
<SelectTrigger className="min-w-0 bg-[#ffffff] dark:bg-[#2a2a2e]">
|
||||
<SelectValue placeholder={t('bots.selectBot')} />
|
||||
</SelectTrigger>
|
||||
<SelectContent>
|
||||
@@ -1239,9 +1245,9 @@ export default function DynamicFormItemComponent({
|
||||
case DynamicFormItemType.TOOLS_SELECTOR:
|
||||
return (
|
||||
<>
|
||||
<div className="space-y-2">
|
||||
<div className="min-w-0 space-y-2">
|
||||
{field.value && field.value.length > 0 ? (
|
||||
<div className="space-y-2">
|
||||
<div className="min-w-0 space-y-2">
|
||||
{field.value.map((toolName: string) => {
|
||||
const currentTool = tools.find(
|
||||
(tool) => tool.name === toolName,
|
||||
@@ -1250,12 +1256,12 @@ export default function DynamicFormItemComponent({
|
||||
return (
|
||||
<div
|
||||
key={toolName}
|
||||
className="flex items-center justify-between rounded-lg border p-3 hover:bg-accent"
|
||||
className="flex min-w-0 items-center justify-between rounded-lg border p-3 hover:bg-accent"
|
||||
>
|
||||
<div className="flex items-center gap-2 flex-1">
|
||||
<div className="flex min-w-0 flex-1 items-center gap-2">
|
||||
<Wrench className="h-4 w-4 shrink-0 text-muted-foreground" />
|
||||
<div className="flex-1 min-w-0">
|
||||
<div className="font-medium">{toolName}</div>
|
||||
<div className="truncate font-medium">{toolName}</div>
|
||||
{currentTool?.human_desc && (
|
||||
<div className="text-sm text-muted-foreground truncate">
|
||||
{currentTool.human_desc}
|
||||
@@ -1379,13 +1385,16 @@ export default function DynamicFormItemComponent({
|
||||
? field.value
|
||||
: [{ role: 'system', content: '' }];
|
||||
return (
|
||||
<div className="space-y-2">
|
||||
<div className="min-w-0 space-y-2">
|
||||
{promptItems.map(
|
||||
(item: { role: string; content: string }, index: number) => (
|
||||
<div key={index} className="flex gap-2 items-center">
|
||||
<div
|
||||
key={index}
|
||||
className="flex min-w-0 flex-col gap-2 sm:flex-row sm:items-center"
|
||||
>
|
||||
{/* 角色选择 */}
|
||||
{index === 0 ? (
|
||||
<div className="w-[120px] px-3 py-2 border rounded bg-gray-50 dark:bg-[#2a292e] text-gray-500 dark:text-white dark:border-gray-600">
|
||||
<div className="w-full shrink-0 rounded border bg-gray-50 px-3 py-2 text-gray-500 sm:w-[120px] dark:border-gray-600 dark:bg-[#2a292e] dark:text-white">
|
||||
system
|
||||
</div>
|
||||
) : (
|
||||
@@ -1410,7 +1419,7 @@ export default function DynamicFormItemComponent({
|
||||
)}
|
||||
{/* 内容输入 */}
|
||||
<Textarea
|
||||
className="w-[300px]"
|
||||
className="min-h-20 w-full min-w-0 flex-1 resize-y overflow-x-hidden break-all sm:w-[300px]"
|
||||
value={item.content}
|
||||
onChange={(e) => {
|
||||
const newValue = [...(field.value ?? promptItems)];
|
||||
@@ -1428,7 +1437,6 @@ export default function DynamicFormItemComponent({
|
||||
className="p-2 hover:bg-gray-100 rounded"
|
||||
onClick={() => {
|
||||
const newValue = (field.value ?? promptItems).filter(
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
(_: any, i: number) => i !== index,
|
||||
);
|
||||
field.onChange(newValue);
|
||||
|
||||
@@ -208,7 +208,7 @@ export default function PluginDetailContent({ id }: { id: string }) {
|
||||
</div>
|
||||
|
||||
<div className="flex min-h-0 max-w-full flex-1 flex-col gap-6 overflow-y-auto md:flex-row md:overflow-hidden">
|
||||
<div className="space-y-4 pb-6 md:min-h-0 md:w-[380px] md:flex-shrink-0 md:overflow-y-auto md:overflow-x-hidden xl:w-[420px]">
|
||||
<div className="min-w-0 max-w-full space-y-4 pb-6 md:min-h-0 md:w-[380px] md:flex-shrink-0 md:overflow-y-auto md:overflow-x-hidden xl:w-[420px]">
|
||||
<PluginForm
|
||||
pluginAuthor={pluginAuthor}
|
||||
pluginName={pluginName}
|
||||
|
||||
@@ -42,7 +42,6 @@ export default function PluginForm({
|
||||
setPluginConfig(res);
|
||||
|
||||
// 提取初始配置中的所有文件 key
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const extractFileKeys = (obj: any): string[] => {
|
||||
const keys: string[] = [];
|
||||
if (obj && typeof obj === 'object') {
|
||||
@@ -77,7 +76,6 @@ export default function PluginForm({
|
||||
);
|
||||
|
||||
// 提取最终保存的配置中的所有文件 key
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const extractFileKeys = (obj: any): string[] => {
|
||||
const keys: string[] = [];
|
||||
if (obj && typeof obj === 'object') {
|
||||
@@ -143,13 +141,13 @@ export default function PluginForm({
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<Card>
|
||||
<div className="min-w-0 max-w-full space-y-4">
|
||||
<Card className="min-w-0 overflow-x-hidden">
|
||||
<CardHeader>
|
||||
<CardTitle>{t('plugins.pluginConfig')}</CardTitle>
|
||||
<CardDescription>{t('plugins.saveConfig')}</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent>
|
||||
<CardContent className="min-w-0 overflow-x-hidden">
|
||||
{pluginInfo.manifest.manifest.spec.config.length > 0 ? (
|
||||
<DynamicFormComponent
|
||||
itemConfigList={pluginInfo.manifest.manifest.spec.config}
|
||||
|
||||
@@ -78,7 +78,7 @@ function FormItem({ className, ...props }: React.ComponentProps<'div'>) {
|
||||
<FormItemContext.Provider value={{ id }}>
|
||||
<div
|
||||
data-slot="form-item"
|
||||
className={cn('grid gap-2', className)}
|
||||
className={cn('grid min-w-0 gap-2', className)}
|
||||
{...props}
|
||||
/>
|
||||
</FormItemContext.Provider>
|
||||
@@ -128,7 +128,7 @@ function FormDescription({ className, ...props }: React.ComponentProps<'p'>) {
|
||||
<p
|
||||
data-slot="form-description"
|
||||
id={formDescriptionId}
|
||||
className={cn('text-muted-foreground text-sm', className)}
|
||||
className={cn('text-muted-foreground text-sm break-words', className)}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
@@ -146,7 +146,7 @@ function FormMessage({ className, ...props }: React.ComponentProps<'p'>) {
|
||||
<p
|
||||
data-slot="form-message"
|
||||
id={formMessageId}
|
||||
className={cn('text-destructive text-sm', className)}
|
||||
className={cn('text-destructive text-sm break-words', className)}
|
||||
{...props}
|
||||
>
|
||||
{body}
|
||||
|
||||
@@ -7,7 +7,7 @@ function Textarea({ className, ...props }: React.ComponentProps<'textarea'>) {
|
||||
<textarea
|
||||
data-slot="textarea"
|
||||
className={cn(
|
||||
'border-input placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 flex field-sizing-content min-h-16 w-full rounded-md border bg-transparent px-3 py-2 text-base shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 md:text-sm',
|
||||
'border-input placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-ring/50 aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive dark:bg-input/30 flex min-h-16 w-full min-w-0 max-w-full resize-y overflow-x-hidden rounded-md border bg-transparent px-3 py-2 text-base break-words shadow-xs transition-[color,box-shadow] outline-none focus-visible:ring-[3px] disabled:cursor-not-allowed disabled:opacity-50 md:text-sm',
|
||||
className,
|
||||
)}
|
||||
{...props}
|
||||
|
||||
Reference in New Issue
Block a user