Questionnaire
An assistant’s questions, answered in the chat and sent as one Message.
All at once #
export const QuestionnaireStyle = forSlots(QuestionnaireSlots)(Recipes.Questionnaire({}))
export const TRIP_QUESTIONS: ReadonlyArray<Questionnaire.Question> = [
Questionnaire.single({
id: 'pace',
prompt: 'How busy should the days be?',
options: [
{ value: 'slow', label: 'Slow', description: 'One thing a day' },
{ value: 'full', label: 'Full', description: 'Morning to night' },
],
other: 'Something else',
}),
Questionnaire.multiple({
id: 'likes',
prompt: 'What do you enjoy?',
options: [
{ value: 'food', label: 'Food' },
{ value: 'museums', label: 'Museums' },
{ value: 'walks', label: 'Walks' },
],
}),
Questionnaire.text({ id: 'avoid', prompt: 'Anything to avoid?', optional: true }),
]
/**
* Its Model from `Questionnaire.init({ id: 'preview-trip', questions:
* TRIP_QUESTIONS })`, folded by `Questionnaire.update`, whose
* `OutMessage.Answered` carries every answer once the form is sent.
*/
export const questionnaire = <Message>(
style: NamedStyle<typeof QuestionnaireSlots>,
model: Questionnaire.Model,
onMessage: (message: Questionnaire.Message) => Message,
h: HtmlBuilder<Message>,
): Html =>
h.div(
[h.Style({ inlineSize: 'min(28rem, 100%)' })],
[
Questionnaire.view(
{
model,
onMessage,
title: 'A few questions before I plan',
style,
radioGroup: RadioGroupStyle,
checkboxGroup: CheckboxGroupStyle,
input: InputStyle,
textarea: TextareaStyle,
submitButton: ButtonStyle,
},
h,
),
],
)One at a time, in a card #
export const QuestionnaireCardStyle = forSlots(QuestionnaireSlots)(
Recipes.Questionnaire({ variant: 'card' }),
)
const QuestionBackStyle = forSlots(ButtonSlots)(
Recipes.Button({ tone: 'neutral', variant: 'outline' }),
)
/**
* One question at a time: its Model from `Questionnaire.init({ id:
* 'preview-trip-paged', questions: TRIP_QUESTIONS, layout: 'paged' })`.
* Next refuses a missing answer and moves the focus to the next question.
*/
export const questionnairePaged = <Message>(
style: NamedStyle<typeof QuestionnaireSlots>,
model: Questionnaire.Model,
onMessage: (message: Questionnaire.Message) => Message,
h: HtmlBuilder<Message>,
): Html =>
h.div(
[h.Style({ inlineSize: 'min(28rem, 100%)' })],
[
Questionnaire.view(
{
model,
onMessage,
style,
radioGroup: RadioGroupStyle,
checkboxGroup: CheckboxGroupStyle,
input: InputStyle,
button: QuestionBackStyle,
submitButton: ButtonStyle,
},
h,
),
],
)Usage
Each example above names the function that drew it, over the theme module Create a theme writes. The preview passes it the style picked above instead of its default.