Skip to content

Elicitation

<aparte-elicitation>

The default presenter for a request to the human. It renders nothing itself: it registers as the presenter for the config governing its subtree, and mounts a panel inside the nearest <aparte-composer> when something asks — a tool handler calling requestUserInput, or core’s own approval gate.

It dispatches no events on purpose. A request is answered through the typed presenter contract, not by listening for one; the aparte-tool-decision event this replaced existed only because the buttons used to live in a segment renderer with no reference to the client.

It has no children to project: connectedCallback sets display: none, and the composer it presents in is found by walking UP from this.parentElement — anything placed inside this element is only hidden with it. So its position matters but its content does not: mount it anywhere inside the <aparte-chat> whose questions it should answer.

Not the element to reach for when you want a question UI of your own shape. It is one caller of setElicitationPresenter, and among presenters registered for the same chat the most recent one wins — so an app with a framework-native presenter registers that and does not mount this, and a second <aparte-elicitation> in one chat is redundant rather than additive. It is also not usable outside a chat that has an <aparte-composer>: with nowhere to mount a panel the request is REJECTED, on purpose, rather than borrowed into another chat’s composer.

The panel it mounts is styled by @aparte/core/styles.css — the --aparte-elic-* and --aparte-approval-* knobs below theme it. They are declared here rather than on the composer because this presenter is what builds the panel; the composer only lends it the slot.

Width Open in a tab
The real element, in its own document so this site's CSS cannot reach it. It renders the same example printed below — every framework mounts this same element, so the rendering is what you get in all five; the code is what changes.
<!-- Renders nothing by itself: it registers as the presenter for its subtree, so a
tool handler calling requestUserInput() gets its panel mounted in the composer. -->
<aparte-chat style="height: 20rem">
<aparte-chat-viewport></aparte-chat-viewport>
<aparte-elicitation></aparte-elicitation>
<aparte-composer>
<div class="aparte-composer-shell">
<div class="aparte-composer-row">
<aparte-composer-input></aparte-composer-input>
<aparte-composer-send></aparte-composer-send>
</div>
</div>
</aparte-composer>
</aparte-chat>
<script>
// `aparte` is the `@aparte/core` module the frame exposes; in your app this line is
// `import { requestUserInput } from '@aparte/core'`. A tool handler asks; the panel
// mounts in the composer of the chat whose presenter this element is.
aparte.requestUserInput({
message: 'Which environment should I deploy to?',
schema: {
type: 'enum',
options: [
{ value: 'staging', label: 'Staging', recommended: true },
{ value: 'prod', label: 'Production', description: 'Live traffic' },
],
},
});
</script>
MethodDescription
aparteConfigChanged(next: AparteConfig, previous: AparteConfig): voidThe boundary above us appeared, changed, or went away — move the registration with it. connectedCallback alone is not enough and cannot be: registering is a WRITE, and under all four wrappers it happens before attachConfig runs, so it lands on the global singleton. requestUserInput() then resolves the instance config, finds nothing, and rejects the request — the model hears the user refuse a question the user never saw. See AparteConfigAware.

Override any of these on :root, on a subtree, or on one instance — custom properties inherit downward. Some are this element’s own; others are site-wide tokens that also style it, and overriding one of those at :root moves everything that reads it. The full set is in the CSS variables reference.

VariableDefaultDescription
--aparte-elic-gapvar(--aparte-space-3)Vertical gap between the panel’s rows (message, body, tabs).
--aparte-elic-paddingvar(--aparte-space-3) var(--aparte-space-2)Padding inside the panel.
--aparte-elic-max-height50vhCap on the panel’s height; its body scrolls, the panel does not.
--aparte-elic-field-gapvar(--aparte-space-4)Space and separator padding between two fields of an object schema.
--aparte-elic-message-sizevar(--aparte-font-size-base)Font size of the question text at the top of the panel.
--aparte-elic-title-sizevar(--aparte-font-size-base)Font size of a field’s title.
--aparte-elic-desc-sizevar(--aparte-font-size-sm)Font size of a field’s description.
--aparte-elic-option-paddingvar(--aparte-space-4) var(--aparte-space-5)Padding of one enum/boolean option row.
--aparte-elic-option-radiusvar(--aparte-radius-md)Corner radius of an option row.
--aparte-elic-option-title-sizevar(--aparte-font-size-md)Font size of an option’s label, and of the text inputs.
--aparte-elic-option-desc-sizevar(--aparte-font-size-sm)Font size of an option’s secondary line.
--aparte-elic-control-size15pxSize of the radio/checkbox control in an option row.
--aparte-elic-input-radiusvar(--aparte-radius-md)Corner radius of the text inputs and of the Skip button.
--aparte-elic-textarea-min-height64pxMinimum height of a multi-line string field.
--aparte-elic-input-size0.85remFont size of the approval panel’s instruction field (the free-text note the user writes).
--aparte-elic-skip-sizevar(--aparte-font-size-md)Font size of the corner “Skip” affordance (the decline).
--aparte-elic-step-sizevar(--aparte-font-size-sm)Font size of a step tab, when the schema is asked one field at a time.
--aparte-elic-step-paddingvar(--aparte-space-2) var(--aparte-space-1)Padding of a step tab.
--aparte-elic-step-gapvar(--aparte-space-7)Gap between step tabs.
--aparte-elic-step-underline2pxThickness of the current step’s underline (a tab, not a pill).
--aparte-elic-dismiss-room72pxSpace the tab rail and the question message keep clear for the corner escape. Widen it for a locale whose “Skip” word is wider.
--aparte-approval-gap4pxGap between the stacked options of an approval request.
--aparte-approval-option-size0.85remFont size of an approval option button.
--aparte-approval-option-padding8px 10pxPadding of an approval option button.
--aparte-approval-option-radius8pxCorner radius of an approval option button.
--aparte-approval-args-max-height8.5remHeight cap of the arguments block before it scrolls.
--aparte-approval-args-sizevar(--aparte-font-size-sm)Font size of the arguments block.

The element is the same object everywhere — the tag does not change. What changes is how an attribute is written and how an event reaches you.

<aparte-elicitation></aparte-elicitation>

Installation and the framework-specific traps: React · Vue · Svelte · Angular.