kcg-ai-monitoring/frontend/src/shared/components/common/PrintButton.tsx
htlee c51873ab85 fix(frontend): a11y/호환성 — backdrop-filter webkit prefix + Button/Input/Select 접근 이름
axe/forms/backdrop 에러 3종 모두 해결:

1) CSS: backdrop-filter Safari 호환성
   - design-system CSS에 -webkit-backdrop-filter 추가
   - trk-pulse 애니메이션을 outline-color → opacity로 변경
     (composite만 트리거, paint/layout 없음 → 더 나은 성능)

2) 아이콘 전용 <button> aria-label 추가 (9곳):
   - MainLayout 알림 버튼 → '알림'
   - UserRoleAssignDialog 닫기 → '닫기'
   - AIAssistant/MLOpsPage 전송 → '전송'
   - ChinaFishing 좌/우 네비 → '이전'/'다음'
   - 공통 컴포넌트 (PrintButton/ExcelExport/SaveButton) type=button 누락 보정

3) <input>/<textarea> 접근 이름 27곳 추가:
   - 로그인 폼, ParentReview/LabelSession/ParentExclusion 폼 (10)
   - NoticeManagement 제목/내용/시작일/종료일 (4)
   - SystemConfig/DataHub/PermissionsPanel 검색·역할 입력 (5)
   - VesselDetail 조회 시작/종료/MMSI (3)
   - GearIdentification InputField에 label prop 추가
   - AIAssistant/MLOpsPage 질의 input/textarea
   - MainLayout 페이지 내 검색
   - 공통 placeholder → aria-label 자동 복제 (3)

Button 컴포넌트에는 접근성 정책 JSDoc 명시 (타입 강제는 API 복잡도 대비
이득 낮아 문서 가이드 + 코드 리뷰로 대응).

검증:
- 실제 위반 지표: inaccessible button 0, inaccessible input 0, textarea 0
- tsc , eslint , vite build 
- dist CSS에 -webkit-backdrop-filter 확인됨
2026-04-08 13:04:23 +09:00

53 lines
1.6 KiB
TypeScript

import { Printer } from 'lucide-react';
/*
* SFR-02 공통컴포넌트: 출력 버튼
*/
interface PrintButtonProps {
/** 출력 대상 element ref 또는 window.print() 사용 */
targetRef?: React.RefObject<HTMLElement | null>;
label?: string;
className?: string;
}
export function PrintButton({ targetRef, label = '출력', className = '' }: PrintButtonProps) {
const handlePrint = () => {
if (targetRef?.current) {
const printWindow = window.open('', '_blank');
if (!printWindow) return;
printWindow.document.write(`
<html>
<head>
<title>인쇄</title>
<style>
body { font-family: 'Pretendard', sans-serif; color: #1e293b; padding: 20px; }
table { width: 100%; border-collapse: collapse; font-size: 11px; }
th, td { border: 1px solid #cbd5e1; padding: 6px 8px; text-align: left; }
th { background: #f1f5f9; font-weight: 600; }
h1, h2, h3 { margin: 0 0 8px; }
@media print { body { padding: 0; } }
</style>
</head>
<body>${targetRef.current.innerHTML}</body>
</html>
`);
printWindow.document.close();
printWindow.print();
} else {
window.print();
}
};
return (
<button
type="button"
onClick={handlePrint}
className={`flex items-center gap-1.5 px-3 py-1.5 rounded-lg text-[10px] font-medium bg-surface-overlay border border-border text-muted-foreground hover:text-heading hover:border-border transition-colors ${className}`}
>
<Printer className="w-3 h-3" />
{label}
</button>
);
}