Add support for displaying a bundled or remote icon next to agent responses#95
Add support for displaying a bundled or remote icon next to agent responses#95
Conversation
Add LocalAssetImage composable to load images from either remote URLs or the app's assets/icons folder (tries .png, .webp, .jpg, .jpeg). Update ChatMessageItem to render a circular company icon for non-user messages (39dp) when ConciergeTheme provides an asset, spacing the icon 12dp from the message. Refactor message rendering into a new TextMessageCard composable to handle layout and padding differences when an icon is present. Also add a sample logo.png to testapp assets.
Rework ChatMessageItem layout to standardize bot message rendering. Treat company icon as present only if non-empty and route those cases to a new RenderTextMessageWithIcon that places the icon left of the message card. Extract shared parts into AgentResponseContent (markdown + citations/footer) and BotMessageSuffix (prompt suggestions + CTA) and use them for both text and mixed messages. Also unify card padding/alignment and preserve user-message alignment/appearance.
| modifier = Modifier.fillMaxWidth(), | ||
| verticalAlignment = Alignment.Top | ||
| ) { | ||
| LocalAssetImage( |
There was a problem hiding this comment.
Could we use a fixed size parent here so that the image loading in doesnt cause shifting?
| * Renders nothing if the remote request fails or no matching local file is found. | ||
| */ | ||
| @Composable | ||
| internal fun LocalAssetImage( |
There was a problem hiding this comment.
is there any way to cache the resource (ex: remember or CompositionLocal) so multiple agent chat icons can reuse?
There was a problem hiding this comment.
its now cached in-memory via a hash map to prevent multiple asset loads / fetches
| contentDescription = null, | ||
| modifier = Modifier | ||
| .padding(top = style.padding) | ||
| .size(39.dp) |
There was a problem hiding this comment.
should we preemptively allow for theme customization of this value?
There was a problem hiding this comment.
yes, we could make this customizable
| .size(39.dp) | ||
| .clip(CircleShape) | ||
| ) | ||
| Spacer(modifier = Modifier.width(12.dp)) |
There was a problem hiding this comment.
should we preemptively allow for theme customization of this value too?
Changes include: adding companyIconSize and companyIconSpacing to ConciergeLayout tokens and themeDemo.json, mapping CSS keys in CSSKeyMapper, exposing defaults in ConciergeStyles (39dp / 12dp), and introducing a simple bitmap cache in LocalAssetImage to avoid repeated asset decoding. Documentation (style-guide.md) updated to reflect the new properties.
timkimadobe
left a comment
There was a problem hiding this comment.
Suggestion about naming for new styling properties, otherwise looks great thanks Ryan!
| | `--message-border-radius` | `cssLayout.messageBorderRadius` | `Double` | `10.0` | Message bubble corner radius (dp) | | ||
| | `--message-padding` | `cssLayout.messagePadding` | `List<Double>` | `[8, 16]` | Message content padding (dp) | | ||
| | `--message-max-width` | `cssLayout.messageMaxWidth` | `Double?` | `null` | Max message width (dp or %) | | ||
| | `--company-icon-size` | `cssLayout.companyIconSize` | `Double?` | `39.0` | Size (dp) of the company icon shown to the left of agent text messages | |
There was a problem hiding this comment.
what do you think of the naming scheme:
--agent-icon-size
--agent-icon-spacing
?
Description
Adds support for displaying a company brand icon next to agent text message bubbles. The icon is configurable via
assets.icons.companyin the theme JSON and accepts either a remote URL or a local asset name resolved from the app'sassets/icons/folder (supports.png,.webp,.jpg,.jpeg).When a non-empty icon is configured, agent text responses render with a circular icon to the left of the message card, with start padding removed from the card so text aligns flush with the gap. The no-icon layout is unchanged.
The icon is only shown on text responses — multimodal/product card messages are not affected.
New file:
LocalAssetImage.kt— composable that routes to the existingAsyncImagefor remote URLs, or loads raster images fromassets/icons/viaBitmapFactoryModified file:
ChatMessageItem.kt— addsRenderTextMessageWithIconfor the icon layout; guards icon path withtakeIf { it.isNotEmpty() }to handle themes that setcompanyto an empty stringRelated Issue
Motivation and Context
How Has This Been Tested?
assets.icons.companyto local sold colored png. It was also tested with a remote CDN URL.assets.icons.companyto an empty string — no icon is shown and the message layout is visually identical to upstreamScreenshots (if appropriate):
Types of changes
Checklist: