LayoutShell's <main> sets overflow:hidden + min-height:0; pages must handle their own scroll. SwaggerPage's root div had no height constraint, so the Swagger UI rendered below the viewport with no scrollbar. Match the pattern used by AppsTab/DashboardTab/etc.: flex:1 + min-height:0 + overflow-y:auto on the page root. Inline style since this is a leaf page with no existing module. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
38 lines
1.2 KiB
TypeScript
38 lines
1.2 KiB
TypeScript
import { useEffect, useRef } from 'react';
|
|
import { config } from '../../config';
|
|
import { useAuthStore } from '../../auth/auth-store';
|
|
import 'swagger-ui-dist/swagger-ui.css';
|
|
|
|
export default function SwaggerPage() {
|
|
const containerRef = useRef<HTMLDivElement>(null);
|
|
const token = useAuthStore((s) => s.accessToken);
|
|
|
|
useEffect(() => {
|
|
let cancelled = false;
|
|
|
|
import('swagger-ui-dist/swagger-ui-bundle').then((mod) => {
|
|
const SwaggerUIBundle = mod.default || mod;
|
|
if (cancelled || !containerRef.current || typeof SwaggerUIBundle !== 'function') return;
|
|
SwaggerUIBundle({
|
|
url: `${config.apiBaseUrl}/api-docs`,
|
|
domNode: containerRef.current,
|
|
requestInterceptor: (req: { headers: Record<string, string> }) => {
|
|
if (token) {
|
|
req.headers['Authorization'] = `Bearer ${token}`;
|
|
}
|
|
return req;
|
|
},
|
|
});
|
|
});
|
|
|
|
return () => { cancelled = true; };
|
|
}, [token]);
|
|
|
|
return (
|
|
<div style={{ flex: 1, minHeight: 0, overflowY: 'auto', padding: '1rem 1.5rem' }}>
|
|
<h2 style={{ marginBottom: '1rem' }}>API Documentation</h2>
|
|
<div ref={containerRef} />
|
|
</div>
|
|
);
|
|
}
|