refactor: optimised UI and UX

- add tag style to status;
- add button style to action links of each domain;
- add Notiflix for better notification experiences
This commit is contained in:
jamo.siu@gmail.com committed 2026-10-12 16:22:37 +08:00
1 parent 46e6607d46
commit cc5e98f29c
9 files changed
+181 -49

No files matched your search

+66
View File
@@ -0,0 +1,66 @@
"use client"
import { Notify } from "notiflix/build/notiflix-notify-aio"
// The Notify AIO build ships its styles inline and injects them on first use, so unlike a
// React toaster there is no element to mount: configuring the module once here is the whole
// integration. Components call the notify* helpers below instead of touching notiflix, so
// placement, colouring and timing all live in this one module.
/** Failures carry detail worth reading, so they outlive the routine 3s default. */
const FAILURE_TIMEOUT_MS = 6000
// Notify has no dark-mode option of its own, so toasts are coloured with the same tinted
// palette the app already uses for status tags and buttons, switching on the same
// prefers-colour-scheme query globals.css does.
const toastTheme = {
light: {
success: { background: "#ecfdf5", textColor: "#047857" }, // emerald-50 / emerald-700
warning: { background: "#fffbeb", textColor: "#b45309" }, // amber-50 / amber-700
failure: { background: "#fef2f2", textColor: "#dc2626" }, // red-50 / red-600
},
dark: {
success: { background: "rgba(16, 185, 129, 0.1)", textColor: "#34d399" }, // emerald-500/10 / emerald-400
warning: { background: "rgba(245, 158, 11, 0.1)", textColor: "#fbbf24" }, // amber-500/10 / amber-400
failure: { background: "rgba(239, 68, 68, 0.1)", textColor: "#f87171" }, // red-500/10 / red-400
},
}
// Module bodies also run on the server during SSR, so guard the setup. The import itself is
// safe on the server — Notiflix only touches the DOM when a toast is actually shown.
if (typeof window !== "undefined") {
const dark = window.matchMedia("(prefers-color-scheme: dark)")
const applyTheme = () => {
const theme = dark.matches ? toastTheme.dark : toastTheme.light
Notify.init({
position: "right-top",
// The 280px default squeezes the file paths in apply messages onto too many lines.
width: "400px",
// Messages wrap rather than widen the toast, and file paths show up in them, so allow
// well past the 110-character default before Notiflix starts truncating.
messageMaxLength: 500,
success: theme.success,
warning: theme.warning,
failure: theme.failure,
})
}
applyTheme()
// Track the OS theme if it changes while the page is open.
dark.addEventListener("change", applyTheme)
}
export function notifySuccess(message: string) {
Notify.success(message)
}
export function notifyWarning(message: string) {
Notify.warning(message)
}
export function notifyFailure(message: string) {
// Per-type options cannot carry a timeout (it is read from the common settings only), so
// the longer delay is applied per call.
Notify.failure(message, { timeout: FAILURE_TIMEOUT_MS })
}