Web Components for AI Chat Interfaces
A framework-agnostic UI kit of 35 production-ready components for building AI and LLM chat interfaces. Built with Lit 3.x, TypeScript strict mode, and Shadow DOM encapsulation.
Every team building an AI product ends up implementing the same chat UI from scratch: message bubbles, streaming indicators, file uploads, model selectors, feedback buttons, parameter panels. It takes weeks of work, and the result is rarely accessible or themeable.
Loquix provides a complete set of composable Web Components that cover the entire AI chat experience. Drop in a <loquix-chat-container> with a message list, composer, and header â and you have a full-featured chat UI with streaming support, file attachments, inline editing, and user feedback out of the box.
Because these are standard Web Components, they work with any framework â or no framework at all.
The component library is the foundation. The long-term vision is a full ecosystem for building AI agents: additional theme packs, first-class bindings for React/Vue/Svelte/Angular, backend integrations with popular AI providers, and ready-made agent templates that combine all of these into deployable starting points.
npm install @loquix/core litImport the CSS variables and the components you need. Each define/* import auto-registers the custom element:
import '@loquix/core/tokens/variables.css';
import '@loquix/core/define/define-chat-container';
import '@loquix/core/define/define-chat-header';
import '@loquix/core/define/define-message-list';
import '@loquix/core/define/define-message-item';
import '@loquix/core/define/define-message-content';
import '@loquix/core/define/define-chat-composer';<loquix-chat-container layout="full">
<loquix-chat-header slot="header" agent-name="My Assistant"></loquix-chat-header>
<loquix-message-list slot="messages">
<loquix-message-item role="assistant" status="complete">
<loquix-message-content>Hello! How can I help you?</loquix-message-content>
</loquix-message-item>
</loquix-message-list>
<loquix-chat-composer slot="composer" placeholder="Type a message..."></loquix-chat-composer>
</loquix-chat-container>document.addEventListener('loquix-submit', e => {
console.log('User sent:', e.detail.content);
});Apply a built-in theme or customize with CSS custom properties:
@import '@loquix/core/tokens/themes/dark.css';
:root {
--loquix-message-assistant-bg: #1e293b;
--loquix-message-user-bg: #3b82f6;
--loquix-input-border-radius: 12px;
}For quick prototyping without a bundler:
<link rel="stylesheet" href="https://unpkg.com/@loquix/core/src/tokens/variables.css" />
<script src="https://unpkg.com/@loquix/core/cdn/loquix.min.js"></script>If you need the class without auto-registration (e.g., for subclassing):
import { LoquixChatContainer } from '@loquix/core/classes/loquix-chat-container';The best way to explore all components, their properties, and variants is through Storybook:
pnpm storybookEvery component has interactive stories with controls for live property editing, slot composition examples, and accessibility checks built in.
Handle a streaming AI response with a typing indicator and stop button:
import '@loquix/core/define/define-message-item';
import '@loquix/core/define/define-message-content';
import '@loquix/core/define/define-typing-indicator';
import '@loquix/core/define/define-generation-controls';
const messageList = document.querySelector('loquix-message-list');
const composer = document.querySelector('loquix-chat-composer');
document.addEventListener('loquix-submit', async e => {
const content = e.detail.content;
// Add user message (use textContent to avoid XSS)
const userMsg = document.createElement('loquix-message-item');
userMsg.setAttribute('role', 'user');
userMsg.setAttribute('status', 'complete');
const userContent = document.createElement('loquix-message-content');
userContent.textContent = content;
userMsg.appendChild(userContent);
messageList.appendChild(userMsg);
// Add streaming assistant message
const assistantMsg = document.createElement('loquix-message-item');
assistantMsg.setAttribute('role', 'assistant');
assistantMsg.setAttribute('status', 'streaming');
const assistantContent = document.createElement('loquix-message-content');
assistantContent.setAttribute('streaming-cursor', 'caret');
assistantMsg.appendChild(assistantContent);
messageList.appendChild(assistantMsg);
// Set composer to streaming state (shows generation controls)
composer.setAttribute('streaming', '');
// Stream the response
const response = await fetch('/api/chat', { method: 'POST', body: JSON.stringify({ content }) });
const reader = response.body.getReader();
const decoder = new TextDecoder();
while (true) {
const { done, value } = await reader.read();
if (done) break;
assistantContent.textContent += decoder.decode(value);
}
// Finalize
assistantContent.removeAttribute('streaming-cursor');
assistantMsg.setAttribute('status', 'complete');
composer.removeAttribute('streaming');
});
// Handle stop
document.addEventListener('loquix-stop', () => {
// Abort the stream, mark message as complete
});Add file attachments with drag-and-drop and paste support (drag-and-drop is handled by the composer):
<loquix-chat-composer slot="composer" placeholder="Type a message...">
<loquix-attachment-panel
slot="toolbar-top"
accepted-types="image/*,.pdf,.txt"
max-size="10485760"
max-files="5"
></loquix-attachment-panel>
</loquix-chat-composer>import '@loquix/core/define/define-attachment-panel';
import '@loquix/core/define/define-attachment-chip';
import '@loquix/core/define/define-message-attachments';
const panel = document.querySelector('loquix-attachment-panel');
// Track files added via button or paste
document.addEventListener('loquix-attachment-add', e => {
console.log('Files attached:', e.detail.attachments);
});
// loquix-submit emits content only; read attachments from the panel
document.addEventListener('loquix-submit', e => {
const content = e.detail.content;
const attachments = panel.attachments; // current file list
// Send content + attachments to your backend
});Let users choose between AI models and operating modes:
<loquix-chat-header slot="header" agent-name="My Assistant">
<loquix-model-selector slot="controls" value="gpt-4o"></loquix-model-selector>
<loquix-mode-selector slot="mode-switcher" variant="tabs" value="chat"></loquix-mode-selector>
</loquix-chat-header>import '@loquix/core/define/define-model-selector';
import '@loquix/core/define/define-mode-selector';
const modelSelector = document.querySelector('loquix-model-selector');
modelSelector.models = [
{ value: 'gpt-4o', label: 'GPT-4o', tier: 'flagship', cost: '$5/1M tokens' },
{ value: 'claude-sonnet', label: 'Claude Sonnet', tier: 'balanced', cost: '$3/1M tokens' },
{ value: 'gpt-4o-mini', label: 'GPT-4o Mini', tier: 'fast', cost: '$0.15/1M tokens' },
];
const modeSelector = document.querySelector('loquix-mode-selector');
modeSelector.modes = [
{ value: 'chat', label: 'Chat', description: 'Free conversation' },
{ value: 'research', label: 'Research', description: 'Deep analysis with citations' },
{ value: 'code', label: 'Code', description: 'Programming assistant' },
];
document.addEventListener('loquix-model-change', e => {
console.log('Model switched to:', e.detail.to);
});
document.addEventListener('loquix-mode-change', e => {
console.log('Mode switched to:', e.detail.to);
});From message bubbles and avatars to model selectors and parameter tuning panels. Every component you need for a modern AI chat interface, designed to work together or independently.
Built for real-time AI responses. Streaming cursor variants (caret, block), animated typing indicators (dots, text, steps), and generation controls (stop, pause, resume) are first-class citizens, not afterthoughts.
Complete file handling pipeline: drag-and-drop upload zones, progress tracking with status indicators, paste-to-upload from clipboard, MIME type validation, file size limits, and image previews with URL sanitization.
Over 100 CSS custom properties (--loquix-*) for colors, spacing, typography, and component-specific tokens. Every component exposes ::part() selectors for deep styling. Ships with light and dark themes.
All interactions emit typed, bubbling custom events that cross Shadow DOM boundaries (composed: true). Listen for loquix-submit, loquix-feedback, loquix-model-change, loquix-attachment-add, and more at any level of your application.
Standard Web Components (Custom Elements v1) that work everywhere: vanilla JavaScript, React, Vue, Svelte, Angular, or any other framework. No adapters required â just HTML tags.
Pluggable localization system via LocalizeController. Built-in English defaults with support for custom translation providers. Every user-facing string uses translatable term keys.
Strict mode throughout. Full type definitions for all components, events, controllers, and data interfaces. IntelliSense and compile-time checks work out of the box.
| Category | Components |
|---|---|
| Chat Layout | chat-container chat-header chat-composer composer-toolbar message-list |
| Messages | message-item message-content message-avatar message-actions message-attachments |
| Actions | action-button action-copy action-edit action-feedback |
| Input & Selection | prompt-input dropdown-select suggestion-chips follow-up-suggestions example-gallery |
| AI Controls | generation-controls typing-indicator mode-selector model-selector parameter-panel |
| File Handling | attachment-panel attachment-chip drop-zone |
| Navigation & UI | scroll-anchor nudge-banner caveat-notice disclosure-badge filter-bar |
| Templates | template-card template-picker welcome-screen |
All components use the loquix- prefix (e.g., <loquix-chat-container>).
Loquix targets WCAG 2.1 Level AA compliance. Every component is checked against axe-core rules via the @storybook/addon-a11y integration.
Keyboard Navigation â Full keyboard support in every interactive component. Tab between elements, arrow keys for lists and dropdowns, Enter/Space for activation, Escape to dismiss.
ARIA Semantics â Proper use of aria-label, aria-pressed, aria-expanded, aria-selected, and semantic roles (toolbar, listbox, status, note, banner) throughout.
Focus Management â Native <dialog> for modals with built-in focus trapping. Auto-focus on search inputs when dropdowns open.
Screen Reader Support â Semantic HTML structure with appropriate heading hierarchy, live regions for streaming content updates, and meaningful labels for all interactive controls.
Contributions are welcome. Here's how to get started:
git clone https://github.com/loquix-dev/loquix.git
cd loquix
pnpm install
pnpm storybook # develop with live preview
pnpm test # run tests (Chromium + WebKit)
pnpm build # build the libraryProject structure:
packages/core/src/components/core/â components (loquix-*.ts,*.styles.ts,*.test.ts)packages/core/src/controllers/â shared controllers (keyboard, resize, autoscroll)packages/core/src/events/â typed event definitionspackages/core/src/tokens/â CSS custom properties and themesdocs/â Storybook stories and documentation
Conventions:
- Each component is a single
loquix-*.tsfile with a separate.styles.tsand.test.ts - Registration happens in
define-*.tsfiles withcustomElements.get()guard - Events use
loquix-prefix,bubbles: true,composed: true - CSS variables use
--loquix-prefix - All tests must pass on both Chromium and WebKit before merging
Development is organized into phases, from core chat primitives to advanced AI interaction patterns.
-
chat-containerâ layout shell (full, panel, floating, inline) -
chat-headerâ agent identity, controls, mode switcher slots -
message-listâ scrollable message container with auto-scroll -
message-itemâ message unit (user, assistant, system, tool roles) -
message-contentâ markdown, code blocks, streaming cursor -
message-avatarâ icon, image, initials, animated variants -
message-actionsâ hover/focus action toolbar (copy, edit, feedback) -
chat-composerâ input area with slots for toolbars, suggestions, controls -
prompt-inputâ textarea with auto-resize, submit-on-enter -
generation-controlsâ stop, pause, resume, skip buttons -
typing-indicatorâ dots, text, steps variants -
disclosure-badgeâ AI-generated content marker -
caveat-noticeâ model limitation warnings - Design tokens â 100+ CSS custom properties (
--loquix-*) - Light and dark themes
- Event system â typed bubbling events (
loquix-*,composed: true) - TypeScript strict mode with full type definitions
-
welcome-screenâ initial CTA with slots for suggestions, gallery, templates -
suggestion-chipsâ static, contextual, adaptive, follow-up variants -
follow-up-suggestionsâ post-response continuation prompts -
template-pickerâ template selection dialog with categories and search -
template-cardâ single template card with variables -
example-galleryâ curated, community, dynamic example showcases -
nudge-bannerâ inline, toast, banner, floating-button variants
-
mode-selectorâ tabs, dropdown, toggle, pills variants -
model-selectorâ model picker with tiers, costs, capabilities -
attachment-panelâ file upload with paste, MIME validation -
attachment-chipâ file preview with type icon and removal -
parameter-panelâ temperature, tokens, presets, advanced controls -
filter-barâ source filters and negative prompting -
voice-tone-selectorâ tone presets with global/project/session scoping
-
stream-of-thoughtâ real-time AI reasoning display (plan, tool calls, decisions) -
action-planâ step list before execution (advisory and contractual variants) -
verification-dialogâ confirmation for risky/destructive actions with cost estimates -
citation-inlineâ superscript, highlight, badge inline source annotations -
references-panelâ aggregated source list (panel, aside, nested variants) -
variations-carouselâ multiple response variants with diff highlighting -
branches-navâ conversation branch tree navigation
-
memory-panelâ AI memory management (global/project/session scoping) -
prompt-enhancerâ pre-send prompt improvement with diff view -
inline-action-toolbarâ contextual toolbar on text selection (expand, shorten, translate) -
connector-selectorâ external data source connections -
incognito-indicatorâ privacy mode status badge -
cost-estimateâ token/credit cost display with breakdowns -
session-historyâ conversation history sidebar with search -
prompt-detailsâ system prompt and context transparency panel
Detailed plans for these packages will be published as the core library stabilizes.
- Theme packs â additional prebuilt themes beyond light/dark
-
@loquix/reactâ React wrappers with hooks and context providers -
@loquix/vueâ Vue bindings with composables -
@loquix/svelteâ Svelte component wrappers - Provider integrations â prebuilt adapters for OpenAI, Anthropic, Google, and other AI services
- Agent templates â full-stack starter kits that combine components, providers, and backend into deployable agents
- Documentation site â full API reference, guides, and tutorials beyond Storybook
- Lit 3.x with Shadow DOM encapsulation
- Shared controllers â keyboard, resize, autoscroll, streaming, upload, agent
- i18n â
LocalizeControllerwith pluggable translation providers - Storybook â interactive stories with
@storybook/addon-a11y(axe-core) - Test suite â 896 tests on Chromium + WebKit via Web Test Runner
- CDN bundle â single-file IIFE build for prototyping
- Custom Elements Manifest â machine-readable component metadata
- Vite library build with multi-entry exports
MIT

