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
Original file line number Diff line number Diff line change
Expand Up @@ -270,11 +270,11 @@ describe('ProvidersSection — Cindy AI 账户资产模块', () => {
);

const buyPlan = screen.getByText('settings.providers.xd.asset.buyPlan').closest('button');
expect(buyPlan?.style.backgroundColor).toBe('var(--accent-cta-bg-pure)');
expect(buyPlan?.style.color).toBe('var(--accent-pure-cta-fg)');
expect(buyPlan?.className).toContain('bg-[var(--accent-cta-bg-pure)]');
expect(buyPlan?.className).toContain('text-[var(--accent-pure-cta-fg)]');
const usageButton = screen.getByText('settings.providers.xd.asset.viewUsage').closest('button');
expect(usageButton?.style.backgroundColor).toBe('var(--settings-btn-secondary-bg)');
expect(usageButton?.style.color).toBe('var(--settings-btn-secondary-text)');
expect(usageButton?.className).toContain('bg-[var(--surface-elevated)]');
expect(usageButton?.className).toContain('text-[var(--text-primary)]');
expect(screen.queryByText('billing.settings.topupCard.action')).toBeNull();
expect(screen.queryByText('settings.providers.xd.asset.upgradePlan')).toBeNull();

Expand All @@ -292,8 +292,8 @@ describe('ProvidersSection — Cindy AI 账户资产模块', () => {
expect(screen.queryByText('billing.settings.topupCard.action')).toBeNull();

const upgrade = screen.getByText('settings.providers.xd.asset.upgradePlan').closest('button');
expect(upgrade?.style.backgroundColor).toBe('var(--accent-cta-bg-pure)');
expect(upgrade?.style.color).toBe('var(--accent-pure-cta-fg)');
expect(upgrade?.className).toContain('bg-[var(--accent-cta-bg-pure)]');
expect(upgrade?.className).toContain('text-[var(--accent-pure-cta-fg)]');

fireEvent.click(screen.getByText('settings.providers.xd.asset.upgradePlan'));
await waitFor(() =>
Expand All @@ -313,8 +313,8 @@ describe('ProvidersSection — Cindy AI 账户资产模块', () => {
expect(screen.queryByText('settings.providers.xd.asset.upgradePlan')).toBeNull();

const topup = screen.getByText('billing.settings.topupCard.action').closest('button');
expect(topup?.style.backgroundColor).toBe('var(--accent-cta-bg-pure)');
expect(topup?.style.color).toBe('var(--accent-pure-cta-fg)');
expect(topup?.className).toContain('bg-[var(--accent-cta-bg-pure)]');
expect(topup?.className).toContain('text-[var(--accent-pure-cta-fg)]');

fireEvent.click(screen.getByText('billing.settings.topupCard.action'));
await waitFor(() =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import { useEffect, useMemo, useRef, useState } from 'react';
import { useTranslation } from 'react-i18next';

import { Input } from '@/components/ui/input';
import { Switch } from '@/components/ui/switch';
import { cn } from '@/lib/utils';
import { toast } from '@/lib/toast';
Expand Down Expand Up @@ -40,18 +41,7 @@ const ROW_HINT_CLASS =
/** 行间分割线:左右缩进与行内边距对齐。 */
const DIVIDER_CLASS = 'mx-4 h-px bg-[var(--settings-theme-card-border)]';

/**
* 数字输入框的框体规格,与设置页统一输入框 `SettingsTextInput` 的 md 档一致
* (DESIGN.md §4-5:单行输入走药丸圆角;fill 必须是 `--surface-elevated` —— 设置卡片
* 本身是 ivory,ivory 输入压在 ivory 卡上会与背景同色、填充对比度归零)。
* 上下调节沿用浏览器原生步进器,不自绘 —— 设置页的控件样式统一是独立议题,留待整体收敛。
*/
const NUMBER_INPUT_CLASS = cn(
'h-9 w-24 shrink-0 rounded-full px-4 text-13 outline-none transition-colors',
'bg-[var(--surface-elevated)] text-[var(--settings-input-text)]',
'border border-[var(--settings-input-border)] focus:border-[var(--settings-input-border-focus)]',
'focus:ring-2 focus:ring-[var(--focus-ring)]',
);
/** 数字输入走标准 Input md 档(32/36/40 中的 36px),原生步进器不自绘。 */

/**
* 均衡档并发值:本机核数的一半,至少 2(与 main 侧 toolchain-thread-cap 的口径一致),
Expand Down Expand Up @@ -308,13 +298,13 @@ export function AgentResourceSection() {
{t('settings.agentResource.maxConcurrentHint')}
</span>
</span>
<input
<Input
type="number"
min={0}
max={MAX_CONCURRENT_CAP}
disabled={applyingPreset}
value={maxDraft ?? String(settings.maxConcurrentCommands)}
onChange={(e) => setMaxDraft(e.target.value)}
onChange={setMaxDraft}
onBlur={() => {
// 唯一提交点(DESIGN §14.3:Settings 单行编辑器 Enter 不得提交):
// 仅 0..64 的整数且与当前值不同才写盘;非法/未变草稿作废,
Expand All @@ -327,7 +317,8 @@ export function AgentResourceSection() {
if (raw === settings.maxConcurrentCommands) return;
persist('maxConcurrentCommands', raw);
}}
className={NUMBER_INPUT_CLASS}
size="md"
className="w-24 shrink-0"
/>
</label>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import { useState, useEffect } from 'react';
import { useTranslation } from 'react-i18next';
import { Input } from '@/components/ui/input';
import { cn } from '@/lib/utils';
import { toast } from '@/lib/toast';
import { DefaultOverrideControls } from './DefaultOverrideControls';
Expand All @@ -22,18 +23,7 @@ const ROW_HINT_CLASS =
/** 行间分割线:左右缩进与行内边距对齐。 */
const DIVIDER_CLASS = 'mx-4 h-px bg-[var(--settings-theme-card-border)]';

/**
* 数字输入框的框体规格,与设置页统一输入框 `SettingsTextInput` 的 md 档一致
* (DESIGN.md §4-5:单行输入走药丸圆角;fill 必须是 `--surface-elevated` —— 设置卡片
* 本身是 ivory,ivory 输入压在 ivory 卡上会与背景同色、填充对比度归零)。
* 上下调节沿用浏览器原生步进器,不自绘 —— 设置页的控件样式统一是独立议题,留待整体收敛。
*/
const NUMBER_INPUT_CLASS = cn(
'h-9 w-24 shrink-0 rounded-full px-4 text-13 outline-none transition-colors',
'bg-[var(--surface-elevated)] text-[var(--settings-input-text)]',
'border border-[var(--settings-input-border)] focus:border-[var(--settings-input-border-focus)]',
'focus:ring-2 focus:ring-[var(--focus-ring)]',
);
/** 数字输入走标准 Input md 档(32/36/40 中的 36px),原生步进器不自绘。 */

interface CollaborationSettings {
workerSoftLimit: number;
Expand Down Expand Up @@ -114,16 +104,17 @@ export function CollaborationSection() {
{t('settings.collaboration.workerSoftLimitHint')}
</span>
</span>
<input
<Input
type="number"
min={1}
max={settings.workerHardLimit}
value={settings.workerSoftLimit}
onChange={(e) => {
const v = Math.max(1, Math.min(settings.workerHardLimit, Number(e.target.value) || 1));
value={String(settings.workerSoftLimit)}
onChange={(text) => {
const v = Math.max(1, Math.min(settings.workerHardLimit, Number(text) || 1));
persist('workerSoftLimit', v);
}}
className={NUMBER_INPUT_CLASS}
size="md"
className="w-24 shrink-0"
/>
</label>

Expand All @@ -139,16 +130,20 @@ export function CollaborationSection() {
{t('settings.collaboration.workerHardLimitHint')}
</span>
</span>
<input
<Input
type="number"
min={settings.workerSoftLimit}
max={20}
value={settings.workerHardLimit}
onChange={(e) => {
const v = Math.max(settings.workerSoftLimit, Math.min(20, Number(e.target.value) || settings.workerSoftLimit));
value={String(settings.workerHardLimit)}
onChange={(text) => {
const v = Math.max(
settings.workerSoftLimit,
Math.min(20, Number(text) || settings.workerSoftLimit),
);
persist('workerHardLimit', v);
}}
className={NUMBER_INPUT_CLASS}
size="md"
className="w-24 shrink-0"
/>
</label>

Expand All @@ -164,17 +159,18 @@ export function CollaborationSection() {
{t('settings.collaboration.idleReleaseHint')}
</span>
</span>
<input
<Input
type="number"
min={0}
max={120}
value={settings.workerIdleReleaseMinutes}
onChange={(e) => {
const raw = Number(e.target.value);
value={String(settings.workerIdleReleaseMinutes)}
onChange={(text) => {
const raw = Number(text);
const v = Math.max(0, Math.min(120, Number.isFinite(raw) ? Math.trunc(raw) : 0));
persist('workerIdleReleaseMinutes', v);
}}
className={NUMBER_INPUT_CLASS}
size="md"
className="w-24 shrink-0"
/>
</label>
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ import { useModelAccessStatus } from '@/hooks/useModelAccessStatus';
import { useModelAccessCreditUsage } from '@/hooks/useModelAccessCreditUsage';
import { useXdAssetPrimaryAction } from '@/hooks/useXdAssetPrimaryAction';
import { useReducedMotion } from '@/hooks/useReducedMotion';
import { Button } from '@/components/ui/button';
import { useConfirmDialog } from '@/components/ui/confirm-dialog-provider';
import { useSignInToCindy } from '@/hooks/useSignInToCindy';
import { useProviderOAuthDeviceCode } from '@/hooks/useProviderOAuthDeviceCode';
Expand Down Expand Up @@ -201,23 +202,9 @@ function PillButton({
disabled?: boolean;
}) {
return (
<button
type="button"
onClick={onClick}
disabled={disabled}
className={cn(
'flex h-8 shrink-0 items-center justify-center rounded-full px-6 text-13 font-medium transition-colors',
'border',
disabled && 'cursor-not-allowed opacity-60',
)}
style={{
backgroundColor: 'var(--settings-btn-secondary-bg)',
borderColor: 'var(--settings-btn-secondary-border)',
color: 'var(--settings-btn-secondary-text)',
}}
>
<Button variant="secondary" size="md" onClick={onClick} disabled={disabled}>
{label}
</button>
</Button>
);
}

Expand All @@ -238,24 +225,9 @@ function CtaPillButton({
className?: string;
}) {
return (
<button
type="button"
onClick={onClick}
className={cn(
'flex shrink-0 items-center justify-center rounded-full px-6 text-13 font-medium transition-opacity hover:opacity-90',
size === 'lg' ? 'h-9' : 'h-8',
className,
)}
style={{
// Black Pill(最高强调档)按 DESIGN.md §4 用 pure 对:--accent-cta-bg-pure
// (Light 纯黑 / Dark 纯白反转)配 --accent-pure-cta-fg。--accent-cta-bg 在
// 默认 Light 下是 #262626,与规范的 #000000 差一档,不能混用。
backgroundColor: 'var(--accent-cta-bg-pure)',
color: 'var(--accent-pure-cta-fg)',
}}
>
<Button variant="cta" size={size} onClick={onClick} className={className}>
{label}
</button>
</Button>
);
}

Expand Down
Loading