Brand Concierge Style Guide (Android)
This document provides a comprehensive reference for all styling properties supported by the Brand Concierge Android SDK. Themes are configured using JSON files that follow a web-compatible CSS variable format.
data-variant=warning
data-slots=text
Overview
The theme configuration is loaded from a JSON file using ConciergeThemeLoader.load(context, filename). The framework supports CSS-like variable names (prefixed with --) that are automatically mapped to native Kotlin properties.
Loading a theme
// Load from app assets
val theme = ConciergeThemeLoader.load(context, "theme-default")
// Use default theme
val defaultTheme = ConciergeThemeLoader.default()
Applying a theme
Apply the theme using the ConciergeTheme composable:
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.platform.LocalContext
import com.adobe.marketing.mobile.concierge.ui.theme.ConciergeTheme
import com.adobe.marketing.mobile.concierge.ui.theme.ConciergeThemeLoader
@Composable
fun MyApp() {
val context = LocalContext.current
// Load theme from assets
val theme = remember {
ConciergeThemeLoader.load(context, "my-theme")
?: ConciergeThemeLoader.default()
}
ConciergeTheme(theme = theme) {
// Your app content here
// Concierge UI components will use the theme
}
}
You can also load themes by filename directly:
@Composable
fun MyApp() {
ConciergeTheme(themeFileName = "my-theme.json") {
// Your app content here
}
}
Applying a theme in XML/Views
For XML-based apps using ConciergeChatView, pass the theme when binding:
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// Load theme
val theme = ConciergeThemeLoader.load(this, "my-theme")
val surfaces = listOf("web://example.com/your-surface.html")
val chatView = findViewById<ConciergeChatView>(R.id.concierge_chat)
chatView.bind(
lifecycleOwner = this,
viewModelStoreOwner = this,
surfaces = surfaces,
theme = theme,
onClose = { finish() }
)
}
}
Important: The ConciergeTheme composable provides theme tokens to all child composables through CompositionLocal.
Default theming
- When no theme is loaded (
theme = null): The SDK uses built-in light or dark colors (LightConciergeColors/DarkConciergeColors) based on the device’s light/dark setting. - When a theme is loaded (
theme = <ConciergeThemeData>): The theme JSON always takes precedence.
JSON structure
The theme JSON file contains these top-level keys:
metadataheaderbehaviordisclaimertextarraysassetscomponentsthemeValue formats
Understanding the value formats used throughout this document.
Colors
Colors are specified as hex strings:
"--color-primary": "#EB1000"
"--message-user-background": "#EBEEFF"
"--input-box-shadow": "0 2px 8px 0 #00000014"
Supported formats:
#RRGGBB- 6 digit hex#RRGGBBAA- 8 digit hex with alpha
Dimensions
Dimensions use CSS pixel units:
"--input-height-mobile": "52px"
"--input-border-radius-mobile": "12px"
"--message-max-width": "100%"
Padding
Padding follows CSS shorthand syntax:
"--message-padding": "8px 16px"
Formats:
8px- All sides8px 16px- Vertical, horizontal8px 16px 4px- Top, horizontal, bottom8px 16px 4px 2px- Top, right, bottom, left
Shadows
Shadows use CSS box-shadow syntax:
"--input-box-shadow": "0 2px 8px 0 #00000014"
"--multimodal-card-box-shadow": "0 1px 3px 0 #00000014"
Format: offsetX offsetY blurRadius spreadRadius color. Set to "none" to disable a shadow entirely.
--multimodal-card-box-shadow renders as a drop shadow on ExtendedProductCard, but only two of the five values are actually applied — Compose's Modifier.shadow is elevation-based, not a literal box-shadow renderer:
offsetXoffsetYblurRadiuselevation (dp)spreadRadiuscolorambientColor and spotColorLow alpha values (e.g. #00000014 ≈ 8%) are barely visible against a white background — increase alpha (e.g. #00000040+) for a more visible effect.
--input-box-shadow is parsed into the same shape but isn't rendered by any composable yet (see status table below).
Gradients
Some color tokens (input border, mic icon, arrow send button background, mic waveform bars) support a two-color linear gradient as an alternative to a solid color. Each gradient-capable token is configured via 3 CSS variables sharing a common prefix — a start color, an end color, and an optional angle:
"--input-outline-gradient-start-color": "#12B0A0",
"--input-outline-gradient-end-color": "#6DD3C4",
"--input-outline-gradient-angle": "90deg"
- Both the start and end color must be set for the gradient to render. Setting only one (or setting only the angle) does not produce a partial/fading gradient — the unset side is treated as a not-yet-configured placeholder, and the token silently falls back to its solid-color counterpart (e.g.
--input-outline-color) exactly as if no gradient keys had been set at all. - The angle accepts a CSS
<n>degvalue or a direction keyword (to top,to right,to bottom,to left,to top right,to top left,to bottom right,to bottom left) and follows CSSlinear-gradientconvention:0deg/to toppoints up, increasing clockwise. Defaults to180deg(to bottom) when omitted. - Once both colors are set, the gradient takes priority over the corresponding solid-color token (e.g.
--input-outline-gradient-*overrides--input-outline-color). - The angle-to-render conversion is exact only for the 4 axis-aligned angles (
0/90/180/270); other angles are a close visual approximation, not pixel-exact CSS gradient math.
Font Weights
Font weights use CSS numeric or named values:
100ultraLightW100200thinW200300lightLight400 / normalregularNormal500mediumMedium600semiboldSemiBold700 / boldboldBold800heavyW800900blackBlackText Alignment
leftTextAlign.StartcenterTextAlign.CenterrightTextAlign.EndMetadata
Theme identification information.
metadata.brandName""metadata.version"0.0.0"metadata.language"en-US"metadata.namespace"brand-concierge"Example
{
"metadata": {
"brandName": "Concierge Demo",
"version": "1.0.0",
"language": "en-US",
"namespace": "brand-concierge"
}
}
Header
Chat header title, subtitle, and image configuration. This is a separate top-level header object — it is not part of text.
header.title"Concierge"header.subtitle"Powered by Adobe"header.imagenulllayoutType is "imageOnly". A local asset basename under assets/icons/ (matched against .png, .webp, .jpg, .jpeg, in that order) or an absolute http(s) URL. Falls back to a default chat icon when unset, blank, or unresolvable.header.layoutTypenull"imageOnly" renders only the image; "textOnly", null, or any other/unknown value renders only the title and subtitle (the default).header.imageHeightnull (48dp)"24px". Width follows the image's aspect ratio (wrap content).Note:
title/subtitleonly fall back to the defaults above when both are blank or unset. If you set either one, the other is left blank rather than defaulted — setting onlyheader.subtitlehides the title instead of showing "Concierge".
Example
{
"header": {
"title": "Acme Assistant",
"subtitle": "Here to help",
"image": "logo",
"layoutType": "imageOnly",
"imageHeight": "24px"
}
}
Behavior
Feature toggles and interaction configuration.
Multimodal Carousel
behavior.multimodalCarousel.cardClickAction"openLink"behavior.multimodalCarousel.carouselStyle"paged""paged" = snap to item with prev/next buttons and page dots; "scroll" = continuous horizontal scroll with no paging controls.Input
behavior.input.enableVoiceInputfalsebehavior.input.sendButtonStyle"default""default" (paper airplane icon) or "arrow" (filled circle with upward arrow)behavior.input.disableMultilinetruebehavior.input.showAiChatIconnullicon property: a local asset basename under assets/icons/ or an absolute http(s) URL — same resolution rules as citations.phoneIcon/storeIcon. null or an empty icon hides it. Tooltip/content description is set via text["input.aiChatIcon.tooltip"].behavior.input.enableMicPulseBackgroundtruefalse for a bare waveform with no disc, rendered directly on the input background.behavior.input.stopRecordingIconnullassets/icons/, or an absolute http(s) URL. Falls back to the Material stop-circle icon when null, blank, or unresolvable.Chat
behavior.chat.messageAlignmentConciergeTextAlignment"start""start" / "leading" / "left", "center" / "justify", or "end" / "trailing" / "right". Case-insensitive; unknown values fall back to "start".behavior.chat.messageWidth"100%""100%", "768px")behavior.chat.userMessageBubbleStyle"default""default" = all corners rounded; "balloon" = rounded except bottom-right corner is square (speech balloon style). Corner radius is controlled by --message-border-radius (default 12dp).Product Card
behavior.productCard.cardStyle"actionButton""actionButton" = image overlay with primary/secondary action buttons; "productDetail" = extended card with image, badge, name, subtitle, and price.behavior.productCard.cardsAlignment"center""start" = left-aligned; "center" = centered; "end" = right-aligned.Welcome Card
behavior.welcomeCard.closeButtonAlignment"end""start" (left of title) or "end" (right of title)behavior.welcomeCard.promptFullWidthtruetrue = full-width rows with image thumbnails; false = compact pill chips with iconbehavior.welcomeCard.promptMaxLines—1 for uniform pill heights with ellipsis.behavior.welcomeCard.contentAlignment"top""top" (anchored to top) or "center" (vertically centered)Prompt Suggestions
behavior.promptSuggestions.itemMaxLines1behavior.promptSuggestions.showHeaderfalsetext["suggestions.header"].Feedback
behavior.feedback.displayMode"modal""modal" renders a centered modal card; "action" renders a ModalBottomSheet.behavior.feedback.thumbsPlacement"inline""inline" places thumbs beside the sources accordion header; "below" places them below the accordion with a "Was this helpful?" label.behavior.feedback.showCloseButtonnullnull = shown for "action", hidden for "modal".behavior.feedback.showCancelButtonnullnull = shown for "modal", hidden for "action". Both set to false is honored: Submit and (in action mode) drag-down still dismiss.behavior.feedback.alwaysDisplayfalsetrue, shows the feedback thumbs as soon as the response finishes streaming, bypassing the server's feedbackEligible flag. Does not bypass the streaming-complete requirement.Citations
behavior.citations.showLinkIconfalsebehavior.citations.phoneIconnullkind is "phone" (assigned by the response's linkHints, not inferred from the URL). A local asset basename under assets/icons/ or an absolute http(s) URL — same resolution rules as behavior.input.showAiChatIcon.icon. Falls back to the built-in pop-out icon when null, blank, or unresolvable.behavior.citations.storeIconnullphoneIcon, for links with kind "store".behavior.citations.defaultLinkIconnullphoneIcon, for links with any other kind — including links with no matching linkHints entry.behavior.citations.linkIconStyle.size16behavior.citations.linkIconStyle.spacing2behavior.citations.linkIconStyle.color--message-concierge-link-color, else primaryphoneIcon/storeIcon/defaultLinkIcon/linkIconStyle only affect links rendered inline within AI message text. The citation list icon (in the expanded sources accordion) is a fixed 14dp size tinted with the citation URL color, and always uses the built-in pop-out icon — only showLinkIcon applies to it.
Example
{
"behavior": {
"multimodalCarousel": {
"cardClickAction": "openLink",
"carouselStyle": "scroll"
},
"productCard": {
"cardStyle": "productDetail",
"cardsAlignment": "center"
},
"input": {
"enableVoiceInput": true,
"sendButtonStyle": "default",
"disableMultiline": false,
"showAiChatIcon": {
"icon": "ai-assistant-icon"
}
},
"chat": {
"messageAlignment": "left",
"messageWidth": "100%",
"userMessageBubbleStyle": "balloon"
},
"feedback": {
"displayMode": "action",
"thumbsPlacement": "below",
"showCloseButton": true,
"showCancelButton": false,
"alwaysDisplay": false
},
"citations": {
"showLinkIcon": true
},
"welcomeCard": {
"closeButtonAlignment": "start",
"promptFullWidth": false,
"promptMaxLines": 1,
"contentAlignment": "top"
},
"promptSuggestions": {
"itemMaxLines": 1,
"showHeader": true
}
}
}
Disclaimer
Legal disclaimer text with embedded links.
disclaimer.text"AI responses may be inaccurate. Check answers and sources. {Terms}"{placeholders} for linksdisclaimer.linkstext and url.disclaimer.links[].text""Terms for {Terms})disclaimer.links[].url""Example
{
"disclaimer": {
"text": "AI responses may be inaccurate. Check answers and sources. {Terms}",
"links": [
{
"text": "Terms",
"url": "https://www.adobe.com/legal/licenses-terms/adobe-gen-ai-user-guidelines.html"
}
]
}
}
To hide the disclaimer, omit the disclaimer key from the theme or set disclaimer.text to an empty string.
Text (Copy)
Localized UI strings using dot-notation keys.
✅ Content Recommendations
While there are no strict requirements for character limits in many of these text fields, it is strongly recommended that the values be tested on target device(s) prior to deployment, ensuring the UI renders as desired.
Welcome Screen
text["welcome.heading"]"Explore what you can do with Adobe apps."text["welcome.subheading"]"Choose an option or tell us..."Input
text["input.placeholder"]"Tell us what you'd like to do or create"text["input.aiChatIcon.tooltip"]"Ask AI"System Messages
text["error.network"]"I'm sorry, I'm having trouble..."text["loading.message"]"Generating response from our knowledge base"Feedback Dialog
text["feedback.dialog.title.positive"]"Your feedback is appreciated"text["feedback.dialog.title.negative"]"Your feedback is appreciated"text["feedback.dialog.question.positive"]"What went well? Select all that apply."text["feedback.dialog.question.negative"]"What went wrong? Select all that apply."text["feedback.dialog.notes"]"Notes"text["feedback.dialog.submit"]"Submit"text["feedback.dialog.cancel"]"Cancel"text["feedback.dialog.notes.placeholder"]"Additional notes (optional)"text["feedback.toast.success"]"Thank you for the feedback."Sources & Feedback Footer
text["sourcesLabel"]"Sources"text["feedbackHelpfulLabel"]"Was this helpful?"behavior.feedback.thumbsPlacement is "below". Set to "" to hide.Prompt Suggestions
text["suggestions.header"]"Suggestions"behavior.promptSuggestions.showHeader is true.Example
{
"text": {
"welcome.heading": "Welcome to Brand Concierge!",
"welcome.subheading": "I'm your personal guide to help you explore.",
"input.placeholder": "How can I help?",
"error.network": "I'm sorry, I'm having trouble connecting.",
"loading.message": "Generating response from our knowledge base...",
"feedbackHelpfulLabel": "Was this helpful?",
"sourcesLabel": "Sources & Feedback",
"suggestions.header": "Suggestions",
"feedback.dialog.title.positive": "Your feedback is appreciated",
"feedback.dialog.title.negative": "Your feedback is appreciated",
"feedback.dialog.question.positive": "What went well? Select all that apply.",
"feedback.dialog.question.negative": "What went wrong? Select all that apply.",
"feedback.dialog.notes": "Notes",
"feedback.dialog.submit": "Submit",
"feedback.dialog.cancel": "Cancel",
"feedback.dialog.notes.placeholder": "Additional notes (optional)",
"feedback.toast.success": "Thank you for the feedback."
}
}
Arrays
List-based configuration for examples and feedback options.
Welcome Examples
You shouldn't have more than four items in your provided welcome examples.
Always test your values on device to ensure the UI looks as desired.
arrays["welcome.examples"]text, optional image, and optional backgroundColor (hex string).arrays["welcome.examples"][].textarrays["welcome.examples"][].imagenull or omitted).arrays["welcome.examples"][].backgroundColornull or omitted).Feedback Options
You shouldn't have more than five options available for feedback.
Always test your values on device to ensure the UI looks as desired.
arrays["feedback.positive.options"]arrays["feedback.negative.options"]Example
{
"arrays": {
"welcome.examples": [
{
"text": "I'd like to explore templates to see what I can create.",
"image": "https://example.com/template.png",
"backgroundColor": "#F5F5F5"
}
],
"feedback.positive.options": [
"Helpful and relevant recommendations",
"Clear and easy to understand",
"Other"
],
"feedback.negative.options": [
"Didn't understand my request",
"Unhelpful or irrelevant information",
"Other"
]
}
}
Assets
Icon and image asset configuration.
assets.icons.company""http:// or https://) or a local asset name (without extension) resolved from the app's assets/icons/ folder. Supported local formats: .png, .webp, .jpg, .jpeg. Leave empty to show no icon.Example
{
"assets": {
"icons": {
"company": "https://example.com/brand-icon.png"
}
}
}
To use a local asset instead, place the image file in your app's assets/icons/ directory and set the value to the filename without its extension:
{
"assets": {
"icons": {
"company": "company-logo"
}
}
}
Theme Tokens
Visual styling using CSS-like variable names. All properties in the theme object use the --property-name format.
Typography
--font-familytypography.fontFamilyStringnull (system font)--line-height-bodytypography.lineHeightDouble1.0Colors - Primary
--color-primarycolors.primaryColors.primaryString"#1976D2"--color-textcolors.primaryColors.textString"#000000"--color-containercolors.containerString?null (falls back to hardcoded light/dark value)Colors - Surface
--main-container-backgroundcolors.surfaceColors.mainContainerBackgroundString"#FFFFFF"--main-container-bottom-backgroundcolors.surfaceColors.mainContainerBottomBackgroundString"#FFFFFF"--message-blocker-backgroundcolors.surfaceColors.messageBlockerBackgroundString"#FFFFFF"Colors - Messages
--message-user-backgroundcolors.message.userBackgroundString"#E3F2FD"--message-user-textcolors.message.userTextString"#000000"--message-concierge-backgroundcolors.message.conciergeBackgroundString"#F5F5F5"--message-concierge-textcolors.message.conciergeTextString"#000000"--message-concierge-link-colorcolors.message.conciergeLinkString"#1976D2"Colors - Buttons
--button-primary-backgroundcolors.button.primaryBackgroundString"#1976D2"--button-primary-textcolors.button.primaryTextString"#FFFFFF"--button-primary-hovercolors.button.primaryHoverString"#1565C0"--button-secondary-bordercolors.button.secondaryBorderString"#1976D2"--button-secondary-textcolors.button.secondaryTextString"#1976D2"--button-secondary-hovercolors.button.secondaryHoverString"#E3F2FD"--color-button-secondary-hover-textcolors.button.secondaryHoverTextString"#1976D2"--submit-button-fill-colorcolors.button.submitFillString"#FFFFFF"--submit-button-fill-color-disabledcolors.button.submitFillDisabledString"#E0E0E0"--color-button-submitcolors.button.submitTextString"#1976D2"--color-button-submit-hovercolors.button.submitTextHoverString"#1565C0"--button-disabled-backgroundcolors.button.disabledBackgroundString"#E0E0E0"Colors - Input
--input-backgroundcolors.input.backgroundString"#FFFFFF"--input-text-colorcolors.input.textString"#000000"--input-outline-colorcolors.input.outlineString?null--input-outline-gradient-start-colorcolors.input.outlineGradientString?null--input-outline-color when both gradient colors are set--input-outline-gradient-end-colorcolors.input.outlineGradientString?null--input-outline-gradient-anglecolors.input.outlineGradientString"180deg"--input-focus-outline-colorcolors.input.outlineFocusString"#1976D2"--input-send-icon-colorcolors.input.sendIconColorString?nullonSurface--input-send-arrow-icon-colorcolors.input.sendArrowIconColorString?nullonPrimary. Only used when sendButtonStyle is "arrow"--input-send-arrow-background-colorcolors.input.sendArrowBackgroundColorString?nullsendIconColor then primary. Only used when sendButtonStyle is "arrow"--input-send-arrow-background-gradient-start-colorcolors.input.sendArrowBackgroundGradientString?nullsendButtonStyle is "arrow"--input-send-arrow-background-gradient-end-colorcolors.input.sendArrowBackgroundGradientString?null--input-send-arrow-background-gradient-anglecolors.input.sendArrowBackgroundGradientString"180deg"--input-mic-icon-colorcolors.input.micIconColorString?nullprimary--input-mic-icon-gradient-start-colorcolors.input.micIconGradientString?null--input-mic-icon-gradient-end-colorcolors.input.micIconGradientString?null--input-mic-icon-gradient-anglecolors.input.micIconGradientString"180deg"--input-mic-recording-icon-colorcolors.input.micRecordingIconColorString?nullonPrimary when enableMicPulseBackground is true, otherwise primary--input-mic-waveform-gradient-start-colorcolors.input.micWaveformGradientString?nullmicRecordingIconColor--input-mic-waveform-gradient-end-colorcolors.input.micWaveformGradientString?nullmicRecordingIconColor--input-mic-waveform-gradient-anglecolors.input.micWaveformGradientString"180deg"Colors - Welcome Prompts
--welcome-prompt-background-colorcolors.welcomePrompt.backgroundColorString?null (falls back to surface)backgroundColor is not defined in the prompt configuration.--welcome-prompt-text-colorcolors.welcomePrompt.textColorString?null (falls back to onSurface)Colors - Prompt Suggestions
--suggestion-background-colorcolors.promptSuggestion.backgroundColorString?null (falls back to --color-container then hardcoded light/dark value)--suggestion-text-colorcolors.promptSuggestion.textColorString?null (falls back to --message-concierge-text then onSurface)Colors - Circular Citations
--citations-background-colorcolors.citation.backgroundColorString"#E0E0E0"--citations-text-colorcolors.citation.textColorString"#000000"Colors - Feedback
--feedback-icon-btn-backgroundcolors.feedback.iconButtonBackgroundString"#FFFFFF"--feedback-icon-btn-hover-backgroundcolors.feedback.iconButtonHoverBackgroundString"#F5F5F5"Feedback Dialog Colors
These tokens style the feedback dialog (modal card and action bottom sheet).
--feedback-sheet-background-colorcolors.feedback.sheetBackgroundString?colors.background--feedback-title-text-colorcolors.feedback.titleTextString?colors.onBackground / colors.primary.text--feedback-question-text-colorcolors.feedback.questionTextString?--feedback-options-text-colorcolors.feedback.optionsTextString?--feedback-checkbox-border-colorcolors.feedback.checkboxBorderString?"#7F7F7F" (light) / "#B0B0B0" (dark)--feedback-drag-handle-colorcolors.feedback.dragHandleString?"#CCCCCC"--feedback-submit-button-fill-colorcolors.feedback.submitButtonFillString?colors.button.primaryBackground--feedback-submit-button-text-colorcolors.feedback.submitButtonTextString?colors.button.primaryText--feedback-cancel-button-fill-colorcolors.feedback.cancelButtonFillString?null (transparent; outline style)null = transparent (outline style); set to a color for a solid fill. The cancel button border is always applied — set --feedback-cancel-button-border-width to 0 to suppress it. Also tints the X close icon.--feedback-cancel-button-text-colorcolors.feedback.cancelButtonTextString?colors.button.secondaryText--feedback-cancel-button-border-colorcolors.feedback.cancelButtonBorderString?colors.button.secondaryBorder--feedback-cancel-button-border-width > 0, regardless of whether cancelButtonFill is set.Contrast note: When
--feedback-sheet-background-coloris pinned, also set--feedback-title-text-color,--feedback-question-text-color, and--feedback-options-text-colorto maintain text contrast. System defaults track the device palette, not the themed surface.
Colors - Disclaimer
--disclaimer-colorcolors.disclaimerString"#757575"Colors - Thinking Animation
--thinking-dot-colorcolors.thinking.dotColorString?null (falls back to --color-primary at 70% opacity)Colors - Extended Product Cards
Used when behavior.productCard.cardStyle is "productDetail".
--product-card-outline-colorcssLayout.productCardOutlineColorString"#E3E3E3"--product-card-background-colorcssLayout.productCardBackgroundColorString"#FFFFFF"--product-card-title-colorcssLayout.productCardTitleColorString"#191F1C"--product-card-subtitle-colorcssLayout.productCardSubtitleColorString"#4F4F4F"--product-card-price-colorcssLayout.productCardPriceColorString"#191F1C"--product-card-badge-text-colorcssLayout.productCardBadgeTextColorString"#FFFFFF"--product-card-badge-background-colorcssLayout.productCardBadgeBackgroundColorString--product-card-was-price-colorcssLayout.productCardWasPriceColorString"#6E6E6E"--product-card-cta-button-background-colorcolors.productCardCtaButton.backgroundString"#BB5811"--product-card-cta-button-text-colorcolors.productCardCtaButton.textString"#FFFFFF"Colors - CTA Button
--cta-button-background-colorcolors.ctaButton.backgroundString"#EDEDED"--cta-button-text-colorcolors.ctaButton.textString"#191F1C"--cta-button-icon-colorcolors.ctaButton.iconColorString"#161313"Layout value format: All layout measurements are specified as CSS strings in the JSON theme object (e.g.
"8px","16px") and integer quantities as numeric strings (e.g."700","400"). The SDK parses these into their internal Kotlin types (Doublefor dp values,Intfor weights and orders). The Type and Default columns below reflect the internal representation.
Layout - Input
--input-height-mobilecssLayout.inputHeightDouble52.0--input-border-radius-mobilecssLayout.inputBorderRadiusDouble12.0--input-outline-widthcssLayout.inputOutlineWidthDouble2.0--input-focus-outline-widthcssLayout.inputFocusOutlineWidthDouble2.0--input-font-sizecssLayout.inputFontSizeDouble16.0--input-button-heightcssLayout.inputButtonHeightDouble24.0--input-button-width alone is enough to override the default; when both are set, width wins.--input-button-widthcssLayout.inputButtonWidthDouble24.0--input-button-height — same shared input-row icon size, preferred over height when both are set.--input-button-border-radiuscssLayout.inputButtonBorderRadiusDouble8.0--input-box-shadowcssLayout.inputBoxShadowMap<String, Any>nullLayout - Messages
--message-border-radiuscssLayout.messageBorderRadiusDouble10.0--message-paddingcssLayout.messagePaddingList<Double>[8, 16]--message-max-widthcssLayout.messageMaxWidthDouble?null--agent-icon-sizecssLayout.agentIconSizeDouble?39.0--agent-icon-spacingcssLayout.agentIconSpacingDouble?12.0Layout - Chat
--chat-interface-max-widthcssLayout.chatInterfaceMaxWidthDouble768.0--chat-history-paddingcssLayout.chatHistoryPaddingDouble16.0--chat-history-padding-top-expandedcssLayout.chatHistoryPaddingTopExpandedDouble8.0--chat-history-bottom-paddingcssLayout.chatHistoryBottomPaddingDouble12.0--message-blocker-heightcssLayout.messageBlockerHeightDouble105.0Layout - Cards & Carousel
--border-radius-cardcssLayout.borderRadiusCardDouble16.0--multimodal-card-box-shadowcssLayout.multimodalCardBoxShadowMap<String, Any>nullLayout - Extended Product Cards
When behavior.productCard.cardStyle is "productDetail", product recommendations display as extended cards with image, badge, name, subtitle, and price. The following theme tokens customize the extended product card layout. See Colors - Extended Product Cards for color properties.
--product-card-widthcssLayout.productCardWidthDouble250.0--product-card-min-heightcssLayout.productCardMinHeightDouble240.0--product-card-max-height.--product-card-max-heightcssLayout.productCardMaxHeightDouble360.0--product-card-border-radiuscssLayout.productCardBorderRadiusDouble8.0--product-image-widthcssLayout.productImageWidthDouble190.0--product-image-heightcssLayout.productImageHeightDouble190.0--product-image-scalecssLayout.productImageScaleString"fill""fit" shows the whole image uncropped inside the fixed image slot; "fill" (default, or any other value) scales to fill the slot and crops overflow.--product-card-title-font-sizecssLayout.productCardTitleFontSizeDouble14.0--product-card-title-font-weightcssLayout.productCardTitleFontWeightInt700--product-card-subtitle-font-sizecssLayout.productCardSubtitleFontSizeDouble12.0--product-card-subtitle-font-weightcssLayout.productCardSubtitleFontWeightInt400--product-card-price-font-sizecssLayout.productCardPriceFontSizeDouble14.0--product-card-price-font-weightcssLayout.productCardPriceFontWeightInt400--product-card-badge-font-sizecssLayout.productCardBadgeFontSizeDouble12.0--product-card-badge-font-weightcssLayout.productCardBadgeFontWeightInt700--product-card-was-price-font-sizecssLayout.productCardWasPriceFontSizeDouble12.0--product-card-was-price-font-weightcssLayout.productCardWasPriceFontWeightInt400--product-card-was-price-text-prefixcssLayout.productCardWasPriceTextPrefixString"was "--product-card-text-horizontal-paddingcssLayout.productCardTextHorizontalPaddingDouble16.0--product-card-text-top-paddingcssLayout.productCardTextTopPaddingDouble24.0--product-card-text-bottom-paddingcssLayout.productCardTextBottomPaddingDouble16.0--product-card-title-subtitle-spacingcssLayout.productCardTitleSubtitleSpacingDouble8.0--product-card-text-spacing when unset.--product-card-section-spacingcssLayout.productCardSectionSpacingDouble16.0--product-card-text-spacing when unset.--product-card-price-spacingcssLayout.productCardPriceSpacingDouble0.0--product-card-text-spacingcssLayout.productCardTextSpacingDouble?null--product-card-title-subtitle-spacing (default 8.0) and --product-card-section-spacing (default 16.0) when they aren't set individually. Prefer setting those two directly (dp).--product-card-carousel-horizontal-paddingcssLayout.productCardCarouselHorizontalPaddingDouble0.0--chat-history-padding when unset).--product-card-carousel-spacingcssLayout.productCardCarouselSpacingDouble12.0--product-card-cta-button-border-radiuscssLayout.productCardCtaButtonBorderRadiusDouble40.0--product-card-cta-button-horizontal-paddingcssLayout.productCardCtaButtonHorizontalPaddingDouble16.0--product-card-cta-button-vertical-paddingcssLayout.productCardCtaButtonVerticalPaddingDouble8.0--product-card-cta-button-font-sizecssLayout.productCardCtaButtonFontSizeDouble12.0--product-card-cta-button-font-weightcssLayout.productCardCtaButtonFontWeightInt600Layout - Buttons
--button-height-scssLayout.buttonHeightSmallDouble30.0--cta-button-border-radiuscssLayout.ctaButtonBorderRadiusDouble99.0--cta-button-horizontal-paddingcssLayout.ctaButtonHorizontalPaddingDouble16.0--cta-button-vertical-paddingcssLayout.ctaButtonVerticalPaddingDouble12.0--cta-button-font-sizecssLayout.ctaButtonFontSizeDouble14.0--cta-button-font-weightcssLayout.ctaButtonFontWeightInt400--cta-button-icon-sizecssLayout.ctaButtonIconSizeDouble16.0Layout - Feedback
--feedback-container-gapcssLayout.feedbackContainerGapDouble4.0--feedback-icon-btn-size-desktopcomponents.feedback.iconButtonSizeDesktopDouble32.0Feedback Dialog Layout
These tokens style the feedback dialog layout (modal card and action bottom sheet).
--feedback-submit-button-border-radiuscssLayout.feedbackSubmitButtonBorderRadiusDouble?10.0--feedback-cancel-button-border-radiuscssLayout.feedbackCancelButtonBorderRadiusDouble?10.0--feedback-cancel-button-border-widthcssLayout.feedbackCancelButtonBorderWidthDouble?1.0--feedback-submit-button-font-weightcssLayout.feedbackSubmitButtonFontWeightInt?600--feedback-cancel-button-font-weightcssLayout.feedbackCancelButtonFontWeightInt?600--feedback-checkbox-border-radiuscssLayout.feedbackCheckboxBorderRadiusDouble?6.0--feedback-title-text-aligncssLayout.feedbackTitleTextAlignConciergeTextAlignment?null (START)"start" / "leading" / "left", "center" / "justify", or "end" / "trailing" / "right". Case-insensitive; unknown values fall back to START.--feedback-title-font-sizecssLayout.feedbackTitleFontSizeDouble?22.0Components - Feedback
Non-CSS components.feedback overrides for the feedback dialog.
components.feedback.iconButtonSizeDesktop32--feedback-icon-btn-size-desktop.components.feedback.positiveNotesEnabledtruecomponents.feedback.negativeNotesEnabledtrueNote: The notes field is only available in
"modal"display mode, gated bycomponents.feedback.positiveNotesEnabled/negativeNotesEnabled.
Layout - Citations
--citations-text-font-weightcssLayout.citationsTextFontWeightInt700--citations-desktop-button-font-sizecssLayout.citationsDesktopButtonFontSizeDouble14.0Layout - Disclaimer
--disclaimer-font-sizecssLayout.disclaimerFontSizeDouble12.0--disclaimer-font-weightcssLayout.disclaimerFontWeightInt400Layout - Welcome Screen
--welcome-input-ordercssLayout.welcomeInputOrderInt3--welcome-cards-ordercssLayout.welcomeCardsOrderInt2--header-title-font-sizecssLayout.headerTitleFontSizeDoublenull (uses headlineSmall)--welcome-title-font-sizecssLayout.welcomeTitleFontSizeDoublenull (uses headlineSmall)--welcome-text-aligncssLayout.welcomeTextAlignString"center""left", "center", "right")--welcome-content-paddingcssLayout.welcomeContentPaddingDouble20.0--welcome-prompt-image-sizecssLayout.welcomePromptImageSizeDouble75.0--welcome-prompt-spacingcssLayout.welcomePromptSpacingDouble8.0--welcome-title-bottom-spacingcssLayout.welcomeTitleBottomSpacingDouble8.0--welcome-prompts-top-spacingcssLayout.welcomePromptsTopSpacingDouble8.0--welcome-prompt-paddingcssLayout.welcomePromptPaddingDouble0.0--welcome-prompt-corner-radiuscssLayout.welcomePromptCornerRadiusDouble8.0--suggestion-item-border-radiuscssLayout.suggestionItemBorderRadiusDouble10.0Layout - Thinking Animation
--thinking-dot-sizecssLayout.thinkingDotSizeDouble8.0--thinking-dot-spacingcssLayout.thinkingDotSpacingDouble8.0--thinking-bubble-border-radiuscssLayout.thinkingBubbleBorderRadiusDouble8.0--thinking-bubble-padding-horizontalcssLayout.thinkingBubblePaddingHorizontalDouble16.0--thinking-bubble-padding-verticalcssLayout.thinkingBubblePaddingVerticalDouble8.0--thinking-dot-vertical-alignmentcssLayout.thinkingDotVerticalAlignmentString"center""top", "center", or "bottom"Complete Example
{
"metadata": {
"brandName": "Concierge Demo",
"version": "1.0.0",
"language": "en-US",
"namespace": "brand-concierge"
},
"header": {
"title": "Concierge",
"subtitle": "Powered by Adobe"
},
"behavior": {
"multimodalCarousel": {
"cardClickAction": "openLink",
"carouselStyle": "paged"
},
"productCard": {
"cardStyle": "actionButton",
"cardsAlignment": "center"
},
"input": {
"enableVoiceInput": true,
"sendButtonStyle": "default",
"disableMultiline": false,
"showAiChatIcon": {
"icon": "ai-assistant-icon"
}
},
"chat": {
"messageAlignment": "left",
"messageWidth": "100%",
"userMessageBubbleStyle": "balloon"
},
"feedback": {
"displayMode": "action",
"thumbsPlacement": "inline",
"alwaysDisplay": false
},
"citations": {
"showLinkIcon": false
},
"welcomeCard": {
"closeButtonAlignment": "start",
"promptFullWidth": false,
"promptMaxLines": 1,
"contentAlignment": "top"
}
},
"disclaimer": {
"text": "AI responses may be inaccurate. Check answers and sources. {Terms}",
"links": [
{
"text": "Terms",
"url": "https://www.adobe.com/legal/licenses-terms/adobe-gen-ai-user-guidelines.html"
}
]
},
"text": {
"welcome.heading": "Welcome to Brand Concierge!",
"welcome.subheading": "I'm your personal guide to help you explore.",
"input.placeholder": "How can I help?",
"input.aiChatIcon.tooltip": "Ask AI",
"error.network": "I'm sorry, I'm having trouble connecting to our services right now.",
"loading.message": "Generating response from our knowledge base...",
"feedbackHelpfulLabel": "Was this helpful?",
"sourcesLabel": "Sources",
"feedback.dialog.title.positive": "Your feedback is appreciated",
"feedback.dialog.title.negative": "Your feedback is appreciated",
"feedback.dialog.question.positive": "What went well? Select all that apply.",
"feedback.dialog.question.negative": "What went wrong? Select all that apply.",
"feedback.dialog.notes": "Notes",
"feedback.dialog.submit": "Submit",
"feedback.dialog.cancel": "Cancel",
"feedback.dialog.notes.placeholder": "Additional notes (optional)",
"feedback.toast.success": "Thank you for the feedback."
},
"arrays": {
"welcome.examples": [
{
"text": "I'd like to explore templates to see what I can create.",
"image": "https://example.com/template.png",
"backgroundColor": "#F5F5F5"
},
{
"text": "Help me find recommendations.",
"image": "https://example.com/example.png",
"backgroundColor": "#F5F5F5"
},
{
"text": "Where can I learn more?",
"image": "https://example.com/learn-more.png",
"backgroundColor": "#F5F5F5"
}
],
"feedback.positive.options": [
"Helpful and relevant recommendations",
"Clear and easy to understand",
"Friendly and conversational tone",
"Visually appealing presentation",
"Other"
],
"feedback.negative.options": [
"Didn't understand my request",
"Unhelpful or irrelevant information",
"Too vague or lacking detail",
"Errors or poor quality response",
"Other"
]
},
"assets": {
"icons": {
"company": ""
}
},
"theme": {
"--welcome-input-order": "3",
"--welcome-cards-order": "2",
"--header-title-font-size": "18px",
"--welcome-title-font-size": "16px",
"--welcome-text-align": "left",
"--welcome-content-padding": "16px",
"--welcome-prompt-image-size": "16px",
"--welcome-prompt-padding": "12px",
"--welcome-prompt-corner-radius": "20px",
"--welcome-prompt-background-color": "#F5F5F5",
"--welcome-prompt-text-color": "#000000",
"--welcome-prompt-spacing": "8px",
"--suggestion-background-color": "#F0F0F0",
"--suggestion-text-color": "#131313",
"--suggestion-item-border-radius": "10px",
"--thinking-dot-color": "#1B6B58",
"--thinking-dot-size": "8px",
"--thinking-dot-spacing": "8px",
"--thinking-bubble-border-radius": "8px",
"--thinking-bubble-padding-horizontal": "16px",
"--thinking-bubble-padding-vertical": "8px",
"--thinking-dot-vertical-alignment": "center",
"--welcome-title-bottom-spacing": "6px",
"--welcome-prompts-top-spacing": "12px",
"--font-family": "",
"--color-primary": "#EB1000",
"--color-text": "#131313",
"--color-container": "#F0F0F0",
"--line-height-body": "1.75",
"--main-container-background": "#FFFFFF",
"--main-container-bottom-background": "#FFFFFF",
"--message-blocker-background": "#00000066",
"--message-user-background": "#E3F2FD",
"--message-user-text": "#000000",
"--message-concierge-background": "#F5F5F5",
"--message-concierge-text": "#000000",
"--message-concierge-link-color": "#1976D2",
"--message-max-width": "100%",
"--message-border-radius": "10px",
"--message-padding": "8px 16px",
"--agent-icon-size": "39px",
"--agent-icon-spacing": "12px",
"--chat-interface-max-width": "768px",
"--chat-history-padding": "16px",
"--chat-history-padding-top-expanded": "0",
"--chat-history-bottom-padding": "0",
"--message-blocker-height": "105px",
"--input-height-mobile": "52px",
"--input-border-radius-mobile": "12px",
"--button-primary-background": "#1976D2",
"--button-primary-text": "#FFFFFF",
"--button-primary-hover": "#1565C0",
"--button-secondary-border": "#1976D2",
"--button-secondary-text": "#1976D2",
"--button-secondary-hover": "#E3F2FD",
"--color-button-secondary-hover-text": "#1976D2",
"--button-height-s": "30px",
"--button-disabled-background": "#E0E0E0",
"--submit-button-fill-color": "#FFFFFF",
"--submit-button-fill-color-disabled": "#C6C6C6",
"--color-button-submit": "#1976D2",
"--color-button-submit-hover": "#1565C0",
"--cta-button-background-color": "#EDEDED",
"--cta-button-text-color": "#191F1C",
"--cta-button-icon-color": "#161313",
"--cta-button-border-radius": "99px",
"--cta-button-horizontal-padding": "16px",
"--cta-button-vertical-padding": "12px",
"--cta-button-font-size": "14px",
"--cta-button-font-weight": "400",
"--cta-button-icon-size": "16px",
"--disclaimer-color": "#757575",
"--disclaimer-font-size": "12px",
"--disclaimer-font-weight": "400",
"--input-background": "#FFFFFF",
"--input-outline-color": null,
"--input-outline-gradient-start-color": "#1976D2",
"--input-outline-gradient-end-color": "#4B75FF",
"--input-outline-gradient-angle": "90deg",
"--input-outline-width": "2px",
"--input-box-shadow": "0 2px 8px 0 #00000014",
"--input-focus-outline-width": "2px",
"--input-text-color": "#000000",
"--input-focus-outline-color": "#1976D2",
"--input-send-icon-color": "#000000",
"--input-send-arrow-icon-color": "#FFFFFF",
"--input-send-arrow-background-color": "#1976D2",
"--input-send-arrow-background-gradient-start-color": "#1976D2",
"--input-send-arrow-background-gradient-end-color": "#4B75FF",
"--input-send-arrow-background-gradient-angle": "135deg",
"--input-mic-icon-color": "#000000",
"--input-mic-icon-gradient-start-color": "#1976D2",
"--input-mic-icon-gradient-end-color": "#4B75FF",
"--input-mic-icon-gradient-angle": "135deg",
"--input-mic-recording-icon-color": "#FFFFFF",
"--input-mic-waveform-gradient-start-color": "#1976D2",
"--input-mic-waveform-gradient-end-color": "#4B75FF",
"--input-mic-waveform-gradient-angle": "180deg",
"--input-font-size": "16px",
"--input-button-height": "32px",
"--input-button-width": "32px",
"--input-button-border-radius": "8px",
"--input-send-icon-color": "#1976D2",
"--input-mic-icon-color": "#1976D2",
"--citations-text-font-weight": "700",
"--citations-desktop-button-font-size": "12px",
"--citations-background-color": "#E0E0E0",
"--citations-text-color": "#000000",
"--feedback-icon-btn-background": "#FFFFFF",
"--feedback-icon-btn-hover-background": "#F5F5F5",
"--feedback-icon-btn-size-desktop": "32px",
"--feedback-container-gap": "4px",
"--feedback-sheet-background-color": "#FFFFFF",
"--feedback-title-text-color": "#131313",
"--feedback-question-text-color": "#424242",
"--feedback-options-text-color": "#131313",
"--feedback-checkbox-border-color": "#131313",
"--feedback-drag-handle-color": "#CCCCCC",
"--feedback-submit-button-fill-color": "#EB1000",
"--feedback-submit-button-text-color": "#FFFFFF",
"--feedback-submit-button-border-radius": "10px",
"--feedback-submit-button-font-weight": "600",
"--feedback-cancel-button-fill-color": null,
"--feedback-cancel-button-text-color": "#EB1000",
"--feedback-cancel-button-border-color": "#EB1000",
"--feedback-cancel-button-border-width": "1px",
"--feedback-cancel-button-border-radius": "10px",
"--feedback-cancel-button-font-weight": "600",
"--feedback-checkbox-border-radius": "6px",
"--feedback-title-text-align": "start",
"--feedback-title-font-size": "22px",
"--multimodal-card-box-shadow": "none",
"--border-radius-card": "16px",
"--product-card-outline-color": "#E3E3E3",
"--product-card-width": "222px",
"--product-card-min-height": "240px",
"--product-card-max-height": "360px",
"--product-card-border-radius": "8px",
"--product-image-width": "190px",
"--product-image-height": "190px",
"--product-image-scale": "fill",
"--product-card-title-font-weight": "700",
"--product-card-title-font-size": "14px",
"--product-card-title-color": "#191F1C",
"--product-card-subtitle-font-weight": "400",
"--product-card-subtitle-font-size": "12px",
"--product-card-subtitle-color": "#4F4F4F",
"--product-card-price-font-weight": "400",
"--product-card-price-font-size": "14px",
"--product-card-price-color": "#191F1C",
"--product-card-badge-font-weight": "700",
"--product-card-badge-font-size": "12px",
"--product-card-badge-text-color": "#FFFFFF",
"--product-card-badge-background-color": "#1976D2",
"--product-card-background-color": "#FFFFFF",
"--product-card-was-price-color": "#6E6E6E",
"--product-card-was-price-font-size": "12px",
"--product-card-was-price-font-weight": "400",
"--product-card-was-price-text-prefix": "previously ",
"--product-card-text-horizontal-padding": "16px",
"--product-card-text-top-padding": "24px",
"--product-card-text-bottom-padding": "16px",
"--product-card-title-subtitle-spacing": "8px",
"--product-card-section-spacing": "16px",
"--product-card-price-spacing": "0px",
"--product-card-carousel-horizontal-padding": "16px",
"--product-card-carousel-spacing": "12px",
"--product-card-cta-button-background-color": "#BB5811",
"--product-card-cta-button-text-color": "#FFFFFF",
"--product-card-cta-button-border-radius": "40px",
"--product-card-cta-button-horizontal-padding": "16px",
"--product-card-cta-button-vertical-padding": "8px",
"--product-card-cta-button-font-size": "12px",
"--product-card-cta-button-font-weight": "600"
}
}
Implementation Status
This section documents which properties are fully implemented, partially implemented, or not yet implemented in the Android SDK based on actual usage in composables.
Legend
Note: The tables below include a "Used In" column showing which UI composables consume each theme property.
Implementation Summary
Overall Implementation Status:
- Colors: ~70% implemented (most core colors used, hover states not applicable)
- Typography: 60% implemented (
fontFamilynot yet supported) - Layout: ~15% implemented (only outline widths and font sizes currently used)
- Behavior: ~10% implemented (only
enableVoiceInputfunctional) - Text/Copy: ~50% implemented (main strings used;
*.ariaaccessibility-label keys andtext["header.*"]are not supported at all — see Header for the real title/subtitle keys)
Key Differences from Web/iOS:
- Hover states (
--button-primary-hover,--feedback-icon-btn-hover-background) are parsed but not applicable on Android - Box shadows are parsed but not currently rendered
- Most layout dimensions (padding, margins, border radius) are hardcoded rather than theme-driven
*.ariatext keys andbehavior.privacyNotice.*are not parsed by the Android SDK at all (not just unused) — omit them
Metadata
metadata.brandNamemetadata.versionmetadata.languagemetadata.namespaceHeader
header.title"Concierge" only when both title and subtitle are unsetChatHeaderheader.subtitle"Powered by Adobe" only when both title and subtitle are unsetChatHeaderheader.imagelayoutType is "imageOnly"; falls back to a default chat icon when unset/blank/unresolvableChatHeaderheader.layoutTypeChatHeaderheader.imageHeightChatHeaderBehavior
behavior.multimodalCarousel.cardClickActionbehavior.multimodalCarousel.carouselStyleProductCarouselbehavior.productCard.cardStyleRecommendationCards, ProductCarouselbehavior.productCard.cardsAlignment"start", "center", "end")RecommendationCardsbehavior.input.enableVoiceInputInputActionButtonsbehavior.input.sendButtonStyle"default" (paper airplane) or "arrow" (filled circle with upward arrow)SendButtonbehavior.input.disableMultilinetrueChatTextFieldbehavior.input.showAiChatIconChatInputPanelbehavior.input.enableMicPulseBackgroundMicButtonbehavior.input.stopRecordingIconInputActionButtonsbehavior.chat.messageAlignment"start" (default, full-width), "center", or "end" alignment for agent message bubblesChatMessageItembehavior.chat.messageWidthbehavior.chat.userMessageBubbleStyle"default" (all corners rounded) or "balloon" (square bottom-right corner)ChatMessageItembehavior.welcomeCard.closeButtonAlignment"start" or "end" close button positionChatHeaderbehavior.welcomeCard.promptFullWidthSuggestedPromptItembehavior.welcomeCard.promptMaxLinesSuggestedPromptItembehavior.welcomeCard.contentAlignment"top" or "center" vertical positionConciergeChatDisclaimer
disclaimer.textConciergeDisclaimerdisclaimer.linksConciergeDisclaimerText (Copy)
text["welcome.heading"]WelcomeCardtext["welcome.subheading"]WelcomeCardtext["input.placeholder"]ChatTextFieldtext["input.aiChatIcon.tooltip"]ChatInputPaneltext["error.network"]text["loading.message"]ConciergeThinkingtext["feedback.dialog.title.positive"]FeedbackDialogtext["feedback.dialog.title.negative"]FeedbackDialogtext["feedback.dialog.question.positive"]FeedbackDialogtext["feedback.dialog.question.negative"]FeedbackDialogtext["feedback.dialog.notes"]FeedbackDialogtext["feedback.dialog.submit"]FeedbackDialogtext["feedback.dialog.cancel"]FeedbackDialogtext["feedback.dialog.notes.placeholder"]FeedbackDialogtext["feedback.toast.success"]text["sourcesLabel"]ChatFooter → SourcesAccordionButtontext["feedbackHelpfulLabel"]below thumbs placement modeFeedbackButtonsBehavior — Feedback & Citations
behavior.feedback.displayModeFeedbackDialogbehavior.feedback.thumbsPlacementChatFooterbehavior.feedback.showCloseButtondisplayMode when nullFeedbackDialogbehavior.feedback.showCancelButtondisplayMode when nullFeedbackDialogbehavior.feedback.alwaysDisplayfeedbackEligible (not the streaming-complete requirement) once the response finishesChatFooterbehavior.citations.showLinkIconExpandedCitations → CitationItem; ConciergeResponse → LinkHintUiUtilsbehavior.citations.phoneIconkind: "phone"LinkHintUiUtilsbehavior.citations.storeIconkind: "store"LinkHintUiUtilsbehavior.citations.defaultLinkIconkindLinkHintUiUtilsbehavior.citations.linkIconStyleConciergeResponseArrays
arrays["welcome.examples"]WelcomeCard → PromptSuggestionsarrays["feedback.positive.options"]FeedbackDialogarrays["feedback.negative.options"]FeedbackDialogAssets
assets.icons.companyChatMessageItem (RenderTextMessageWithIcon, RenderMixedMessage)Theme Tokens - Typography
--font-family--line-height-bodyConciergeStyles.withThemeTypography--input-font-sizeChatTextField--citations-desktop-button-font-sizeCircularCitation--disclaimer-font-sizeConciergeDisclaimer (DisclaimerStyle)Theme Tokens - Colors
Note: The following base colors are not configurable via JSON themes. They are hardcoded in LightConciergeColors / DarkConciergeColors and serve as fallback colors throughout the UI:
secondary,onSurfaceVariant,outline,error,onError
These colors are used internally by composables but cannot be customized in theme JSON files. See "Fallback Colors" section at the end.
Note:
container(card/chip background) is now configurable via--color-container.
--thinking-dot-colorConciergeThinking--thinking-dot-sizeConciergeThinking--thinking-dot-spacingConciergeThinking--thinking-bubble-border-radiusChatMessageItem--thinking-bubble-padding-horizontalChatMessageItem--thinking-bubble-padding-verticalChatMessageItem--thinking-dot-vertical-alignmentConciergeThinking--color-primary--thinking-dot-color not set)--color-textmicButtonColor in parsed theme (mic icon uses --color-primary in UI)ChatHeader, WelcomeCard, prompt suggestions (when theme loaded)--color-container--suggestion-background-color is not setProductCard, PromptSuggestions, ChatInputPanel (fallback)--main-container-backgroundChatScreen, WelcomeCard, FeedbackDialog--main-container-bottom-background--message-blocker-background--message-user-backgroundChatMessageItem--message-user-textChatMessageItem--message-concierge-backgroundChatMessageItem--message-concierge-textChatMessageItem, FeedbackDialog, FeedbackButtons, PromptSuggestions, ExpandedCitations, ChatFooter, ProductCard text, ProductCarousel switcher color--message-concierge-link-colorExpandedCitations (citation URLs); message body links when applied--button-primary-backgroundProductActionButtons--button-primary-textProductActionButtons--button-primary-hover--button-secondary-borderProductActionButtons--button-secondary-textProductActionButtons--button-secondary-hover--color-button-secondary-hover-text--submit-button-fill-colorFeedbackDialog--submit-button-fill-color-disabled--color-button-submitFeedbackDialog, InputActionButtons--color-button-submit-hover--button-disabled-background--input-backgroundChatInputPanel--input-text-colorChatTextField, FeedbackDialog--input-outline-colorChatInputPanel--input-outline-gradient-start-color--input-outline-colorChatInputPanel--input-outline-gradient-end-colorChatInputPanel--input-outline-gradient-angleChatInputPanel--input-focus-outline-colorChatInputPanel--input-send-icon-colorSendButton--input-send-arrow-icon-colorSendButton--input-send-arrow-background-colorSendButton--input-send-arrow-background-gradient-start-colorSendButton--input-send-arrow-background-gradient-end-colorSendButton--input-send-arrow-background-gradient-angleSendButton--input-mic-icon-colorMicButton--input-mic-icon-gradient-start-colorMicButton--input-mic-icon-gradient-end-colorMicButton--input-mic-icon-gradient-angleMicButton--input-mic-recording-icon-colorMicButton, AnimatedAudioWave--input-mic-waveform-gradient-start-colorAnimatedAudioWave--input-mic-waveform-gradient-end-colorAnimatedAudioWave--input-mic-waveform-gradient-angleAnimatedAudioWave--welcome-prompt-background-colorSuggestedPromptItem--welcome-prompt-text-colorSuggestedPromptItem--suggestion-background-colorPromptSuggestions--suggestion-text-colorPromptSuggestions--citations-background-colorCircularCitation--citations-text-colorCircularCitation--feedback-icon-btn-backgroundFeedbackComponents--feedback-icon-btn-hover-background--feedback-sheet-background-colorFeedbackDialog--feedback-title-text-colorFeedbackDialog--feedback-question-text-colorFeedbackDialog--feedback-options-text-colorFeedbackDialog--feedback-checkbox-border-colorFeedbackDialog--feedback-drag-handle-colorFeedbackDialog--feedback-submit-button-fill-colorFeedbackDialog--feedback-submit-button-text-colorFeedbackDialog--feedback-cancel-button-fill-colorFeedbackDialog--feedback-cancel-button-text-colorFeedbackDialog--feedback-cancel-button-border-colorFeedbackDialog--disclaimer-colorConciergeDisclaimer (DisclaimerStyle)--cta-button-background-colorCtaButton--cta-button-text-colorCtaButton--cta-button-icon-colorCtaButton--product-card-outline-colorExtendedProductCard--product-card-background-colorExtendedProductCard--product-card-title-colorExtendedProductCard--product-card-subtitle-colorExtendedProductCard--product-card-price-colorExtendedProductCard--product-card-badge-text-colorExtendedProductCard--product-card-badge-background-colorExtendedProductCard--product-card-was-price-colorExtendedProductCard--product-card-cta-button-background-colorExtendedProductCard--product-card-cta-button-text-colorExtendedProductCardNote: The feedback dialog checkbox uses --color-primary for the check box filled color; the checkmark icon is white and is not configurable via theme.
Theme Tokens - Layout
--input-height-mobile--input-border-radius-mobileChatInputPanel--input-outline-widthChatInputPanel--input-focus-outline-widthChatInputPanel--input-font-sizeChatTextField--input-button-heightConciergeStyles.inputRowIconSize--input-button-widthConciergeStyles.inputRowIconSize--input-button-border-radius--input-box-shadow--message-border-radiusChatMessageItem--message-padding--message-max-width--agent-icon-sizeChatMessageItem (RenderTextMessageWithIcon)--agent-icon-spacingChatMessageItem (RenderTextMessageWithIcon)--chat-interface-max-width--chat-history-padding--chat-history-padding-top-expanded--chat-history-bottom-padding--message-blocker-height--border-radius-card--multimodal-card-box-shadowExtendedProductCard--product-card-widthExtendedProductCard, ProductCarousel--product-card-min-heightExtendedProductCard--product-card-max-heightExtendedProductCard--product-card-border-radiusExtendedProductCard--product-image-widthExtendedProductCard--product-image-heightExtendedProductCard--product-image-scale"fit" (uncropped) or "fill" (default, cropped)ExtendedProductCard--product-card-title-font-sizeExtendedProductCard--product-card-title-font-weightExtendedProductCard--product-card-subtitle-font-sizeExtendedProductCard--product-card-subtitle-font-weightExtendedProductCard--product-card-price-font-sizeExtendedProductCard--product-card-price-font-weightExtendedProductCard--product-card-badge-font-sizeExtendedProductCard--product-card-badge-font-weightExtendedProductCard--product-card-was-price-font-sizeExtendedProductCard--product-card-was-price-font-weightExtendedProductCard--product-card-was-price-text-prefixExtendedProductCard--product-card-text-horizontal-paddingExtendedProductCard--product-card-text-top-paddingExtendedProductCard--product-card-text-bottom-paddingExtendedProductCard--product-card-title-subtitle-spacingExtendedProductCard--product-card-section-spacingExtendedProductCard--product-card-price-spacingExtendedProductCard--product-card-text-spacing--product-card-carousel-horizontal-paddingProductCarousel--product-card-carousel-spacingProductCarousel--product-card-cta-button-border-radiusExtendedProductCard--product-card-cta-button-horizontal-paddingExtendedProductCard--product-card-cta-button-vertical-paddingExtendedProductCard--product-card-cta-button-font-sizeExtendedProductCard--product-card-cta-button-font-weightExtendedProductCard--button-height-s--cta-button-border-radiusCtaButton--cta-button-horizontal-paddingCtaButton--cta-button-vertical-paddingCtaButton--cta-button-font-sizeCtaButton--cta-button-font-weightCtaButton--cta-button-icon-sizeCtaButton--feedback-container-gap--feedback-icon-btn-size-desktop--feedback-submit-button-border-radiusFeedbackDialog--feedback-submit-button-font-weightFeedbackDialog--feedback-cancel-button-border-radiusFeedbackDialog--feedback-cancel-button-border-widthFeedbackDialog--feedback-cancel-button-font-weightFeedbackDialog--feedback-checkbox-border-radiusFeedbackDialog--feedback-title-text-alignFeedbackDialog--feedback-title-font-sizeFeedbackDialog--citations-text-font-weight--citations-desktop-button-font-sizeCircularCitation--disclaimer-font-sizeConciergeDisclaimer (DisclaimerStyle)--disclaimer-font-weightConciergeDisclaimer (DisclaimerStyle)--welcome-input-order--welcome-cards-order--header-title-font-sizeChatHeader--welcome-title-font-sizeWelcomeCard--welcome-text-alignWelcomeCard--welcome-content-paddingWelcomeCard--welcome-prompt-image-sizeSuggestedPromptItem--welcome-prompt-spacingWelcomeCard--welcome-title-bottom-spacingWelcomeCard--welcome-prompts-top-spacingWelcomeCard--welcome-prompt-paddingSuggestedPromptItem--welcome-prompt-corner-radiusSuggestedPromptItem--suggestion-item-border-radiusPromptSuggestionsUnsupported CSS Variables
The following CSS variables from web themes are not supported on Android (desktop-only properties like --input-height and --input-border-radius without -mobile suffix):
--input-height--input-height-mobile instead--input-border-radius--input-border-radius-mobile instead--message-alignmentbehavior.chat.messageAlignment instead--message-widthbehavior.chat.messageWidth insteadFallback Colors (Not Theme-Configurable)
The following colors from LightConciergeColors / DarkConciergeColors are hardcoded and cannot be customized via JSON themes. They serve as fallback colors throughout the UI:
secondaryonSurfaceVariantChatFooter, FeedbackDialog (unchecked checkboxes)container--color-containerProductCard, PromptSuggestions (fallback when --suggestion-background-color not set), ChatInputPanel (fallback)outlineChatFooter separator, ProductActionButtons (secondary button fallback), FeedbackDialog text field border, ProductCarousel nav buttonserrorErrorOverlay backgroundonErrorErrorOverlay message textonSurfaceVoiceRecordingPanel, FeedbackDialog, fallback for feedback buttonsNote: While these colors provide consistent fallback styling, they cannot be overridden in theme JSON files. If you need custom colors for these UI elements, use the theme-specific CSS variables that map to these elements (e.g., use --input-outline-color instead of relying on the outline fallback).
Recommendations for Theme Authors
What to Focus On
When creating themes for the Android SDK, focus on these actively used properties for the best results:
Essential Colors (Highest Impact):
--color-primary- Primary brand color (used for buttons, feedback checkbox checked state, mic button icon, thinking animation fallback)--color-text- Primary text color for main background (header, welcome card when theme loaded, prompt suggestions).--main-container-background- Main screen background color (welcome card, chat area, feedback dialog)--main-container-bottom-background- Bottom container background (input area)--message-user-background/--message-user-text- User message styling--message-concierge-background/--message-concierge-text- AI message styling, feedback dialog styling, feedback button icons, expanded citation text, chat footer (Sources label and icon)--message-concierge-link-color- Links in AI content and expanded citation URLs--button-primary-background/--button-primary-text- Primary buttons--button-secondary-border/--button-secondary-text- Secondary buttons--input-background/--input-text-color- Input field colors--input-outline-color/--input-focus-outline-color- Input borders--input-send-icon-color/--input-mic-icon-color- Send and mic button icon colors--input-send-arrow-icon-color/--input-send-arrow-background-color- Arrow send button colors (whensendButtonStyleis"arrow")--input-mic-recording-icon-color- Waveform animation color during voice recording--input-mic-waveform-gradient-start-color/--input-mic-waveform-gradient-end-color/--input-mic-waveform-gradient-angle- Optional gradient for the waveform bars (falls back to--input-mic-recording-icon-color)--input-outline-gradient-start-color/-end-color/-angle,--input-mic-icon-gradient-*,--input-send-arrow-background-gradient-*- Optional gradients for the input border, mic icon, and arrow send button circle (each overrides its solid-color counterpart when set — see Gradients)--submit-button-fill-color/--color-button-submit- Submit button--disclaimer-color/--disclaimer-font-size/--disclaimer-font-weight- Disclaimer text at bottom--citations-background-color/--citations-text-color- Citation pill (badge).--feedback-icon-btn-background- Feedback button styling
Essential Text/Copy:
header.title/header.subtitle- Header title and subtitle (root-levelheaderobject, nottext)text["welcome.heading"]- Welcome screen titletext["welcome.subheading"]- Welcome screen descriptiontext["input.placeholder"]- Input field hinttext["loading.message"]- Loading indicator text- All
text["feedback.dialog.*"]- Feedback dialog strings
Essential Behavior:
behavior.input.enableVoiceInput- Show/hide microphone buttonbehavior.input.sendButtonStyle-"default"(paper airplane) or"arrow"(filled circle with upward arrow)behavior.input.enableMicPulseBackground- Show/hide the pulsing colored disc behind the mic/waveform icon while recording (defaulttrue; setfalsefor a bare waveform)behavior.productCard.cardStyle- Use"productDetail"for extended product cards (image, badge, name, subtitle, price)behavior.productCard.cardsAlignment- Horizontal alignment of product cards:"start"(left),"center"(default), or"end"(right)behavior.multimodalCarousel.carouselStyle- Use"paged"for prev/next/dots or"scroll"for continuous scrollbehavior.welcomeCard.closeButtonAlignment- Close button position ("start"or"end")behavior.welcomeCard.promptFullWidth- Full-width cards vs compact pill chipsbehavior.welcomeCard.promptMaxLines- Max prompt text lines (set1for uniform pills)behavior.welcomeCard.contentAlignment- Welcome card vertical position ("top"or"center")
Essential Layout:
--input-outline-width/--input-focus-outline-width- Input border thickness--input-border-radius-mobile- Input field corner radius--input-font-size- Input text size--input-send-icon-color/--input-mic-icon-color- Input button icon colors--disclaimer-font-size- Disclaimer text size--citations-desktop-button-font-size- Citation text size--line-height-body- Text line spacing
Extended Product Cards (when behavior.productCard.cardStyle is "productDetail"):
--product-card-width/--product-card-min-height/--product-card-max-height- Card dimensions--product-card-title-*/--product-card-subtitle-*/--product-card-price-*- Text styling--product-card-badge-*- Badge styling--product-card-background-color/--product-card-outline-color- Card appearance--product-card-was-price-*- Strikethrough price styling
What Can Be Skipped
These properties are parsed but not currently used and can be omitted without affecting the UI:
- Hover states (all
*-hoverproperties) - Box shadows (all
*-box-shadowproperties) - Most layout dimensions (padding, margins, border radius) - currently hardcoded
- Disabled button states
- Accessibility labels (
*.ariatext keys are not parsed by the Android SDK at all) - Welcome screen ordering (
--welcome-input-order,--welcome-cards-order) - Font family (
--font-family- not yet implemented)
Testing Your Theme
- Test core flows: Create a theme, load it, send messages, provide feedback
- Check on multiple devices: Test on different screen sizes and Android versions
- Verify contrast ratios: Ensure text is readable on all backgrounds
- Test with and without a theme: With no theme loaded, the welcome card and prompts follow system light/dark (dark background + light text in dark mode). With a theme loaded, welcome example
backgroundColorand theme colors are applied - Test light/dark modes: If supporting both, verify colors work in both contexts