@reliability-design/web 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/dist/components/rel-accordion/rel-accordion.stories.ts +313 -0
  2. package/dist/components/rel-accordion/rel-accordion.ts +114 -0
  3. package/dist/components/rel-alert/rel-alert.stories.ts +412 -0
  4. package/dist/components/rel-alert/rel-alert.ts +194 -0
  5. package/dist/components/rel-avatar/rel-avatar.stories.ts +327 -0
  6. package/dist/components/rel-avatar/rel-avatar.ts +100 -0
  7. package/dist/components/rel-badge/rel-badge.stories.ts +350 -0
  8. package/dist/components/rel-badge/rel-badge.ts +70 -0
  9. package/dist/components/rel-breadcrumb/rel-breadcrumb.stories.ts +306 -0
  10. package/dist/components/rel-breadcrumb/rel-breadcrumb.ts +97 -0
  11. package/dist/components/rel-button/rel-button.stories.ts +356 -0
  12. package/dist/components/rel-button/rel-button.ts +204 -0
  13. package/dist/components/rel-card/rel-card.stories.ts +299 -0
  14. package/dist/components/rel-card/rel-card.ts +33 -0
  15. package/dist/components/rel-cardmedia/rel-cardmedia.stories.ts +368 -0
  16. package/dist/components/rel-cardmedia/rel-cardmedia.ts +80 -0
  17. package/dist/components/rel-checkbox/rel-checkbox.stories.ts +414 -0
  18. package/dist/components/rel-checkbox/rel-checkbox.ts +164 -0
  19. package/dist/components/rel-chip/rel-chip.stories.ts +552 -0
  20. package/dist/components/rel-chip/rel-chip.ts +261 -0
  21. package/dist/components/rel-container/rel-container.stories.ts +239 -0
  22. package/dist/components/rel-container/rel-container.ts +74 -0
  23. package/dist/components/rel-divider/rel-divider.stories.ts +229 -0
  24. package/dist/components/rel-divider/rel-divider.ts +44 -0
  25. package/dist/components/rel-layout/rel-layout.stories.ts +713 -0
  26. package/dist/components/rel-layout/rel-layout.ts +60 -0
  27. package/dist/components/rel-menu/rel-menu.stories.ts +910 -0
  28. package/dist/components/rel-menu/rel-menu.ts +319 -0
  29. package/dist/components/rel-progress/rel-progress.stories.ts +817 -0
  30. package/dist/components/rel-progress/rel-progress.ts +182 -0
  31. package/dist/components/rel-radio/rel-radio.stories.ts +1048 -0
  32. package/dist/components/rel-radio/rel-radio.ts +187 -0
  33. package/dist/components/rel-segmented-button/rel-segmented-button.stories.ts +1079 -0
  34. package/dist/components/rel-segmented-button/rel-segmented-button.ts +150 -0
  35. package/dist/components/rel-select/rel-select.stories.ts +1201 -0
  36. package/dist/components/rel-select/rel-select.ts +261 -0
  37. package/dist/components/rel-slider/rel-slider.stories.ts +730 -0
  38. package/dist/components/rel-slider/rel-slider.ts +440 -0
  39. package/dist/components/rel-snackbar/rel-snackbar.stories.ts +808 -0
  40. package/dist/components/rel-snackbar/rel-snackbar.ts +212 -0
  41. package/dist/components/rel-stepper/rel-stepper.stories.ts +752 -0
  42. package/dist/components/rel-stepper/rel-stepper.ts +425 -0
  43. package/dist/components/rel-switch/rel-switch.stories.ts +441 -0
  44. package/dist/components/rel-switch/rel-switch.ts +161 -0
  45. package/dist/components/rel-tab/rel-tab.stories.ts +492 -0
  46. package/dist/components/rel-tab/rel-tab.ts +145 -0
  47. package/dist/components/rel-textfield/rel-textfield.stories.ts +710 -0
  48. package/dist/components/rel-textfield/rel-textfield.ts +224 -0
  49. package/dist/components/rel-toast/rel-toast.stories.ts +394 -0
  50. package/dist/components/rel-toast/rel-toast.ts +154 -0
  51. package/dist/components/rel-tooltip/rel-tooltip.stories.ts +364 -0
  52. package/dist/components/rel-tooltip/rel-tooltip.ts +80 -0
  53. package/dist/index.d.mts +372 -0
  54. package/dist/index.d.ts +372 -0
  55. package/dist/index.js +4593 -0
  56. package/dist/index.js.map +1 -0
  57. package/dist/index.mjs +4544 -0
  58. package/dist/index.mjs.map +1 -0
  59. package/dist/styles/vars.css +184 -0
  60. package/package.json +32 -0
@@ -0,0 +1,224 @@
1
+ import { LitElement, html, css } from "lit";
2
+ import { customElement, property, state } from "lit/decorators.js";
3
+
4
+ export type TextFieldState = "default" | "focused" | "error" | "disabled";
5
+ export type TextFieldSize = "small" | "medium" | "large";
6
+
7
+ @customElement("rel-textfield")
8
+ export class RelTextfield extends LitElement {
9
+ @property({ type: String }) label?: string;
10
+ @property({ type: String }) placeholder: string = "";
11
+ @property({ type: String }) type: string = "text";
12
+ @property({ type: String }) value: string = "";
13
+ @property({ type: String }) leftIcon?: string;
14
+ @property({ type: String }) rightIcon?: string;
15
+ @property({ type: String }) supportingText?: string;
16
+ @property({ type: String }) state: TextFieldState = "default";
17
+ @property({ type: String }) size: TextFieldSize = "medium";
18
+
19
+ @state() private internalState: TextFieldState = "default";
20
+
21
+ static styles = css`
22
+ :host {
23
+ display: block;
24
+ font-family: var(--rel-fontFamilies-primary);
25
+ }
26
+
27
+ /* Wrapper */
28
+ .textfield-wrapper {
29
+ display: flex;
30
+ flex-direction: column;
31
+ gap: 4px;
32
+ width: 100%;
33
+ }
34
+
35
+ /* Label */
36
+ .textfield-label {
37
+ font-size: 0.85rem;
38
+ font-weight: 500;
39
+ color: #111;
40
+ }
41
+
42
+ /* Container */
43
+ .textfield-container {
44
+ display: flex;
45
+ align-items: center;
46
+ position: relative;
47
+ border: 1px solid #ccc;
48
+ border-radius: 6px;
49
+ background: white;
50
+ transition: border 0.2s;
51
+ }
52
+
53
+ .textfield-container.disabled {
54
+ background: #f5f5f5;
55
+ cursor: not-allowed;
56
+ }
57
+
58
+ /* Input */
59
+ .textfield-input {
60
+ flex: 1;
61
+ border: none;
62
+ outline: none;
63
+ font-size: 0.9rem;
64
+ padding: 0.5rem 0.75rem;
65
+ background: transparent;
66
+ font-family: var(--rel-fontFamilies-primary);
67
+ }
68
+
69
+ .textfield-input:disabled {
70
+ cursor: not-allowed;
71
+ color: #999;
72
+ }
73
+
74
+ .icon {
75
+ position: absolute;
76
+ display: flex;
77
+ pointer-events: none;
78
+ color: #7e8186;
79
+ }
80
+
81
+ .icon.left {
82
+ left: 8px;
83
+ }
84
+
85
+ .icon.right {
86
+ right: 8px;
87
+ }
88
+
89
+ .textfield-wrapper.small .textfield-input {
90
+ padding: 0.5rem 1rem;
91
+ font-size: 0.9rem;
92
+ }
93
+
94
+ .textfield-wrapper.medium .textfield-input {
95
+ padding: 0.688rem 1rem;
96
+ font-size: 1rem;
97
+ }
98
+
99
+ .textfield-wrapper.large .textfield-input {
100
+ padding: 0.875rem 1rem;
101
+ font-size: 1.1rem;
102
+ }
103
+
104
+ /* Adjust padding when icons are present */
105
+ .textfield-wrapper .textfield-input.has-left-icon {
106
+ padding-left: 2.5rem;
107
+ }
108
+
109
+ .textfield-wrapper .textfield-input.has-right-icon {
110
+ padding-right: 2.5rem;
111
+ }
112
+
113
+ /* States */
114
+ .textfield-wrapper.focused .textfield-container {
115
+ border-color: #111;
116
+ }
117
+
118
+ .textfield-wrapper.error .textfield-container {
119
+ border-color: #d50000;
120
+ }
121
+
122
+ .textfield-wrapper.disabled .textfield-container {
123
+ border-color: #d7d9db;
124
+ }
125
+
126
+ /* Supporting text */
127
+ .textfield-support {
128
+ font-size: 0.75rem;
129
+ color: #666;
130
+ }
131
+
132
+ .textfield-support.error {
133
+ color: #d50000;
134
+ }
135
+ `;
136
+
137
+ private get currentState(): TextFieldState {
138
+ return this.state !== "default" ? this.state : this.internalState;
139
+ }
140
+
141
+ private handleFocus() {
142
+ if (this.state !== "disabled" && this.state !== "error") {
143
+ this.internalState = "focused";
144
+ }
145
+ }
146
+
147
+ private handleBlur() {
148
+ if (this.internalState === "focused") {
149
+ this.internalState = "default";
150
+ }
151
+ }
152
+
153
+ private handleInput(e: Event) {
154
+ const input = e.target as HTMLInputElement;
155
+ this.value = input.value;
156
+ this.dispatchEvent(
157
+ new CustomEvent("input-change", {
158
+ detail: { value: this.value },
159
+ bubbles: true,
160
+ composed: true,
161
+ })
162
+ );
163
+ }
164
+
165
+ render() {
166
+ const wrapperClasses = [
167
+ "textfield-wrapper",
168
+ this.size,
169
+ this.currentState,
170
+ ].join(" ");
171
+
172
+ const inputClasses = [
173
+ "textfield-input",
174
+ this.leftIcon ? "has-left-icon" : "",
175
+ this.rightIcon ? "has-right-icon" : "",
176
+ ]
177
+ .filter(Boolean)
178
+ .join(" ");
179
+
180
+ return html`
181
+ <div class="${wrapperClasses}">
182
+ ${this.label
183
+ ? html`<label class="textfield-label">${this.label}</label>`
184
+ : ""}
185
+
186
+ <div
187
+ class="textfield-container ${this.state === "disabled"
188
+ ? "disabled"
189
+ : ""}"
190
+ >
191
+ ${this.leftIcon
192
+ ? html`<span class="icon left">${this.leftIcon}</span>`
193
+ : ""}
194
+
195
+ <input
196
+ type="${this.type}"
197
+ class="${inputClasses}"
198
+ placeholder="${this.placeholder}"
199
+ .value="${this.value}"
200
+ ?disabled="${this.state === "disabled"}"
201
+ aria-invalid="${this.state === "error"}"
202
+ @focus="${this.handleFocus}"
203
+ @blur="${this.handleBlur}"
204
+ @input="${this.handleInput}"
205
+ />
206
+
207
+ ${this.rightIcon
208
+ ? html`<span class="icon right">${this.rightIcon}</span>`
209
+ : ""}
210
+ </div>
211
+
212
+ ${this.supportingText
213
+ ? html`<div
214
+ class="textfield-support ${this.state === "error"
215
+ ? "error"
216
+ : ""}"
217
+ >
218
+ ${this.supportingText}
219
+ </div>`
220
+ : ""}
221
+ </div>
222
+ `;
223
+ }
224
+ }
@@ -0,0 +1,394 @@
1
+ import type { Meta, StoryObj } from '@storybook/web-components-vite';
2
+ import { html } from 'lit';
3
+ import './rel-toast';
4
+
5
+ /**
6
+ * The Toast component displays brief, temporary notifications at the bottom of the screen.
7
+ * Built with Lit web components for framework-agnostic usage.
8
+ *
9
+ * ## Features
10
+ * - **2 Types**: default (dark), error (red)
11
+ * - **Action Button**: Optional action with custom label
12
+ * - **Auto Dismiss**: Configurable duration (default 4000ms)
13
+ * - **Manual Dismiss**: Close button always available
14
+ * - **Animations**: Smooth fade-in-up animation
15
+ * - **Programmatic Control**: show() and close() methods
16
+ */
17
+ const meta: Meta = {
18
+ title: 'Components/Toast',
19
+ tags: ['autodocs'],
20
+ component: 'rel-toast',
21
+ argTypes: {
22
+ message: {
23
+ control: 'text',
24
+ description: 'Message to display in the toast',
25
+ table: {
26
+ type: { summary: 'string' },
27
+ },
28
+ },
29
+ type: {
30
+ control: { type: 'select' },
31
+ options: ['default', 'error'],
32
+ description: 'Visual style of the toast',
33
+ table: {
34
+ defaultValue: { summary: 'default' },
35
+ type: { summary: 'string' },
36
+ },
37
+ },
38
+ actionLabel: {
39
+ control: 'text',
40
+ description: 'Label for the action button (optional)',
41
+ table: {
42
+ type: { summary: 'string' },
43
+ },
44
+ },
45
+ duration: {
46
+ control: 'number',
47
+ description: 'Auto-dismiss duration in milliseconds (0 = no auto-dismiss)',
48
+ table: {
49
+ defaultValue: { summary: 4000 },
50
+ type: { summary: 'number' },
51
+ },
52
+ },
53
+ },
54
+ };
55
+
56
+ export default meta;
57
+ type Story = StoryObj;
58
+
59
+ /**
60
+ * Default toast - standard notification with dark background
61
+ */
62
+ export const Default: Story = {
63
+ render: () => {
64
+ const showToast = () => {
65
+ const toast = document.querySelector('rel-toast') as any;
66
+ if (toast) toast.show();
67
+ };
68
+ return html`
69
+ <div>
70
+ <button @click="${showToast}" style="padding: 12px 24px; background: #111; color: white; border: none; border-radius: 6px; cursor: pointer;">
71
+ Show Toast
72
+ </button>
73
+ <rel-toast message="This is a toast notification"></rel-toast>
74
+ </div>
75
+ `;
76
+ },
77
+ };
78
+
79
+ /**
80
+ * Error toast - error notification with red background
81
+ */
82
+ export const ErrorToast: Story = {
83
+ render: () => {
84
+ const showToast = () => {
85
+ const toast = document.querySelector('rel-toast') as any;
86
+ if (toast) toast.show();
87
+ };
88
+ return html`
89
+ <div>
90
+ <button @click="${showToast}" style="padding: 12px 24px; background: #d50000; color: white; border: none; border-radius: 6px; cursor: pointer;">
91
+ Show Error Toast
92
+ </button>
93
+ <rel-toast message="An error occurred!" type="error"></rel-toast>
94
+ </div>
95
+ `;
96
+ },
97
+ };
98
+
99
+ /**
100
+ * With action button - toast with actionable button
101
+ */
102
+ export const WithAction: Story = {
103
+ render: () => {
104
+ const showToast = () => {
105
+ const toast = document.querySelector('rel-toast') as any;
106
+ if (toast) toast.show();
107
+ };
108
+ const handleAction = () => {
109
+ alert('Action clicked!');
110
+ };
111
+ return html`
112
+ <div>
113
+ <button @click="${showToast}" style="padding: 12px 24px; background: #111; color: white; border: none; border-radius: 6px; cursor: pointer;">
114
+ Show Toast with Action
115
+ </button>
116
+ <rel-toast
117
+ message="Item added to cart"
118
+ actionLabel="UNDO"
119
+ @action="${handleAction}"
120
+ ></rel-toast>
121
+ </div>
122
+ `;
123
+ },
124
+ };
125
+
126
+ /**
127
+ * Without action - simple toast with just message and close button
128
+ */
129
+ export const WithoutAction: Story = {
130
+ render: () => {
131
+ const showToast = () => {
132
+ const toast = document.querySelector('rel-toast') as any;
133
+ if (toast) toast.show();
134
+ };
135
+ return html`
136
+ <div>
137
+ <button @click="${showToast}" style="padding: 12px 24px; background: #111; color: white; border: none; border-radius: 6px; cursor: pointer;">
138
+ Show Simple Toast
139
+ </button>
140
+ <rel-toast message="Changes saved successfully"></rel-toast>
141
+ </div>
142
+ `;
143
+ },
144
+ };
145
+
146
+ /**
147
+ * Long duration - toast that stays visible for 8 seconds
148
+ */
149
+ export const LongDuration: Story = {
150
+ render: () => {
151
+ const showToast = () => {
152
+ const toast = document.querySelector('rel-toast') as any;
153
+ if (toast) toast.show();
154
+ };
155
+ return html`
156
+ <div>
157
+ <button @click="${showToast}" style="padding: 12px 24px; background: #111; color: white; border: none; border-radius: 6px; cursor: pointer;">
158
+ Show Long Toast (8s)
159
+ </button>
160
+ <rel-toast message="This toast will stay for 8 seconds" duration="8000"></rel-toast>
161
+ </div>
162
+ `;
163
+ },
164
+ };
165
+
166
+ /**
167
+ * Short duration - toast that dismisses quickly (2 seconds)
168
+ */
169
+ export const ShortDuration: Story = {
170
+ render: () => {
171
+ const showToast = () => {
172
+ const toast = document.querySelector('rel-toast') as any;
173
+ if (toast) toast.show();
174
+ };
175
+ return html`
176
+ <div>
177
+ <button @click="${showToast}" style="padding: 12px 24px; background: #111; color: white; border: none; border-radius: 6px; cursor: pointer;">
178
+ Show Quick Toast (2s)
179
+ </button>
180
+ <rel-toast message="Quick message" duration="2000"></rel-toast>
181
+ </div>
182
+ `;
183
+ },
184
+ };
185
+
186
+ /**
187
+ * No auto-dismiss - toast stays until manually closed
188
+ */
189
+ export const NoAutoDismiss: Story = {
190
+ render: () => {
191
+ const showToast = () => {
192
+ const toast = document.querySelector('rel-toast') as any;
193
+ if (toast) toast.show();
194
+ };
195
+ return html`
196
+ <div>
197
+ <button @click="${showToast}" style="padding: 12px 24px; background: #111; color: white; border: none; border-radius: 6px; cursor: pointer;">
198
+ Show Persistent Toast
199
+ </button>
200
+ <rel-toast message="This toast won't auto-dismiss. Click X to close." duration="0"></rel-toast>
201
+ </div>
202
+ `;
203
+ },
204
+ };
205
+
206
+ /**
207
+ * Save notification - realistic save confirmation
208
+ */
209
+ export const SaveNotification: Story = {
210
+ render: () => {
211
+ const showToast = () => {
212
+ const toast = document.querySelector('rel-toast') as any;
213
+ if (toast) toast.show();
214
+ };
215
+ return html`
216
+ <div>
217
+ <button @click="${showToast}" style="padding: 12px 24px; background: #0edb90; color: #111; border: none; border-radius: 6px; cursor: pointer; font-weight: 600;">
218
+ Save Changes
219
+ </button>
220
+ <rel-toast message="Your changes have been saved"></rel-toast>
221
+ </div>
222
+ `;
223
+ },
224
+ };
225
+
226
+ /**
227
+ * Delete notification - error toast with undo action
228
+ */
229
+ export const DeleteNotification: Story = {
230
+ render: () => {
231
+ const showToast = () => {
232
+ const toast = document.querySelector('rel-toast') as any;
233
+ if (toast) toast.show();
234
+ };
235
+ const handleUndo = () => {
236
+ alert('Delete undone!');
237
+ };
238
+ return html`
239
+ <div>
240
+ <button @click="${showToast}" style="padding: 12px 24px; background: #d50000; color: white; border: none; border-radius: 6px; cursor: pointer;">
241
+ Delete Item
242
+ </button>
243
+ <rel-toast
244
+ message="Item deleted"
245
+ type="error"
246
+ actionLabel="UNDO"
247
+ @action="${handleUndo}"
248
+ ></rel-toast>
249
+ </div>
250
+ `;
251
+ },
252
+ };
253
+
254
+ /**
255
+ * Network error - error toast for connection issues
256
+ */
257
+ export const NetworkError: Story = {
258
+ render: () => {
259
+ const showToast = () => {
260
+ const toast = document.querySelector('rel-toast') as any;
261
+ if (toast) toast.show();
262
+ };
263
+ const handleRetry = () => {
264
+ alert('Retrying...');
265
+ };
266
+ return html`
267
+ <div>
268
+ <button @click="${showToast}" style="padding: 12px 24px; background: #d50000; color: white; border: none; border-radius: 6px; cursor: pointer;">
269
+ Simulate Network Error
270
+ </button>
271
+ <rel-toast
272
+ message="Network connection failed"
273
+ type="error"
274
+ actionLabel="RETRY"
275
+ duration="0"
276
+ @action="${handleRetry}"
277
+ ></rel-toast>
278
+ </div>
279
+ `;
280
+ },
281
+ };
282
+
283
+ /**
284
+ * Copy notification - confirmation for copy action
285
+ */
286
+ export const CopyNotification: Story = {
287
+ render: () => {
288
+ const showToast = () => {
289
+ const toast = document.querySelector('rel-toast') as any;
290
+ if (toast) toast.show();
291
+ };
292
+ return html`
293
+ <div>
294
+ <button @click="${showToast}" style="padding: 12px 24px; background: #111; color: white; border: none; border-radius: 6px; cursor: pointer;">
295
+ Copy to Clipboard
296
+ </button>
297
+ <rel-toast message="Copied to clipboard" duration="2000"></rel-toast>
298
+ </div>
299
+ `;
300
+ },
301
+ };
302
+
303
+ /**
304
+ * Multiple toasts demo - shows handling of sequential toasts
305
+ */
306
+ export const MultipleToasts: Story = {
307
+ render: () => {
308
+ let toastCount = 0;
309
+ const showToast = () => {
310
+ toastCount++;
311
+ const container = document.querySelector('#toast-container');
312
+ if (container) {
313
+ const toast = document.createElement('rel-toast') as any;
314
+ toast.setAttribute('message', `Toast notification #${toastCount}`);
315
+ toast.style.position = 'fixed';
316
+ toast.style.bottom = `${24 + (toastCount - 1) * 70}px`;
317
+ container.appendChild(toast);
318
+ toast.show();
319
+
320
+ // Clean up after toast dismisses
321
+ toast.addEventListener('dismissed', () => {
322
+ setTimeout(() => {
323
+ container.removeChild(toast);
324
+ toastCount--;
325
+ }, 300);
326
+ });
327
+ }
328
+ };
329
+ return html`
330
+ <div>
331
+ <button @click="${showToast}" style="padding: 12px 24px; background: #111; color: white; border: none; border-radius: 6px; cursor: pointer;">
332
+ Show Multiple Toasts
333
+ </button>
334
+ <div id="toast-container"></div>
335
+ </div>
336
+ `;
337
+ },
338
+ };
339
+
340
+ /**
341
+ * All types showcase - displays both toast types
342
+ */
343
+ export const AllTypes: Story = {
344
+ render: () => {
345
+ const showDefaultToast = () => {
346
+ const toast = document.querySelector('#default-toast') as any;
347
+ if (toast) toast.show();
348
+ };
349
+ const showErrorToast = () => {
350
+ const toast = document.querySelector('#error-toast') as any;
351
+ if (toast) toast.show();
352
+ };
353
+ return html`
354
+ <div style="display: flex; gap: 16px;">
355
+ <button @click="${showDefaultToast}" style="padding: 12px 24px; background: #111; color: white; border: none; border-radius: 6px; cursor: pointer;">
356
+ Show Default
357
+ </button>
358
+ <button @click="${showErrorToast}" style="padding: 12px 24px; background: #d50000; color: white; border: none; border-radius: 6px; cursor: pointer;">
359
+ Show Error
360
+ </button>
361
+ <rel-toast id="default-toast" message="Default toast notification" type="default"></rel-toast>
362
+ <rel-toast id="error-toast" message="Error toast notification" type="error"></rel-toast>
363
+ </div>
364
+ `;
365
+ },
366
+ };
367
+
368
+ /**
369
+ * Action variations - toasts with and without actions
370
+ */
371
+ export const ActionVariations: Story = {
372
+ render: () => {
373
+ const showWithAction = () => {
374
+ const toast = document.querySelector('#with-action') as any;
375
+ if (toast) toast.show();
376
+ };
377
+ const showWithoutAction = () => {
378
+ const toast = document.querySelector('#without-action') as any;
379
+ if (toast) toast.show();
380
+ };
381
+ return html`
382
+ <div style="display: flex; gap: 16px;">
383
+ <button @click="${showWithAction}" style="padding: 12px 24px; background: #111; color: white; border: none; border-radius: 6px; cursor: pointer;">
384
+ With Action
385
+ </button>
386
+ <button @click="${showWithoutAction}" style="padding: 12px 24px; background: #111; color: white; border: none; border-radius: 6px; cursor: pointer;">
387
+ Without Action
388
+ </button>
389
+ <rel-toast id="with-action" message="Item added" actionLabel="UNDO"></rel-toast>
390
+ <rel-toast id="without-action" message="Operation completed"></rel-toast>
391
+ </div>
392
+ `;
393
+ },
394
+ };