diff --git a/packages/angular-test-app/src/preview-examples/toast-position.ts b/packages/angular-test-app/src/preview-examples/toast-position.ts
new file mode 100644
index 00000000000..f7d54a13737
--- /dev/null
+++ b/packages/angular-test-app/src/preview-examples/toast-position.ts
@@ -0,0 +1,38 @@
+/*
+ * SPDX-FileCopyrightText: 2023 Siemens AG
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+import { Component, TemplateRef, ViewChild } from '@angular/core';
+import { ToastService } from '@siemens/ix-angular';
+
+@Component({
+ selector: 'app-example',
+ template: `
+
+ Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy
+ eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam
+ voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet
+ clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit
+ amet.
+
+ Show Toast
+ `,
+})
+export default class Toast {
+ @ViewChild('customToast', { read: TemplateRef })
+ customModalRef!: TemplateRef;
+
+ constructor(private readonly toastService: ToastService) {}
+
+ async showToastMessage() {
+ this.toastService.setPosition('top-right');
+ this.toastService.show({
+ message: 'Hello World!',
+ });
+ }
+}
diff --git a/packages/angular/src/toast/toast.service.ts b/packages/angular/src/toast/toast.service.ts
index 6fe0313d8ad..7ab1db567d1 100644
--- a/packages/angular/src/toast/toast.service.ts
+++ b/packages/angular/src/toast/toast.service.ts
@@ -8,14 +8,26 @@
*/
import { Injectable } from '@angular/core';
-import { toast, ToastConfig as IxToastConfig } from '@siemens/ix';
+import {
+ getToastContainer,
+ toast,
+ ToastConfig as IxToastConfig,
+} from '@siemens/ix';
import { ToastConfig } from './toast.config';
@Injectable({
providedIn: 'root',
})
export class ToastService {
- public async show(config: ToastConfig) {
+ setPosition(position: 'bottom-right' | 'top-right') {
+ getToastContainer().position = position;
+ }
+
+ getPosition() {
+ return getToastContainer().position;
+ }
+
+ async show(config: ToastConfig) {
if (typeof config.message === 'string') {
return toast(config as IxToastConfig);
}
diff --git a/packages/core/component-doc.json b/packages/core/component-doc.json
index 2db85c000f6..533a693d83e 100644
--- a/packages/core/component-doc.json
+++ b/packages/core/component-doc.json
@@ -8243,7 +8243,7 @@
},
{
"name": "position",
- "type": "string",
+ "type": "\"bottom-right\" | \"top-right\"",
"mutable": false,
"attr": "position",
"reflectToAttr": false,
@@ -8252,6 +8252,11 @@
"default": "'bottom-right'",
"values": [
{
+ "value": "bottom-right",
+ "type": "string"
+ },
+ {
+ "value": "top-right",
"type": "string"
}
],
diff --git a/packages/core/src/components.d.ts b/packages/core/src/components.d.ts
index 76dcbf98a8f..c8ab8bf6a2e 100644
--- a/packages/core/src/components.d.ts
+++ b/packages/core/src/components.d.ts
@@ -1395,7 +1395,7 @@ export namespace Components {
interface IxToastContainer {
"containerClass": string;
"containerId": string;
- "position": string;
+ "position": 'bottom-right' | 'top-right';
/**
* Display a toast message
* @param config
@@ -3743,7 +3743,7 @@ declare namespace LocalJSX {
interface IxToastContainer {
"containerClass"?: string;
"containerId"?: string;
- "position"?: string;
+ "position"?: 'bottom-right' | 'top-right';
}
interface IxToggle {
/**
diff --git a/packages/core/src/components/toast/styles/toast-container.scss b/packages/core/src/components/toast/styles/toast-container.scss
index 1f895dbeb1f..c085b0caac5 100644
--- a/packages/core/src/components/toast/styles/toast-container.scss
+++ b/packages/core/src/components/toast/styles/toast-container.scss
@@ -20,6 +20,11 @@
position: fixed;
}
+.toast-container--top-right {
+ right: 1rem;
+ top: 2rem;
+}
+
.toast-container--bottom-right {
right: 1rem;
bottom: 2rem;
diff --git a/packages/core/src/components/toast/toast-container.tsx b/packages/core/src/components/toast/toast-container.tsx
index c0d17886bf6..a4265668242 100644
--- a/packages/core/src/components/toast/toast-container.tsx
+++ b/packages/core/src/components/toast/toast-container.tsx
@@ -7,7 +7,15 @@
* LICENSE file in the root directory of this source tree.
*/
-import { Component, Element, h, Host, Method, Prop } from '@stencil/core';
+import {
+ Component,
+ Element,
+ h,
+ Host,
+ Method,
+ Prop,
+ Watch,
+} from '@stencil/core';
import { TypedEvent } from '../utils/typed-event';
import { ToastConfig } from './toast-utils';
@@ -28,7 +36,9 @@ export class ToastContainer {
/**
*/
- @Prop() position = 'bottom-right';
+ @Prop() position: 'bottom-right' | 'top-right' = 'bottom-right';
+
+ private readonly PREFIX_POSITION_CLASS = 'toast-container--';
get hostContainer() {
return document.getElementById(this.containerId);
@@ -39,11 +49,22 @@ export class ToastContainer {
const toastContainer = document.createElement('div');
toastContainer.id = this.containerId;
toastContainer.classList.add(this.containerClass);
- toastContainer.classList.add(`toast-container--${this.position}`);
+ toastContainer.classList.add(
+ `${this.PREFIX_POSITION_CLASS}${this.position}`
+ );
document.body.appendChild(toastContainer);
}
}
+ @Watch('position')
+ onPositionChange(newPosition: string, oldPosition: string) {
+ const toastContainer = document.getElementById(this.containerId);
+ toastContainer.classList.remove(
+ `${this.PREFIX_POSITION_CLASS}${oldPosition}`
+ );
+ toastContainer.classList.add(`${this.PREFIX_POSITION_CLASS}${newPosition}`);
+ }
+
/**
* Display a toast message
* @param config
diff --git a/packages/core/src/components/toast/toast-utils.ts b/packages/core/src/components/toast/toast-utils.ts
index f289dde82dd..5c40a125995 100644
--- a/packages/core/src/components/toast/toast-utils.ts
+++ b/packages/core/src/components/toast/toast-utils.ts
@@ -8,6 +8,7 @@
*/
export type ToastType = 'info' | 'success' | 'error' | 'warning';
+export type ToastPosition = 'bottom-right' | 'top-right';
export interface ToastConfig {
title?: string;
@@ -19,7 +20,7 @@ export interface ToastConfig {
iconColor?: string;
}
-function getToastContainer() {
+export function getToastContainer() {
const containerList = Array.from(
document.querySelectorAll('ix-toast-container')
);
@@ -39,6 +40,10 @@ function getToastContainer() {
return container;
}
+export function setToastPosition(position: ToastPosition) {
+ getToastContainer().position = position;
+}
+
async function toast(config: ToastConfig) {
const context = getToastContainer();
const toast = await context.showToast(config);
diff --git a/packages/core/src/tests/toast/position/index.html b/packages/core/src/tests/toast/position/index.html
new file mode 100644
index 00000000000..fe470c055f8
--- /dev/null
+++ b/packages/core/src/tests/toast/position/index.html
@@ -0,0 +1,78 @@
+
+
+
+
+
+
+ Stencil Component Starter
+
+
+
+
+
+
+
diff --git a/packages/core/src/tests/toast/toast.e2e.ts b/packages/core/src/tests/toast/toast.e2e.ts
index f615cd0923c..63f455dc81e 100644
--- a/packages/core/src/tests/toast/toast.e2e.ts
+++ b/packages/core/src/tests/toast/toast.e2e.ts
@@ -16,4 +16,10 @@ regressionTest.describe('toast', () => {
await page.waitForTimeout(200);
expect(await page.screenshot({ fullPage: true })).toMatchSnapshot();
});
+
+ regressionTest('position', async ({ page }) => {
+ await page.goto('toast/position');
+ await page.waitForTimeout(200);
+ expect(await page.screenshot({ fullPage: true })).toMatchSnapshot();
+ });
});
diff --git a/packages/core/src/tests/toast/toast.e2e.ts-snapshots/toast-position-1-chromium---theme-classic-dark-linux.png b/packages/core/src/tests/toast/toast.e2e.ts-snapshots/toast-position-1-chromium---theme-classic-dark-linux.png
new file mode 100644
index 00000000000..075853d3558
Binary files /dev/null and b/packages/core/src/tests/toast/toast.e2e.ts-snapshots/toast-position-1-chromium---theme-classic-dark-linux.png differ
diff --git a/packages/core/src/tests/toast/toast.e2e.ts-snapshots/toast-position-1-chromium---theme-classic-light-linux.png b/packages/core/src/tests/toast/toast.e2e.ts-snapshots/toast-position-1-chromium---theme-classic-light-linux.png
new file mode 100644
index 00000000000..416fc10b8c5
Binary files /dev/null and b/packages/core/src/tests/toast/toast.e2e.ts-snapshots/toast-position-1-chromium---theme-classic-light-linux.png differ
diff --git a/packages/documentation/docs/controls/toast.md b/packages/documentation/docs/controls/toast.md
index 24aaae7dc25..0c559dc15d7 100644
--- a/packages/documentation/docs/controls/toast.md
+++ b/packages/documentation/docs/controls/toast.md
@@ -1,5 +1,6 @@
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
+import { ApiTableSinceTag } from '@site/src/components/ApiTableTag';
import Playground from '@site/src/components/Playground';
import SourceToast from './../auto-generated/previews/web-component/toast.md';
@@ -12,6 +13,11 @@ import SourceAngularToastCustom from './../auto-generated/previews/angular/toast
import SourceReactToastCustom from './../auto-generated/previews/react/toast-custom.md';
import SourceVueToastCustom from './../auto-generated/previews/vue/toast-custom.md';
+import SourceToastPosition from './../auto-generated/previews/web-component/toast-position.md';
+import SourceAngularToastPosition from './../auto-generated/previews/angular/toast-position.ts.md';
+import SourceReactToastPosition from './../auto-generated/previews/react/toast-position.md';
+import SourceVueToastPosition from './../auto-generated/previews/vue/toast-position.md';
+
import ApiToastConfigJavaScript from './\_toast/javascript/toast-config.md';
import ApiToastServiceAngular from './\_toast/angular/toast-service.html.md';
@@ -42,6 +48,19 @@ frameworks={{
vue: SourceVueToastCustom
}}>
+## Position
+
+
+
+
+
## API
diff --git a/packages/html-test-app/src/preview-examples/toast-position.html b/packages/html-test-app/src/preview-examples/toast-position.html
new file mode 100644
index 00000000000..55af39d7140
--- /dev/null
+++ b/packages/html-test-app/src/preview-examples/toast-position.html
@@ -0,0 +1,33 @@
+
+
+
+
+
+ Test example
+
+
+
+
+
+ Trigger toast
+
+
+
+
+
diff --git a/packages/react-test-app/src/preview-examples/toast-position.tsx b/packages/react-test-app/src/preview-examples/toast-position.tsx
new file mode 100644
index 00000000000..d899f60868d
--- /dev/null
+++ b/packages/react-test-app/src/preview-examples/toast-position.tsx
@@ -0,0 +1,36 @@
+/*
+ * SPDX-FileCopyrightText: 2023 Siemens AG
+ *
+ * SPDX-License-Identifier: MIT
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+import { setToastPosition, ToastPosition } from '@siemens/ix';
+import { IxButton, showToast } from '@siemens/ix-react';
+import React, { useEffect } from 'react';
+
+function useToastPosition(position: ToastPosition) {
+ useEffect(() => {
+ setToastPosition(position);
+ }, []);
+}
+
+export default () => {
+ useToastPosition('top-right');
+
+ return (
+ <>
+ {
+ showToast({
+ message: 'My toast message!',
+ });
+ }}
+ >
+ Trigger toast
+
+ >
+ );
+};
diff --git a/packages/vue-test-app/src/Root.vue b/packages/vue-test-app/src/Root.vue
index ac77d4fc6bc..9905ffedba4 100644
--- a/packages/vue-test-app/src/Root.vue
+++ b/packages/vue-test-app/src/Root.vue
@@ -70,6 +70,7 @@ import Tile from './preview-examples/tile.vue';
import Timepicker from './preview-examples/timepicker.vue';
import ToastCustom from './preview-examples/toast-custom.vue';
import Toast from './preview-examples/toast.vue';
+import ToastPosition from './preview-examples/toast-position.vue';
import ToggleColor from './preview-examples/toggle-color.vue';
import ToggleCustomLabel from './preview-examples/toggle-custom-label.vue';
import ToggleDisabled from './preview-examples/toggle-disabled.vue';
@@ -135,6 +136,7 @@ const routes: any = {
'/preview/timepicker': Timepicker,
'/preview/toast': Toast,
'/preview/toast-custom': ToastCustom,
+ '/preview/toast-position': ToastPosition,
'/preview/toggle': Toggle,
'/preview/toggle-disabled': ToggleDisabled,
'/preview/toggle-color': ToggleColor,
diff --git a/packages/vue-test-app/src/preview-examples/toast-position.vue b/packages/vue-test-app/src/preview-examples/toast-position.vue
new file mode 100644
index 00000000000..6b2374ed148
--- /dev/null
+++ b/packages/vue-test-app/src/preview-examples/toast-position.vue
@@ -0,0 +1,11 @@
+
+
+
+
+ Trigger toast
+
+
diff --git a/packages/vue/src/toast/toast.ts b/packages/vue/src/toast/toast.ts
index 424ace54b6e..9b6491db278 100644
--- a/packages/vue/src/toast/toast.ts
+++ b/packages/vue/src/toast/toast.ts
@@ -7,12 +7,20 @@
* LICENSE file in the root directory of this source tree.
*/
-import { toast, ToastConfig as IxToastConfig } from '@siemens/ix';
+import {
+ getToastContainer,
+ toast,
+ ToastConfig as IxToastConfig,
+} from '@siemens/ix';
export type ToastConfig = {
message: string | HTMLElement;
};
+export function setToastPosition(position: 'bottom-right' | 'top-right') {
+ getToastContainer().position = position;
+}
+
export async function showToast(
config: Omit & ToastConfig
) {