Skip to main content

Style questions

Let's set up the right panel configuration and styling for the question component

The result will look like this:

Right panel config working

Create a question preset

Define which elements and functionalities will be included in the question component's right panel configuration. Begin by creating a preset for your question component. This is where you decide which elements can be customized, e.g. the image, colors or font used for styling the question.

src/components/question/question.preset.ts
import { numeric, object } from "@zoovu/theme-editor-parameter-types";

export const questionPreset = object(
{
fontSize: numeric({
default: { value: 32, unit: "px" },
label: "Font size",
units: [ "px", "%", "rem", "em" ],
}),
},
{ label: "Question", addSeparator: true }
)

Create a question configuration

Next, make sure the actual configuration matches your answer preset exactly. The values from the preset will be injected into the QuestionConfiguration object and then used within the Vue component.

src/components/question/question.configuration.ts
import { NumericValue } from "@zoovu/theme-editor-parameter-types";

export class QuestionConfiguration {
fontSize: NumericValue = { value: 10, unit: "px" };
}

Use the configuration in the styles file

Now, let's write a function that takes configuration as arguments and returns css

You can read more about creating styles using CSS in JS here.

src/components/question/question.style.ts
import { ComponentStyleDefinition } from "@zoovu/runner-browser-api";

import { QuestionConfiguration } from "./question.configuration";
import { numericValueToString } from "../../util/numeric-value-to-string";

export const questionStyle: ComponentStyleDefinition<
| "question"
> = {
question: (questionConfiguration: QuestionConfiguration) => ({
fontSize: numericValueToString(questionConfiguration.fontSize),
color: "#00A9FF",
}),
};

export type QuestionStyle = Record<keyof typeof questionStyle, string>

Import the question preset into the root preset

src/flow-step.preset.ts
import { object, remoteComponentConfig, } from "@zoovu/theme-editor-parameter-types";
import { paddingPreset } from "./util/padding/padding.preset";
import { questionPreset } from "./components/question/question.preset";

const flowStepPreset = remoteComponentConfig(
object(
{
padding: paddingPreset,
question: questionPreset,
},
{ label: "FlowStepComponent" }
)
);

export default flowStepPreset;

Root configuration should be the same as root preset

The root configuration must match your root preset exactly. The preset values selected in Experience Designer are mapped onto the root configuration object. This configuration is then visible and can be used within the Vue component.

src/flow-step.configuration.ts
import { QuestionConfiguration } from "./components/question/question.configuration";
import { PaddingConfiguration } from "./util/padding/padding.configuration";


export class FlowStepConfiguration {
padding: PaddingConfiguration = new PaddingConfiguration();
question: QuestionConfiguration = new QuestionConfiguration();
}

Create the Question vue component

You will get questionText and componentConfiguration via props from the root component.

styles will be injected by @ComponentStyle annotation

This is where you can use the new question CSS class prepared in the previous steps.

src/components/question/question.vue
<template>
<h2 :class="styles.question">{{ questionText }}</h2>
</template>

<script lang="ts">
import { Component, Mixins, Prop, ComponentConfig, ComponentStyle } from "@zoovu/runner-browser-api";
import { ZoovuFacadeMixin } from "@zoovu/exd-api";

import { QuestionConfiguration } from "./question.configuration";
import { QuestionStyle, questionStyle } from "./question.style";

@Component({})
export default class QuestionComponent extends Mixins(ZoovuFacadeMixin) {
@Prop()
questionText: string;

@ComponentConfig(QuestionConfiguration)
componentConfiguration: QuestionConfiguration;

@ComponentStyle(questionStyle)
styles: QuestionStyle;
}
</script>

Use the Question component in the root component

src/flow-step.component.vue
<template>
<div :class="styles.mainContainer">
<question-component
:question-text="questionText"
:component-configuration="componentConfiguration.question"
/>
<ul :class="styles.answers">
<li>First answer will be here</li>
<li>Second answer will be here</li>
<li>...</li>
</ul>
</div>
</template>

<script lang="ts">
import { Component, Mixins, ComponentConfig, ComponentStyle } from "@zoovu/runner-browser-api";
import { Question, ZoovuFacadeMixin } from "@zoovu/exd-api";
import { FlowStepConfiguration } from "./flow-step.configuration";
import { FlowStepStyle, flowStepStyle } from "./flow-step.style";
import QuestionComponent from "./components/question/question.vue";


@Component({
components: { QuestionComponent },
})
export default class FlowStepComponent extends Mixins(ZoovuFacadeMixin) {
@ComponentConfig(FlowStepConfiguration)
componentConfiguration: FlowStepConfiguration;

@ComponentStyle(flowStepStyle)
styles: FlowStepStyle;

get question(): Question {
return this.zoovuFacade.firstQuestionFromCurrentPage;
}

get questionText(): string {
return this.question.text;
}
}
</script>

<style lang="css" scoped>
@import url('https://fonts.googleapis.com/css?family=Poppins');
</style>

Test your right panel config

For example, change Question -> Font size to 40px and see that the setting is instantly injected into the component.

Right panel config working