A web component to manage audience questions during a live streamed event. Originally used at CascadiaJS 2020.
To use the component in one of your projects, include a script
tag in the <head>
of your index.html
file.
<script type="module">
import { defineCustomElements } from 'https://cdn.jsdelivr.net/npm/@cascadiajs/q-and-a/loader/index.es2017.js';
defineCustomElements();
</script>
If your application does not support modules or you want to add a fallback for older browsers include this script.
<script nomodule src="https://unpkg.com/@cascadiajs/q-and-a/dist/q-and-a/q-and-a.js"></script>
Then you can use the element anywhere in your template, JSX, html etc.
<q-and-a user-id="my-user" correlation-id="my-id"></q-and-a>
Please see the documentation regarding how to configure the component here.
The component does a great job submitting and fetching questions from the audience at a configurable interval, but it is up to you to implement the logic in the backend so all users are seeing the same content during your session. For an example project implementation of a backend using Begin, please see this repo.
When a user submits a question, the component will post the following object to the configured endpoint.
{
/**
* The question the user asked
*/
"question": "What skills do I need to focus on to be a good mentor?",
/**
* Optional user identifier, if configured for the component
*/
"userId": "user-1",
/**
* Optional correlation id, if configured for the component
*/
"correlationId": "keynote-talk"
}
The component will fetch a list of questions asked from the backend at a configurable interval of time. These questions can look like the question above, but should also include two additional manditory fields, key
and count
.
[
{
/**
* The question the user asked. Must be present on all questions retrieved from the server.
*/
question: 'What kind of problem is your favorite to solve?',
/**
* Unique question identifier. Must be present on all questions retrieved from the server.
*/
key: 'question2',
/**
* Count of times the question has been asked and upvoted by the other users. Must be present on all questions retrieved from the server
*/
count: '4',
/**
* Optional user identifier, if configured for the component
*/
userId: 'user-4',
/**
* Optional correlation id, if configured for the component
*/
correlationId: 'keynote-talk',
},
];
When a user clicks on a +1
button for a question, they are saying "I also want to know the answer to this question". These +1s are posted to the backend with the following shape. The userId
is an optional field that will be sent if it is configured for the component. This way you can prevent users from spamming the +1s on a question, or see who all voted for the question.
{
"key": "question1",
"userId": "user-4",
"correlationId": "talk1"
}
You can also use a Firebase Realtime Database and Callable Functions to store your questions in and have the list updated each time a question is submitted or voted for. To do so, pass the url of the realtime database to the set use-firebase
to true and provide the additionaly required information.
firebase-db
- URL for the Firebase Realtime Database.firebase-token
- The web api key for your project.firebase-project-id
- The project ID for your firebase project.
By default the component is expecting two callable functions to exist to handle asking a question and handling upvoting of questions. By default it is expected to be called askQuestion
and incrementQuestion
respectively. You can set different values for these function names by setting a value in firebase-ask-fn
or firebase-increment-fn
.
Example
<q-and-a
id="qa"
user-id="user-1"
correlation-id="talk1"
use-firebase="true"
firebase-token="<your web api token>"
firebase-db="<your database url>"
firebase-project-id="<your project id>"
firebase-ask-fn="callableAsk"
firebase-increment-fn="callableIncrement"
</q-and-a>
You'll still have to implement the endpoint to write data to the database.
Note: per Firebase documentation, it's totally fine to use the Web API Key in a public setting. This only identifies your Firebase app and doesn't grant any additional permissions.
You can update colors the component uses with the primary-color
and secondary-color
props.
primary-color
sets the color for the button border and secondary-color
is used for question and header text color.
If you want more granular control over styles, we've exposed a number of sections via css shadow parts
form
question-textarea
submit-button
confirmation-message
error-message
placeholder-text
loading-message
This component was built with Stencil.
Stencil is a compiler for building fast web apps using Web Components.
Stencil combines the best concepts of the most popular frontend frameworks into a compile-time rather than run-time tool. Stencil takes TypeScript, JSX, a tiny virtual DOM layer, efficient one-way data binding, an asynchronous rendering pipeline (similar to React Fiber), and lazy-loading out of the box, and generates 100% standards-based Web Components that run in any browser supporting the Custom Elements v1 spec.
Stencil components are just Web Components, so they work in any major framework or with no framework at all.
npm ci
npm start
To build the component for production, run:
npm run build
To run the unit tests for the components, run:
npm test
Need help? Check out our docs here.
We love contributions! Please be sure to read CONTRIBUTING.md prior to opening any pull requests or creating issues.