Repository navigation
fix(icons): fall back to Stepfun Mono when Color component is absent … #7743
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
diegosouzapw
merged 4 commits into
cheaper-inference:release/v3.8.49
from
Dan-ex-hub:fix/stepfun-missing-color-icon-lobehub-v5
Jul 19, 2026
Merged
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
4fbce2d
fix(icons): fall back to Stepfun Mono when Color component is absent …
Dan-ex-hub 0b33f55
fix(ui): resolve Next.js hydration mismatch on sidebar collapsed state
Dan-ex-hub bc83682
merge: sync with release/v3.8.49 tip for pre-green
diegosouzapw b942be5
test(ui): add regression guards for Stepfun mono fallback and sidebar…
Dan-ex-hub File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
56 changes: 56 additions & 0 deletions
56
tests/unit/stepfun-mono-fallback-and-sidebar-hydration-7743.test.ts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| import test from "node:test"; | ||
| import assert from "node:assert/strict"; | ||
| import fs from "node:fs"; | ||
|
|
||
| // Regression guards for PR #7743: | ||
| // 1) @lobehub/icons v5.13+ dropped the Stepfun `Color` sub-component. Importing it | ||
| // causes a build-time module-not-found error that breaks the whole dashboard. | ||
| // Lock in the Mono fallback so a future bump can't silently re-import it. | ||
| // 2) DashboardLayout must not read localStorage synchronously during the initial | ||
| // `useState` render — that produces a client/server markup mismatch (hydration | ||
| // error) because the server always renders the `false` (collapsed=false) branch. | ||
| // The fix defers the localStorage read to a `useEffect`. | ||
|
|
||
| const lobeProviderIconsSrc = fs.readFileSync( | ||
| new URL("../../src/shared/components/lobeProviderIcons.ts", import.meta.url), | ||
| "utf8" | ||
| ); | ||
|
|
||
| const dashboardLayoutSrc = fs.readFileSync( | ||
| new URL("../../src/shared/components/layouts/DashboardLayout.tsx", import.meta.url), | ||
| "utf8" | ||
| ); | ||
|
|
||
| test("lobeProviderIcons never imports the removed Stepfun Color sub-component", () => { | ||
| assert.doesNotMatch( | ||
| lobeProviderIconsSrc, | ||
| /@lobehub\/icons\/es\/Stepfun\/components\/Color/, | ||
| "Stepfun/components/Color does not exist in @lobehub/icons v5.13+ and must not be imported" | ||
| ); | ||
| }); | ||
|
|
||
| test("lobeProviderIcons maps both Stepfun mono and color slots to StepfunMonoIcon", () => { | ||
| const stepfunEntry = lobeProviderIconsSrc.match(/Stepfun:\s*{\s*mono:\s*(\w+),\s*color:\s*(\w+)\s*}/); | ||
| assert.ok(stepfunEntry, "Stepfun entry must exist in LOBE_ICON_COMPONENTS"); | ||
| const [, mono, color] = stepfunEntry; | ||
| assert.equal(mono, "StepfunMonoIcon"); | ||
| assert.equal(color, "StepfunMonoIcon", "color slot must fall back to the Mono icon"); | ||
| }); | ||
|
|
||
| test("DashboardLayout does not read localStorage synchronously inside the collapsed useState initializer", () => { | ||
| const collapsedStateMatch = dashboardLayoutSrc.match(/const \[collapsed, setCollapsed\] = useState\(([^)]*)\)/); | ||
| assert.ok(collapsedStateMatch, "collapsed useState declaration must exist"); | ||
| assert.equal( | ||
| collapsedStateMatch[1].trim(), | ||
| "false", | ||
| "collapsed must initialize to a constant so server and first client render match (no hydration mismatch)" | ||
| ); | ||
| }); | ||
|
|
||
| test("DashboardLayout defers the sidebar-collapsed localStorage read to a useEffect", () => { | ||
| const effectIndex = dashboardLayoutSrc.indexOf("useEffect(() => {"); | ||
| assert.ok(effectIndex >= 0, "a useEffect must exist"); | ||
| const effectBody = dashboardLayoutSrc.slice(effectIndex, dashboardLayoutSrc.indexOf("}, []);", effectIndex)); | ||
| assert.match(effectBody, /localStorage\.getItem\(SIDEBAR_COLLAPSED_KEY\)/); | ||
| assert.match(effectBody, /setCollapsed\(true\)/); | ||
| }); |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since the
LobeIconEntrytype definescoloras optional (color?: LobeIconComponent) andgetLobeProviderIconautomatically falls back tomonowhencoloris undefined, we can simply omit thecolorproperty forStepfuninstead of duplicatingStepfunMonoIcon. This is consistent with other mono-only icons in this map (e.g.,Suno,Ai21,Anthropic).