The style configuration provides comprehensive settings for customizing the appearance of Inkeep widgets. This includes theming, typography, spacing, and component-specific styles.
The theme configuration is defined through the UserTheme interface which extends Partial<IkpTheme>. This allows for deep customization of the widget's appearance.
import { type InkeepBaseSettings } from "@inkeep/cxkit-types" ;
const baseSettings : InkeepBaseSettings = {
theme : {
// Basic color customization
primaryColors : {
primary : "#26D6FF" ,
secondary : "#6366F1" ,
},
// Syntax highlighter themes
syntaxHighlighter : {
lightTheme : themes . github ,
darkTheme : themes . dracula ,
},
// Custom styles injection
styles : [
{
key : "google-fonts" ,
type : "link" ,
value :
"https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap" ,
},
{
key : "custom-theme" ,
type : "style" ,
value : `
.ikp-ai-chat-message {
border-radius: 8px;
padding: 12px;
}
[data-theme='dark'] .ikp-ai-chat-message {
background: #2D3748;
}
` ,
},
],
// CSS variables container class name
varsClassName : "ikp-variables" ,
// Disable loading the default font for the widgets
disableLoadingDefaultFont : true ,
},
};
The primaryColors property allows you to define the color variations used throughout the widget. It accepts the following color options:
primaryColors: {
textBold ?: string // Bold text color
textSubtle ?: string // Subtle text color
lighter ?: string // Lightest shade
light ?: string // Light shade
lightSubtle ?: string // Subtle light shade
medium ?: string // Medium shade
mediumSubtle ?: string // Subtle medium shade
strong ?: string // Strong shade
stronger ?: string // Stronger shade
textColorOnPrimary ?: string // Text color on primary background
}
All colors should be provided as valid CSS color values (hex, rgb, hsl, etc). Each property is optional, allowing you to customize only the specific color variations you need.
The syntaxHighlighter property lets you configure different themes for code blocks in light and dark modes.
By default, the Prism syntax highlighting theme we use is in light mode and in dark mode. To use a different theme, you can provide it in the theme.syntaxHighlighter prop.
syntaxHighlighter: {
lightTheme: themes . github , // Theme for light mode
darkTheme: themes . dracula // Theme for dark mode
}
You can use published Prism themes or .
The styles property allows injection of custom styles through two methods:
External Resources (type: 'link'):
{
key: 'google-fonts' ,
type: 'link' ,
value: 'https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap'
}
Inline CSS (type: 'style'):
{
key: 'custom-theme' ,
type: 'style' ,
value: `
.ikp-ai-chat-message {
border-radius: 8px;
padding: 12px;
}
`
}
Each style entry requires:
key: A unique identifier to prevent duplicates and enable updates
type: Either 'link' for external resources or 'style' for inline CSS
value: The style content (URL for links or CSS code for styles)
The varsClassName property specifies the class name for the container that holds CSS variables:
varsClassName: "ikp-variables" ; // Default value
This class is added to a wrapper div that provides theming context.
The color mode configuration allows you to control how the widget handles light and dark modes. This is configured through the colorMode property in the base settings:
const baseSettings : InkeepBaseSettings = {
colorMode : {
// Force a specific color mode
forcedColorMode?: string ,
// Enable system color mode detection
enableSystem?: boolean ,
// Sync with external element
sync?: {
// Element to watch for color mode changes
target : HTMLElement | string ,
// Attributes to monitor
attributes : string [],
// Function to determine dark mode
isDarkMode : ( attributes : Record < string , string | null >) => boolean ,
// Optional callback for color mode changes
onChange?: ( colorMode : string ) => void
}
}
}
Use forcedColorMode to explicitly set the color mode for the current page:
colorMode: {
forcedColorMode: "dark" ; // Forces dark mode
}
Enable enableSystem to automatically switch between dark and light modes based on the user's system preferences:
colorMode: {
enableSystem: true ; // Follows system preference
}
The sync property allows you to synchronize the widget's color mode with your application's theme:
colorMode: {
sync: {
// Watch the document root for theme changes
target: document . documentElement ,
// Monitor the data-theme attribute
attributes: [ 'data-theme' ],
// Determine dark mode based on attribute value
isDarkMode: ( attrs ) => attrs [ 'data-theme' ] === 'dark' ,
// Optional: Handle color mode changes
onChange: ( mode ) => console . log ( `Color mode changed to: ${ mode } ` )
}
}
Common sync configurations:
Data Attribute Sync :
{
target: document . documentElement ,
attributes: [ 'data-theme' ],
isDarkMode: ( attrs ) => attrs [ 'data-theme' ] === 'dark'
}
Class-based Sync :
{
target: document . documentElement ,
attributes: [ 'class' ],
isDarkMode: ( attrs ) => attrs [ 'class' ]?. includes ( 'dark-mode' )
}
Inkeep provides a set of CSS variables that you can use to customize the widget's appearance. These variables are prefixed with --ikp- and are available within the scope of the widget.
You can use Inkeep CSS variables within your stylesheets to customize elements. For example:
.ikp-chat-button__button {
background : var ( --ikp-colors-inkeep-primary-medium );
}
To apply specific styles for dark mode, use the [data-theme='dark'] attribute selector:
[ data-theme = "dark" ] .ikp-chat-button__button {
background : #353e52 ;
}
The AI assistant avatar can be customized through the aiChatSettings using the aiAssistantAvatar property:
it's either a string URL or an object to specify light and dark mode avatars:
aiAssistantAvatar: {
light: string ;
dark ?: string ;
}
The user avatar can be customized using the userAvatar property in the aiChatSettings.
import { type InkeepAIChatSettings } from "@inkeep/cxkit-react" ;
export const aiChatSettings : InkeepAIChatSettings = {
aiAssistantAvatar : "http://example.com/assistant-avatar.png" ,
userAvatar : "http://example.com/user-avatar.png" ,
// ...rest of aiChatSettings
};
You can customize various icons throughout the widget by providing a customIcons dictionary in the baseSettings. Each icon can be either a built-in icon or a custom SVG/image.
Icon Name Description search Search icon in search bar thumbsUp Thumbs up icon thumbsDown Thumbs down icon messageCopy Copy message icon codeCopy Copy code icon in code header openLinkInNewTab Used on hover in chat citations and search results (when shouldOpenLinksInNewTab is true) openLinkInSameTab Used on hover in chat citations and search results (when shouldOpenLinksInNewTab is false) breadcrumbSeparator Breadcrumb separator icon switchToSearch Switch to search icon switchToChat Switch to chat icon chatSubmit Chat submit icon close Close icon info Info icon next to the disclaimer and chat mode toggle command Command icon in search bar
import { type InkeepBaseSettings } from "@inkeep/cxkit-react" ;
export const baseSettings : InkeepBaseSettings = {
customIcons : {
// Using a built-in icon
search : {
builtIn : "IoSearch" ,
},
// Using custom SVG/image URLs
thumbsUp : {
custom : "/path/to/thumbs-up.svg" ,
},
thumbsDown : {
custom : "/path/to/thumbs-down.svg" ,
},
messageCopy : {
custom : "/path/to/message-copy.svg" ,
},
codeCopy : {
custom : "/path/to/code-copy.svg" ,
},
openLinkInNewTab : {
custom : "path/to/open-link-in-new-tab.svg" ,
},
openLinkInSameTab : {
custom : "path/to/open-link-in-same-tab.svg" ,
},
breadcrumbSeparator : {
custom : "path/to/breadcrumb-separator.svg" ,
},
switchToSearch : {
custom : "/path/to/switch-to-search.svg" ,
},
switchToChat : {
custom : "/path/to/switch-to-chat.svg" ,
},
chatSubmit : {
custom : "/path/to/chat-submit.svg" ,
},
close : {
custom : "/path/to/close.svg" ,
},
info : {
custom : "/path/to/info.svg" ,
},
command : {
custom : "/path/to/command.svg" ,
},
},
// ...rest of baseSettings
};
If the url for a custom icon is a .svg file it will be rendered as an <svg>, all other file types will be rendered using an <img> tag.
The default theme includes these core settings:
fontFamily: {
heading: "'Space Grotesk', system-ui, sans-serif" ,
body: "'Inter', system-ui, sans-serif" ,
mono: "'Fira Code', monospace" ,
},
fontSize: {
'3xs' : '0.45rem' ,
'2xs' : '0.625rem' ,
xs: '0.75rem' ,
sm: '0.875rem' ,
md: '1rem' ,
lg: '1.125rem' ,
xl: '1.25rem' ,
'2xl' : '1.5rem' ,
'3xl' : '1.875rem' ,
'4xl' : '2.25rem' ,
'5xl' : '3rem' ,
'6xl' : '3.75rem' ,
'7xl' : '4.5rem' ,
'8xl' : '6rem' ,
'9xl' : '8rem' ,
}
zIndex: {
hide: - 1 ,
auto: 'auto' ,
base: 0 ,
docked: 10 ,
dropdown: 1000 ,
sticky: 1100 ,
banner: 1200 ,
overlay: 1300 ,
modal: 1400 ,
popover: 1500 ,
skipLink: 1600 ,
toast: 1700 ,
tooltip: 1800 ,
}
All component class names are prefixed with ikp-. Here's the complete list of available class names:
ikp-ai-chat-wrapper
ikp-ai-chat-root
ikp-ai-chat-header
ikp-ai-chat-header__toolbar
ikp-ai-chat-header__toolbar-header
ikp-ai-chat-header__toolbar-header-wrapper
ikp-ai-chat-content
ikp-ai-chat-content-scroll-area
ikp-ai-chat-content-scroll-area__viewport
ikp-ai-chat-content-scroll-area__scrollbar
ikp-ai-chat-content-scroll-area__thumb
ikp-ai-chat-content-scroll-area__corner
ikp-ai-chat-disclaimer
ikp-ai-chat-disclaimer-label
ikp-ai-chat-disclaimer-trigger
ikp-ai-chat-disclaimer-content
ikp-ai-chat-disclaimer-text
ikp-ai-chat-disclaimer-arrow
ikp-ai-chat-example-questions
ikp-ai-chat-example-questions-label
ikp-ai-chat-example-questions-list
ikp-ai-chat-example-question
ikp-ai-chat-example-question-button
ikp-ai-chat-workflows
ikp-ai-chat-workflows-label
ikp-ai-chat-workflows-list
ikp-ai-chat-workflow
ikp-ai-chat-workflow__icon
ikp-ai-chat-messages
ikp-ai-chat-message-wrapper
ikp-ai-chat-message-header
ikp-ai-chat-message-loading
ikp-ai-chat-message-avatar
ikp-ai-chat-message-avatar-fallback
ikp-ai-chat-message-avatar-image
ikp-ai-chat-message-avatar-content
ikp-ai-chat-message-name
ikp-ai-chat-message-content-wrapper
ikp-ai-chat-message-content
ikp-ai-chat-message-attachments
ikp-ai-chat-message-attachments__list
ikp-ai-chat-message-attachments__item
ikp-ai-chat-message-attachments__item-icon
ikp-ai-chat-message-attachments__item-title
ikp-ai-chat-message-attachments-preview
ikp-ai-chat-message-attachments-preview__overlay
ikp-ai-chat-message-attachments-preview__content
ikp-ai-chat-message-attachments-preview__header
ikp-ai-chat-message-attachments-preview__close
ikp-ai-chat-message-attachments-preview__body
ikp-ai-chat-message-part
ikp-ai-chat-message-toolbar
ikp-ai-chat-message-annotation-actions
ikp-ai-chat-message-annotation-action
ikp-ai-chat-message-action
ikp-ai-chat-message-sources
ikp-ai-chat-message-sources__header
ikp-ai-chat-message-sources__list
ikp-ai-chat-message-source-item
ikp-ai-chat-message-source-item__icon
ikp-ai-chat-message-source-item__breadcrumbs
ikp-ai-chat-message-source-item__breadcrumb
ikp-ai-chat-message-source-item__breadcrumb-icon
ikp-ai-chat-message-source-item__title
ikp-ai-chat-message-source-item__tag
ikp-ai-chat-message-source-item__description
ikp-ai-chat-message-source-item__description-part
ikp-ai-chat-message-source-item__indicator
ikp-ai-chat-footer
ikp-ai-chat-input__fieldset
ikp-ai-chat-input__group
ikp-ai-chat-input
ikp-ai-chat-input__send-button
ikp-ai-chat-input__send-button-icon
ikp-ai-chat-attachments-bar
ikp-ai-chat-attachments-bar__list
ikp-ai-chat-attachments-bar__attachment
ikp-ai-chat-attachments-bar__attachment-icon
ikp-ai-chat-attachments-bar__attachment-title
ikp-ai-chat-attachments-bar__attachment-delete
ikp-ai-chat-attachments-bar__actions
ikp-ai-chat-attachments-bar__info-tip
ikp-ai-chat-attachments-bar__info-tip-icon
ikp-ai-chat-attachments-bar__info-tip-arrow
ikp-ai-chat-attachments-bar__info-tip-text
ikp-ai-chat-attachments-bar__inputs
ikp-ai-chat-attachments-bar__input
ikp-ai-chat-attachments-bar__input-icon
ikp-ai-chat-attachments-bar__modal
ikp-ai-chat-attachments-bar__modal-overlay
ikp-ai-chat-attachments-bar__modal-content
ikp-ai-chat-attachments-bar__modal-header
ikp-ai-chat-attachments-bar__modal-close
ikp-ai-chat-attachments-bar__modal-body
ikp-ai-chat-attachments-bar__modal-heading
ikp-ai-chat-attachments-bar__modal-description
ikp-ai-chat-attachments-bar__modal-help
ikp-ai-chat-attachments-bar__form
ikp-ai-chat-attachments-bar__form-title
ikp-ai-chat-attachments-bar__form-title-label
ikp-ai-chat-attachments-bar__form-title-input
ikp-ai-chat-attachments-bar__form-title-error
ikp-ai-chat-attachments-bar__form-content
ikp-ai-chat-attachments-bar__form-content-label
ikp-ai-chat-attachments-bar__form-content-input
ikp-ai-chat-attachments-bar__form-content-error
ikp-ai-chat-attachments-bar__form-submit-button
ikp-ai-chat-action-bar
ikp-ai-chat__chat-actions
ikp-ai-chat__chat-action
ikp-ai-chat__chat-action-label
ikp-ai-chat__chat-action-feeback
ikp-ai-chat-help-actions
ikp-ai-chat-help-action
ikp-ai-chat-help-actions__trigger
ikp-ai-chat-help-actions__menu
ikp-ai-chat-help-actions__menu-arrow
ikp-ai-chat-help-actions__menu-item
ikp-ai-chat-help-actions_menu-item-icon
ikp-ai-chat-tagline__container
ikp-ai-chat-tagline__text
ikp-ai-chat-tagline__logo
ikp-ai-chat-tagline__brand-name
ikp-ai-chat-feedback-modal
ikp-ai-chat-feedback-modal__overlay
ikp-ai-chat-feedback-modal__content
ikp-ai-chat-feedback-modal__header
ikp-ai-chat-feedback-modal__close
ikp-ai-chat-feedback-modal__body
ikp-ai-chat-feedback-form
ikp-ai-chat-feedback-item
ikp-ai-chat-feedback-item__checkbox
ikp-ai-chat-feedback-item__checkbox-indicator
ikp-ai-chat-feedback-item__label
ikp-ai-chat-feedback-item__description
ikp-ai-chat-feedback-form__submit-button
ikp-ai-chat-form__wrapper
ikp-ai-chat-form
ikp-ai-chat-form__close
ikp-ai-chat-form__header
ikp-ai-chat-form__heading
ikp-ai-chat-form__description
ikp-ai-chat-form__content
ikp-ai-chat-form__field
ikp-ai-chat-form__field-label
ikp-ai-chat-form__field-text
ikp-ai-chat-form__field-email
ikp-ai-chat-form__field-file
ikp-ai-chat-form__field-text-area
ikp-ai-chat-form__field-checkbox
ikp-ai-chat-form__field-checkbox-indicator
ikp-ai-chat-form__field-select
ikp-ai-chat-form__field-select__trigger
ikp-ai-chat-form__field-select__value
ikp-ai-chat-form__field-select__icon
ikp-ai-chat-form__field-select__content
ikp-ai-chat-form__field-select__viewport
ikp-ai-chat-form__field-select__item
ikp-ai-chat-form__field-select__item-indicator
ikp-ai-chat-form__field-select__item-text
ikp-ai-chat-form__field-error
ikp-ai-chat-form__error
ikp-ai-chat-form__footer
ikp-ai-chat-form__cancel
ikp-ai-chat-form__submit
ikp-ai-chat-form__success
ikp-ai-chat-form__success-heading
ikp-ai-chat-form__success-message
ikp-ai-chat-form__success-button
ikp-ai-chat-link ikp-codeblock-container
ikp-codeblock-header
ikp-codeblock-header-language
ikp-codeblock-copy-button
ikp-codeblock-highlighter-wrapper
ikp-codeblock-highlighter
ikp-codeblock-code
ikp-markdown-h1
ikp-markdown-h2
ikp-markdown-p
ikp-markdown-li
ikp-markdown-ul
ikp-markdown-ol
ikp-markdown-link
ikp-markdown-source-link
ikp-markdown-table
ikp-markdown-th
ikp-markdown-td
ikp-markdown-code
ikp-markdown-input
ikp-markdown-sup
ikp-markdown-img
ikp-markdown-hr ikp-search-bar__container
ikp-search-bar__button
ikp-search-bar__content-wrapper
ikp-search-bar__text
ikp-search-bar__icon
ikp-search-bar__kbd-wrapper
ikp-search-bar__cmd-icon
ikp-search-bar__ctrl
ikp-search-bar__kbd-shortcut-key ikp-modal
ikp-modal__overlay
ikp-modal__content
ikp-modal__close ikp-chat-button__text
ikp-chat-button__button
ikp-chat-button__container
ikp-chat-button__avatar-image
ikp-chat-button__avatar-content ikp-icon
ikp-loading-indicator__text
ikp-loading-indicator__dots
ikp-loading-indicator__dot
ikp-view_toggle
ikp-view_toggle_button
ikp-view_toggle_icon