mirror of
https://github.com/maziggy/bambuddy.git
synced 2026-10-05 05:31:31 +02:00
The app was built dark-first, so hundreds of hardcoded Tailwind semantic text/icon utilities at light shades (text-amber-400, text-blue-300, ...) had no dark: variant. With darkMode:'class' they applied in light theme too, producing washed-out text on pale tints and white cards — including the three reported spots (AMS Drying banner, Archives no-3MF warning, debug-logging banner). Give each a theme-aware pair: a darker readable shade in light theme with the original pinned to dark:, so dark theme is unchanged. ~100 files. The bambu-* CSS-variable palette (self-correcting) and the dark-only SpoolBuddy kiosk are left untouched. Plain text-white is already theme-aware via the existing index.css .text-white override, so it needed no changes.
71 lines
2.5 KiB
TypeScript
71 lines
2.5 KiB
TypeScript
import { useEffect } from 'react';
|
|
import { QRCodeSVG } from 'qrcode.react';
|
|
import { X, AlertTriangle } from 'lucide-react';
|
|
import { useTranslation } from 'react-i18next';
|
|
import { Button } from './Button';
|
|
import { buildApiKeyQrPayload } from '../utils/apiKeyQr';
|
|
|
|
interface ApiKeyQRCodeModalProps {
|
|
/** Raw API key string (only available in-memory right after creation). */
|
|
apiKey: string;
|
|
/** Base URL a client uses to reach Bambuddy. Defaults to the current origin. */
|
|
baseUrl?: string;
|
|
onClose: () => void;
|
|
}
|
|
|
|
export function ApiKeyQRCodeModal({ apiKey, baseUrl, onClose }: ApiKeyQRCodeModalProps) {
|
|
const { t } = useTranslation();
|
|
const origin = baseUrl ?? window.location.origin;
|
|
const payload = buildApiKeyQrPayload(origin, apiKey);
|
|
|
|
// Close on Escape key
|
|
useEffect(() => {
|
|
const handleKeyDown = (e: KeyboardEvent) => {
|
|
if (e.key === 'Escape') onClose();
|
|
};
|
|
window.addEventListener('keydown', handleKeyDown);
|
|
return () => window.removeEventListener('keydown', handleKeyDown);
|
|
}, [onClose]);
|
|
|
|
return (
|
|
<div
|
|
className="fixed inset-0 bg-black/70 flex items-center justify-center z-50 p-4"
|
|
onClick={onClose}
|
|
>
|
|
<div
|
|
className="bg-bambu-dark-secondary rounded-xl border border-bambu-dark-tertiary w-full max-w-sm"
|
|
onClick={(e) => e.stopPropagation()}
|
|
>
|
|
{/* Header */}
|
|
<div className="flex items-center justify-between px-6 py-4 border-b border-bambu-dark-tertiary">
|
|
<h2 className="text-lg font-semibold text-white">{t('settings.apiKeyQrTitle')}</h2>
|
|
<button
|
|
onClick={onClose}
|
|
className="text-bambu-gray hover:text-white transition-colors"
|
|
aria-label={t('common.close')}
|
|
>
|
|
<X className="w-5 h-5" />
|
|
</button>
|
|
</div>
|
|
|
|
{/* Content */}
|
|
<div className="p-6 flex flex-col items-center">
|
|
<p className="text-sm text-bambu-gray mb-4 text-center">
|
|
{t('settings.apiKeyQrCaption')}
|
|
</p>
|
|
<div className="bg-white p-4 rounded-lg mb-4">
|
|
<QRCodeSVG value={payload} size={256} />
|
|
</div>
|
|
<div className="flex items-start gap-2 text-xs text-amber-700 dark:text-amber-400 mb-4">
|
|
<AlertTriangle className="w-4 h-4 flex-shrink-0 mt-0.5" />
|
|
<span>{t('settings.apiKeyQrWarning')}</span>
|
|
</div>
|
|
<Button onClick={onClose} className="w-full">
|
|
{t('common.close')}
|
|
</Button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|