Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions changelog/unreleased/keys-card-prefix-line.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
### English

- Console: API key cards show the key prefix on its own full-width line at a readable size.
- Console: the sidebar is easier to read, with larger menu text, icons and rows.

### 中文

- 控制台:API 密钥卡片将密钥前缀单独整行显示,字号更易读。
- 控制台:侧边栏菜单的文字、图标和行高加大,更易阅读。
20 changes: 10 additions & 10 deletions frontend/src/components/layout/AppSidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ function NavList({ collapsed, onNavigate }: { collapsed: boolean; onNavigate?: (
const activeRect = active.getBoundingClientRect()
gsap.to(indicator, {
x: activeRect.left - navRect.left,
y: activeRect.top - navRect.top + activeRect.height / 2 - 8,
y: activeRect.top - navRect.top + activeRect.height / 2 - 9,
autoAlpha: 1,
scaleY: 1,
duration: window.matchMedia('(prefers-reduced-motion: reduce)').matches ? 0 : 0.28,
Expand All @@ -63,13 +63,13 @@ function NavList({ collapsed, onNavigate }: { collapsed: boolean; onNavigate?: (

return (
<nav ref={navRef} className="relative flex flex-col gap-5">
<span ref={indicatorRef} aria-hidden className="pointer-events-none absolute left-0 top-0 h-4 w-0.5 origin-center rounded-full bg-accent opacity-0" />
<span ref={indicatorRef} aria-hidden className="pointer-events-none absolute left-0 top-0 h-[18px] w-0.5 origin-center rounded-full bg-accent opacity-0" />
{groups.map((group) => (
<div key={group.key} className="flex flex-col gap-0.5">
{collapsed ? (
<Separator className="mx-auto mb-1 w-6" />
) : (
<span className="px-3 pb-1 text-xs font-medium text-muted">{group.label}</span>
<span className="px-3 pb-1 text-caption font-medium text-muted">{group.label}</span>
)}
{nav.filter((item) => item.section === group.key).map((item) => {
const Icon = item.icon
Expand All @@ -81,12 +81,12 @@ function NavList({ collapsed, onNavigate }: { collapsed: boolean; onNavigate?: (
onClick={onNavigate}
aria-label={t(item.key)}
title={collapsed ? t(item.key) : undefined}
className={({ isActive }) => `group/navitem relative flex items-center gap-2.5 rounded-lg py-1.5 text-body transition-colors will-change-transform ${collapsed ? 'mx-auto w-10 justify-center px-0' : 'px-3'} ${isActive ? 'bg-default font-medium text-foreground' : 'font-normal text-muted hover:bg-default hover:text-foreground'}`}
className={({ isActive }) => `group/navitem relative flex h-9 items-center gap-3 rounded-lg text-nav transition-colors will-change-transform ${collapsed ? 'mx-auto w-10 justify-center px-0' : 'px-3'} ${isActive ? 'bg-default font-medium text-foreground' : 'font-normal text-muted hover:bg-default hover:text-foreground'}`}
onMouseDown={(event) => pressScale(event.currentTarget)}
>
{({ isActive }) => (
<>
<span className="inline-flex shrink-0" data-nav-icon><Icon size={16} weight={isActive ? 'fill' : 'regular'} /></span>
<span className="inline-flex shrink-0" data-nav-icon><Icon size={18} weight={isActive ? 'fill' : 'regular'} /></span>
{!collapsed && <span className="truncate" data-nav-label>{t(item.key)}</span>}
{collapsed && <span className="pointer-events-none absolute left-full z-50 ml-2 invisible whitespace-nowrap rounded-lg bg-foreground px-2 py-1 text-xs font-medium text-background opacity-0 shadow-overlay transition-opacity duration-150 group-hover/navitem:visible group-hover/navitem:opacity-100">{t(item.key)}</span>}
</>
Expand All @@ -104,8 +104,8 @@ function Brand({ compact = false }: { compact?: boolean }) {
const { t } = useI18n()
return (
<div className={`flex items-center gap-3 ${compact ? 'justify-center' : 'px-2'}`}>
<BrandMark size={32} />
{!compact && <div><div className="text-body font-semibold">CLI2API</div><div className="text-caption text-muted">{t('controlPlane')}</div></div>}
<BrandMark size={34} />
{!compact && <div><div className="text-nav font-semibold">CLI2API</div><div className="text-xs text-muted">{t('controlPlane')}</div></div>}
</div>
)
}
Expand Down Expand Up @@ -159,9 +159,9 @@ export function AppSidebar({ mobileOpen, onClose }: Props) {
showStatusSkeleton ? (
<SidebarStatusSkeleton label={t('refreshing')} />
) : (
<div className="rounded-xl bg-surface shadow-surface p-3">
<div className="rounded-xl bg-surface shadow-surface p-3.5">
<div className="flex items-center justify-between gap-3">
<div className="flex items-center gap-2 text-body font-medium">
<div className="flex items-center gap-2 text-nav font-medium">
<span className="status-dot" data-state={healthy ? 'ok' : 'danger'} />
{healthy ? t('running') : t('degraded')}
</div>
Expand Down Expand Up @@ -198,7 +198,7 @@ export function AppSidebar({ mobileOpen, onClose }: Props) {

return (
<>
<aside className={`hidden h-dvh shrink-0 flex-col bg-surface-secondary text-foreground transition-[width] duration-300 ease-out md:flex ${collapsed ? 'w-[76px] px-2.5 py-4' : 'w-[248px] px-3 py-4'}`}>
<aside className={`hidden h-dvh shrink-0 flex-col bg-surface-secondary text-foreground transition-[width] duration-300 ease-out md:flex ${collapsed ? 'w-[76px] px-2.5 py-4' : 'w-[240px] px-3 py-4'}`}>
<div className={`flex h-9 shrink-0 items-center ${collapsed ? 'justify-center' : 'justify-start'}`}><Brand compact={collapsed} /></div>
<div className="mt-5 min-h-0 flex-1 overflow-y-auto overscroll-contain"><NavList collapsed={collapsed} /></div>
{footer}
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/components/layout/SidebarUpdateItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,10 @@ export function SidebarUpdateItem({ collapsed, onNavigate }: { collapsed: boolea
onClick={() => setOpen(true)}
aria-label={label}
title={collapsed ? label : undefined}
className={`flex w-full items-center gap-2.5 rounded-lg py-1.5 text-body transition-colors hover:bg-default ${collapsed ? 'mx-auto w-10 justify-center px-0' : 'px-3'} ${hasUpdate ? 'font-medium text-accent' : 'text-muted hover:text-foreground'}`}
className={`flex h-9 w-full items-center gap-3 rounded-lg text-nav transition-colors hover:bg-default ${collapsed ? 'mx-auto w-10 justify-center px-0' : 'px-3'} ${hasUpdate ? 'font-medium text-accent' : 'text-muted hover:text-foreground'}`}
>
<span className="relative inline-flex shrink-0">
<Icon size={16} weight={hasUpdate ? 'fill' : 'regular'} />
<Icon size={18} weight={hasUpdate ? 'fill' : 'regular'} />
{hasUpdate && collapsed ? <span className="absolute -right-0.5 -top-0.5 size-1.5 rounded-full bg-accent" /> : null}
</span>
{!collapsed && <span className="truncate">{label}</span>}
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/index.css
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
--text-section: 0.9375rem;
--text-section--line-height: 1.375rem;
--text-section--font-weight: 600;
--text-nav: 0.875rem;
--text-nav--line-height: 1.25rem;
--text-body: 0.8125rem;
--text-body--line-height: 1.25rem;
--text-xs: 0.75rem;
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/pages/KeysPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -213,13 +213,13 @@ export function KeysPage() {
<Card.Header className="flex-row items-start justify-between gap-3 px-3 pt-3 pb-2.5">
<div className="min-w-0">
<Card.Title className="truncate text-body">{key.name}</Card.Title>
<Card.Description className="mono mt-1 truncate">{key.prefix}</Card.Description>
</div>
<Chip size="sm" variant="soft" color={key.enabled ? 'success' : 'default'}>
{key.enabled ? t('enabled') : t('disabled')}
</Chip>
</Card.Header>
<Card.Content className="space-y-2.5 px-3 pb-2.5">
<div className="mono w-full rounded-lg bg-surface-secondary px-3 py-2 text-body text-foreground" title={key.prefix}>{key.prefix}</div>
<div className="flex flex-wrap items-center gap-1.5">
{(key.providers.length ? key.providers : ['all']).map((entry) => (
<Chip key={entry} size="sm" variant="soft">
Expand Down

Large diffs are not rendered by default.

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions internal/webui/static/assets/index-Ca-WI-xc.css

Large diffs are not rendered by default.

2 changes: 0 additions & 2 deletions internal/webui/static/assets/index-ClPqPvYi.css

This file was deleted.

4 changes: 2 additions & 2 deletions internal/webui/static/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,8 @@
<meta name="twitter:title" content="CLI2API" />
<meta name="twitter:description" content="Qoder CLI → OpenAI-compatible API. Self-hosted gateway." />
<meta name="twitter:image" content="/og-card.svg" />
<script type="module" crossorigin src="/assets/index-uMr9hDfZ.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-ClPqPvYi.css">
<script type="module" crossorigin src="/assets/index-3YaYZVo0.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-Ca-WI-xc.css">
</head>
<body>
<div id="root"></div>
Expand Down
Loading