Files
bolt-diy/app/root.tsx
Stijnus 4e37f5a80c fix: resolve toast message visibility and deployment success notifications
## Issues Fixed
- Toast messages appearing in background/blurred due to z-index conflicts
- Missing success toast notifications for deployment completions
- Scoped ToastContainer limiting toast visibility to chat component only

## Changes Made

### Global Toast System
- Move ToastContainer from Chat.client.tsx to root.tsx for global availability
- Add highest z-index (1000) to ensure toasts appear above all UI elements
- Remove duplicate ToastContainer from chat component

### Z-Index System Updates
- Add .z-toast class with z-index: $zIndexMax + 1 (1000)
- Apply toast z-index to .Toastify__toast-container in toast.scss
- Ensure proper layering hierarchy for all toast messages

### Deployment Success Notifications
- Add missing toast.success() calls to all deployment services:
  - NetlifyDeploy: "🚀 Netlify deployment completed successfully!"
  - VercelDeploy: "🚀 Vercel deployment completed successfully!"
  - GitHubDeploy: "🚀 GitHub deployment preparation completed successfully!"
  - GitLabDeploy: "🚀 GitLab deployment preparation completed successfully!"

## Result
- All toast messages now appear in foreground with proper z-index
- Deployment success notifications are clearly visible to users
- Consistent toast behavior across the entire application
- No more blurred or background toast messages

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-29 14:05:22 +02:00

153 lines
4.3 KiB
TypeScript

import { useStore } from '@nanostores/react';
import type { LinksFunction } from '@remix-run/cloudflare';
import { Links, Meta, Outlet, Scripts, ScrollRestoration } from '@remix-run/react';
import tailwindReset from '@unocss/reset/tailwind-compat.css?url';
import { themeStore } from './lib/stores/theme';
import { stripIndents } from './utils/stripIndent';
import { createHead } from 'remix-island';
import { useEffect } from 'react';
import { DndProvider } from 'react-dnd';
import { HTML5Backend } from 'react-dnd-html5-backend';
import { ClientOnly } from 'remix-utils/client-only';
import { cssTransition, ToastContainer } from 'react-toastify';
import reactToastifyStyles from 'react-toastify/dist/ReactToastify.css?url';
import globalStyles from './styles/index.scss?url';
import xtermStyles from '@xterm/xterm/css/xterm.css?url';
import 'virtual:uno.css';
const toastAnimation = cssTransition({
enter: 'animated fadeInRight',
exit: 'animated fadeOutRight',
});
export const links: LinksFunction = () => [
{
rel: 'icon',
href: '/favicon.svg',
type: 'image/svg+xml',
},
{ rel: 'stylesheet', href: reactToastifyStyles },
{ rel: 'stylesheet', href: tailwindReset },
{ rel: 'stylesheet', href: globalStyles },
{ rel: 'stylesheet', href: xtermStyles },
{
rel: 'preconnect',
href: 'https://fonts.googleapis.com',
},
{
rel: 'preconnect',
href: 'https://fonts.gstatic.com',
crossOrigin: 'anonymous',
},
{
rel: 'stylesheet',
href: 'https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap',
},
];
const inlineThemeCode = stripIndents`
setTutorialKitTheme();
function setTutorialKitTheme() {
let theme = localStorage.getItem('bolt_theme');
if (!theme) {
theme = window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
}
document.querySelector('html')?.setAttribute('data-theme', theme);
}
`;
export const Head = createHead(() => (
<>
<meta charSet="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<Meta />
<Links />
<script dangerouslySetInnerHTML={{ __html: inlineThemeCode }} />
</>
));
export function Layout({ children }: { children: React.ReactNode }) {
const theme = useStore(themeStore);
useEffect(() => {
document.querySelector('html')?.setAttribute('data-theme', theme);
}, [theme]);
return (
<>
<ClientOnly>{() => <DndProvider backend={HTML5Backend}>{children}</DndProvider>}</ClientOnly>
<ToastContainer
closeButton={({ closeToast }) => {
return (
<button className="Toastify__close-button" onClick={closeToast}>
<div className="i-ph:x text-lg" />
</button>
);
}}
icon={({ type }) => {
switch (type) {
case 'success': {
return <div className="i-ph:check-bold text-bolt-elements-icon-success text-2xl" />;
}
case 'error': {
return <div className="i-ph:warning-circle-bold text-bolt-elements-icon-error text-2xl" />;
}
}
return undefined;
}}
position="bottom-right"
pauseOnFocusLoss
transition={toastAnimation}
autoClose={3000}
/>
<ScrollRestoration />
<Scripts />
</>
);
}
import { logStore } from './lib/stores/logs';
export default function App() {
const theme = useStore(themeStore);
useEffect(() => {
logStore.logSystem('Application initialized', {
theme,
platform: navigator.platform,
userAgent: navigator.userAgent,
timestamp: new Date().toISOString(),
});
// Initialize debug logging with improved error handling
import('./utils/debugLogger')
.then(({ debugLogger }) => {
/*
* The debug logger initializes itself and starts disabled by default
* It will only start capturing when enableDebugMode() is called
*/
const status = debugLogger.getStatus();
logStore.logSystem('Debug logging ready', {
initialized: status.initialized,
capturing: status.capturing,
enabled: status.enabled,
});
})
.catch((error) => {
logStore.logError('Failed to initialize debug logging', error);
});
}, []);
return (
<Layout>
<Outlet />
</Layout>
);
}