diff --git a/templates/devtest/toast-and-message.tmpl b/templates/devtest/toast-and-message.tmpl
index 85385082b7..7c6d347784 100644
--- a/templates/devtest/toast-and-message.tmpl
+++ b/templates/devtest/toast-and-message.tmpl
@@ -4,6 +4,7 @@
Toast
+
diff --git a/web_src/css/modules/toast.css b/web_src/css/modules/toast.css
index 33c1f7547c..ffef40779e 100644
--- a/web_src/css/modules/toast.css
+++ b/web_src/css/modules/toast.css
@@ -1,5 +1,7 @@
.toastify {
- color: var(--color-white);
+ color: var(--color-text);
+ background: var(--color-menu);
+ border: 1px solid var(--color-secondary);
position: fixed;
opacity: 0;
transition: all .2s ease;
@@ -16,6 +18,11 @@
opacity: 1;
}
+.toast-success .toast-icon { color: var(--color-success-text); }
+.toast-info .toast-icon { color: var(--color-info-text); }
+.toast-warning .toast-icon { color: var(--color-warning-text); }
+.toast-error .toast-icon { color: var(--color-error-text); }
+
.toast-body {
flex: 1;
padding: 5px 0;
diff --git a/web_src/js/modules/devtest.ts b/web_src/js/modules/devtest.ts
index 01359e0fb5..8efe7e9959 100644
--- a/web_src/js/modules/devtest.ts
+++ b/web_src/js/modules/devtest.ts
@@ -1,21 +1,19 @@
-import {showInfoToast, showWarningToast, showErrorToast} from './toast.ts';
-import type {Toast} from './toast.ts';
+import {showSuccessToast, showInfoToast, showWarningToast, showErrorToast} from './toast.ts';
import {registerGlobalInitFunc} from './observer.ts';
import {showFomanticModal} from './fomantic/modal.ts';
import {createElementFromHTML} from '../utils/dom.ts';
import {html} from '../utils/html.ts';
import {showGlobalErrorMessage} from './errors.ts';
import {AnsiLineRenderer} from '../render/ansi.ts';
-
-type LevelMap = Record Toast | null>;
+import type {Intent} from '../types.ts';
function initDevtestPage() {
const toastButtons = document.querySelectorAll('.toast-test-button');
if (toastButtons.length) {
- const levelMap: LevelMap = {info: showInfoToast, warning: showWarningToast, error: showErrorToast};
+ const levelMap = {success: showSuccessToast, info: showInfoToast, warning: showWarningToast, error: showErrorToast};
for (const el of toastButtons) {
el.addEventListener('click', () => {
- const level = el.getAttribute('data-toast-level')!;
+ const level = el.getAttribute('data-toast-level') as Intent;
const message = el.getAttribute('data-toast-message')!;
levelMap[level](message);
});
diff --git a/web_src/js/modules/toast.test.ts b/web_src/js/modules/toast.test.ts
index b29e9a32bd..2c16f0cae3 100644
--- a/web_src/js/modules/toast.test.ts
+++ b/web_src/js/modules/toast.test.ts
@@ -1,16 +1,21 @@
-import {showInfoToast, showErrorToast, showWarningToast} from './toast.ts';
+import {showSuccessToast, showInfoToast, showErrorToast, showWarningToast} from './toast.ts';
+
+test('showSuccessToast', async () => {
+ showSuccessToast('success', {duration: -1});
+ expect(document.querySelector('.toastify')).toBeTruthy();
+});
test('showInfoToast', async () => {
- showInfoToast('success 😀', {duration: -1});
+ showInfoToast('info', {duration: -1});
expect(document.querySelector('.toastify')).toBeTruthy();
});
test('showWarningToast', async () => {
- showWarningToast('warning 😐', {duration: -1});
+ showWarningToast('warning', {duration: -1});
expect(document.querySelector('.toastify')).toBeTruthy();
});
test('showErrorToast', async () => {
- showErrorToast('error 🙁', {duration: -1});
+ showErrorToast('error', {duration: -1});
expect(document.querySelector('.toastify')).toBeTruthy();
});
diff --git a/web_src/js/modules/toast.ts b/web_src/js/modules/toast.ts
index a6cfef6848..0f6a054593 100644
--- a/web_src/js/modules/toast.ts
+++ b/web_src/js/modules/toast.ts
@@ -12,25 +12,25 @@ export type Toast = ReturnType;
type ToastLevels = {
[intent in Intent]: {
icon: SvgName,
- background: string,
duration: number,
}
};
const levels: ToastLevels = {
- info: {
+ success: {
icon: 'octicon-check',
- background: 'var(--color-green)',
duration: 2500,
},
+ info: {
+ icon: 'octicon-info',
+ duration: 5000,
+ },
warning: {
icon: 'gitea-exclamation',
- background: 'var(--color-orange)',
duration: -1, // requires dismissal to hide
},
error: {
icon: 'gitea-exclamation',
- background: 'var(--color-red)',
duration: -1, // requires dismissal to hide
},
};
@@ -43,7 +43,7 @@ type ToastOpts = {
type ToastifyElement = HTMLElement & {_giteaToastifyInstance?: Toast};
/** See https://github.com/apvarun/toastify-js#api for options */
-function showToast(message: string, level: Intent, {gravity, position, duration, useHtmlBody, preventDuplicates = true, ...other}: ToastOpts = {}): Toast | null {
+function showToast(message: string, level: Intent = 'info', {gravity, position, duration, useHtmlBody, preventDuplicates = true, ...other}: ToastOpts = {}): Toast | null {
const parent = document.querySelector('.ui.dimmer.active') ?? document.body;
const duplicateKey = preventDuplicates ? (typeof preventDuplicates === 'string' ? preventDuplicates : `${level}-${message}`) : '';
@@ -59,7 +59,7 @@ function showToast(message: string, level: Intent, {gravity, position, duration,
}
}
- const {icon, background, duration: levelDuration} = levels[level ?? 'info'];
+ const {icon, duration: levelDuration} = levels[level];
const bodyHtml = useHtmlBody ? message : htmlEscape(message);
const toast = Toastify({
selector: parent,
@@ -69,10 +69,10 @@ function showToast(message: string, level: Intent, {gravity, position, duration,
`,
escapeMarkup: false,
+ className: `toast-${level}`,
gravity: gravity ?? 'top',
position: position ?? 'center',
duration: duration ?? levelDuration,
- style: {background},
...other,
});
@@ -84,6 +84,10 @@ function showToast(message: string, level: Intent, {gravity, position, duration,
return toast;
}
+export function showSuccessToast(message: string, opts?: ToastOpts): Toast | null {
+ return showToast(message, 'success', opts);
+}
+
export function showInfoToast(message: string, opts?: ToastOpts): Toast | null {
return showToast(message, 'info', opts);
}
diff --git a/web_src/js/svg.ts b/web_src/js/svg.ts
index a24b542e0d..bd8b96691b 100644
--- a/web_src/js/svg.ts
+++ b/web_src/js/svg.ts
@@ -50,6 +50,7 @@ import octiconHistory from '../../public/assets/img/svg/octicon-history.svg';
import octiconHorizontalRule from '../../public/assets/img/svg/octicon-horizontal-rule.svg';
import octiconHome from '../../public/assets/img/svg/octicon-home.svg';
import octiconImage from '../../public/assets/img/svg/octicon-image.svg';
+import octiconInfo from '../../public/assets/img/svg/octicon-info.svg';
import octiconIssueClosed from '../../public/assets/img/svg/octicon-issue-closed.svg';
import octiconIssueOpened from '../../public/assets/img/svg/octicon-issue-opened.svg';
import octiconItalic from '../../public/assets/img/svg/octicon-italic.svg';
@@ -139,6 +140,7 @@ const svgs = {
'octicon-horizontal-rule': octiconHorizontalRule,
'octicon-home': octiconHome,
'octicon-image': octiconImage,
+ 'octicon-info': octiconInfo,
'octicon-issue-closed': octiconIssueClosed,
'octicon-issue-opened': octiconIssueOpened,
'octicon-italic': octiconItalic,
diff --git a/web_src/js/types.ts b/web_src/js/types.ts
index 8c2ad5f7b2..a3168ca69d 100644
--- a/web_src/js/types.ts
+++ b/web_src/js/types.ts
@@ -1,7 +1,7 @@
export type TimeoutId = ReturnType;
export type IntervalId = ReturnType;
-export type Intent = 'error' | 'warning' | 'info';
+export type Intent = 'error' | 'warning' | 'info' | 'success';
export type Mention = {
key: string,