Visual Elements
Overview
{
/**
* @throws UIError
*/
addButton: (payload: RPCCallPayload<'ui:button:add'>) => Promise<Button>;
/**
* @throws UIError
*/
addForm: <P extends RPCCallPayload<'ui:form:open'>>(payload: P) =>
Promise<Form<P>>;
/**
* @throws UIError
*/
showForm: <K extends RPCCallPayload<'ui:form:open'>>(payload: K) =>
Promise<MapFormReturn<K['form']['elements']>>;
/**
* @throws UIError
*/
addPrompt: (payload: RPCCallPayload<'ui:prompt:open'>) => Promise<Prompt>;
/**
* @throws UIError
*/
showPrompt: (payload: RPCCallPayload<'ui:prompt:open'>) =>
Promise<EventPayload<'ui:prompt:input'>['input']>;
/**
* @throws UIError
*/
showToast: (payload: RPCCallPayload<'ui:toast:show'>) => Promise<void>;
}
As seen above, all functions that create UI elements can throw errors when something is wrong. The information in the error will provide useful information, hinting at the problem
export type UIError = {reason: string};
Button
Toolbar Buttons and ParticipantAction Buttons are currently supported
Add a button
Syntax
const button = await plugin.ui.addButton(buttonState: ToolbarButton | ParticipantActionsButton)
Parameter Details
interface ToolbarButtonPayload {
position: 'toolbar';
icon: string | {custom: {main: string; hover: string}};
tooltip: string;
roles: Array<'chair' | 'guest'>;
opensPopup?: PopupRequest;
}
// what you need to send for a participant action
interface ParticipantActionsButtonPayload {
position: 'participantActions';
label: string;
opensPopup?: PopupRequest;
}
- position: Where the button should be rendered. Accepted values are
'toolbar'
or'participantActions'
;
Toolbar button properties:
icon: This can either be a Pexip-provided icon or a custom one as a raw svg string
For a custom icon, once you've got a valid
.svg
file, a good idea is to run the file through https://jakearchibald.github.io/svgomg/ or a similar tool that optimises your svg and provides a valid string representation. You can then copy the optimised svg as a string and that's what you can pass asicon: {custom: {main: string, hover: string}}
tooltip: Button tooltip and
alt
prop where a render isn't possibleroles: Restricts availability to particular participant roles
Participant actions button properties:
- label: The text displayed for you participant action
Return Value
// If ToolbarButton:
interface Button {
// buttonId is just metadata
onClick: Signal<{buttonId: string}>;
/**
* @throws UIError
*/
update: (payload: ButtonRPCPayload[K]['add']) => Promise<void>;
/**
* @throws UIError
*/
remove: () => Promise<void>;
}
// Participant Actions
{
onClick: Signal<{participantUuid: string}>;
/**
* @throws UIError
*/
update: (payload: ButtonRPCPayload[K]['add']) => Promise<void>;
/**
* @throws UIError
*/
remove: () => Promise<void>;
}
onClick
Syntax
// ToolbarButton
button.onClick.add(() => {
console.log('button clicked');
});
// ParticipantAction Button
button.onClick.add(({participantUuid}) => {
console.log('button clicked for participant with id ', participantUuid);
});
Update the button
Syntax
button.update(buttonState)
Parameter Details
- buttonState: Refer to Add a button
Return Value
void
Remove the button
Syntax
button.remove()
Return Value
void
Example
const button = await plugin.ui.addButton({
position: 'toolbar',
icon: 'IconPlayRound',
tooltip: 'Record',
roles: ['chair'],
});
button.onClick.add(async () => {
await button.update({
position: 'toolbar',
icon: 'IconStopRound',
tooltip: 'Stop Recording',
roles: ['chair'],
});
});
Form
Approach 1: Show a form & get input
Shows form and asynchronously resolves with the user input, after which, the form is automatically unloaded from the UI. This is the preferred way unless an explicit reference to the form is needed.
Syntax
await plugin.ui.showForm(formContent);
Parameter details
{
title: string;
description?: string;
form: {
elements: Record<string, FormElement>;
submitBtnTitle: string;
};
opensPopup?: PopupRequest;
}
title: Title of the form
description: Subtitle of the form
form:
submitBtnTitle: Submit button text
elements: Form content
interface FormElementBase {
name: string;
autoComplete?: string;
isOptional?: boolean;
}
export interface InputElement extends FormElementBase {
type: 'number' | 'text' | 'password' | 'email' | 'tel' | 'url';
}
export interface SelectElement extends FormElementBase {
type: 'select';
options: Array<{id: string; label: string}>;
}
export type ChecklistOption = {id: string; label: string};
export interface ChecklistElement extends FormElementBase {
type: 'checklist';
options: ChecklistOption[];
}
export type FormElement = InputElement | SelectElement | ChecklistElement;
Return Value
Input from the form. Object with keys based on the element's key and value types
based on the element's type
.
Example
export const FormContent = {
title: 'This is an example form',
description:
'In this example form, we show all possible input elements you can make use of through the plugin system💪',
form: {
elements: {
randomText: {
name: 'Enter some random text',
type: 'text',
},
email: {
name: 'Enter your email address',
type: 'email',
autoComplete: 'email',
},
favoriteNumber: {
name: 'What is your favorite number?',
type: 'number',
},
secretPassword: {
name: 'Enter a very secret password😈',
type: 'password',
},
telephoneNumber: {
name: 'What is your phone number?',
type: 'tel',
},
url: {name: 'Enter a url', type: 'url'},
favoriteMeal: {
name: 'What is your favorite meal?',
type: 'select',
options: [
{id: '0', label: 'taco🌮'},
{id: '1', label: 'pizza🍕'},
{id: '2', label: 'hamburger🍔'},
],
},
sleepNights: {
name: 'Which nights are you going to stay?',
type: 'checklist',
options: [
{id: '0', label: '24'},
{id: '1', label: '25'},
{id: '2', label: '26'},
{id: '3', label: '27'},
{id: '4', label: '28'},
{id: '5', label: '29'},
],
},
},
submitBtnTitle: 'Submit your input!',
},
} as const;
const input = await plugin.ui.showForm(FormContent);
input.favoriteNumber; // number
input.email; // string
input.sleepNights; // {[id]: boolean}
Approach 2: Add a form & interact with the form
Adds an UI form element. Developer has the task to register for events and manage the form's lifecycle.
Syntax
const form = await plugin.ui.addForm(formContent)
Parameter details
Return Value
export interface Form extends PluginElement {
onInput: Signal<Event<'ui:form:input'>>;
/**
* @throws UIError
*/
remove: () => Promise<void>;
}
onInput
Object with keys based on the element's key and value types based on the
element's type
.
Syntax
form.onInput.add(formInput => {
//do stuff
});
Remove the form
Syntax
form.remove()
Return Value
void
Example
const form = await plugin.addForm(formContent);
form.onInput.add(formInput => {
//do stuff
form.remove();
});
Prompt
Approach 1: Show a prompt & get input
Shows a promp and asynchronously resolves with the user input, after which, the prompt is automatically unloaded from the UI. This is the preferred way unless an explicit reference to the prompt is needed.
plugin.ui.showPrompt(promptContent)
Parameters
{
title: string;
description?: string;
prompt: {
primaryAction: string;
secondaryAction?: string;
};
opensPopup?: PopupRequest;
}
title: Title of the prompt
description: Subtitle of the prompt
prompt:
primaryAction: Primary action text
secondaryAction?: Secondary action text. Optional.
Return Value: string
Example
const formPrompt: RPCCallPayload<'ui:prompt:open'> = {
title: 'This is a prompt',
description:
'We need some info about you, and we hope you can fill out a form for us',
prompt: {
primaryAction: 'Go to form',
secondaryAction: 'Dismiss',
},
};
const input = await plugin.ui.showPrompt(formPrompt);
if (input === 'Go to form') {
plugin.ui.showForm(FormContent);
}
Approach 2: Add a prompt & interact with the form
Adds an UI prompt element. Developer has the task to register for events and manage the form's lifecycle.
plugin.ui.addPrompt(promptContent)
Parameter details
Return Value
export interface Prompt extends PluginElement {
onInput: Signal<Event<'ui:prompt:input'>>;
/**
* @throws UIError
*/
remove: () => Promise<void>;
}
onInput
Syntax
prompt.onInput.add(string => {
//do stuff
});
Remove the prompt
Syntax
prompt.remove()
Return Value
void
Example
const prompt = await plugin.addPrompt(promptContent);
prompt.onInput.add(string => {
//do stuff
prompt.remove();
});
Toast
A basic Toast component with the sidenote that requests are queued up and the next one shows when the previous times out.
Parameters
export type NotificationToastMessage = {
message: string;
};
- timeout: How long should the Toast stay for. Default of 5000ms
Example
await plugin.ui.showToast({message: string});