mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-30 19:09:28 +00:00
DESIGN.md already said app-wide surfaces must not compete through ad-hoc
z-index literals, and the code disagreed: three overlapping numbering
schemes, and comments narrating the fight ("defaults to z-130, renders
UNDER the onboarding overlay (z-1300) ... bump it above with z-[1310]").
Picking a number meant reading someone else's near miss.
Name the rungs — modal, over-modal, switcher, and the boot chain — and
point the call sites at them. Every rung keeps the exact value it had, so
nothing moves; what changes is that the next overlay has a name to reach
for instead of a number to guess. Local stacking within a component stays
on plain z-10/z-20.
77 lines
2.1 KiB
TypeScript
77 lines
2.1 KiB
TypeScript
import { Component, type ErrorInfo, type ReactNode } from 'react'
|
|
|
|
import { Button } from '@/components/ui/button'
|
|
import { ErrorState } from '@/components/ui/error-state'
|
|
import { useI18n } from '@/i18n'
|
|
|
|
export interface ErrorBoundaryFallbackProps {
|
|
error: Error
|
|
reset: () => void
|
|
}
|
|
|
|
interface ErrorBoundaryProps {
|
|
children: ReactNode
|
|
fallback?: (props: ErrorBoundaryFallbackProps) => ReactNode
|
|
label?: string
|
|
onError?: (error: Error, info: ErrorInfo) => void
|
|
}
|
|
|
|
interface ErrorBoundaryState {
|
|
error: Error | null
|
|
}
|
|
|
|
export class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {
|
|
state: ErrorBoundaryState = { error: null }
|
|
|
|
static getDerivedStateFromError(error: Error): ErrorBoundaryState {
|
|
return { error }
|
|
}
|
|
|
|
componentDidCatch(error: Error, info: ErrorInfo) {
|
|
const tag = this.props.label ? `[error-boundary:${this.props.label}]` : '[error-boundary]'
|
|
console.error(tag, error, info.componentStack)
|
|
this.props.onError?.(error, info)
|
|
}
|
|
|
|
reset = () => {
|
|
this.setState({ error: null })
|
|
}
|
|
|
|
render() {
|
|
const { error } = this.state
|
|
|
|
if (!error) {
|
|
return this.props.children
|
|
}
|
|
|
|
if (this.props.fallback) {
|
|
return this.props.fallback({ error, reset: this.reset })
|
|
}
|
|
|
|
return <RootErrorFallback error={error} reset={this.reset} />
|
|
}
|
|
}
|
|
|
|
function RootErrorFallback({ error, reset }: ErrorBoundaryFallbackProps) {
|
|
const { t } = useI18n()
|
|
|
|
return (
|
|
<div className="fixed inset-0 z-(--z-crash) grid place-items-center bg-(--ui-chat-surface-background) p-6">
|
|
<ErrorState
|
|
className="w-full max-w-[28rem]"
|
|
description={error.message || t.errors.boundaryDesc}
|
|
title={t.errors.boundaryTitle}
|
|
>
|
|
<Button className="font-semibold" onClick={reset} size="lg">
|
|
{t.common.retry}
|
|
</Button>
|
|
<Button onClick={() => window.location.reload()} variant="text">
|
|
{t.errors.reloadWindow}
|
|
</Button>
|
|
<Button onClick={() => void window.hermesDesktop?.revealLogs()?.catch(() => undefined)} variant="text">
|
|
{t.errors.openLogs}
|
|
</Button>
|
|
</ErrorState>
|
|
</div>
|
|
)
|
|
}
|