Files
bambuddy/frontend/src/components/ApiKeyQRCodeModal.tsx
T
maziggy 1d344a8536 fix(ui): resolve light-theme low-contrast semantic text app-wide (#1909)
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.
2026-07-07 09:54:10 +02:00

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>
);
}