Files
openchamber/packages/ui/src/components/views/SettingsWindow.tsx
T
gsxdsm a264393f1b feat: extend quota providers and add usage dropdown (#254) (#284)
* feat: extend quota providers and add usage dropdown

Add new quota providers:
- Claude (Anthropic API)
- Codex (OpenAI/ChatGPT)
- GitHub Copilot (base + add-on)
- Kimi for Coding
- OpenRouter

UI enhancements:
- Add rate limits dropdown in header with timer icon
- Desktop: sticky header with Used/Remaining toggle, refresh button
- Mobile: full-screen dropdown with same controls
- Per-provider sticky headers with provider logos
- Auto-refresh on open if no data exists

Usage settings page:
- Provider icon next to header
- Show in dropdown toggle per provider
- Global display selector (Usage vs Quota remaining)
- Auto-refresh controls in sidebar

Settings persistence:
- Add usageDisplayMode and usageDropdownProviders settings
- Server-side sanitization for new settings

Provider logo aliases:
- codex -> openai, claude -> anthropic

Bug fixes:
- Fix React error #310 by calling hooks before early returns
- Add aria-describedby to SettingsWindow dialog
- Remove horizontal scroll from dropdown

* fix: Remove duplicate github copilot declarations
2026-02-04 11:13:23 +02:00

41 lines
1.4 KiB
TypeScript

import React from 'react';
import * as DialogPrimitive from '@radix-ui/react-dialog';
import { cn } from '@/lib/utils';
import { SettingsView } from './SettingsView';
interface SettingsWindowProps {
open: boolean;
onOpenChange: (open: boolean) => void;
}
/**
* Settings rendered as a centered window with blurred backdrop.
* Used for desktop and web (non-mobile) environments.
*/
export const SettingsWindow: React.FC<SettingsWindowProps> = ({ open, onOpenChange }) => {
const descriptionId = React.useId();
return (
<DialogPrimitive.Root open={open} onOpenChange={onOpenChange}>
<DialogPrimitive.Portal>
<DialogPrimitive.Overlay
className="fixed inset-0 z-50 bg-black/50 backdrop-blur-md"
/>
<DialogPrimitive.Content
aria-describedby={descriptionId}
className={cn(
'fixed z-50 top-[50%] left-[50%] translate-x-[-50%] translate-y-[-50%]',
'w-[90vw] max-w-[1200px] h-[85vh] max-h-[900px]',
'rounded-xl border shadow-2xl overflow-hidden',
'bg-background'
)}
>
<DialogPrimitive.Description id={descriptionId} className="sr-only">
OpenChamber settings window.
</DialogPrimitive.Description>
<SettingsView onClose={() => onOpenChange(false)} isWindowed />
</DialogPrimitive.Content>
</DialogPrimitive.Portal>
</DialogPrimitive.Root>
);
};