# Chat Create a custom chat feed or AI prompt interface. ## Layout Columns Use Tailwind's [grid column](https://tailwindcss.com/docs/grid-template-columns) utility classes to define horizontal columns for your layout. ```astro
(feed)
Lorem, ipsum dolor sit amet consectetur adipisicing elit. Reprehenderit dolor ullam, qui et itaque quam distinctio dicta nostrum veritatis harum iure hic sequi aperiam, explicabo earum totam deserunt. Fugiat, temporibus.
` tag represents a single *bubble* element. ```astro --- let messageFeed = [ { id: 0, host: true, avatar: 48, name: 'Jane', timestamp: 'Yesterday @ 2:30pm', message: 'Some message text.', color: 'variant-soft-primary', }, { id: 1, host: false, avatar: 14, name: 'Michael', timestamp: 'Yesterday @ 2:45pm', message: 'Some message text.', color: 'variant-soft-primary', }, ]; ---{ messageFeed.map((bubble) => { // Determine if host/guest role const role = bubble.host === true ? 'host' : 'guest'; // Render the bubble template return ``` ## Message Bubbles Provide styling to each bubble element. ```astro --- let messageFeed = [ { id: 0, host: true, avatar: 48, name: 'Jane', timestamp: 'Yesterday @ 2:30pm', message: 'Some message text.', color: 'preset-tonal-primary', }, { id: 1, host: false, avatar: 14, name: 'Michael', timestamp: 'Yesterday @ 2:45pm', message: 'Some message text.', color: 'preset-tonal-primary', }, ]; ---{JSON.stringify({ role, ...bubble }, null, 2)}; }) }{ messageFeed.map((bubble) => { return ( <> {/* If Host, else Guest */} {bubble.host ? ( // Host Bubble ``` ## Prompt Use Skeleton's [input group](/docs/tailwind/forms#groups) styles to create a custom text prompt. *** ## Scroll to Bottom Bind your scrollable feed panel element reference ([Svelte](https://svelte.dev/docs/svelte/bind) | [React](https://react.dev/learn/referencing-values-with-refs#refs-and-the-dom)), then use [scrollTo](https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollTo) to scroll the panel to the bottom on demand. Scroll behavior can be set via `behavior: 'smooth'`. ```ts function scrollChatBottom(behavior?: 'auto' | 'instant' | 'smooth' = 'smooth') { // `elemChat` represents our scrollable panel element elemChat.scrollTo({ top: elemChat.scrollHeight, behavior }); } ``` ## Add a Message Below we'll cover how to append the message feed with a new message from the host user. Per our above examples, we'll use the same `messageFeed` data structure. ```ts let messageFeed = [ /* ...*/ ]; ``` Then bind to the textarea for your prompt in order to capture any message typed by the user. Here's an example of how we might append a new message to the `messageFeed` array. ```ts function addMessage(): void { const newMessage = { id: messageFeed.length, host: true, avatar: 48, name: 'Jane', timestamp: new date(), message: elemPrompt.value, color: 'preset-tonal-primary', }; // Append the new message to the message feed messageFeed = [...messageFeed, newMessage]; // Clear the textarea message elemPrompt.value = ''; // Smoothly scroll to the bottom of the feed setTimeout(() => { scrollChatBottom('smooth'); }, 0); } ``` This can be triggered when the prompt's SEND button is clicked. ```svelte ```{/*) : ( // Guest Bubble*/} {bubble.name}
{bubble.timestamp}{bubble.message}
)} > ); }) }{/*{bubble.name}
{bubble.timestamp}{bubble.message}
*/}