| import type { KeyboardEvent } from "react"; |
| import { Icon } from "./Icon"; |
|
|
| type Props = { |
| text: string; |
| isEditing: boolean; |
| editValue: string; |
| onEditChange: (value: string) => void; |
| onBeginEdit: () => void; |
| onSubmitEdit: () => void | Promise<void>; |
| onCancelEdit: () => void; |
| }; |
|
|
| export function UserBubble({ |
| text, |
| isEditing, |
| editValue, |
| onEditChange, |
| onBeginEdit, |
| onSubmitEdit, |
| onCancelEdit, |
| }: Props) { |
| const handleKeyDown = (e: KeyboardEvent<HTMLTextAreaElement>) => { |
| if (e.key === "Enter" && !e.shiftKey) { |
| e.preventDefault(); |
| onSubmitEdit(); |
| } |
| if (e.key === "Escape") { |
| e.preventDefault(); |
| onCancelEdit(); |
| } |
| }; |
|
|
| return ( |
| <div className="flex w-full justify-end"> |
| {!isEditing ? ( |
| <div className="flex w-full max-w-[80%] items-start gap-2 sm:max-w-[85%]"> |
| <button |
| type="button" |
| onClick={onBeginEdit} |
| title="Edit and resend" |
| aria-label="Edit message" |
| className="mt-1 flex h-9 w-9 shrink-0 items-center justify-center rounded-full border border-outline-variant bg-white text-primary shadow-sm transition-colors hover:border-primary/35 hover:bg-surface-container-low focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary" |
| > |
| <Icon name="edit" className="text-xl" /> |
| </button> |
| <button |
| type="button" |
| onClick={onBeginEdit} |
| title="Edit and resend" |
| className="min-w-0 flex-1 rounded-2xl rounded-tr-none bg-primary px-6 py-4 text-left shadow-sm transition-opacity hover:opacity-95 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary" |
| > |
| <p className="break-words font-body-md text-body-md text-on-primary"> |
| {text} |
| </p> |
| </button> |
| </div> |
| ) : ( |
| <div className="max-w-[80%] w-full min-w-[min(100%,280px)] rounded-2xl rounded-tr-none border border-outline-variant bg-white p-4 shadow-md ring-2 ring-primary/15"> |
| <textarea |
| className="min-h-[88px] w-full resize-none rounded-lg border border-outline-variant bg-surface-container-low px-3 py-2.5 font-body-md text-body-md text-on-background placeholder:text-secondary/60 focus:border-primary focus:outline-none focus:ring-1 focus:ring-primary" |
| value={editValue} |
| onChange={(e) => onEditChange(e.target.value)} |
| onKeyDown={handleKeyDown} |
| rows={4} |
| aria-label="Edit your message" |
| autoFocus |
| /> |
| <div className="mt-3 flex flex-wrap items-center justify-end gap-2"> |
| <button |
| type="button" |
| onClick={onCancelEdit} |
| className="rounded-xl border border-outline-variant bg-white px-4 py-2 font-body-sm text-sm font-semibold text-secondary transition-colors hover:bg-surface-container-high" |
| > |
| Cancel |
| </button> |
| <button |
| type="button" |
| onClick={onSubmitEdit} |
| className="flex items-center gap-2 rounded-xl bg-primary px-4 py-2 font-body-sm text-sm font-bold text-on-primary shadow-sm transition-all hover:opacity-95 active:scale-[0.98]" |
| > |
| Resend |
| <Icon name="send" className="text-lg" /> |
| </button> |
| </div> |
| </div> |
| )} |
| </div> |
| ); |
| } |
|
|