Specialized components
UI framework
Chat feature module
17 min
overview the chat feature module provides a comprehensive real time communication system that can be integrated into ir engine applications it enables users to exchange text messages, share media files, and participate in video calls without leaving the application this module demonstrates how the ui primitives, specialized input components, and icon system can be combined to create a complex, interactive feature by encapsulating all chat related functionality in a cohesive module, the system maintains separation of concerns while providing a complete communication solution architecture the chat feature module is organized into several key components that work together to create a complete communication interface sequencediagram participant user participant chatpage as chat tsx (main layout) participant chatsection as chatsection tsx participant channelslist as channelslist tsx participant chatstate as chatstate ts participant messagecontainer as messagecontainer tsx participant messagelistcomp as message tsx (messagelist) user >>chatpage opens chat chatpage >>chatsection renders chatsection >>channelslist renders, displays channels user >>channelslist clicks on channel channelslist >>chatstate sets selectedchannelid chatstate >>messagecontainer notifies of selectedchannelid change messagecontainer >>messagelistcomp renders messages for selected channel messagelistcomp >>user shows messages main components the module consists of several react components that handle different aspects of the chat interface chatpage ( chat tsx ) the top level component that serves as the entry point and layout container for the chat feature chatsection ( chatsection tsx ) manages the sidebar containing channel lists and user information channelslist ( channelslist tsx ) displays available chat channels and handles channel selection messagecontainer ( messagecontainer tsx ) renders the main message area based on the selected channel message components ( message tsx ) contains sub components for message display and input videocall ( videocall tsx or mediacall tsx ) handles video communication interfaces state management the module uses a dedicated state management system to track chat specific information // from src/components/chat/chatstate ts import { definestate } from '@ir engine/hyperflux'; export const chatstate = definestate({ name 'ui chat chatstate', initial () => ({ selectedchannelid null as string | null, istyping false, unreadmessages {} as record\<string, number>, activecall null as string | null // additional state properties }) }); this centralized state allows different components to track which channel is currently selected monitor typing indicators track unread message counts manage active call information implementation details chatpage component the chatpage component serves as the main container for the chat interface // from src/pages/chat/chat tsx import react from 'react'; import { chatsection } from '@ir engine/ui/src/components/chat/chatsection'; import { messagecontainer } from '@ir engine/ui/src/components/chat/message'; export function chatpage() { return ( \<div classname="flex h screen bg ui background"> \<chatsection classname="w 64 border r border ui outline" /> \<messagecontainer classname="flex 1" /> \</div> ); } this component creates a full height layout with a fixed width sidebar and flexible main area imports and composes the main chat components applies appropriate styling using tailwind classes chatsection component the chatsection component manages the sidebar containing channels and user information // from src/components/chat/chatsection tsx import react from 'react'; import { channelslist } from ' /channelslist'; import { userprofile } from ' /userprofile'; import { searchinput } from '@ir engine/ui'; export const chatsection = ({ classname }) => { return ( \<div classname={`flex flex col ${classname}`}> \<div classname="p 3 border b border ui outline"> \<userprofile /> \</div> \<div classname="p 3"> \<searchinput placeholder="search channels" onchange={handlesearch} /> \</div> \<div classname="flex 1 overflow y auto"> \<channelslist /> \</div> \<div classname="p 3 border t border ui outline"> \<userstatus /> \</div> \</div> ); }; this component provides a vertical layout with user profile at top and status at bottom includes a search input for filtering channels renders the channelslist in a scrollable container uses ui primitives like searchinput from the core framework channelslist component the channelslist component displays available channels and handles selection // from src/components/chat/channelslist tsx import react from 'react'; import { usemutablestate } from '@ir engine/hyperflux'; import { chatstate } from ' /chatstate'; import { hashtagmd, lockmd } from '@ir engine/ui/src/icons'; export const channelslist = () => { const chatstate = usemutablestate(chatstate); const selectedchannelid = chatstate selectedchannelid value; // fetch channels from api or state const channels = usechannels(); const handlechannelclick = (channelid) => { chatstate selectedchannelid set(channelid); }; return ( \<div classname="space y 1 py 2"> {channels map(channel => ( \<div key={channel id} classname={`flex items center px 3 py 2 rounded cursor pointer ${ selectedchannelid === channel id ? 'bg ui hover primary text ui primary' 'hover\ bg ui hover' }`} onclick={() => handlechannelclick(channel id)} \> {channel isprivate ? ( \<lockmd classname="w 4 h 4 mr 2 text text secondary" /> ) ( \<hashtagmd classname="w 4 h 4 mr 2 text text secondary" /> )} \<span classname="truncate">{channel name}\</span> {channel unreadcount > 0 && ( \<span classname="ml auto bg ui primary text white rounded full w 5 h 5 flex items center justify center text xs"> {channel unreadcount} \</span> )} \</div> ))} \</div> ); }; this component uses the chatstate to track and update the selected channel displays channels with appropriate icons from the icon system highlights the selected channel with different styling shows unread message counts as badges handles channel selection through click events messagecontainer component the messagecontainer component manages the main message area // from src/components/chat/messagecontainer tsx import react from 'react'; import { usehookstate } from '@hookstate/core'; import { getmutablestate } from '@ir engine/hyperflux'; import { chatstate } from ' /chatstate'; import { messageheader, messagelist, messageinput } from ' /message'; import { mediacall } from ' /mediacall'; export const messagecontainer = ({ classname }) => { const selectedchannelid = usehookstate(getmutablestate(chatstate) selectedchannelid) value; const activecall = usehookstate(getmutablestate(chatstate) activecall) value; return ( \<div classname={`flex flex col ${classname}`}> {selectedchannelid ? ( <> \<messageheader channelid={selectedchannelid} /> \<div classname="flex 1 flex"> \<div classname={`flex 1 flex flex col ${activecall ? 'md\ w 1/2' 'w full'}`}> \<messagelist channelid={selectedchannelid} /> \<messageinput channelid={selectedchannelid} /> \</div> {activecall && ( \<div classname="hidden md\ block md\ w 1/2 border l border ui outline"> \<mediacall callid={activecall} /> \</div> )} \</div> \</> ) ( \<div classname="flex 1 flex items center justify center text text secondary"> \<p>select a channel to start chatting\</p> \</div> )} \</div> ); }; this component observes the selected channel id from chatstate conditionally renders message components when a channel is selected handles layout adjustments when a video call is active provides a responsive design that adapts to different screen sizes message components the message tsx file contains several sub components for handling different aspects of message display and input // from src/components/chat/message tsx import react, { usestate } from 'react'; import { button, input } from '@ir engine/ui'; import { sendmd, phonemd } from '@ir engine/ui/src/icons'; // message header with channel info and actions export const messageheader = ({ channelid }) => { const channel = usechannel(channelid); const startcall = () => { // initiate call logic }; return ( \<div classname="px 4 py 3 border b border ui outline flex items center"> \<h2 classname="text lg font medium">{channel? name || 'unknown channel'}\</h2> \<div classname="ml auto"> \<button variant="secondary" onclick={startcall}> \<phonemd classname="w 4 h 4 mr 2" /> call \</button> \</div> \</div> ); }; // message list that displays conversation history export const messagelist = ({ channelid }) => { const messages = usemessages(channelid); return ( \<div classname="flex 1 overflow y auto p 4 space y 4"> {messages map(message => ( \<div key={message id} classname="flex"> \<img src={message sender avatar} alt={message sender name} classname="w 8 h 8 rounded full mr 3" /> \<div> \<div classname="flex items baseline"> \<span classname="font medium">{message sender name}\</span> \<span classname="ml 2 text xs text text secondary"> {formattime(message timestamp)} \</span> \</div> \<p classname="mt 1">{message text}\</p> \</div> \</div> ))} \</div> ); }; // message input for composing and sending messages export const messageinput = ({ channelid }) => { const \[message, setmessage] = usestate(''); const sendmessage = () => { if (!message trim()) return; // send message logic console log(`sending message to ${channelid} ${message}`); setmessage(''); }; return ( \<div classname="p 4 border t border ui outline"> \<div classname="flex"> \<input value={message} onchange={(e) => setmessage(e target value)} placeholder="type a message " onkeydown={(e) => e key === 'enter' && sendmessage()} classname="flex 1" /> \<button variant="primary" onclick={sendmessage} disabled={!message trim()} classname="ml 2" \> \<sendmd classname="w 4 h 4" /> \</button> \</div> \</div> ); }; these components use ui primitives like button and input from the core framework incorporate icons from the icon system implement specific chat functionality like message display and sending handle user interactions and state updates videocall component the videocall or mediacall component manages video communication // from src/components/chat/mediacall tsx import react from 'react'; import { button } from '@ir engine/ui'; import { micmd, micoffmd, videomd, videooffmd, phoneoffmd } from '@ir engine/ui/src/icons'; export const mediacall = ({ callid }) => { const \[ismuted, setmuted] = usestate(false); const \[isvideoenabled, setvideoenabled] = usestate(true); const participants = usecallparticipants(callid); const togglemute = () => setmuted(!ismuted); const togglevideo = () => setvideoenabled(!isvideoenabled); const endcall = () => { // end call logic }; return ( \<div classname="flex flex col h full"> \<div classname="p 3 border b border ui outline"> \<h3 classname="font medium">active call ({participants length})\</h3> \</div> \<div classname="flex 1 p 2 grid grid cols 2 gap 2 overflow y auto"> {participants map(participant => ( \<div key={participant id} classname="aspect video bg ui secondary rounded overflow hidden relative" \> {participant videostream ? ( \<video srcobject={participant videostream} autoplay muted={participant islocal} /> ) ( \<div classname="absolute inset 0 flex items center justify center"> \<usercirclelg classname="w 12 h 12 text text secondary" /> \</div> )} \<div classname="absolute bottom 2 left 2 bg black bg opacity 50 text white text xs px 2 py 1 rounded"> {participant name} {participant islocal && '(you)'} {participant ismuted && \<micoffmd classname="w 3 h 3 ml 1 inline" />} \</div> \</div> ))} \</div> \<div classname="p 3 border t border ui outline flex justify center space x 2"> \<button variant={ismuted ? 'danger' 'secondary'} onclick={togglemute} \> {ismuted ? \<micoffmd classname="w 5 h 5" /> \<micmd classname="w 5 h 5" />} \</button> \<button variant={isvideoenabled ? 'secondary' 'danger'} onclick={togglevideo} \> {isvideoenabled ? \<videomd classname="w 5 h 5" /> \<videooffmd classname="w 5 h 5" />} \</button> \<button variant="danger" onclick={endcall}> \<phoneoffmd classname="w 5 h 5" /> \</button> \</div> \</div> ); }; this component manages the video call interface with participant video streams provides controls for microphone, camera, and call management uses icons to represent call states and actions handles responsive layout for multiple participants usage example to integrate the chat feature into an application import react from 'react'; import { chatpage } from '@ir engine/ui/src/pages/chat/chat'; function appwithchat() { return ( \<div classname="app container"> \<header classname="app header"> {/ app header content /} \</header> \<main classname="app content"> \<chatpage /> \</main> \</div> ); } this example shows how the entire chat feature can be added to an application by simply importing and rendering the chatpage component next steps with an understanding of how a complex feature module like chat is structured, the next chapter explores the state management system that enables these components to share and react to data changes next state management (hyperflux) docid\ tkcijzojlrkuqwxbxn2yo