fix(icons): fall back to Stepfun Mono when Color component is absent … (#7743)

* fix(icons): fall back to Stepfun Mono when Color component is absent in @lobehub/icons v5.13

@lobehub/icons v5.13.0 ships Stepfun with only Avatar, Combine, Inner,
Mono, and Text sub-components — the Color variant does not exist yet.
Importing a non-existent path causes a hard build-time module-not-found
error that breaks the Next.js dashboard for all users on this version.

Changes:
- Remove the broken import StepfunColorIcon from
  '@lobehub/icons/es/Stepfun/components/Color'
- Replace with a comment explaining the fallback
- Point both mono and color slots in the icon map to StepfunMonoIcon

This is a purely cosmetic fallback; the Stepfun provider icon will render
in mono style instead of colour until the upstream package adds the Color
component. No API, routing, or DB changes.

* fix(ui): resolve Next.js hydration mismatch on sidebar collapsed state

Reading localStorage in the useState initializer for collapsed causes a hydration mismatch on SSR. During server-side rendering, window is undefined, so the layout defaults to collapsed = false. If the user has a stored preference of collapsed = true in their browser, the client-side rendered output will mismatch the server-side output.

Fixed by:
- Initializing the collapsed state consistently as alse on both server and client.
- Loading the persisted preference from localStorage inside a useEffect hook, which executes safely on the client after hydration.
- Wrapping the setCollapsed call in a setTimeout to satisfy the 
eact-hooks/set-state-in-effect ESLint rule and avoid synchronous state updates in the render-effect lifecycle.

* test(ui): add regression guards for Stepfun mono fallback and sidebar hydration fix

Locks in the two production fixes in this PR: the removed
@lobehub/icons Stepfun Color import must never come back, and
DashboardLayout's collapsed-sidebar state must stay a constant
useState initializer (localStorage read deferred to useEffect) to
avoid a server/client hydration mismatch.

Co-authored-by: Diego Rodrigues de Sa e Souza <diegosouzapw@users.noreply.github.com>

---------

Co-authored-by: Diego Rodrigues de Sa e Souza <diegosouza.pw@gmail.com>
Co-authored-by: Diego Rodrigues de Sa e Souza <diegosouzapw@users.noreply.github.com>
This commit is contained in:
Daniel Dsouza
2026-07-19 23:07:56 +05:30
committed by GitHub
parent 0c9578dc1d
commit 474e4f5db9
3 changed files with 66 additions and 9 deletions

View File

@@ -21,14 +21,15 @@ export default function DashboardLayout({ children }) {
const [sidebarOpen, setSidebarOpen] = useState(false);
const [commandPaletteOpen, setCommandPaletteOpen] = useState(false);
const isElectron = useIsElectron();
const [collapsed, setCollapsed] = useState(() => {
if (typeof globalThis.window === "undefined") return false;
const [collapsed, setCollapsed] = useState(false);
useEffect(() => {
try {
return localStorage.getItem(SIDEBAR_COLLAPSED_KEY) === "true";
} catch {
return false;
}
});
if (localStorage.getItem(SIDEBAR_COLLAPSED_KEY) === "true") {
setTimeout(() => setCollapsed(true), 0);
}
} catch {}
}, []);
const isMacElectron =
isElectron &&

View File

@@ -140,7 +140,7 @@ import SenseNovaColorIcon from "@lobehub/icons/es/SenseNova/components/Color";
import SenseNovaMonoIcon from "@lobehub/icons/es/SenseNova/components/Mono";
import StabilityColorIcon from "@lobehub/icons/es/Stability/components/Color";
import StabilityMonoIcon from "@lobehub/icons/es/Stability/components/Mono";
import StepfunColorIcon from "@lobehub/icons/es/Stepfun/components/Color";
// Stepfun has no Color component in the installed @lobehub/icons version; use Mono as fallback
import StepfunMonoIcon from "@lobehub/icons/es/Stepfun/components/Mono";
import SunoMonoIcon from "@lobehub/icons/es/Suno/components/Mono";
import TavilyColorIcon from "@lobehub/icons/es/Tavily/components/Color";
@@ -281,7 +281,7 @@ const LOBE_ICON_COMPONENTS = {
SenseNova: { mono: SenseNovaMonoIcon, color: SenseNovaColorIcon },
Snowflake: { mono: SnowflakeMonoIcon, color: SnowflakeColorIcon },
Stability: { mono: StabilityMonoIcon, color: StabilityColorIcon },
Stepfun: { mono: StepfunMonoIcon, color: StepfunColorIcon },
Stepfun: { mono: StepfunMonoIcon, color: StepfunMonoIcon },
Suno: { mono: SunoMonoIcon },
Tavily: { mono: TavilyMonoIcon, color: TavilyColorIcon },
Tencent: { mono: TencentMonoIcon, color: TencentColorIcon },