96 lines
3.1 KiB
Plaintext
96 lines
3.1 KiB
Plaintext
|
|
---
|
||
|
|
title: Feedback and messaging
|
||
|
|
description: Configure Toast and compose messaging interfaces from Message, Bubble, Attachment, and MessageScroller.
|
||
|
|
order: 13
|
||
|
|
toc:
|
||
|
|
- id: toast-provider
|
||
|
|
title: Toast Provider
|
||
|
|
- id: send-toast
|
||
|
|
title: Send a toast
|
||
|
|
- id: message-composition
|
||
|
|
title: Message composition
|
||
|
|
- id: attachments
|
||
|
|
title: Attachment states
|
||
|
|
- id: scrolling
|
||
|
|
title: Message scrolling
|
||
|
|
---
|
||
|
|
|
||
|
|
## Toast Provider {#toast-provider}
|
||
|
|
|
||
|
|
Mount one `Toaster` near the application root:
|
||
|
|
|
||
|
|
```tsx
|
||
|
|
import { Toaster } from "@workspace/ui/components/toast"
|
||
|
|
|
||
|
|
export function App() {
|
||
|
|
return (
|
||
|
|
<>
|
||
|
|
<Routes />
|
||
|
|
<Toaster />
|
||
|
|
</>
|
||
|
|
)
|
||
|
|
}
|
||
|
|
```
|
||
|
|
|
||
|
|
The default viewport is fixed to the bottom on small screens and the bottom-right on larger screens. Toasts support stacking, expansion, swipe dismissal, keyboard focus, and icons for `success`, `info`, `warning`, `error`, and `loading` types.
|
||
|
|
|
||
|
|
## Send a toast {#send-toast}
|
||
|
|
|
||
|
|
Use the manager exported by the module:
|
||
|
|
|
||
|
|
```tsx
|
||
|
|
import { Button } from "@workspace/ui/components/button"
|
||
|
|
import { toast } from "@workspace/ui/components/toast"
|
||
|
|
|
||
|
|
;<Button
|
||
|
|
onClick={() =>
|
||
|
|
toast.add({
|
||
|
|
title: "Saved",
|
||
|
|
description: "Your profile has been updated.",
|
||
|
|
type: "success",
|
||
|
|
})
|
||
|
|
}
|
||
|
|
>
|
||
|
|
Save
|
||
|
|
</Button>
|
||
|
|
```
|
||
|
|
|
||
|
|
When notifications need an isolated scope, create a manager with `createToastManager()` and pass it to both `Toaster` and the caller. The default accessible name of the close button comes from the UI localization context.
|
||
|
|
|
||
|
|
## Message composition {#message-composition}
|
||
|
|
|
||
|
|
```tsx
|
||
|
|
import {
|
||
|
|
Message,
|
||
|
|
MessageContent,
|
||
|
|
MessageFooter,
|
||
|
|
MessageGroup,
|
||
|
|
} from "@workspace/ui/components/message"
|
||
|
|
import { Bubble, BubbleContent } from "@workspace/ui/components/bubble"
|
||
|
|
|
||
|
|
;<MessageGroup>
|
||
|
|
<Message align="end">
|
||
|
|
<MessageContent>
|
||
|
|
<Bubble align="end" variant="tinted">
|
||
|
|
<BubbleContent>Tomorrow at three works for me.</BubbleContent>
|
||
|
|
</Bubble>
|
||
|
|
<MessageFooter>Read · 14:32</MessageFooter>
|
||
|
|
</MessageContent>
|
||
|
|
</Message>
|
||
|
|
</MessageGroup>
|
||
|
|
```
|
||
|
|
|
||
|
|
Keep message IDs, authors, delivery state, and actions in the product layer. The UI primitives derive layout only from props and `data-*` state.
|
||
|
|
|
||
|
|
## Attachment states {#attachments}
|
||
|
|
|
||
|
|
`Attachment` supports `idle`, `uploading`, `processing`, `error`, and `done`. `AttachmentMedia`, `AttachmentTitle`, `AttachmentDescription`, and `AttachmentActions` adapt their presentation to the state; the application still owns progress and retry behavior.
|
||
|
|
|
||
|
|
Use the default `orientation="horizontal"` for rows and `orientation="vertical"` for thumbnail grids. `AttachmentGroup` adds horizontal scrolling and snap behavior for a collection.
|
||
|
|
|
||
|
|
## Message scrolling {#scrolling}
|
||
|
|
|
||
|
|
Keep `MessageScrollerProvider`, `MessageScroller`, `MessageScrollerViewport`, and `MessageScrollerContent` in that hierarchy. Wrap each message in `MessageScrollerItem`, adding `scrollAnchor` to the item that should anchor follow mode. `MessageScrollerButton direction="end"` reveals and hides itself from the current scroll state.
|
||
|
|
|
||
|
|
Do not assign `scrollTop` directly when appending messages. Use the follow and visibility state exposed by these primitives so a user reading older messages is not forced back to the bottom.
|