Nova · Composition
Modal
A dialog is an action pushed onto a canvas of its own, opened with a fragment that carries the frame and its Cancel. The form inside knows nothing of the frame. Saving says so on a channel the page listens to, and closes itself.
{
canvases: [
{ id: 'modal.page', initial: 'modal.guests' },
{ id: 'modal.over' },
],
actions: {
modal.guests: {
id: 'modal.guests',
data: { guests: ['Ada'] },
layout: {
component: 'Stack',
children: [
{ component: 'Text', children: 'Guests' },
{
for: '$.guests',
as: 'guest',
do: { component: 'Text', children: '$guest' },
},
{
component: 'Button',
ref: 'new',
children: 'Add a guest',
},
],
},
triggers: [
{
event: 'ui:click',
ref: 'new',
do: [
{
push: {
action: 'modal.form',
canvas: 'modal.over',
with: ['modal.frame'],
},
},
],
},
{
message: 'modal.saved',
do: [{ push: 'guests', value: '@event.payload' }],
},
],
},
modal.form: {
id: 'modal.form',
data: { name: '' },
layout: {
component: 'Stack',
children: [
{
component: 'Input',
ref: 'name',
model: '$.name',
props: { placeholder: 'Their name' },
},
{ component: 'Button', ref: 'save', children: 'Save' },
],
},
triggers: [
{
event: 'ui:click',
ref: 'save',
do: [
{ emit: { channel: 'modal.saved', payload: '$.name' } },
{ pop: true },
],
},
],
},
},
fragments: {
modal.frame: {
kind: 'fragment',
id: 'modal.frame',
layout: {
component: 'Stack',
children: [
{ component: 'Text', children: 'New guest' },
{ slot: 'body' },
{
component: 'Button',
ref: 'cancel',
children: 'Cancel',
},
],
},
triggers: [
{ event: 'ui:click', ref: 'cancel', do: [{ pop: true }] },
],
},
},
}Guests
Ada
press new type 'Grace' into name, on modal.over press save, on modal.over
{ modal.page: ['modal.guests'], modal.over: [] }Guests Ada Grace Add a guest
Left: the action as the package ships it. Right: the same action running in this page, rendered with this site’s components. Below: the action run as the example specifies, on the installed package.