Feat: Add ChatInput component #3221 (#4915)

### What problem does this PR solve?

Feat: Add ChatInput component #3221

### Type of change


- [x] New Feature (non-breaking change which adds functionality)
This commit is contained in:
balibabu 2025-02-12 19:32:49 +08:00 committed by GitHub
parent a03f5dd9f6
commit 891ee85fa6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 69 additions and 4 deletions

View File

@ -0,0 +1,46 @@
import { useEventListener } from 'ahooks';
import { Mic, Paperclip, Send } from 'lucide-react';
import { useRef, useState } from 'react';
import { Button } from './ui/button';
import { Textarea } from './ui/textarea';
export function ChatInput() {
const textareaRef = useRef<HTMLTextAreaElement>(null);
const [textareaHeight, setTextareaHeight] = useState<number>(40);
useEventListener(
'keydown',
(ev) => {
if (ev.shiftKey && ev.code === 'Enter') {
setTextareaHeight((h) => {
return h + 10;
});
}
},
{
target: textareaRef,
},
);
return (
<section className="flex items-end bg-colors-background-neutral-strong px-4 py-3 rounded-xl m-8">
<Button variant={'icon'} className="w-10 h-10">
<Mic />
</Button>
<Textarea
ref={textareaRef}
placeholder="Tell us a little bit about yourself "
className="resize-none focus-visible:ring-0 focus-visible:ring-offset-0 bg-transparent border-none min-h-0 max-h-20"
style={{ height: textareaHeight }}
/>
<div className="flex gap-2">
<Button variant={'icon'} size={'icon'}>
<Paperclip />
</Button>
<Button variant={'tertiary'} size={'icon'}>
<Send />
</Button>
</div>
</section>
);
}

View File

@ -9,7 +9,7 @@ const Textarea = React.forwardRef<
return (
<textarea
className={cn(
'flex min-h-[80px] w-full rounded-md border border-input bg-colors-background-inverse-weak px-3 py-2 text-base ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm',
'flex min-h-[80px] w-full rounded-md border border-input bg-colors-background-inverse-weak px-3 py-2 text-base ring-offset-background placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 md:text-sm overflow-hidden',
className,
)}
ref={ref}

View File

@ -1,3 +1,4 @@
import { Button } from '@/components/ui/button';
import { zodResolver } from '@hookform/resolvers/zod';
import { FormProvider, useForm } from 'react-hook-form';
import { z } from 'zod';
@ -35,7 +36,7 @@ export function AppSettings() {
<div className="text-2xl font-bold mb-4 text-colors-text-neutral-strong px-6">
App settings
</div>
<div className="overflow-auto max-h-[88vh] px-6 ">
<div className="overflow-auto max-h-[81vh] px-6 ">
<FormProvider {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-6">
<ChatBasicSetting></ChatBasicSetting>
@ -44,6 +45,14 @@ export function AppSettings() {
</form>
</FormProvider>
</div>
<div className="p-6 text-center">
<p className="text-colors-text-neutral-weak mb-1">
There are unsaved changes
</p>
<Button variant={'tertiary'} className="w-full">
Update
</Button>
</div>
</section>
);
}

View File

@ -1,3 +1,9 @@
import { ChatInput } from '@/components/chat-input';
export function ChatBox() {
return <section className="border-x flex-1">ChatBox</section>;
return (
<section className="border-x flex-1">
<ChatInput></ChatInput>
</section>
);
}

View File

@ -35,6 +35,7 @@ module.exports = {
'colors-text-core-standard': 'var(--colors-text-core-standard)',
'colors-text-neutral-strong': 'var(--colors-text-neutral-strong)',
'colors-text-neutral-standard': 'var(--colors-text-neutral-standard)',
'colors-text-neutral-weak': 'var(--colors-text-neutral-weak)',
'colors-text-functional-danger': 'var(--colors-text-functional-danger)',
'colors-text-inverse-strong': 'var(--colors-text-inverse-strong)',
'colors-text-persist-light': 'var(--colors-text-persist-light)',

View File

@ -41,6 +41,7 @@
--colors-background-inverse-strong: rgba(11, 10, 18, 0.8);
--colors-background-inverse-weak: rgba(17, 16, 23, 0.1);
--colors-background-neutral-standard: white;
--colors-background-neutral-strong: rgba(226, 223, 246, 1);
--colors-background-functional-solid-danger: rgba(222, 17, 53, 1);
--colors-background-core-strong: rgba(98, 72, 246, 1);
--colors-background-sentiment-solid-primary: rgba(127, 105, 255, 1);
@ -53,7 +54,8 @@
--colors-text-core-standard: rgba(127, 105, 255, 1);
--colors-text-neutral-strong: rgba(17, 16, 23, 1);
--colors-text-neutral-standard: rgba(53, 51, 65, 1);
--colors-text-neutral-standard: rgba(152, 148, 176, 1);
--colors-text-neutral-weak: rgba(170, 160, 197, 1);
--colors-text-functional-danger: rgba(255, 81, 81, 1);
--colors-text-inverse-strong: rgba(255, 255, 255, 1);
--colors-text-persist-light: rgba(255, 255, 255, 1);
@ -136,6 +138,7 @@
--colors-text-core-standard: rgba(137, 126, 255, 1);
--colors-text-neutral-strong: rgba(255, 255, 255, 1);
--colors-text-neutral-standard: rgba(230, 227, 246, 1);
--colors-text-neutral-weak: rgba(170, 160, 197, 1);
--colors-text-functional-danger: rgba(255, 81, 81, 1);
--colors-text-inverse-strong: rgba(17, 16, 23, 1);
--colors-text-persist-light: rgba(255, 255, 255, 1);