mirror of
https://github.com/hansjone/netx.git
synced 2026-10-09 15:33:18 +08:00
Polish HeroUI chrome, topology toolbar, and session client IP.
Checkpoint before workbench facade redesign: list defaults, API key quota, toast portal, topology canvas editor toolbar with More menu, and trusted-proxy client IP for sessions. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
5096117ad4
commit
c4526e36d8
64 changed files with 6316 additions and 4521 deletions
|
|
@ -1,4 +1,13 @@
|
|||
import { createContext, useCallback, useContext, useEffect, useMemo, useState, type ReactNode } from "react";
|
||||
import {
|
||||
createContext,
|
||||
useCallback,
|
||||
useContext,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useState,
|
||||
type ReactNode,
|
||||
} from "react";
|
||||
import { createPortal } from "react-dom";
|
||||
|
||||
export type ToastState = { type: "ok" | "error"; text: string } | null;
|
||||
|
||||
|
|
@ -27,12 +36,22 @@ function useToastState(autoHideMs: number): ToastApi {
|
|||
return useMemo(() => ({ toast, showOk, showError, clear }), [toast, showOk, showError, clear]);
|
||||
}
|
||||
|
||||
function ToastViewport({ toast }: { toast: NonNullable<ToastState> }) {
|
||||
if (typeof document === "undefined") return null;
|
||||
return createPortal(
|
||||
<div className={`app-toast app-toast--${toast.type}`} role="status" aria-live="polite">
|
||||
{toast.text}
|
||||
</div>,
|
||||
document.body,
|
||||
);
|
||||
}
|
||||
|
||||
export function ToastProvider({ children, autoHideMs = 2600 }: { children: ReactNode; autoHideMs?: number }) {
|
||||
const api = useToastState(autoHideMs);
|
||||
return (
|
||||
<ToastContext.Provider value={api}>
|
||||
{children}
|
||||
{api.toast ? <div className={`toast toast--${api.toast.type}`}>{api.toast.text}</div> : null}
|
||||
{api.toast ? <ToastViewport toast={api.toast} /> : null}
|
||||
</ToastContext.Provider>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue