-
Notifications
You must be signed in to change notification settings - Fork 328
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: AssistantModalPrimitive (#321)
- Loading branch information
Showing
11 changed files
with
259 additions
and
5 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"@assistant-ui/react": patch | ||
--- | ||
|
||
feat: AssistantModalPrimitive |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
--- | ||
title: AssistantModalPrimitive | ||
description: A modal chat UI usually displayed in the bottom right corner of the screen. | ||
--- | ||
|
||
import { Code } from "@radix-ui/themes"; | ||
import { ParametersTable, DataAttributesTable } from "@/components/docs"; | ||
|
||
## Anatomy | ||
|
||
```tsx | ||
import { AssistantModalPrimitive } from "@assistant-ui/react"; | ||
|
||
const Thread = () => ( | ||
<AssistantModalPrimitive.Root> | ||
<AssistantModalPrimitive.Trigger> | ||
<FloatingAssistantButton /> | ||
</AssistantModalPrimitive.Trigger> | ||
<AssistantModalPrimitive.Content> | ||
<Thread /> | ||
</AssistantModalPrimitive.Content> | ||
</ThreadPrimitive.Root> | ||
); | ||
``` | ||
|
||
## API Reference | ||
|
||
### Root | ||
|
||
Contains all parts of the assistant modal. | ||
|
||
<ParametersTable | ||
type="AssistantModalRootProps" | ||
parameters={[ | ||
{ | ||
name: "defaultOpen", | ||
type: "boolean", | ||
default: "false", | ||
description: "The open state of the assistant modal when it is initially rendered. Use when you do not need to control its open state.", | ||
}, | ||
{ | ||
name: "open", | ||
type: "boolean", | ||
description: "Not recommended. The controlled open state of the assistant modal. Must be used in conjunction with onOpenChange.", | ||
}, | ||
{ | ||
name: "onOpenChange", | ||
type: "(open: boolean) => void", | ||
description: "Event handler called when the open state of the assistant modal changes.", | ||
}, | ||
{ | ||
name: "modal", | ||
type: "boolean", | ||
default: "false", | ||
description: "The modality of the assistant modal. When set to true, interaction with outside elements will be disabled and only modal content will be visible to screen readers." | ||
} | ||
]} | ||
/> | ||
|
||
### Trigger | ||
|
||
A button that toggles the open state of the assistant modal. `AssistantModalPrimitive.Content` will position itself against this button. | ||
|
||
This primitive renders a `<button>` element unless `asChild` is set. | ||
|
||
<ParametersTable | ||
type="AssistantModalTriggerProps" | ||
parameters={[ | ||
{ | ||
name: "asChild", | ||
}, | ||
]} | ||
/> | ||
|
||
<DataAttributesTable | ||
data={[ | ||
{ | ||
attribute: "[data-state]", | ||
values: <Code>"open" | "closed"</Code>, | ||
}, | ||
]} | ||
/> | ||
|
||
### Content | ||
|
||
The component that pops out when the assistant modal is open. | ||
|
||
This primitive renders a `<div>` element unless `asChild` is set. | ||
|
||
<ParametersTable | ||
type="AssistantModalContentProps" | ||
parameters={[ | ||
{ | ||
name: "asChild", | ||
}, | ||
{ | ||
name: "side", | ||
type: "'top' | 'right' | 'bottom' | 'left'", | ||
default: "'top'", | ||
description: "The side of the assistant modal to position against.", | ||
}, | ||
{ | ||
name: "align", | ||
type: "'start' | 'center' | 'end'", | ||
default: "'end'", | ||
description: "The alignment of the assistant modal to position against.", | ||
}, | ||
{ | ||
name: "dissmissOnInteractOutside", | ||
type: "boolean", | ||
default: "false", | ||
description: "Dismiss the assistant modal when the user interacts outside of it.", | ||
}, | ||
]} | ||
/> | ||
|
||
Refer to radix-ui's Documentation for [Popover.Content](https://www.radix-ui.com/primitives/docs/components/popover#content) for more details. | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
47 changes: 47 additions & 0 deletions
47
packages/react/src/primitives/assistantModal/AssistantModalContent.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
import { ComponentPropsWithoutRef, ElementRef, forwardRef } from "react"; | ||
import * as PopoverPrimitive from "@radix-ui/react-popover"; | ||
import { ScopedProps, usePopoverScope } from "./AssistantModalRoot"; | ||
import { composeEventHandlers } from "@radix-ui/primitive"; | ||
|
||
type AssistantModalContentElement = ElementRef<typeof PopoverPrimitive.Content>; | ||
type AssistantModalContentProps = ComponentPropsWithoutRef< | ||
typeof PopoverPrimitive.Content | ||
> & { | ||
dissmissOnInteractOutside?: boolean; | ||
}; | ||
|
||
export const AssistantModalContent = forwardRef< | ||
AssistantModalContentElement, | ||
AssistantModalContentProps | ||
>( | ||
( | ||
{ | ||
__scopeAssistantModal, | ||
side, | ||
align, | ||
onInteractOutside, | ||
dissmissOnInteractOutside = false, | ||
...props | ||
}: ScopedProps<AssistantModalContentProps>, | ||
forwardedRef, | ||
) => { | ||
const scope = usePopoverScope(__scopeAssistantModal); | ||
|
||
return ( | ||
<PopoverPrimitive.Portal {...scope}> | ||
<PopoverPrimitive.Content | ||
{...scope} | ||
{...props} | ||
ref={forwardedRef} | ||
side={side ?? "top"} | ||
align={align ?? "end"} | ||
onInteractOutside={composeEventHandlers( | ||
onInteractOutside, | ||
dissmissOnInteractOutside ? undefined : (e) => e.preventDefault(), | ||
)} | ||
/> | ||
</PopoverPrimitive.Portal> | ||
); | ||
}, | ||
); | ||
AssistantModalContent.displayName = "AssistantModalContent"; |
44 changes: 44 additions & 0 deletions
44
packages/react/src/primitives/assistantModal/AssistantModalRoot.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
import { FC, useState } from "react"; | ||
import * as PopoverPrimitive from "@radix-ui/react-popover"; | ||
import type { Scope } from "@radix-ui/react-context"; | ||
import { composeEventHandlers } from "@radix-ui/primitive"; | ||
import { useOnComposerFocus } from "../../utils/hooks/useOnComposerFocus"; | ||
|
||
export type ScopedProps<P> = P & { __scopeAssistantModal?: Scope }; | ||
export const usePopoverScope = PopoverPrimitive.createPopoverScope(); | ||
|
||
type AssistantModalRootProps = PopoverPrimitive.PopoverProps; | ||
|
||
const useAssistantModalOpenState = (defaultOpen = false) => { | ||
const state = useState(defaultOpen); | ||
|
||
const [, setOpen] = state; | ||
useOnComposerFocus(() => { | ||
setOpen(true); | ||
}); | ||
|
||
return state; | ||
}; | ||
|
||
export const AssistantModalRoot: FC<AssistantModalRootProps> = ({ | ||
__scopeAssistantModal, | ||
defaultOpen, | ||
open, | ||
onOpenChange, | ||
...rest | ||
}: ScopedProps<AssistantModalRootProps>) => { | ||
const scope = usePopoverScope(__scopeAssistantModal); | ||
|
||
const [modalOpen, setOpen] = useAssistantModalOpenState(defaultOpen); | ||
|
||
return ( | ||
<PopoverPrimitive.Root | ||
{...scope} | ||
open={open === undefined ? modalOpen : open} | ||
onOpenChange={composeEventHandlers(onOpenChange, setOpen)} | ||
{...rest} | ||
/> | ||
); | ||
}; | ||
|
||
AssistantModalRoot.displayName = "AssistantModalRoot"; |
23 changes: 23 additions & 0 deletions
23
packages/react/src/primitives/assistantModal/AssistantModalTrigger.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import { ComponentPropsWithoutRef, ElementRef, forwardRef } from "react"; | ||
import * as PopoverPrimitive from "@radix-ui/react-popover"; | ||
import { ScopedProps, usePopoverScope } from "./AssistantModalRoot"; | ||
|
||
type AssistantModalTriggerElement = ElementRef<typeof PopoverPrimitive.Trigger>; | ||
type AssistantModalTriggerProps = ComponentPropsWithoutRef< | ||
typeof PopoverPrimitive.Trigger | ||
>; | ||
|
||
export const AssistantModalTrigger = forwardRef< | ||
AssistantModalTriggerElement, | ||
AssistantModalTriggerProps | ||
>( | ||
( | ||
{ __scopeAssistantModal, ...rest }: ScopedProps<AssistantModalTriggerProps>, | ||
ref, | ||
) => { | ||
const scope = usePopoverScope(__scopeAssistantModal); | ||
|
||
return <PopoverPrimitive.Trigger {...scope} {...rest} ref={ref} />; | ||
}, | ||
); | ||
AssistantModalTrigger.displayName = "AssistantModalTrigger"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
export { AssistantModalRoot as Root } from "./AssistantModalRoot"; | ||
export { AssistantModalTrigger as Trigger } from "./AssistantModalTrigger"; | ||
export { AssistantModalContent as Content } from "./AssistantModalContent"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
export * as ThreadPrimitive from "./thread"; | ||
export * as ComposerPrimitive from "./composer"; | ||
export * as MessagePrimitive from "./message"; | ||
export * as BranchPickerPrimitive from "./branchPicker"; | ||
export * as ActionBarPrimitive from "./actionBar"; | ||
export * as AssistantModalPrimitive from "./assistantModal"; | ||
export * as BranchPickerPrimitive from "./branchPicker"; | ||
export * as ComposerPrimitive from "./composer"; | ||
export * as ContentPartPrimitive from "./contentPart"; | ||
export * as MessagePrimitive from "./message"; | ||
export * as ThreadPrimitive from "./thread"; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.