| import { useState } from 'react'; |
| import { EXAMPLE_QUERIES } from '../constants'; |
|
|
| interface QueryInputProps { |
| onSearch: (query: string, intent?: string) => void; |
| disabled: boolean; |
| } |
|
|
| export default function QueryInput({ onSearch, disabled }: QueryInputProps) { |
| const [query, setQuery] = useState(''); |
| const [intent, setIntent] = useState(''); |
| const [showIntent, setShowIntent] = useState(false); |
|
|
| function handleSubmit(e: React.FormEvent) { |
| e.preventDefault(); |
| const trimmed = query.trim(); |
| if (trimmed) onSearch(trimmed, intent.trim() || undefined); |
| } |
|
|
| function handleExample(q: string, exIntent?: string) { |
| setQuery(q); |
| if (exIntent) { |
| setIntent(exIntent); |
| setShowIntent(true); |
| } else { |
| setIntent(''); |
| setShowIntent(false); |
| } |
| onSearch(q, exIntent); |
| } |
|
|
| return ( |
| <div style={{ marginBottom: '1.5rem' }}> |
| <form onSubmit={handleSubmit} style={{ display: 'flex', gap: '0.5rem' }}> |
| <div style={{ flex: 1, display: 'flex', flexDirection: 'column', gap: '0.35rem' }}> |
| <input |
| type="text" |
| value={query} |
| onChange={e => setQuery(e.target.value)} |
| disabled={disabled} |
| placeholder={disabled ? 'Loading browser models\u2026' : 'Enter a search query\u2026'} |
| style={{ |
| width: '100%', |
| padding: '0.6rem 0.9rem', |
| fontSize: '1rem', |
| fontFamily: 'system-ui, -apple-system, sans-serif', |
| border: '1px solid var(--input-border)', |
| borderRadius: '6px', |
| background: disabled ? 'var(--bg-section)' : 'var(--bg-input)', |
| color: disabled ? 'var(--text-muted)' : 'var(--text)', |
| outline: 'none', |
| transition: 'border-color 0.15s', |
| }} |
| onFocus={e => { if (!disabled) e.target.style.borderColor = '#4285F4'; }} |
| onBlur={e => { e.target.style.borderColor = ''; }} |
| /> |
| {showIntent && ( |
| <input |
| type="text" |
| value={intent} |
| onChange={e => setIntent(e.target.value)} |
| disabled={disabled} |
| placeholder="Intent: background context to disambiguate (e.g. 'web page load times')" |
| style={{ |
| width: '100%', |
| padding: '0.45rem 0.9rem', |
| fontSize: '0.85rem', |
| fontFamily: 'system-ui, -apple-system, sans-serif', |
| border: '1px solid var(--input-border)', |
| borderRadius: '6px', |
| background: disabled ? 'var(--bg-section)' : 'var(--bg-input)', |
| color: disabled ? 'var(--text-muted)' : 'var(--text-secondary)', |
| outline: 'none', |
| transition: 'border-color 0.15s', |
| }} |
| onFocus={e => { if (!disabled) e.target.style.borderColor = '#f57f17'; }} |
| onBlur={e => { e.target.style.borderColor = ''; }} |
| /> |
| )} |
| </div> |
| <button |
| type="submit" |
| disabled={disabled || !query.trim()} |
| style={{ |
| padding: '0.6rem 1.2rem', |
| fontSize: '1rem', |
| fontFamily: 'system-ui, -apple-system, sans-serif', |
| background: disabled || !query.trim() ? 'var(--border)' : '#4285F4', |
| color: '#fff', |
| border: 'none', |
| borderRadius: '6px', |
| cursor: disabled || !query.trim() ? 'not-allowed' : 'pointer', |
| transition: 'background 0.15s', |
| fontWeight: 600, |
| alignSelf: 'flex-start', |
| height: '2.5rem', |
| }} |
| > |
| Search |
| </button> |
| </form> |
| |
| <div style={{ marginTop: '0.5rem', display: 'flex', gap: '0.4rem', flexWrap: 'wrap', alignItems: 'center' }}> |
| {!showIntent && ( |
| <button |
| onClick={() => setShowIntent(true)} |
| disabled={disabled} |
| style={{ |
| padding: '0.2rem 0.5rem', |
| fontSize: '0.75rem', |
| fontFamily: 'system-ui, -apple-system, sans-serif', |
| background: 'none', |
| color: disabled ? 'var(--text-muted)' : '#f57f17', |
| border: '1px solid #f57f1740', |
| borderRadius: '4px', |
| cursor: disabled ? 'not-allowed' : 'pointer', |
| }} |
| > |
| + Add intent |
| </button> |
| )} |
| {showIntent && !intent.trim() && ( |
| <button |
| onClick={() => { setShowIntent(false); setIntent(''); }} |
| style={{ |
| padding: '0.2rem 0.5rem', |
| fontSize: '0.75rem', |
| fontFamily: 'system-ui, -apple-system, sans-serif', |
| background: 'none', |
| color: 'var(--text-muted)', |
| border: '1px solid var(--border)', |
| borderRadius: '4px', |
| cursor: 'pointer', |
| }} |
| > |
| Hide intent |
| </button> |
| )} |
| <span style={{ fontSize: '0.8rem', color: 'var(--text-secondary)', fontFamily: 'system-ui, -apple-system, sans-serif' }}> |
| Demo queries: |
| </span> |
| {EXAMPLE_QUERIES.map(ex => ( |
| <button |
| key={ex.query} |
| onClick={() => handleExample(ex.query, ex.intent)} |
| disabled={disabled} |
| title={ex.intent ? `Intent: ${ex.intent}` : undefined} |
| style={{ |
| padding: '0.25rem 0.6rem', |
| fontSize: '0.8rem', |
| fontFamily: 'system-ui, -apple-system, sans-serif', |
| background: 'var(--example-bg)', |
| color: disabled ? 'var(--text-muted)' : '#4285F4', |
| border: `1px solid ${ex.intent ? '#f57f1740' : 'var(--example-border)'}`, |
| borderRadius: '4px', |
| cursor: disabled ? 'not-allowed' : 'pointer', |
| }} |
| > |
| {ex.query}{ex.intent ? ' *' : ''} |
| </button> |
| ))} |
| </div> |
| </div> |
| ); |
| } |
|
|