diff --git a/src/renderer/inbox/components/Banner.tsx b/src/renderer/inbox/components/Banner.tsx new file mode 100644 index 0000000..a63e592 --- /dev/null +++ b/src/renderer/inbox/components/Banner.tsx @@ -0,0 +1,27 @@ +import React from 'react'; + +/** + * v0.2.6 #24+#41 — 4 banner 의 inline style 중복 제거. severity 별 theme map. + */ +const THEMES = { + warning: { bg: '#fff7e6', border: '#d99500', text: '#946100' }, + error: { bg: '#fce4e4', border: '#a33', text: '#a33' }, + info: { bg: '#e8f0fe', border: '#4a7ec0', text: '#234' } +} as const; + +interface Props { + severity: 'warning' | 'error' | 'info'; + children: React.ReactNode; +} + +export function Banner({ severity, children }: Props): React.ReactElement { + const t = THEMES[severity]; + return ( +
+ {children} +
+ ); +} diff --git a/src/renderer/inbox/components/ExpiryBanner.tsx b/src/renderer/inbox/components/ExpiryBanner.tsx index bed77be..a08bcf9 100644 --- a/src/renderer/inbox/components/ExpiryBanner.tsx +++ b/src/renderer/inbox/components/ExpiryBanner.tsx @@ -1,6 +1,7 @@ import React, { useEffect, useState } from 'react'; import type { Note } from '@shared/types'; import { useInbox } from '../store.js'; +import { Banner } from './Banner.js'; export function ExpiryBanner(): React.ReactElement | null { const candidates = useInbox((s) => s.expiredCandidates); @@ -72,10 +73,7 @@ function ExpiryBannerInner({ candidates, onTrash, onSnooze }: InnerProps): React } return ( -
+
오늘 기준 만료 {candidates.length}개
+
); } diff --git a/src/renderer/inbox/components/FailedBanner.tsx b/src/renderer/inbox/components/FailedBanner.tsx index 254c3ad..a41ccc2 100644 --- a/src/renderer/inbox/components/FailedBanner.tsx +++ b/src/renderer/inbox/components/FailedBanner.tsx @@ -1,32 +1,31 @@ import React from 'react'; import { useInbox } from '../store.js'; +import { Banner } from './Banner.js'; export function FailedBanner(): React.ReactElement | null { const count = useInbox((s) => s.failedCount); const retryAllFailed = useInbox((s) => s.retryAllFailed); if (count === 0) return null; return ( -
- ❌ AI 처리 실패 {count} - -
+ +
+ ❌ AI 처리 실패 {count} + +
+
); } diff --git a/src/renderer/inbox/components/OllamaBanner.tsx b/src/renderer/inbox/components/OllamaBanner.tsx index 2de6fa8..0ad9120 100644 --- a/src/renderer/inbox/components/OllamaBanner.tsx +++ b/src/renderer/inbox/components/OllamaBanner.tsx @@ -1,5 +1,6 @@ import React from 'react'; import { useInbox } from '../store.js'; +import { Banner } from './Banner.js'; interface OllamaBannerProps { onOpenSettings?: () => void; @@ -14,7 +15,8 @@ export function OllamaBanner({ onOpenSettings }: OllamaBannerProps = {}): React. ? '`ollama pull gemma4:e4b` 실행 후 앱을 재시작해주세요.' : 'Inkling 정리가 잠시 멈췄습니다. Ollama를 실행해주세요.'; return ( -
+ +
⚠ {message}
+
+
); } diff --git a/src/renderer/inbox/components/RecallBanner.tsx b/src/renderer/inbox/components/RecallBanner.tsx index c0436d8..e770169 100644 --- a/src/renderer/inbox/components/RecallBanner.tsx +++ b/src/renderer/inbox/components/RecallBanner.tsx @@ -1,6 +1,7 @@ import React, { useEffect, useRef, useState } from 'react'; import { useInbox } from '../store.js'; import { inboxApi } from '../api.js'; +import { Banner } from './Banner.js'; export function RecallBanner(): React.ReactElement | null { const candidate = useInbox((s) => s.recallCandidate); @@ -47,10 +48,7 @@ export function RecallBanner(): React.ReactElement | null { } return ( -
+
💭 오늘 회상해볼 노트 @@ -90,7 +88,7 @@ export function RecallBanner(): React.ReactElement | null { 더 이상
-
+ ); }