If this is useful, a ❤️ helps others find it.
All tests run on an 8-year-old MacBook Air.
The AI feature is only as good as the UI around it. A powerful diagnosis that's hard to trigger, slow to show, or confusing to read doesn't get used.
Here's what I learned from iterating on HiyokoLogcat's AI button.
Where to put the trigger
Inline with the content, not in a toolbar.
My first version had an "AI Diagnose" button in the top toolbar. Users had to: spot the error, note the line number, click the toolbar button, somehow tell it which line.
The fix: put a small icon directly on each error line. Click the icon → diagnose that line. Zero ambiguity.
{logLines.map((line, idx) => (
{line.message}
{line.level === 'E' && (
handleDiagnose(idx)}
title="AI診断"
>
🐥
)}
))}
Show the button only on error lines. No button on debug/info lines — that would be noise.
How to label it
Don't say "AI." Users don't care about the implementation.
| Bad | Better |
|---|---|
| "AI Analyze" | "Diagnose" |
| "GPT Explain" | "What's wrong?" |
| "Neural diagnosis" | "Fix this" |
One word. Action-oriented. No tech jargon.
What to show while waiting
Three states, three UIs:
type DiagnosisState = 'idle' | 'loading' | 'done' | 'error';
function DiagnosisOverlay({ state, result }: Props) {
if (state === 'idle') return null;
return (
{state === 'loading' && (
🐥
診断中...
)}
{state === 'done' && (
{result}
)}
{state === 'error' && (
もう一度お試しください
再試行
)}
);
}
Loading: Show something immediately. A spinner or pulsing text. 3 seconds of silence feels like a crash.
Done: Show the result. No animation needed — the content itself is the payoff.
Error: Short message + retry button. Never a raw error code.
Dismiss behavior
Three ways to close, all feel natural:
- Press ESC
- Click outside the overlay
- Click the X button
useEffect(() => {
const onKey = (e: KeyboardEvent) => {
if (e.key === 'Escape') onClose();
};
window.addEventListener('keydown', onKey);
return () => window.removeEventListener('keydown', onKey);
}, []);
Don't make users hunt for a close button. ESC is the universal "get out of this."
The one thing that matters most
Speed of feedback. If clicking the button produces no visible response for even half a second, users will click it again, or assume it didn't work.
Show something within 100ms of the click. The AI response can take 3 seconds. The UI response cannot.
const handleDiagnose = async (idx: number) => {
setDiagnosisState('loading'); // ← immediate, < 1ms
const result = await invoke('diagnose', { idx }); // ← takes 3s
setDiagnosisState('done');
setResult(result);
};
Hiyoko PDF Vault → https://hiyokoko.gumroad.com/l/HiyokoPDFVault
X → @hiyoyok
Top comments (0)