Skip to content

refactor(web): delete the Semi-style HeroCompat shim layer (Phase 1 done)#12

Merged
dingyi merged 4 commits into
mainfrom
feature/heroui-v3-drop-semi-compat
Apr 27, 2026
Merged

refactor(web): delete the Semi-style HeroCompat shim layer (Phase 1 done)#12
dingyi merged 4 commits into
mainfrom
feature/heroui-v3-drop-semi-compat

Conversation

@dingyi

@dingyi dingyi commented Apr 27, 2026

Copy link
Copy Markdown
Owner

Closes Phase 1 of web/TODO.md — the last three call sites that still
imported @/components/common/ui/HeroCompat are migrated to HeroUI v3

  • Tailwind directly, and the Semi adapter layer is deleted in full.

Summary

1. refactor(model-pricing): drop HeroCompat in DynamicPricingBreakdown

Read-only dynamic-pricing summary moved off Semi-style Avatar / Tag /
Table / Typography. Avatar pulled directly from @heroui/react with
v3 compound API; Tag → ~10-line ToneChip span; Table → native HTML
table; Typography.Text → spans + Tailwind. v2 color='amber' mapped
to v3 color='warning' (closest semantic equivalent — v3 dropped
amber).

2. refactor(ratio-settings): drop HeroCompat in ToolPriceSettings

Per-tool price editor — Banner → InfoBanner; RadioGroup type='button'
→ outline / primary Button pair; Table → native

; InputNumber
→ native <input type='number'> + the project's standard
inputClass; lucide icons; Button theme/loading → v3
variant/isPending.

3. refactor(ratio-settings): drop HeroCompat in TieredPricingEditor

The big one — 1700-line billing-expression editor. All preset
templates, expression parsing / generation logic, the LLM prompt
template, and the in-page cost estimator stay byte-identical; the
commit is purely a UI-layer migration. Notable detail:

  • The timezone selector used Semi's <Select filter allowCreate>,
    which has no v3 compound. Replaced with HTML5 <input list> +
    <datalist> (a single shared datalist sits at the editor root) for
    the same suggest-but-allow-free-input UX.
  • Cost-estimator panel switches from
    --semi-color-{danger,primary}-light-default tokens to
    bg-{danger,primary}/10 for v3 alignment.

4. refactor(web): delete the Semi-style HeroCompat shim layer

The shim layer is no longer reachable. Delete:

  • web/src/components/common/ui/HeroCompat.jsx (re-export shim)
  • web/src/components/common/ui/HeroIconsCompat.jsx (re-export shim)
  • web/src/components/common/ui/HeroIllustrationsCompat.jsx (re-export shim)
  • web/src/components/ui/semi.js (Form / Modal / Table / Banner /
    Tag / Toast / Nav / etc. translation, 1500+ lines)
  • web/src/components/ui/semi-icons.js
  • web/src/components/ui/semi-illustrations.js

Net diff: -1812 lines. After this PR web/src/components/ui/ only
contains ToastViewport.jsx (the v3-native toast portal helper).

Verification

$ rg "from '@/components/(common/ui/Hero|ui/semi)" web/src/
(no matches)

ESLint goes from 94 errors on origin/main to 93 (the deleted semi.js
held one no-multiple-empty-lines offender).

Test plan

  • Open Settings → Ratio → "工具价格设置" tab — visual ↔ JSON mode
    toggle, add/delete row, save.
  • Open Settings → Ratio → 模型定价编辑器, click any model with a
    tiered billing expression — visual / raw mode toggle, presets,
    cost estimator (with all extra-token inputs when expression
    uses cr / cc / img etc.), LLM prompt helper expand /
    copy, request-condition rule groups (param / header / time
    modes).
  • Open the model-pricing detail SideSheet for a model with a
    dynamic billing expression — DynamicPricingBreakdown renders
    tier table + multiplier rows.
  • Verify no console errors about missing components / undefined
    Toast / undefined Tag.

This PR was generated automatically by Cursor.

Made with Cursor

dingyi added 4 commits April 28, 2026 01:13
Rewrite the dynamic-pricing read-only summary to use HeroUI v3 / project
primitives directly instead of the Semi-style HeroCompat wrappers
(Avatar / Tag / Table / Typography). The rendered output is identical:
section icon avatar, tier price table with optional condition summary,
and per-rule multiplier rows.

- Avatar: pull from @heroui/react with v3 compound API
  (Avatar.Fallback) instead of the HeroCompat passthrough; map the v2
  `color='amber'` to v3 `color='warning'` (closest semantic equivalent;
  v3 dropped amber).
- Tag → ToneChip: a ~10-line span helper that reuses the same
  `bg-*/15 text-*` Tailwind palette already used by StatusChip in
  ModelPricingEditor. No more dependency on HeroCompat's Chip-via-Tag
  shim.
- Table → native <table> + Tailwind. The render had no sorting,
  selection, expansion, or pagination; the Semi Table was overkill.
  This drops a chunk of indirection and matches the rest of the
  pricing surface (which already renders breakdowns with plain
  tables).
- Typography.Text → spans / divs styled with Tailwind text utilities.

This is the first of three files migrating off `HeroCompat.jsx` /
`semi.js`. The compat shims stay in place for now; they'll be deleted
once ToolPriceSettings and TieredPricingEditor are migrated too.

Made-with: Cursor
Rewrite the per-tool price editor to use HeroUI v3 Button / Input /
TextArea directly instead of the Semi-style HeroCompat shims. The
visual / functional output is unchanged: visual ↔ JSON mode toggle,
tool key + price rows with delete, "添加" / "恢复默认" controls, and
a save button at the bottom.

Migrations:
- Banner → InfoBanner: matches the local InfoBanner pattern in
  ModelPricingEditor (Lucide Info icon + Tailwind border / bg
  utilities). One less component plumbed through HeroCompat.
- RadioGroup type='button' → outline / primary Button pair: v3
  RadioGroup has no `type='button'` compound, so the v2 prop was a
  silent no-op (the radios stayed as native radio buttons). Replace
  with a tiny rounded-pill segmented control.
- Table → native <table>: removes the unused pagination / size /
  rowKey props the Semi Table demanded; keeps the same column order
  (key, price, delete).
- InputNumber → native <input type='number'> + project's standard
  inputClass: v3 NumberField is a compound component
  (NumberField.Group + .Input + .Increment / .DecrementButton); for a
  single inline numeric cell the native input renders identically and
  is far less ceremony.
- IconCopy / IconDelete / IconPlus → lucide-react Copy / Trash2 / Plus.
- Typography.Text type='danger' → div with text-danger.
- Button theme='solid' loading → variant='primary' isPending.
- Button theme='borderless' → variant='ghost'.

The HeroCompat shim is no longer imported here. Two more files
(TieredPricingEditor and DynamicPricingBreakdown — last one already
done) and the shim itself can be deleted.

Made-with: Cursor
Rewrite the largest billing-expression editor in the project (1700+
lines) on top of HeroUI v3 + native HTML controls + Tailwind, removing
the last "real" caller of the Semi-style HeroCompat / HeroIconsCompat
shims. All preset templates, expression parsing / generation logic, the
LLM prompt template, and the in-page cost estimator stay byte-identical
— this commit is purely a UI-layer migration.

Mappings
--------
- Banner type='info'|'warning'         → InfoBanner (Lucide Info /
                                          AlertTriangle + Tailwind
                                          border / bg utilities,
                                          mirrors ModelPricingEditor).
- Tag color='blue|grey|orange'         → ToneChip (10-line span helper).
- Card bodyStyle / style               → div with rounded-xl
                                          bg-surface-secondary/50 p-4.
- Collapsible isOpen                   → conditional render.
- RadioGroup type='button'             → SegmentedToggle helper that
                                          renders an outline / primary
                                          Button pair (v3 RadioGroup
                                          has no equivalent compound).
- Select / Select.Option               → NativeSelect helper (native
                                          <select>). The timezone
                                          selector — which used Semi's
                                          filter+allowCreate Select —
                                          becomes an HTML5
                                          <input list> + <datalist>
                                          for the same suggest-but-
                                          allow-free-input UX.
- InputNumber                          → NumberInput helper (native
                                          <input type='number'>).
- Input value onChange={(val)=>...}    → native <input> with
                                          event.target.value handlers,
                                          consistent with the rest of
                                          /console.
- TextArea autosize={{minRows,maxRows}}→ v3 TextArea + rows={n}.
- Typography.Text size/type/strong     → spans / divs styled with
                                          text-xs / text-muted /
                                          font-semibold / etc.
- IconCopy / IconDelete / IconPlus     → lucide-react Copy / Trash2 /
                                          Plus.
- Button theme='borderless'|'light'    → variant='ghost'|'secondary',
  + onClick                              onPress.
- Button icon={<X/>} type='danger'     → isIconOnly variant='ghost'
                                          + text-danger className.

Other notes
-----------
- The old PriceInput used Semi `<Input suffix={...}>`; we render the
  suffix as a positioned `<span>` overlay on a relative wrapper, same
  pattern ModelPricingEditor's PriceInput already uses.
- The cost estimator's panel background switches from
  --semi-color-{danger,primary}-light-default tokens to
  bg-{danger,primary}/10 + matching border for v3 alignment.
- A single shared <datalist id='tiered-pricing-tz-list'> sits at the
  editor root rather than being re-emitted for every RuleConditionRow.

After this commit no business file imports `@/components/common/ui/HeroCompat`
nor `@/components/common/ui/HeroIconsCompat`. The shims (and `semi.js` /
`semi-icons.js` / `semi-illustrations.js` underneath them) can be
deleted in a follow-up commit.

Made-with: Cursor
Now that the last three callers (DynamicPricingBreakdown,
ToolPriceSettings, TieredPricingEditor) have been migrated off
@/components/common/ui/HeroCompat in the previous commits, the entire
Semi-style adapter layer is unused. Remove it.

Files deleted:

- web/src/components/common/ui/HeroCompat.jsx          (re-export shim)
- web/src/components/common/ui/HeroIconsCompat.jsx     (re-export shim)
- web/src/components/common/ui/HeroIllustrationsCompat.jsx (re-export shim)
- web/src/components/ui/semi.js                        (Semi → HeroUI v3
                                                        translation, 1500+
                                                        lines: Form / Modal /
                                                        Table / Banner / Tag /
                                                        Toast / Nav / etc.)
- web/src/components/ui/semi-icons.js                  (icon name aliases)
- web/src/components/ui/semi-illustrations.js          (illustration shims)

Net diff: -1812 lines.

Verification:
  $ rg \"from '@/components/(common/ui/Hero(Compat|IconsCompat|IllustrationsCompat)|ui/semi)\" web/src/
  (no matches)

After this commit `web/src/components/ui/` only contains ToastViewport.jsx,
the small v3-native toast portal helper. The directory's job ('Semi UI
compat layer') is done.

Made-with: Cursor
@dingyi
dingyi merged commit aa28fd3 into main Apr 27, 2026
1 check passed
@dingyi
dingyi deleted the feature/heroui-v3-drop-semi-compat branch April 27, 2026 18:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant