Message
One chat message, with its quote, attachment, reactions and delivery state.
SourcePackage @kerf-js/veneer
Preview
tsx
import { state } from '@kerf-js/core'import { Message, Stack } from '@kerf-js/veneer'import type { ChatMessage } from '@kerf-js/veneer'import type { Peer } from '@kerf-js/veneer'export function Kinds() { const retried = state(false) return ( <Stack gap="related"> <Message message={CHAT[1]!} /> <Message message={CHAT[5]!} source={CHAT[1]} /> <Message message={CHAT[7]!} /> <Message message={ retried.value ? { ...FAILED, state: 'sent' } : FAILED } last onRetry={() => (retried.value = true)} /> </Stack> )}const PEOPLE = [ { id: 'mara', name: 'Mara Lindqvist', email: 'mara@kerf.dev', role: 'Owner', team: 'Platform', initials: 'ML', }, { id: 'jun', name: 'Jun Tanaka', email: 'jun@kerf.dev', role: 'Admin', team: 'Platform', initials: 'JT', }, { id: 'priya', name: 'Priya Raman', email: 'priya@kerf.dev', role: 'Member', team: 'Web', initials: 'PR', }, { id: 'tomas', name: 'Tomás Oliveira', email: 'tomas@kerf.dev', role: 'Member', team: 'Web', initials: 'TO', }, { id: 'lena', name: 'Lena Fischer', email: 'lena@kerf.dev', role: 'Member', team: 'Data', initials: 'LF', }, { id: 'noor', name: 'Noor Haddad', email: 'noor@kerf.dev', role: 'Viewer', team: 'Data', initials: 'NH', }, { id: 'sam', name: 'Sam Okafor', email: 'sam@kerf.dev', role: 'Member', team: 'Mobile', initials: 'SO', }, { id: 'ines', name: 'Inés Vidal', email: 'ines@kerf.dev', role: 'Viewer', team: 'Mobile', initials: 'IV', },]const PEERS: Peer[] = PEOPLE.map((p, i) => ({ id: p.id, name: p.name, color: i + 1,}))const [ MARA, JUN, PRIYA, TOMAS, LENA, NOOR, SAM, INES,] = PEERS as [ Peer, Peer, Peer, Peer, Peer, Peer, Peer, Peer,]const AT = 1_793_460_000_000const min = 60_000const CHAT: ChatMessage[] = [ { id: 'm1', author: SAM, time: '15:27', at: AT, day: 'Yesterday', text: 'mobile-bff d-4819 failed its ' + 'health check on ap-south.', }, { id: 'm2', author: SAM, time: '15:28', at: AT + min, day: 'Yesterday', text: 'Looks like the retry change. ' + 'Upstream calls pile up after ' + 'a timeout.', attachment: { kind: 'LOG', name: 'd-4819.log', meta: '48 KB · 1,204 lines', }, }, { id: 'm3', author: JUN, time: '15:31', at: AT + 4 * min, day: 'Yesterday', text: 'Edge cache is holding. Roll ' + 'back and we look at it ' + 'tomorrow?', reactions: [ { emoji: '👍', label: 'Thumbs up', count: 2, names: ['Sam', 'Mara'], }, ], }, { id: 'm4', author: MARA, mine: true, time: '15:33', at: AT + 6 * min, day: 'Yesterday', text: 'Yes, roll it back. I will tell support.', state: 'read', readAt: '15:34', }, { id: 'm5', author: SAM, time: '09:12', at: AT + 1060 * min, day: 'Today', text: 'Rolled back last night. 5xx ' + 'are at zero. @you the fix is ' + 'on a branch.', mentions: ['you'], replies: { count: 2, last: '09:40', people: [JUN, LENA], }, }, { id: 'm6', author: LENA, time: '09:18', at: AT + 1066 * min, day: 'Today', quote: { ref: 'm2', text: 'Upstream calls pile up after a timeout.', }, text: 'search-api had the same thing ' + 'in March. A jittered backoff ' + 'fixed it.', }, { id: 'm7', author: MARA, mine: true, time: '09:21', at: AT + 1069 * min, day: 'Today', text: 'Good catch. Sam, can you add ' + 'that before we retry?', state: 'read', readAt: '09:22', }, { id: 'm8', author: SAM, time: '09:24', at: AT + 1072 * min, day: 'Today', text: 'On it. New deploy after lunch.', reactions: [ { emoji: '🎉', label: 'Party', count: 1, names: ['Mara'], }, ], },]const FAILED: ChatMessage = { id: 'failed', author: MARA, mine: true, time: '09:32', text: 'Sending the graph from my phone', state: 'failed',}Installation
npm install @kerf-js/veneerUsage
tsx
import { Message } from '@kerf-js/veneer'Accessibility
- This has no shortcuts of its own: controls inside it use Tab, Enter and Space as usual, and veneer's parts keep their roles and labels.
API Reference
| Prop | Type | Default | Description |
|---|---|---|---|
message | ChatMessage | — | The message. |
continued | boolean | false | Hides the avatar and name, for a run from one person. |
last | boolean | false | The last of mine: only it shows Sent or Read. |
arrive | boolean | false | Plays the arrival motion. |
source | ChatMessage | — | The quoted message, so its name and time stay current. |
| Event | Type | Default | Description |
|---|---|---|---|
onRetry | ((m: ChatMessage) => void) | — | Sends a failed message again. |
onReact | ((m: ChatMessage, r: MessageReaction | null) => void) | — | Adds or removes a reaction. |
onReplies | ((m: ChatMessage) => void) | — | Opens its replies. |