Skip to main content

Focus Chat Element

The <focus-chat> custom element is the main component for embedding AI chat functionality into your web pages.

Element Definition

<focus-chat 
agent_card_url="https://agent.example.com/card.json"
config='{"greeting": "Hello!"}'
>
</focus-chat>

Attributes

agent_card_url (Required)

Type: String
Purpose: URL to the agent card JSON configuration file

The agent card defines your AI assistant's profile, capabilities, and endpoint information.

Example:

<focus-chat agent_card_url="https://api.example.com/agent-card.json">

Requirements:

  • Must be a valid HTTPS URL
  • Must return valid JSON
  • Must include proper CORS headers

config (Optional)

Type: String (JSON) or CSS Selector
Purpose: Configuration parameters for the chat widget
Default: {}

JSON String Format

<focus-chat 
agent_card_url="..."
config='{"greeting": "Hello!", "title": "Inhotel Chat Assistant"}'
>

Script Reference Format

<script id="chat-config" type="application/json">
{"greeting": "Hello from script!", "title": "Inhotel Chat Assistant"}
</script>

<focus-chat
agent_card_url="..."
config="#chat-config"
>

Element Lifecycle

1. Registration

The custom element is automatically registered when the Focus Chat script loads:

customElements.define('focus-chat', FocusChatElement);

2. Initialization

When the element is added to the DOM:

  1. Attribute Parsing: Reads agent_card_url and config attributes
  2. Shadow DOM Creation: Creates isolated DOM tree
  3. Agent Card Loading: Fetches agent configuration
  4. UI Rendering: Builds chat interface
  5. Event Binding: Attaches interaction handlers

3. Ready State

Element is ready when:

  • Agent card successfully loaded
  • UI components rendered
  • Event listeners attached

DOM Structure

The element creates a Shadow DOM with this structure:

<focus-chat>
#shadow-root
<div class="ih-container">
<div class="ih-trigger">
<!-- Floating chat trigger button -->
</div>
<div class="ih-popup" style="display: none;">
<div class="ih-header">
<!-- Title, avatar, and close button -->
</div>
<div class="ih-body">
<!-- Message list, system messages, streaming responses -->
</div>
<div class="ih-input">
<!-- Textarea, send button -->
</div>
</div>
</div>
</focus-chat>

CSS Styling

Shadow DOM Isolation

The widget uses Shadow DOM for complete style isolation. External CSS cannot affect the widget's appearance.

Configuration-Based Styling

All styling is controlled through configuration parameters:

<focus-chat 
config='{
"header_background_color": "#3b82f6",
"font_family": "Inter, sans-serif"
}'
>

CSS Custom Properties

The widget supports CSS variables for dynamic theming:

<style>
:root {
--ih-header-bg: #3b82f6;
--ih-user-message-bg: #f0f0f0;
--ih-assistant-message-bg: #ffffff;
--ih-font-family: "Inter", sans-serif;
}
</style>


<focus-chat
config='{"header_background_color": "var(--brand-color)"}'
>

JavaScript API

Element Properties

agentCardUrl

Get/set the agent card URL:

const widget = document.querySelector('focus-chat');
console.log(widget.agentCardUrl);
widget.agentCardUrl = 'https://new-agent.example.com/card.json';

config

Get/set the configuration:

const widget = document.querySelector('focus-chat');
console.log(widget.config);
widget.config = {"greeting": "New greeting!"};

Element Methods

reload()

Reload the widget with current configuration:

const widget = document.querySelector('focus-chat');
widget.reload();

openChat()

Programmatically open the chat popup:

const widget = document.querySelector('focus-chat');
widget.openChat();

closeChat()

Programmatically close the chat popup:

const widget = document.querySelector('focus-chat');
widget.closeChat();

sendMessage(message)

Send a message programmatically:

const widget = document.querySelector('focus-chat');
widget.sendMessage('Hello from JavaScript!');

Error Handling

Common Error Types

  1. Agent Card Loading Failed

    {
    type: 'agent-card-error',
    message: 'Failed to load agent card',
    url: 'https://agent.example.com/card.json'
    }
  2. Configuration Error

    {
    type: 'config-error',
    message: 'Invalid JSON configuration',
    config: '{"invalid": json}'
    }
  3. Network Error

    {
    type: 'network-error',
    message: 'Failed to send message',
    endpoint: 'https://api.example.com/chat'
    }

Browser Compatibility

Supported Browsers

  • Chrome 54+: Full support
  • Firefox 63+: Full support
  • Safari 10.1+: Full support
  • Edge 79+: Full support

Polyfill Requirements

For older browsers, include Web Components polyfills:

<script src="https://unpkg.com/@webcomponents/webcomponentsjs@2/webcomponents-loader.js"></script>
<script src="https://embed.agents.inhotel.io/focus-chat/latest/focus-chat.min.js"></script>

Feature Detection

Check for custom element support:

if ('customElements' in window) {
// Focus Chat supported
console.log('Custom elements supported');
} else {
// Provide fallback
console.log('Custom elements not supported');
}

Performance Characteristics

Loading Performance

  • Script Size: ~50KB minified
  • Initialization: <100ms typical
  • Memory Usage: ~2MB baseline

Runtime Performance

  • Message Rendering: <16ms per message
  • Streaming Updates: 60fps smooth
  • Memory Growth: Minimal with history limits

Advanced Usage

Multiple Instances

Multiple widgets on the same page:

<!-- Product support -->
<focus-chat
agent_card_url="https://product.example.com/agent.json"
config='{"source_context": ".product-info"}'
>
</focus-chat>

<!-- General support -->
<focus-chat
agent_card_url="https://support.example.com/agent.json"
config='{"source_context": ".help-section"}'
>
</focus-chat>

Dynamic Configuration

Update configuration at runtime:

const widget = document.querySelector('focus-chat');
const newConfig = {
greeting: 'Updated greeting!',
header_background_color: '#10b981'
};
widget.config = JSON.stringify(newConfig);
widget.reload();

Next Steps