If you have technical questions, please create a support ticket in the DevExpress Support Center.
import React, { useCallback, useState } from 'react';
import Button from 'devextreme-react/button';
import RadioGroup from 'devextreme-react/radio-group';
import SelectBox from 'devextreme-react/select-box';
import NumberBox from 'devextreme-react/number-box';
import Notify from 'devextreme/ui/notify';
import HideToasts from 'devextreme/ui/toast/hide_toasts';
import {
directions, positions, types, radioGroupItems, positionTopLabel, directionLabel,
positionBottomLabel, positionLeftLabel, positionRightLabel, positionLabel,
} from './data.ts';
type NotifyStack = (typeof Notify)['arguments'][1];
function App() {
const [id, setId] = useState(1);
const [isPredefined, setIsPredefined] = useState(true);
const [predefinedPosition, setPredefinedPosition] = useState('bottom center');
const [coordinatePosition, setCoordinatePosition] = useState({
top: undefined,
left: undefined,
bottom: undefined,
right: undefined,
});
const [direction, setDirection] = useState('up-push' as NotifyStack['direction']);
const topNumberBoxValueChanged = useCallback(
(top) => setCoordinatePosition({ coordinatePosition, top }),
[coordinatePosition, setCoordinatePosition],
);
const bottomNumberBoxValueChanged = useCallback(
(bottom) => setCoordinatePosition({ coordinatePosition, bottom }),
[coordinatePosition, setCoordinatePosition],
);
const leftNumberBoxValueChanged = useCallback(
(left) => setCoordinatePosition({ coordinatePosition, left }),
[coordinatePosition, setCoordinatePosition],
);
const rightNumberBoxValueChanged = useCallback(
(right) => setCoordinatePosition({ coordinatePosition, right }),
[coordinatePosition, setCoordinatePosition],
);
const show = useCallback(() => {
const position: NotifyStack['position'] = isPredefined ? predefinedPosition : coordinatePosition;
Notify({
message: `Toast ${id}`,
height: 45,
width: 150,
minWidth: 150,
type: types[Math.floor(Math.random() * 4)],
displayTime: 3500,
animation: {
show: {
type: 'fade', duration: 400, from: 0, to: 1,
},
hide: { type: 'fade', duration: 40, to: 0 },
},
}, {
position,
direction,
});
setId(id + 1);
}, [id, isPredefined, predefinedPosition, coordinatePosition, direction]);
return (
<React.Fragment>
<div className='options'>
<div>Position</div>
<RadioGroup
layout='horizontal'
defaultValue='predefined'
items={radioGroupItems}
onValueChange={(value) => setIsPredefined(value === 'predefined')} />
<SelectBox
items={positions}
value={predefinedPosition}
inputAttr={positionLabel}
onSelectionChanged={({ selectedItem }) => setPredefinedPosition(selectedItem)}
visible={isPredefined} />
<div className='section'>
<NumberBox
visible={!isPredefined}
placeholder='top'
defaultValue={null}
valueChangeEvent='keyup'
disabled={!!coordinatePosition.bottom}
inputAttr={positionTopLabel}
onValueChange={topNumberBoxValueChanged} />
<NumberBox
visible={!isPredefined}
placeholder='bottom'
defaultValue={null}
valueChangeEvent='keyup'
inputAttr={positionBottomLabel}
disabled={!!coordinatePosition.top}
onValueChange={bottomNumberBoxValueChanged} />
</div>
<div className='section'>
<NumberBox
visible={!isPredefined}
placeholder='left'
defaultValue={null}
valueChangeEvent='keyup'
inputAttr={positionLeftLabel}
disabled={!!coordinatePosition.right}
onValueChange={leftNumberBoxValueChanged} />
<NumberBox
visible={!isPredefined}
placeholder='right'
defaultValue={null}
valueChangeEvent='keyup'
inputAttr={positionRightLabel}
disabled={!!coordinatePosition.left}
onValueChange={rightNumberBoxValueChanged} />
</div>
<div>Direction</div>
<SelectBox
items={directions}
inputAttr={directionLabel}
value={direction}
onSelectionChanged={({ selectedItem }) => setDirection(selectedItem)} />
<div className='section'>
<Button text='Show' width='48%' onClick={show} />
<Button text='Hide all' width='48%' onClick={() => HideToasts()} />
</div>
</div>
</React.Fragment>
);
}
export default App;
xxxxxxxxxx
import React, { useCallback, useState } from 'react';
import Button from 'devextreme-react/button';
import RadioGroup from 'devextreme-react/radio-group';
import SelectBox from 'devextreme-react/select-box';
import NumberBox from 'devextreme-react/number-box';
import Notify from 'devextreme/ui/notify';
import HideToasts from 'devextreme/ui/toast/hide_toasts';
import {
directions,
positions,
types,
radioGroupItems,
positionTopLabel,
directionLabel,
positionBottomLabel,
positionLeftLabel,
positionRightLabel,
positionLabel,
} from './data.js';
function App() {
const [id, setId] = useState(1);
const [isPredefined, setIsPredefined] = useState(true);
const [predefinedPosition, setPredefinedPosition] = useState('bottom center');
const [coordinatePosition, setCoordinatePosition] = useState({
top: undefined,
left: undefined,
bottom: undefined,
right: undefined,
});
const [direction, setDirection] = useState('up-push');
const topNumberBoxValueChanged = useCallback(
(top) => setCoordinatePosition({ coordinatePosition, top }),
[coordinatePosition, setCoordinatePosition],
);
const bottomNumberBoxValueChanged = useCallback(
(bottom) => setCoordinatePosition({ coordinatePosition, bottom }),
[coordinatePosition, setCoordinatePosition],
);
const leftNumberBoxValueChanged = useCallback(
(left) => setCoordinatePosition({ coordinatePosition, left }),
[coordinatePosition, setCoordinatePosition],
);
const rightNumberBoxValueChanged = useCallback(
(right) => setCoordinatePosition({ coordinatePosition, right }),
[coordinatePosition, setCoordinatePosition],
);
const show = useCallback(() => {
const position = isPredefined ? predefinedPosition : coordinatePosition;
Notify(
{
message: `Toast ${id}`,
height: 45,
width: 150,
minWidth: 150,
type: types[Math.floor(Math.random() * 4)],
displayTime: 3500,
animation: {
show: {
type: 'fade',
duration: 400,
from: 0,
to: 1,
},
hide: { type: 'fade', duration: 40, to: 0 },
},
},
{
position,
direction,
},
);
setId(id + 1);
}, [id, isPredefined, predefinedPosition, coordinatePosition, direction]);
return (
<React.Fragment>
<div className="options">
<div>Position</div>
<RadioGroup
layout="horizontal"
defaultValue="predefined"
items={radioGroupItems}
onValueChange={(value) => setIsPredefined(value === 'predefined')}
/>
<SelectBox
items={positions}
value={predefinedPosition}
inputAttr={positionLabel}
onSelectionChanged={({ selectedItem }) => setPredefinedPosition(selectedItem)}
visible={isPredefined}
/>
<div className="section">
<NumberBox
visible={!isPredefined}
placeholder="top"
defaultValue={null}
valueChangeEvent="keyup"
disabled={!!coordinatePosition.bottom}
inputAttr={positionTopLabel}
onValueChange={topNumberBoxValueChanged}
/>
<NumberBox
visible={!isPredefined}
placeholder="bottom"
defaultValue={null}
valueChangeEvent="keyup"
inputAttr={positionBottomLabel}
disabled={!!coordinatePosition.top}
onValueChange={bottomNumberBoxValueChanged}
/>
</div>
<div className="section">
<NumberBox
visible={!isPredefined}
placeholder="left"
defaultValue={null}
valueChangeEvent="keyup"
inputAttr={positionLeftLabel}
disabled={!!coordinatePosition.right}
onValueChange={leftNumberBoxValueChanged}
/>
<NumberBox
visible={!isPredefined}
placeholder="right"
defaultValue={null}
valueChangeEvent="keyup"
inputAttr={positionRightLabel}
disabled={!!coordinatePosition.left}
onValueChange={rightNumberBoxValueChanged}
/>
</div>
<div>Direction</div>
<SelectBox
items={directions}
inputAttr={directionLabel}
value={direction}
onSelectionChanged={({ selectedItem }) => setDirection(selectedItem)}
/>
<div className="section">
<Button
text="Show"
width="48%"
onClick={show}
/>
<Button
text="Hide all"
width="48%"
onClick={() => HideToasts()}
/>
</div>
</div>
</React.Fragment>
);
}
export default App;
xxxxxxxxxx
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.tsx';
ReactDOM.render(
<App />,
document.getElementById('app'),
);
xxxxxxxxxx
export const directions = [
'down-push',
'down-stack',
'up-push',
'up-stack',
'left-push',
'left-stack',
'right-push',
'right-stack',
];
export const positions = [
'top left',
'top center',
'top right',
'bottom left',
'bottom center',
'bottom right',
'left center',
'center',
'right center',
];
export const types = ['error', 'info', 'success', 'warning'];
export const radioGroupItems = ['predefined', 'coordinates'];
export const positionTopLabel = { 'aria-label': 'Position Top' };
export const positionBottomLabel = { 'aria-label': 'Position Bottom' };
export const positionLeftLabel = { 'aria-label': 'Position Left' };
export const positionRightLabel = { 'aria-label': 'Position Right' };
export const directionLabel = { 'aria-label': 'Direction' };
export const positionLabel = { 'aria-label': 'Position' };
xxxxxxxxxx
window.exports = window.exports || {};
window.config = {
transpiler: 'ts',
typescriptOptions: {
module: 'system',
emitDecoratorMetadata: true,
experimentalDecorators: true,
jsx: 'react',
},
meta: {
'react': {
'esModule': true,
},
'typescript': {
'exports': 'ts',
},
'devextreme/time_zone_utils.js': {
'esModule': true,
},
'devextreme/localization.js': {
'esModule': true,
},
'devextreme/viz/palette.js': {
'esModule': true,
},
'openai': {
'esModule': true,
},
},
paths: {
'npm:': 'https://unpkg.com/',
'bundles:': 'bundles/',
'externals:': 'bundles/externals/',
},
defaultExtension: 'js',
map: {
'ts': 'npm:plugin-typescript@8.0.0/lib/plugin.js',
'typescript': 'npm:typescript@4.2.4/lib/typescript.js',
'jszip': 'npm:jszip@3.10.1/dist/jszip.min.js',
'react': 'npm:react@17.0.2/umd/react.development.js',
'react-dom': 'npm:react-dom@17.0.2/umd/react-dom.development.js',
'prop-types': 'npm:prop-types/prop-types.js',
'rrule': 'npm:rrule@2.6.4/dist/es5/rrule.js',
'luxon': 'npm:luxon@3.4.4/build/global/luxon.min.js',
'es6-object-assign': 'npm:es6-object-assign',
'devextreme': 'npm:devextreme@link:../../packages/devextreme/artifacts/npm/devextreme/cjs',
'devextreme-react': 'npm:devextreme-react@link:../../packages/devextreme-react/npm/cjs',
'devextreme-quill': 'npm:devextreme-quill@1.7.1/dist/dx-quill.min.js',
'devexpress-diagram': 'npm:devexpress-diagram@2.2.5/dist/dx-diagram.js',
'devexpress-gantt': 'npm:devexpress-gantt@4.1.54/dist/dx-gantt.js',
'@devextreme/runtime': 'npm:@devextreme/runtime@3.0.12',
'inferno': 'npm:inferno@7.4.11/dist/inferno.min.js',
'inferno-compat': 'npm:inferno-compat/dist/inferno-compat.min.js',
'inferno-create-element': 'npm:inferno-create-element@7.4.11/dist/inferno-create-element.min.js',
'inferno-dom': 'npm:inferno-dom/dist/inferno-dom.min.js',
'inferno-hydrate': 'npm:inferno-hydrate/dist/inferno-hydrate.min.js',
'inferno-clone-vnode': 'npm:inferno-clone-vnode/dist/inferno-clone-vnode.min.js',
'inferno-create-class': 'npm:inferno-create-class/dist/inferno-create-class.min.js',
'inferno-extras': 'npm:inferno-extras/dist/inferno-extras.min.js',
'devextreme-cldr-data': 'npm:devextreme-cldr-data@1.0.3',
// SystemJS plugins
'plugin-babel': 'npm:systemjs-plugin-babel@0.0.25/plugin-babel.js',
'systemjs-babel-build': 'npm:systemjs-plugin-babel@0.0.25/systemjs-babel-browser.js',
// Prettier
'prettier/standalone': 'npm:prettier@2.8.8/standalone.js',
'prettier/parser-html': 'npm:prettier@2.8.8/parser-html.js',
},
packages: {
'devextreme': {
defaultExtension: 'js',
},
'devextreme-react': {
main: 'index.js',
},
'devextreme/events/utils': {
main: 'index',
},
'devextreme/localization/messages': {
format: 'json',
defaultExtension: 'json',
},
'devextreme/events': {
main: 'index',
},
'es6-object-assign': {
main: './index.js',
defaultExtension: 'js',
},
},
packageConfigPaths: [
'npm:@devextreme/*/package.json',
'npm:@devextreme/runtime@3.0.12/inferno/package.json',
],
babelOptions: {
sourceMaps: false,
stage0: true,
react: true,
},
};
System.config(window.config);
xxxxxxxxxx
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App.js';
ReactDOM.render(<App />, document.getElementById('app'));
xxxxxxxxxx
export const directions = [
'down-push',
'down-stack',
'up-push',
'up-stack',
'left-push',
'left-stack',
'right-push',
'right-stack',
];
export const positions = [
'top left',
'top center',
'top right',
'bottom left',
'bottom center',
'bottom right',
'left center',
'center',
'right center',
];
export const types = ['error', 'info', 'success', 'warning'];
export const radioGroupItems = ['predefined', 'coordinates'];
export const positionTopLabel = { 'aria-label': 'Position Top' };
export const positionBottomLabel = { 'aria-label': 'Position Bottom' };
export const positionLeftLabel = { 'aria-label': 'Position Left' };
export const positionRightLabel = { 'aria-label': 'Position Right' };
export const directionLabel = { 'aria-label': 'Direction' };
export const positionLabel = { 'aria-label': 'Position' };
xxxxxxxxxx
<html lang="en">
<head></head>
<body class="dx-viewport">
<div class="demo-container">
<div id="app"></div>
</div>
</body>
</html>
xxxxxxxxxx
.options {
padding: 20px;
background-color: rgba(191, 191, 191, 0.15);
position: absolute;
right: 0;
top: 0;
width: 260px;
display: flex;
flex-direction: column;
gap: 5px;
}
.section {
width: 100%;
display: flex;
justify-content: space-between;
}
Specify Position
You can set the position
field to a string (select 'predefined' in the radio group) or an object (select 'coordinates' in the radio group). Note that if you use coordinates for the position
field, you need to specify one vertical and one horizontal coordinate only. For example, if you specify 'top', the demo disables the 'bottom' field, and vice versa.
Specify Direction
The direction
field specifies two options: which way the notification stack grows and whether new notifications appear at the end or at the beginning of the line. For this reason, the field's pull-down menu choices show pairs of values such as 'up-push' and 'up-stack'.
-
'up-push'
New toasts push the previous toasts upwards. -
'up-stack'
Toasts stack on top of each other.
Hide Toasts
To hide all toast messages, use the hideToasts method.