From 338cf32b450aa567e30e83a9ca923e305f2c776a Mon Sep 17 00:00:00 2001
From: Daniel Lu
Date: Tue, 18 Aug 2026 15:08:19 -0700
Subject: [PATCH 1/2] fix: support additional user provided events in
promptfield for omega handling
---
packages/@react-spectrum/ai/exports/index.ts | 1 +
.../@react-spectrum/ai/src/PromptField.tsx | 29 ++++++++++---
.../ai/test/PromptField.test.tsx | 43 ++++++++++++++++++-
3 files changed, 67 insertions(+), 6 deletions(-)
diff --git a/packages/@react-spectrum/ai/exports/index.ts b/packages/@react-spectrum/ai/exports/index.ts
index 7fd5afd63de..fb1a02b611f 100644
--- a/packages/@react-spectrum/ai/exports/index.ts
+++ b/packages/@react-spectrum/ai/exports/index.ts
@@ -49,6 +49,7 @@ export type {
PromptFieldToolbarProps,
PromptFieldTokenValue,
InsertMenuItemProps,
+ AttachFileMenuItemProps,
PromptFieldVoiceButtonProps,
InsertTokenMenuItemProps,
InsertTextMenuItemProps,
diff --git a/packages/@react-spectrum/ai/src/PromptField.tsx b/packages/@react-spectrum/ai/src/PromptField.tsx
index 83958e2f52a..554fed32940 100644
--- a/packages/@react-spectrum/ai/src/PromptField.tsx
+++ b/packages/@react-spectrum/ai/src/PromptField.tsx
@@ -33,7 +33,7 @@ import {
} from 'react';
import {FocusableRef} from '@react-types/shared';
import {getInteractionModality} from 'react-aria/private/interactions/useFocusVisible';
-import {IconContext} from '@react-spectrum/s2';
+import {IconContext, MenuTriggerProps} from '@react-spectrum/s2';
import {Image, Text} from '@react-spectrum/s2/Card';
// @ts-ignore
import intlMessages from '../intl/*.json';
@@ -941,15 +941,17 @@ function buildVoicePrompt(base: TokenFieldValue, voiceText: string): PromptField
return base.replaceRange(base.caretPosition, base.caretPosition, voiceText) as PromptFieldValue;
}
-export interface InsertMenuItemProps {
+// TODO: how do we feed about these extending menutrigger props? IMO the "InsertMenuButton" makes
+// it a bit weird to pass MenuTrigger props to it
+export interface InsertMenuItemProps extends Pick {
children: React.ReactNode;
}
export function InsertMenuButton(props: InsertMenuItemProps) {
- let {children} = props;
+ let {children, onOpenChange} = props;
let stringFormatter = useLocalizedStringFormatter(intlMessages, '@react-spectrum/ai');
return (
-
+
);
}
+export interface AttachFileMenuItemProps extends Omit<
+ MenuItemProps,
+ | 'children'
+ | 'UNSAFE_className'
+ | 'UNSAFE_style'
+ | 'download'
+ | 'href'
+ | 'hrefLang'
+ | 'ping'
+ | 'referrerPolicy'
+ | 'rel'
+ | 'routerOptions'
+ | 'target'
+> {}
-export function AttachFileMenuItem() {
+export function AttachFileMenuItem(props: AttachFileMenuItemProps) {
+ let {onAction, ...otherProps} = props;
let {acceptedAttachmentTypes, setAttachments, onAddAttachments} = useContext(PromptFieldContext);
return (
@@ -941,8 +943,6 @@ function buildVoicePrompt(base: TokenFieldValue, voiceText: string): PromptField
return base.replaceRange(base.caretPosition, base.caretPosition, voiceText) as PromptFieldValue;
}
-// TODO: how do we feed about these extending menutrigger props? IMO the "InsertMenuButton" makes
-// it a bit weird to pass MenuTrigger props to it
export interface InsertMenuItemProps extends Pick {
children: React.ReactNode;
}
diff --git a/packages/@react-spectrum/ai/test/PromptField.test.tsx b/packages/@react-spectrum/ai/test/PromptField.test.tsx
index cd21c38c4ab..4149592afb6 100644
--- a/packages/@react-spectrum/ai/test/PromptField.test.tsx
+++ b/packages/@react-spectrum/ai/test/PromptField.test.tsx
@@ -499,4 +499,12 @@ describeOrSkip('PromptField', () => {
expect(onKeyDown).toHaveBeenCalled();
});
+
+ it('calls onAITermsPress when the AI User Guidelines link is pressed', async () => {
+ let onAITermsPress = jest.fn();
+ let {user} = renderPromptField({onAITermsPress});
+
+ await user.click(screen.getByRole('link', {name: 'AI User Guidelines'}));
+ expect(onAITermsPress).toHaveBeenCalledTimes(1);
+ });
});
diff --git a/packages/@react-spectrum/ai/test/utils/promptFieldTestUtils.tsx b/packages/@react-spectrum/ai/test/utils/promptFieldTestUtils.tsx
index fd0b7852fcb..cbc90241379 100644
--- a/packages/@react-spectrum/ai/test/utils/promptFieldTestUtils.tsx
+++ b/packages/@react-spectrum/ai/test/utils/promptFieldTestUtils.tsx
@@ -197,6 +197,7 @@ export interface HarnessOptions {
uploadProgress?: number;
/** Renders every attachment in the invalid state. */
invalid?: boolean;
+ onAITermsPress?: () => void;
}
export interface HarnessSpies {
@@ -226,7 +227,8 @@ function ControlledPromptField(props: ControlledPromptFieldProps) {
valueRef,
attachmentsRef,
setValueRef,
- spies
+ spies,
+ onAITermsPress
} = props;
let [value, setValue] = useState(initialValue);
let [attachments, setAttachments] = useState(initialAttachments);
@@ -250,7 +252,8 @@ function ControlledPromptField(props: ControlledPromptFieldProps) {
onStop={spies.onStop}
onSubmit={spies.onSubmit}
acceptedAttachmentTypes={acceptedAttachmentTypes}
- onRemoveAttachments={spies.onRemoveAttachments}>
+ onRemoveAttachments={spies.onRemoveAttachments}
+ onAITermsPress={onAITermsPress}>
{attachment => (