Skip to content

Commit 54a411d

Browse files
PetyaMarkovaBogdanovaPetyaMarkovaBogdanova
andauthored
docs(ui5-toolbar): fix documentation (#7667)
fix(ui5-toolbar): documentation Co-authored-by: PetyaMarkovaBogdanova <[email protected]>
1 parent 1941854 commit 54a411d

File tree

5 files changed

+248
-3
lines changed

5 files changed

+248
-3
lines changed

docs/internal/Toolbar.md

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
# Creating a web component abstract item to be used inside Toolbar
2+
3+
*This section explains how to build abstract items in order to be compatible with UI5 Toolbar.*
4+
*It will guide you through the process of how we created `ui5-toolbar-button`, to be
5+
compatible with `ui5-toolbar`. Currently developed items can be used without those efforts. They are:*
6+
1. ui5-toolbar-button
7+
2. ui5-toolbar-select
8+
3. ui5-toolbar-separator
9+
4. ui5-toolbar-spacer
10+
11+
## Abstract items
12+
 
13+
### Why are abstract items needed?
14+
 
15+
When the toolbar renders its slotted items within a popover in the static area, simply relocating the actual DOM nodes within its slots can lead to reference issues, causing the slotted nodes to lose their parent reference (e.g., the toolbar). This is the reason why the toolbar must operate with abstract items. Abstract items are not rendered directly within the DOM; instead, they function as data used by the toolbar to produce corresponding physical web components. On the other hand, useful modifications detected by the toolbar on the physical items are synchronised with the abstract ones. (see step [Events](#events))
16+
 
17+
The `ui5-toolbar` is a composite web component, that slots different UI5 components, designing them as abstract items. They can contain
18+
properties, slots and events, and they can match the API of already existing component.
19+
In order to be suitable for usage inside `ui5-toolbar`, each component should adhere to following guidelines:
20+
21+
22+
1. The component needs to implement a class with component name of the following type:
23+
24+
```javascript
25+
ToolbarButton.ts
26+
```
27+
28+
2. The new component needs to implement two template files with name of the following type:
29+
30+
```javascript
31+
ToolbarButton.hbs and ToolbarPopoverButton.hbs
32+
```
33+
34+
3. It needs to implement **customElement** decorator, which is good to contain custom tag name:
35+
36+
```javascript
37+
@customElement({
38+
tag: "ui5-toolbar-button"
39+
})
40+
```
41+
42+
4. The class should extend **ToolbarItem** base class, which should also be added as a dependency.
43+
44+
```javascript
45+
class ToolbarButton extends ToolbarItem
46+
```
47+
48+
5. Inside the module there should be two template getters: for toolbar and popover representation.
49+
50+
```javascript
51+
static get toolbarTemplate() {
52+
return ToolbarButtonTemplate;
53+
}
54+
55+
static get toolbarPopoverTemplate() {
56+
return ToolbarPopoverButtonTemplate;
57+
}
58+
```
59+
60+
6. After the class declaration there should be a registry call for the item inside the toolbar. **registerToolbarItem** helper should be added as a dependency.
61+
62+
```javascript
63+
import { registerToolbarItem } from "./ToolbarRegistry.js";
64+
```
65+
66+
```javascript
67+
registerToolbarItem(ToolbarButton);
68+
```
69+
70+
7. In the templates there should be mapping of the properties that need to be used in the component inside Toolbar.
71+
72+
Inside ToolbarButton.ts:
73+
 
74+
```typescript
75+
@property()
76+
text!: string;
77+
 
78+
@property({ type: Boolean })
79+
disabled!: boolean;
80+
```
81+
 
82+
Inside ToolbarButtonTemplate.hbs:
83+
 
84+
```html
85+
<ui5-button
86+
  class="ui5-tb-item"
87+
  ?disabled="{{this.disabled}}"
88+
  data-ui5-external-action-item-id="{{this._id}}"
89+
  data-ui5-stable="{{this.stableDomRef}}"
90+
>
91+
  {{this.text}}
92+
</ui5-button>
93+
```
94+
8. The new component's DOM root element needs to have `"ui5-tb-item"` CSS class in order to get default styles for item (margins etc.).
95+
9. The new class needs to be added to the bundle file in the corresponding library.
96+
97+
Inside bundle.common.js:
98+
```javascript
99+
import ToolbarButton from "./dist/ToolbarButton.js";
100+
```
101+
10. Use your newly created component inside the ui5-toolbar like this:
102+
103+
```html
104+
<ui5-toolbar>
105+
  <ui5-toolbar-button text="Button 1" disabled></ui5-toolbar-button>
106+
  <ui5-toolbar-button text="Button 2"></ui5-toolbar-button>
107+
</ui5-toolbar>
108+
```
109+
110+
## Events
111+
 
112+
Abstract items can provide a map of events through the `subscribedEvents` getter. The toolbar will actively monitor these events on the physical items, and when triggered, it will also fire the information to the corresponding abstract item. This mechanism proves useful when the abstract item requires synchronization of changes or interactions with the physical items. Importantly, events described as public offer benefits to consumers of the abstract items informing them about interactions with the physical elements. Additionally, the map contains information about the popover, such as `preventClosing: true`, which ensures that the popover remains open when this event is triggered by the physical item.
113+
 
114+
A good example is the Map of the `ui5-toolbar-select`:
115+
 
116+
```javascript
117+
get subscribedEvents() {
118+
  const map = new Map();
119+
 
120+
  map.set("click", { preventClosing: true });
121+
  map.set("change", { preventClosing: false });
122+
  map.set("open", { preventClosing: true });
123+
  map.set("close", { preventClosing: true });
124+
 
125+
  return map;
126+
}
127+
```
128+
 
129+
The `ui5-toolbar-select` then waits for the toolbar to fire the `change` event, in order to notify (synchronize) its `options` slots:
130+
 
131+
```ts
132+
_onEventHandler(e: Event): void {
133+
  if (e.type === "change") {
134+
    // update options
135+
    const selectedOption = (e as CustomEvent<ToolbarSelectChangeEventDetail>).detail.selectedOption;
136+
    const selectedOptionIndex = Number(selectedOption?.getAttribute("data-ui5-external-action-item-index"));
137+
    this.options.forEach((option: Option, index: number) => {
138+
      if (index === selectedOptionIndex) {
139+
        option.setAttribute("selected", "");
140+
      } else {
141+
        option.removeAttribute("selected");
142+
      }
143+
    });
144+
  }
145+
}
146+
```

packages/main/src/themes/ToolbarPopover.css

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@
1111

1212
.ui5-tb-popover-item {
1313
width: 100%;
14+
}
15+
16+
.ui5-tb-popover-item:not(:last-child) {
1417
margin-bottom: 0.25rem;
1518
}
1619

packages/main/test/pages/Toolbar.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@
267267
});
268268

269269
select.addEventListener("ui5-change", e => {
270-
console.log("Selected " + e.detail.selectedOption.getAttribute("text"));
270+
console.log("Selected " + e.detail.selectedOption.textContent);
271271
});
272272

273273
select.addEventListener("ui5-open", e => {

packages/playground/_stories/main/Toolbar/Toolbar.stories.ts

Lines changed: 97 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,13 @@ const Template: UI5StoryArgs<Toolbar, StoryArgsSlots> = (args) => {
3838
align-content="${ifDefined(args.alignContent)}"
3939
>
4040
${unsafeHTML(args.default)}
41-
</ui5-toolbar>`;
41+
</ui5-toolbar>
42+
<script>
43+
select.addEventListener("ui5-change", e => {
44+
textarea.setAttribute("value", "Selected option is:" + e.detail.selectedOption.textContent);
45+
});
46+
</script>
47+
`;
4248
};
4349

4450
export const Basic = Template.bind({});
@@ -66,3 +72,93 @@ Basic.args = {
6672

6773
export const Types: StoryFn = TemplateToolbarTypes.bind({});
6874

75+
export const MultipleUI5SelectComponents : UI5StoryArgs<Toolbar, StoryArgsSlots> = (args) => {
76+
return html`<ui5-toolbar
77+
align-content="${ifDefined(args.alignContent)}"
78+
>
79+
${unsafeHTML(args.default)}
80+
</ui5-toolbar>
81+
<ui5-textarea disabled id="ToolbarStoryTextarea" placeholder="Change selection of the first Select Box"></ui5-textarea>
82+
<script>
83+
ToolbarStorySelect.addEventListener("ui5-change", e => {
84+
ToolbarStoryTextarea.setAttribute("value", "Selected option is: " + e.detail.selectedOption.textContent);
85+
});
86+
</script>
87+
`;
88+
};
89+
90+
91+
MultipleUI5SelectComponents.storyName = "Multiple Toolbar Select components";
92+
93+
MultipleUI5SelectComponents.args = {
94+
default: `<ui5-toolbar-select id="ToolbarStorySelect">
95+
<ui5-toolbar-select-option>Apple</ui5-toolbar-select-option>
96+
<ui5-toolbar-select-option>Orange</ui5-toolbar-select-option>
97+
<ui5-toolbar-select-option>Pear</ui5-toolbar-select-option>
98+
</ui5-toolbar-select>
99+
<ui5-toolbar-select>
100+
<ui5-toolbar-select-option>1</ui5-toolbar-select-option>
101+
<ui5-toolbar-select-option>2</ui5-toolbar-select-option>
102+
<ui5-toolbar-select-option>3</ui5-toolbar-select-option>
103+
</ui5-toolbar-select>
104+
<ui5-toolbar-select>
105+
<ui5-toolbar-select-option>Bulgaria</ui5-toolbar-select-option>
106+
<ui5-toolbar-select-option>Bolivia</ui5-toolbar-select-option>
107+
<ui5-toolbar-select-option>Brunei</ui5-toolbar-select-option>
108+
<ui5-toolbar-select-option>Bangladesh</ui5-toolbar-select-option>
109+
<ui5-toolbar-select-option>Belarus</ui5-toolbar-select-option>
110+
<ui5-toolbar-select-option>Belgium</ui5-toolbar-select-option>
111+
</ui5-toolbar-select>
112+
<ui5-toolbar-select value-state="Success" width="auto">
113+
<ui5-toolbar-select-option icon="meal" selected="">Apple</ui5-toolbar-select-option>
114+
<ui5-toolbar-select-option icon="meal">Avocado</ui5-toolbar-select-option>
115+
<ui5-toolbar-select-option icon="meal">Mango</ui5-toolbar-select-option>
116+
</ui5-toolbar-select>
117+
<ui5-toolbar-select value-state="Warning" width="auto">
118+
<ui5-toolbar-select-option icon="meal">Orange</ui5-toolbar-select-option>
119+
<ui5-toolbar-select-option icon="meal" selected="">Pumpkin</ui5-toolbar-select-option>
120+
<ui5-toolbar-select-option icon="meal">Carrot</ui5-toolbar-select-option>
121+
<div slot="valueStateMessage">
122+
Information message. This is a <a href="#">Link</a>. Extra long text
123+
used as an information message. Extra long text used as an information
124+
message - 2. Extra long text used as an information message - 3.
125+
</div>
126+
<div slot="valueStateMessage">
127+
Information message 2. This is a <a href="#">Link</a>. Extra long text
128+
used as an information message. Extra long text used as an information
129+
message - 2. Extra long text used as an information message - 3.
130+
</div>
131+
</ui5-toolbar-select>
132+
<ui5-toolbar-select value-state="Error">
133+
<ui5-toolbar-select-option icon="meal">Strawberry</ui5-toolbar-select-option>
134+
<ui5-toolbar-select-option icon="meal">Tomato</ui5-toolbar-select-option>
135+
<ui5-toolbar-select-option icon="meal" selected="">Red Chili Pepper</ui5-toolbar-select-option>
136+
<div slot="valueStateMessage">
137+
Information message. This is a <a href="#">Link</a>. Extra long text
138+
used as an information message. Extra long text used as an information
139+
message - 2. Extra long text used as an information message - 3.
140+
</div>
141+
<div slot="valueStateMessage">
142+
Information message 2. This is a <a href="#">Link</a>. Extra long text
143+
used as an information message. Extra long text used as an information
144+
message - 2. Extra long text used as an information message - 3.
145+
</div>
146+
</ui5-toolbar-select>
147+
<ui5-toolbar-select value-state="Information">
148+
<ui5-toolbar-select-option icon="meal">Blueberry</ui5-toolbar-select-option>
149+
<ui5-toolbar-select-option icon="meal">Grape</ui5-toolbar-select-option>
150+
<ui5-toolbar-select-option icon="meal" selected="">Plum</ui5-toolbar-select-option>
151+
<div slot="valueStateMessage">
152+
Information message. This is a <a href="#">Link</a>. Extra long text
153+
used as an information message. Extra long text used as an information
154+
message - 2. Extra long text used as an information message - 3.
155+
</div>
156+
<div slot="valueStateMessage">
157+
Information message 2. This is a <a href="#">Link</a>. Extra long text
158+
used as an information message. Extra long text used as an information
159+
message - 2. Extra long text used as an information message - 3.
160+
</div>
161+
</ui5-toolbar-select>
162+
`
163+
};
164+

packages/playground/build-scripts-storybook/documentation-prepare.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ const docsGenerator = new DocsGenerator({
1111
reader: new DocsReader({
1212
directoryUtils,
1313
src: directoryUtils.joinPath("../../../docs/**/*.md"),
14-
ignore: ["/**/*/README.md", "/**/*/images", "/**/*/changelog"],
14+
ignore: ["/**/*/README.md", "/**/*/images", "/**/*/changelog", "/**/*/internal"],
1515
}),
1616
parsers: [
1717
new MetadataParser(),

0 commit comments

Comments
 (0)