diff --git a/web/TODO.md b/web/TODO.md index 5da04a60bd9..3d4919d3209 100644 --- a/web/TODO.md +++ b/web/TODO.md @@ -1,6 +1,10 @@ # HeroUI v3 Cleanup -Branch: `feature/heroui-v3-cleanup` +Tracker across PRs: +- PR #9 (merged) — Phase 0, 2, 3. +- PR (this branch) — Phase 4, 6. + +Active branch: `feature/heroui-v3-success-warning-buttons` Goal: bring `web/` into full compliance with HeroUI v3 component rules (ref: https://heroui.com/react/llms.txt and per-component migration guides). @@ -62,26 +66,24 @@ Mapping applied: - [x] Run codemod (102 component files, ~325 prop edits + Chip in semi.js). - [x] Verify zero `variant='solid|bordered|flat|light|faded|shadow'` and zero `radius=` left in `web/src/`. -### Phase 4 — Manual review of `color='success' / 'warning'` - -v3 Button has no built-in success/warning variant. The codemod left -these in place; each needs a Tailwind override (`bg-success`, etc.) or -a swap to the closest semantic intent. - -- [ ] `web/src/components/settings/personal/cards/CheckinCalendar.jsx` — - "补签 / Gift" success Button. -- [ ] `web/src/components/table/channels/modals/ModelTestModal.jsx` — - "测试中" warning indicator. -- [ ] `web/src/components/table/channels/modals/MultiKeyManageModal.jsx` — - warning badge. -- [ ] `web/src/components/table/tokens/index.jsx` — warning label. -- [ ] `web/src/components/table/users/UsersColumnDefs.jsx` — risk warning. -- [ ] `web/src/components/table/users/modals/UserSubscriptionsModal.jsx` — - warning. -- [ ] `web/src/pages/Setting/Operation/SettingsChannelAffinity.jsx` — - warning. -- [ ] `web/src/pages/Setting/Performance/SettingsPerformance.jsx` — - "清理缓存" warning Button. +### Phase 4 — Manual review of `color='success' / 'warning'` ✅ + +v3 Button has no built-in success/warning variant. Centralised the four +tone classes in `web/src/components/common/ui/buttonTones.js` +(`successButtonClass`, `warningButtonClass`, `warningSoftButtonClass`, +`warningGhostButtonClass`) — each overrides `--button-bg / -hover / +-pressed / -fg` using the warning / success tokens `@heroui/styles` +already exposes via Tailwind v4. Pair with v3 `variant='primary'` for +solid tones, `variant='tertiary'` for ghost / icon-only. + +- [x] `CheckinCalendar` "立即签到" → `variant='primary' + successButtonClass`. +- [x] `SettingsPerformance` "清理不活跃缓存" → `variant='primary' + warningButtonClass`. +- [x] `MultiKeyManageModal` "删除自动禁用密钥" → `variant='primary' + warningButtonClass`. +- [x] `SettingsChannelAffinity` "清空规则缓存" (icon-only X) → `variant='tertiary' + warningGhostButtonClass`. +- [x] `ModelTestModal` "前往设置" → `variant='tertiary' + warningGhostButtonClass`. +- [x] `UserSubscriptionsModal` "作废" → `variant='tertiary' + warningGhostButtonClass`. +- [x] `UsersColumnDefs` "提升" → `variant='tertiary' + warningGhostButtonClass`. +- [x] `tokens/index` "不再提醒" → `variant='tertiary' + warningGhostButtonClass`. ### Phase 5 — `startContent` / `endContent` → children @@ -91,12 +93,11 @@ Mostly mechanical but needs human review for ordering and gap classes. - [ ] Write codemod, run, manual sanity pass. -### Phase 6 — `classNames={...}` cleanup - -Single occurrence remaining (`web/src/components/auth/AuthLayout.jsx`), -v3 uses plain `className`. +### Phase 6 — `classNames={...}` cleanup ✅ -- [ ] Migrate. +- [x] `web/src/components/auth/AuthLayout.jsx` — replaced + `classNames={{ base, label }}` with root `className='items-start'` + + `` wrapper for the label tone. ### Phase 7 — Final verification diff --git a/web/src/components/auth/AuthLayout.jsx b/web/src/components/auth/AuthLayout.jsx index 8780efd27ef..f67445a3baa 100644 --- a/web/src/components/auth/AuthLayout.jsx +++ b/web/src/components/auth/AuthLayout.jsx @@ -109,12 +109,9 @@ export function AuthAgreement({ - <> + {t('我已阅读并同意')} {hasUserAgreement ? ( ) : null} - + ); diff --git a/web/src/components/common/ui/buttonTones.js b/web/src/components/common/ui/buttonTones.js new file mode 100644 index 00000000000..82c6b3716f3 --- /dev/null +++ b/web/src/components/common/ui/buttonTones.js @@ -0,0 +1,45 @@ +/* +Copyright (C) 2025 QuantumNous + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU Affero General Public License as +published by the Free Software Foundation, either version 3 of the +License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU Affero General Public License for more details. + +You should have received a copy of the GNU Affero General Public License +along with this program. If not, see . + +For commercial licensing, please contact support@quantumnous.com +*/ + +// HeroUI v3 dropped the `color` prop on Button — the v3 variants only cover +// primary / secondary / tertiary / outline / ghost / danger / danger-soft. +// For warning / success buttons we reuse v3's Button base (so size, padding, +// radius, focus / pressed transitions stay correct) and override the +// CSS variables Button reads (`--button-bg`, `--button-bg-hover`, +// `--button-bg-pressed`, `--button-fg`) using the warning / success tokens +// `@heroui/styles` already exposes via Tailwind v4. +// +// Pair these classes with `variant="primary"` (for solid) or +// `variant="tertiary"` (for soft / icon-only) so disabled / pending state +// styling stays consistent with the rest of the app. + +export const warningButtonClass = + '[--button-bg:var(--color-warning)] [--button-bg-hover:var(--color-warning-hover)] [--button-bg-pressed:var(--color-warning-hover)] [--button-fg:var(--color-warning-foreground)]'; + +export const warningSoftButtonClass = + '[--button-bg:var(--color-warning-soft)] [--button-bg-hover:var(--color-warning-soft-hover)] [--button-bg-pressed:var(--color-warning-soft-hover)] [--button-fg:var(--color-warning-soft-foreground)]'; + +// Ghost-style warning: transparent base, warning-tinted hover, warning text. +// Use with `variant="tertiary"` for low-emphasis cautionary actions +// (e.g. "前往设置", "不再提醒", icon-only delete-cache buttons). +export const warningGhostButtonClass = + 'text-warning [--button-bg-hover:var(--color-warning-soft)] [--button-bg-pressed:var(--color-warning-soft-hover)]'; + +export const successButtonClass = + '[--button-bg:var(--color-success)] [--button-bg-hover:var(--color-success-hover)] [--button-bg-pressed:var(--color-success-hover)] [--button-fg:var(--color-success-foreground)]'; diff --git a/web/src/components/settings/personal/cards/CheckinCalendar.jsx b/web/src/components/settings/personal/cards/CheckinCalendar.jsx index d551a241936..c700f06d597 100644 --- a/web/src/components/settings/personal/cards/CheckinCalendar.jsx +++ b/web/src/components/settings/personal/cards/CheckinCalendar.jsx @@ -42,6 +42,7 @@ import { } from 'lucide-react'; import Turnstile from 'react-turnstile'; import { API, showError, showSuccess, renderQuota } from '../../../../helpers'; +import { successButtonClass } from '../../../common/ui/buttonTones'; const WEEKDAY_KEYS = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']; @@ -369,7 +370,8 @@ const CheckinCalendar = ({ t, status, turnstileEnabled, turnstileSiteKey }) => { diff --git a/web/src/components/table/channels/modals/MultiKeyManageModal.jsx b/web/src/components/table/channels/modals/MultiKeyManageModal.jsx index ca97f0b7fdf..f8e4c7c60ca 100644 --- a/web/src/components/table/channels/modals/MultiKeyManageModal.jsx +++ b/web/src/components/table/channels/modals/MultiKeyManageModal.jsx @@ -35,6 +35,7 @@ import { timestamp2string, } from '../../../../helpers'; import ConfirmDialog from '../../../common/ui/ConfirmDialog'; +import { warningButtonClass } from '../../../common/ui/buttonTones'; // ----------------------------- helpers ----------------------------- @@ -509,7 +510,8 @@ const MultiKeyManageModal = ({ visible, onCancel, channel, onRefresh }) => { )}