webwriter-app / webwriter

Authoring tool for interactive content
https://webwriter.app
Other
15 stars 1 forks source link

Slot API #4

Closed salmenf closed 1 month ago

salmenf commented 1 year ago

More complex widgets may need to contain children.

There are multiple use cases:

  1. Inline: Text segments in the widget that should allow for any inline content
  2. Block: Layout widgets such as grid, slides, etc.

Specification by developers Slots are specified with the <slot> element. A name attribute may be provided which will also be used as an input hint by the editor. Additionally, a data-type attribute may be provided. If it is provided, the editor narrows the possible slot children to this value. Possible values are: "inline" for inline widgets, "block" for block widgets, any valid element name (e.g. "other-widget"), or a space-separated list of those previous three (e. g. "other-widget another-widget" or "inline other-widget"). The <slot> element should be filled with a fallback input so the widget remains fully usable outside of a WebWriter context. The fallback input should store its state as widget attributes.

my-widget/index.ts

// Imports omitted
@customElement("my-widget")
class MyWidget extends LitElementWw {
  render() {
    return html`
      <img src="..." />
      <slot name="caption" data-type="inline">
        <input />
      </slot>
    `
  }
}

Editing by teachers When the widget is rendered by the editor, each slot is first filled with a wrapper element. When the wrapper element is selected, it becomes the actively edited slot. Any editor input is now placed into the wrapper element. Optionally, the possible input is limited by the slot's data-type attribute. Furthermore, the name attribute is used as an input hint.

Usage by students How the element is updated and saved depends on whether there is a slot child present. If there is not slot content, the state is updated and saved as attributes. If there is slot content, the children are updated and saved.

A) Widget without slot content

<my-widget caption="great image"></my-widget>

B) Widget with slot content

<my-widget>
  <span slot="caption"><b>great</b> image</span>
</my-widget>