React UI component for selecting OpenRouter models
npm install @cappasoft/openrouter-model-selector
A beautiful React component for selecting AI models from OpenRouter.
``bash`
npm install @cappasoft/openrouter-model-selector
`tsx
import { useState } from 'react'
import { ModelSelector } from '@cappasoft/openrouter-model-selector'
import '@cappasoft/openrouter-model-selector/styles.css'
export function App() {
const [model, setModel] = useState('openai/gpt-4o')
return (
onValueChange={setModel}
apiKey="sk-or-v1-..."
/>
)
}
`
| Prop | Type | Description |
|------|------|-------------|
| value | string | Currently selected model ID |onValueChange
| | (modelId: string) => void | Callback when model changes |apiKey
| | string | Your OpenRouter API key |disabled?
| | boolean | Disable the selector |contrast?
| | "default" \| "high-contrast" | Increase contrast for secondary text (prices, metadata, headers) |endpoint?
| | string | Custom OpenRouter endpoint (optional) |locale?
| | "en" \| "fr" | UI language (labels + formatting) |labels?
| | Partial | Override i18n labels |className?
| | string | Wrapper class name |showSearch?
| | boolean | Show search input (default: true) |showPricing?
| | boolean | Show pricing (default: true) |showFilters?
| | boolean | Show provider/capability filters (default: true) |variant?
| | "default" \| "compact" | Layout variant |showAllInModal?
| | boolean | Put the full library in a modal |infoToggle?
| | boolean | Adds an βinfoβ button to show the selected model details |
If your app theme makes secondary text too light, prefer using contrast="high-contrast":
`tsx`
onValueChange={setModel}
apiKey="sk-or-v1-..."
contrast="high-contrast"
/>
You can also override the exposed CSS variables (scoped to .orm-root):
`css`
.orm-root {
--orm-text-secondary: hsl(var(--foreground) / 0.85);
}
This component uses CSS isolation to prevent style leaks into your application. All Tailwind classes are scoped to .orm-root, ensuring that:
- β
The component's styles don't affect your app (shadcn, etc.)
- β
Your app's global styles don't affect the component
- β
Portals (Select dropdowns, Dialogs) are properly scoped
1. Root wrapper: The component automatically wraps itself with .orm-root.orm-root
2. Tailwind scoping: All generated Tailwind utilities are prefixed with (e.g., .orm-root .flex, .orm-root .text-sm).orm-root
3. Portal wrapping: Select and Dialog portals are wrapped with to maintain isolation
In some cases (e.g., showAllInModal), you may see .orm-root appear multiple times in the DOM:
`html`
This is intentional and safe. The redundant wrappers ensure robust isolation even when portals are rendered outside the React tree.
If you experience z-index conflicts with your app (e.g., navbar, modals), you can add CSS isolation:
`css`
.orm-root {
isolation: isolate;
}
This creates a new stacking context and prevents z-index conflicts.
Your className prop is applied to the content (not the root wrapper), so it has priority over internal styles:
`tsx`
`bash`
export VITE_OPENROUTER_API_KEY="sk-or-v1-..."
`tsx
import { useState } from 'react'
import { ModelSelector } from '@cappasoft/openrouter-model-selector'
import '@cappasoft/openrouter-model-selector/styles.css'
export function App() {
const initialKey = (import.meta as any).env?.VITE_OPENROUTER_API_KEY ?? ''
const [apiKeyDraft, setApiKeyDraft] = useState(initialKey)
const [apiKey, setApiKey] = useState(initialKey)
const [model, setModel] = useState('openai/gpt-4o')
return (
<>
setApiKeyDraft(e.target.value)} placeholder="sk-or-v1-..." />
>
)
}
`
`tsx`
`tsx`
`tsx`
`tsx``
- π¨ Beautiful UI with dark mode support
- π Smart search by name, provider, or capability
- π Models grouped by provider
- β Curated recommended models
- πͺΆ Lightweight and tree-shakeable
MIT