Migrate the add-model surface (AddModelForm, add_model_tab,
add_auto_router_tab, advanced_settings, cache_control_settings,
conditional_public_model_name, litellm_model_name,
provider_specific_fields) from antd Form + tremor to shadcn primitives
and react-hook-form.
- Root form state moves from antd FormInstance (Form.useForm) to RHF
UseFormReturn, created in ModelsAndEndpointsView.tsx and threaded
through AddModelTab / AddModelForm. Children use useFormContext /
Controller / useWatch / useFieldArray.
- antd Modal -> shadcn Dialog; antd Tag -> Badge; antd Select -> shadcn
Select; antd Radio.Group -> RadioGroup; antd Accordion (tremor) ->
shadcn Accordion; antd Form.List -> RHF useFieldArray.
- Submit helpers (handle_add_model_submit, handle_add_auto_router_submit)
feature-detect antd.resetFields vs RHF.reset so both paths keep
working through the mixed migration window.
- UploadProps type import migrates from antd/es/upload to a local shim
at add_model/add_model_upload_types.ts (structurally compatible with
the antd shape still used by model_add/AddCredentialModal.tsx and
model_add/EditCredentialModal.tsx).
- cache_control_settings ships both an RHF path (new callers) and a
legacy antd bridge used by model_info_view.tsx so the out-of-scope
detail view keeps working without cascading its migration.
- validateJsonValue added to utils/textUtils.ts to replace the antd
Promise-style formItemValidateJSON for RHF rules.
- Tests repaired: AddModelForm, add_model_tab,
conditional_public_model_name, litellm_model_name,
provider_specific_fields, advanced_settings now wrap with RHF
FormProvider instead of antd Form.
Co-authored-by: yuneng-jiang <yuneng-berri@users.noreply.github.com>
- add_plugin_form: replace antd Modal/Form/Input/Select and Tremor
Button with shadcn Dialog + react-hook-form + shadcn Input/Textarea/
Select/Button. Validation messages now rendered inline via
formState.errors instead of antd Form.Item's rules. URL preview keeps
the categorical blue palette and is recorded in .eslintrc allowlist.
- MakeSkillPublicForm: drop antd Form wrapper + Steps. Replace with
inline lucide-based Stepper; step state stays plain React useState.
Dialog was already shadcn.
All 60 claude_code_plugins tests pass (AddPluginForm + helpers).
tsc --noEmit clean; eslint clean with categorical-palette
allowlist.
Co-authored-by: yuneng-jiang <yuneng-berri@users.noreply.github.com>
- MakeAgentPublicForm, MakeMCPPublicForm, MakeModelPublicForm: drop
antd Form + Steps shells. Replace with inline lucide-based Stepper
component; step state stays plain React useState, dialog is already
shadcn Dialog.
- ModelHubTable: replace antd Modal with shadcn Dialog, Tremor
TabGroup/Tab/TabList/TabPanel with shadcn Tabs, Tremor Badge with
shadcn Badge + semantic color helper, Tremor Card/Text/Title/Button
with shadcn primitives + Tailwind, Ant icons with lucide Copy. Keep
categorical palette (blue/green/purple/etc) classes for hub badges;
file remains in .eslintrc allowlist.
- Tests: update mocks to stop stubbing antd (real shadcn Checkbox now
exposes data-state="indeterminate" instead of the old
data-indeterminate prop; tests assert against the Radix attribute).
Split two-click "select/deselect" sequences into separate act()
calls so state updates propagate between clicks.
- All 47 scoped tests pass (MakeAgentPublicForm, MakeMCPPublicForm,
MakeModelPublicForm). ModelHubTable existing 8 tests still pass.
tsc --noEmit clean for migrated files. eslint clean.
Co-authored-by: yuneng-jiang <yuneng-berri@users.noreply.github.com>
- ProjectsPage: antd Table → shadcn Table + @tanstack/react-table with
TableHeaderSortDropdown for sortable columns.
- ProjectDetailsPage: removed antd Layout/Card/Descriptions/Row/Col/Spin/
Tag/Typography/Empty/Flex/Progress; switched to shadcn Card, Badge,
Progress, Skeleton, Tooltip + a CopyableId molecule mirroring
AccessGroupsDetailsPage.
- ProjectBaseForm: antd Form/Form.Item/Form.List → react-hook-form
FormProvider + Controller + useFieldArray. Dynamic model-limit and
metadata rows use useFieldArray. Guardrails tag input implemented as
a TagsSelect (shadcn Input + Select + Badge chips). Multi-model
selection uses the canonical MultiSelect from AccessGroupBaseForm.
Advanced settings section uses shadcn Collapsible.
- CreateProjectModal / EditProjectModal: share a single FormProvider;
submit via form.handleSubmit instead of form.validateFields; reset
defaults on open.
- ProjectBaseForm.test.tsx: wrap ProjectBaseForm in RHF FormProvider
(mock prop replaced by context). Existing Create/Edit modal tests
updated to include the new emptyProjectFormValues export in their
vi.mock factories.
No antd / @ant-design imports remain in src/components/Projects/. The
ProjectsPage status / ID chip keeps its categorical palette (blue/red/
emerald) via the existing .eslintrc.json override.
Co-authored-by: yuneng-jiang <yuneng-berri@users.noreply.github.com>
Migrate EditMembership, LoggingSettings, and TeamVirtualKeysTable off
antd / Tremor to shadcn + react-hook-form per BLUEPRINT.md.
- EditMembership: antd Form.useForm / Form.Item → react-hook-form
useForm + Controller + shadcn Input/Label/Select. Multi-select is
rendered as shadcn Select + Badge chip list following the
AccessGroupBaseForm pattern.
- LoggingSettings: antd Select (single + multi) → shadcn Select +
Badge chip list. The multi-select 'Disabled Callbacks' control now
adds selections one at a time and displays selected values as
dismissible chips. The dynamic-params number input switches from
NumericalInput (which coerces through Number) to a raw Input
type=number so string values like '1.0' round-trip verbatim —
fixing a pre-existing test failure where updateCallbackVar received
'1' instead of '1.0'.
- TeamVirtualKeysTable: swap Tremor Table / Button / Badge / Icon /
Text and antd Popover / Tooltip / Skeleton for shadcn equivalents,
mirroring the canonical VirtualKeysTable migration. Sorting,
column resize, tooltips, and 'Last Active' info popover are
preserved; layout classNames are unchanged.
team/TeamInfo.tsx (1724 LoC) is deferred to BLOCKERS.md — its antd
Form uses Form.List with Promise-based custom validators, Form.useWatch,
shouldUpdate, hidden Form.Item registrations, and Select.OptGroup with
tagRender, all of which exceed this batch's budget.
Co-authored-by: yuneng-jiang <yuneng-berri@users.noreply.github.com>
Scripted pass over all files with @ant-design/icons imports that
only contain icons covered by our mapping table. Each file now
imports lucide icons with 'Outlined' aliases so existing JSX
continues to work unchanged.
Icons mapped:
- Info/Settings/RefreshCcw/Loader2/Search/ArrowLeft/ArrowRight/
ChevronDown/ChevronRight/ChevronUp/ChevronLeft/Plus/PlusCircle/
Minus/MinusCircle/Trash2/Pencil/Copy/Check/CheckCircle2/X/XCircle/
AlertTriangle/AlertCircle/HelpCircle/Wrench/Key/Bot/History/Save/
Globe/Cloud/Server/Database/Upload/Download/Inbox/Link/Ban/EyeOff/
Eye/Code/FileText/File/Clock/User/UserPlus/Users/LayoutGrid/
GitBranch/Zap/Plug/Menu/Filter/MoreHorizontal/Image/Video/Mic/
MapPin/ChevronsUpDown.
Fixups applied after the bulk pass:
- 'spin' prop is antd-specific; replaced with className='animate-spin'
in audit_logs, multi_cost_results, ProjectDetailsPage,
SearchToolTester, EntityUsage, UsagePageView, ai_suggestion_modal.
- agents/add_agent_form: InfoCircleOutlined title/style props (antd)
\u2192 aria-label + Tailwind utilities (lucide React.SVGProps).
After this pass: @ant-design/icons usage drops from 48 \u2192 11 files.
The remaining 11 files import icon names outside the mapping table
and will be migrated individually.
Gates: TS \u2713 | Build \u2713.
Co-authored-by: yuneng-jiang <yuneng-berri@users.noreply.github.com>
- BaseActionButton.test: PencilAltIcon \u2192 lucide Pencil (aliased).
- Full heroicons count in src/ is now 0. @heroicons/react can be
dropped from package.json in a follow-up cleanup once phase 1
migration is fully closed out.
Gates: TS \u2713 | Build \u2713.
Co-authored-by: yuneng-jiang <yuneng-berri@users.noreply.github.com>
- prompts/prompt_info: ArrowLeft/Trash/Pencil rewired to lucide.
- mcp_tools/MCPToolsetsTab: Plus/Pencil/Trash rewired.
- organizations: ChevronDown/ChevronRight/Refresh rewired (Refresh \u2192
RefreshCcw).
- Aliases preserved so downstream JSX continues to use the Heroicon
names, unblocking deletion of the @heroicons package without
touching usages in these large files.
Gates: TS \u2713 | Build \u2713.
Co-authored-by: yuneng-jiang <yuneng-berri@users.noreply.github.com>
- antd Checkbox/Divider/Popover \u2192 shadcn Checkbox/Popover + native
<hr>. antd Slider preserved as AntSlider (shadcn Slider has a
different API).
- Swept bg-white/bg-gray-100/text-gray-700/bg-red-50/text-red-600
to background/muted/foreground + destructive tokens.
- Popover open state now driven by Radix onOpenChange (tracks
outside clicks) instead of the custom hand-rolled toggle.
Gates: TS \u2713 | Build \u2713.
Co-authored-by: yuneng-jiang <yuneng-berri@users.noreply.github.com>
File already uses shadcn Tooltip + lucide icons and swept to semantic
tokens. Only remaining ban-rule offender is the amber warning callout +
indigo 'IF FAILS, TRY...' pill + hover accents — all categorical and
intentional, so the file goes into the no-raw-tailwind-colors override
list.
Gates: Build \u2713.
Co-authored-by: yuneng-jiang <yuneng-berri@users.noreply.github.com>
- Removed stale debug console.log statements that leaked in during
form-state debugging.
- Replaced 'formValues: any' cast with an eslint-disable comment.
Gates: TS \u2713 | Build \u2713.
Co-authored-by: yuneng-jiang <yuneng-berri@users.noreply.github.com>