feat: initial LexAI Chrome extension scaffold
- WXT + React 18 + TypeScript setup - Background service worker (LLM API proxy) - Content script (floating toolbar + text selection) - Options page (provider/model/API key config) - Popup UI - Gitea Actions workflows (CI, preview, release) - Vitest unit tests + Playwright E2E setup - Supports: OpenAI, Anthropic, Groq, OpenRouter
This commit is contained in:
65
entrypoints/popup/Popup.tsx
Normal file
65
entrypoints/popup/Popup.tsx
Normal file
@@ -0,0 +1,65 @@
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { createRoot } from 'react-dom/client';
|
||||
|
||||
function Popup() {
|
||||
const [configured, setConfigured] = useState(false);
|
||||
const [provider, setProvider] = useState('');
|
||||
const [model, setModel] = useState('');
|
||||
|
||||
useEffect(() => {
|
||||
chrome.storage.local.get(['provider', 'apiKey', 'model'], (result) => {
|
||||
if (result.apiKey) {
|
||||
setConfigured(true);
|
||||
setProvider(result.provider || 'openai');
|
||||
setModel(result.model || '');
|
||||
}
|
||||
});
|
||||
}, []);
|
||||
|
||||
const openSettings = () => chrome.runtime.openOptionsPage();
|
||||
|
||||
return (
|
||||
<div style={{ padding: 16, fontFamily: 'system-ui, sans-serif', color: '#1e1e2e' }}>
|
||||
<div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 12 }}>
|
||||
<span style={{ fontSize: 20 }}>⚡</span>
|
||||
<span style={{ fontSize: 16, fontWeight: 700 }}>LexAI</span>
|
||||
</div>
|
||||
|
||||
{configured ? (
|
||||
<div>
|
||||
<div style={{ background: '#e8f5e9', borderRadius: 8, padding: '8px 12px', marginBottom: 12 }}>
|
||||
<div style={{ fontSize: 12, color: '#388e3c', fontWeight: 600 }}>✓ Active</div>
|
||||
<div style={{ fontSize: 12, color: '#555', marginTop: 2 }}>{provider} / {model}</div>
|
||||
</div>
|
||||
<p style={{ fontSize: 12, color: '#6c6f85', marginBottom: 12 }}>
|
||||
Select any text on a webpage to see LexAI options appear.
|
||||
</p>
|
||||
</div>
|
||||
) : (
|
||||
<div style={{ background: '#fff3e0', borderRadius: 8, padding: '8px 12px', marginBottom: 12 }}>
|
||||
<div style={{ fontSize: 12, color: '#e65100', fontWeight: 600 }}>⚠ Setup Required</div>
|
||||
<div style={{ fontSize: 12, color: '#555', marginTop: 2 }}>Add your API key to get started</div>
|
||||
</div>
|
||||
)}
|
||||
|
||||
<button
|
||||
onClick={openSettings}
|
||||
style={{
|
||||
width: '100%',
|
||||
background: '#89b4fa',
|
||||
color: '#1e1e2e',
|
||||
border: 'none',
|
||||
borderRadius: 8,
|
||||
padding: '8px',
|
||||
fontSize: 13,
|
||||
fontWeight: 600,
|
||||
cursor: 'pointer',
|
||||
}}
|
||||
>
|
||||
⚙ Open Settings
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
createRoot(document.getElementById('app')!).render(<Popup />);
|
||||
Reference in New Issue
Block a user