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 확인됨
53 lines
1.6 KiB
TypeScript
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>
|
|
);
|
|
}
|