Skip to content

Theming

aparté is 100% CSS-driven. There is no JavaScript theme logic — you restyle the whole chat by overriding CSS custom properties. Every visual value the components render (colours, spacing, font sizes, weights, line-heights, radii, border widths) flows through a variable, so a well-made theme never has to touch the component internals.

The default theme lives on :root (and :host, for shadow contexts). Override any variable wherever you like — globally, scoped to a subtree, or per chat instance:

/* Global: retheme every aparté chat on the page. */
:root {
--aparte-primary: #7c3aed; /* your brand accent */
}
/* Scoped: only chats inside .support-widget. */
.support-widget {
--aparte-primary: #0ea5e9;
}

Because they are plain CSS variables, they cascade and inherit like any other — no build step, no theme provider, no re-render.

Light is the default. Dark mode is opt-in: set data-aparte-theme="dark" on the chat itself — or on any ancestor (<body>, <html>) — and the components read it.

<!-- on the element itself… -->
<aparte-chat data-aparte-theme="dark"></aparte-chat>
<!-- …or on any ancestor, to theme everything inside -->
<body data-aparte-theme="dark"></body>

Most of the palette derives from a few base tokens, so a rebrand is short:

:root {
--aparte-primary: #b45309; /* accent — send button, links, focus, caret */
--aparte-primary-hover: #92400e;
--aparte-bg: #fbf7f0; /* page background */
--aparte-surface-1: #ffffff; /* cards, code blocks */
--aparte-surface-2: #f4ece0; /* headers, inline code */
--aparte-text: #241a12;
--aparte-text-muted: #7c6f60;
--aparte-border: #e7dccb;
}

Structural values aren’t magic numbers — they route through scales. Adjust a scale and the whole UI re-spaces or re-sizes coherently.

ScaleTokensControls
Spacing--aparte-space-1--aparte-space-8 (2 → 16px)gaps, padding, margins
Font size--aparte-font-size-2xs--aparte-font-size-basecomponent text sizes
Font weight--aparte-font-weight-normal-boldtext weights
Line height--aparte-line-height-none-looseline heights
Radius--aparte-radius-xs--aparte-radius-fullcorner rounding
/* A denser, squarer chat. */
:root {
--aparte-space-6: 8px; /* pull the default 12px paddings/gaps in */
--aparte-radius-lg: 4px; /* squarer bubbles, inputs, cards */
}

Variables are grouped by region. The most-reached-for ones:

Core palette--aparte-primary, --aparte-primary-hover, --aparte-bg, --aparte-surface-1 / -2 / -3, --aparte-text, --aparte-text-muted, --aparte-border, and the status colours --aparte-info / -success / -warning / -error.

Message--aparte-message-gap, --aparte-message-padding, --aparte-message-max-width, and the message surface: --aparte-message-content-bg-user / -assistant, --aparte-message-content-text-user / -assistant, --aparte-message-content-padding, --aparte-message-content-radius.

Avatar--aparte-avatar-size, --aparte-avatar-radius, --aparte-avatar-bg-user / -assistant, --aparte-avatar-image-user / -assistant.

Action bar--aparte-action-bar-btn-size, --aparte-action-bar-btn-color, --aparte-action-bar-btn-hover-bg / -hover-color.

Composer / input--aparte-input-bg, --aparte-input-border, --aparte-input-text, --aparte-input-placeholder, --aparte-composer-control-size (sizes the whole composer control row at once).

Segments — each rich block has its own group: --aparte-code-*, --aparte-thinking-*, --aparte-terminal-*, --aparte-error-*, --aparte-file-tree-*, --aparte-progress-*.

By convention the assistant is plain full-width prose (like ChatGPT / Claude) and only the user message is a bubble. To make both sides bubbles:

:root {
--aparte-message-content-bg-assistant: var(--aparte-surface-2);
--aparte-message-content-text-assistant: var(--aparte-text);
}

Every composer control (input height + buttons) derives from a single token:

:root { --aparte-composer-control-size: 52px; } /* a chunkier composer */
:root {
--aparte-code-font-family: 'JetBrains Mono', ui-monospace, monospace;
}

Overriding on :root rethemes every chat. To run several differently-themed chats on one page, set the variables (and data-aparte-theme) straight on each <aparte-chat> — they inherit down to its viewport, composer and bubbles:

<aparte-chat class="brand-a"></aparte-chat>
<aparte-chat class="brand-b" data-aparte-theme="dark"></aparte-chat>
<style>
.brand-a { --aparte-primary: #16a34a; }
.brand-b { --aparte-primary: #db2777; }
</style>

Some changes need markup or behaviour, not just colours — a custom typing indicator, your own attachment chip, an avatar, extra action-bar buttons. Those are render hooks and the action registry, covered in Customization.