React Component Writing Guide
- Use antd-style for complex styles; for simple cases, use inline
style attribute
- Use
Flexbox and Center from @lobehub/ui for layouts (see references/layout-kit.md)
- Component priority:
src/components > @lobehub/ui/base-ui > @lobehub/ui > custom implementation
- Always prefer
@lobehub/ui/base-ui primitives (Select, Modal, DropdownMenu, Popover, Switch, ScrollArea…) over antd equivalents
- Fall back to
@lobehub/ui higher-level components when base-ui has no match
- Only implement a custom component as a last resort — never reach for antd directly
- Use selectors to access zustand store data
@lobehub/ui Components
If unsure about component usage, search existing code in this project. Most components extend antd with additional props.
Reference: node_modules/@lobehub/ui/es/index.mjs for all available components.
Common Components:
- General: ActionIcon, ActionIconGroup, Block, Button, Icon
- Data Display: Avatar, Collapse, Empty, Highlighter, Markdown, Tag, Tooltip
- Data Entry: CodeEditor, CopyButton, EditableText, Form, FormModal, Input, SearchBar, Select
- Feedback: Alert, Drawer, Modal
- Layout: Center, DraggablePanel, Flexbox, Grid, Header, MaskShadow
- Navigation: Burger, Dropdown, Menu, SideNav, Tabs
Routing Architecture
Hybrid routing: Next.js App Router (static pages) + React Router DOM (main SPA).
| Route Type |
Use Case |
Implementation |
| Next.js App Router |
Auth pages (login, signup, oauth) |
src/app/[variants]/(auth)/ |
| React Router DOM |
Main SPA (chat, settings) |
desktopRouter.config.tsx + desktopRouter.config.desktop.tsx (must match) |
Key Files
- Entry:
src/spa/entry.web.tsx (web), src/spa/entry.mobile.tsx, src/spa/entry.desktop.tsx
- Desktop router (pair — always edit both when changing routes):
src/spa/router/desktopRouter.config.tsx (dynamic imports) and src/spa/router/desktopRouter.config.desktop.tsx (sync imports). Drift can cause unregistered routes / blank screen.
- Mobile router:
src/spa/router/mobileRouter.config.tsx
- Router utilities:
src/utils/router.tsx
.desktop.{ts,tsx} File Sync Rule
CRITICAL: Some files have a .desktop.ts(x) variant that Electron uses instead of the base file. When editing a base file, always check if a .desktop counterpart exists and update it in sync. Drift causes blank pages or missing features in Electron.
Known pairs that must stay in sync:
| Base file (web, dynamic imports) |
Desktop file (Electron, sync imports) |
src/spa/router/desktopRouter.config.tsx |
src/spa/router/desktopRouter.config.desktop.tsx |
src/routes/(main)/settings/features/componentMap.ts |
src/routes/(main)/settings/features/componentMap.desktop.ts |
How to check: After editing any .ts / .tsx file, run Glob for <filename>.desktop.{ts,tsx} in the same directory. If a match exists, update it with the equivalent sync-import change.
Router Utilities
import { dynamicElement, redirectElement, ErrorBoundary } from '@/utils/router';
element: dynamicElement(() => import('./chat'), 'Desktop > Chat');
element: redirectElement('/settings/profile');
errorElement: <ErrorBoundary resetPath="/chat" />;
Navigation
Important: For SPA pages, use Link from react-router-dom, NOT next/link.
// ❌ Wrong
import Link from 'next/link';
<Link href="/">Home</Link>;
// ✅ Correct
import { Link } from 'react-router-dom';
<Link to="/">Home</Link>;
// In components
import { useNavigate } from 'react-router-dom';
const navigate = useNavigate();
navigate('/chat');
// From stores
const navigate = useGlobalStore.getState().navigate;
navigate?.('/settings');
Converted and distributed by TomeVault | Claim this content
1---2name: react3description: React component development guide. Use when working with React components (.tsx files), creating UI, using @lobehub/ui components, implementing routing, or building frontend features. Triggers on React component creation, modification, layout implementation, or navigation tasks.4---56# React Component Writing Guide78- Use antd-style for complex styles; for simple cases, use inline `style` attribute9- Use `Flexbox` and `Center` from `@lobehub/ui` for layouts (see `references/layout-kit.md`)10- Component priority: `src/components` > `@lobehub/ui/base-ui` > `@lobehub/ui` > custom implementation11 - Always prefer `@lobehub/ui/base-ui` primitives (Select, Modal, DropdownMenu, Popover, Switch, ScrollArea…) over antd equivalents12 - Fall back to `@lobehub/ui` higher-level components when base-ui has no match13 - Only implement a custom component as a last resort — never reach for antd directly14- Use selectors to access zustand store data1516## @lobehub/ui Components1718If unsure about component usage, search existing code in this project. Most components extend antd with additional props.1920Reference: `node_modules/@lobehub/ui/es/index.mjs` for all available components.2122**Common Components:**2324- General: ActionIcon, ActionIconGroup, Block, Button, Icon25- Data Display: Avatar, Collapse, Empty, Highlighter, Markdown, Tag, Tooltip26- Data Entry: CodeEditor, CopyButton, EditableText, Form, FormModal, Input, SearchBar, Select27- Feedback: Alert, Drawer, Modal28- Layout: Center, DraggablePanel, Flexbox, Grid, Header, MaskShadow29- Navigation: Burger, Dropdown, Menu, SideNav, Tabs3031## Routing Architecture3233Hybrid routing: Next.js App Router (static pages) + React Router DOM (main SPA).3435| Route Type | Use Case | Implementation |36| ------------------ | --------------------------------- | ---------------------------------------------------------------------------- |37| Next.js App Router | Auth pages (login, signup, oauth) | `src/app/[variants]/(auth)/` |38| React Router DOM | Main SPA (chat, settings) | `desktopRouter.config.tsx` + `desktopRouter.config.desktop.tsx` (must match) |3940### Key Files4142- Entry: `src/spa/entry.web.tsx` (web), `src/spa/entry.mobile.tsx`, `src/spa/entry.desktop.tsx`43- Desktop router (pair — **always edit both** when changing routes): `src/spa/router/desktopRouter.config.tsx` (dynamic imports) and `src/spa/router/desktopRouter.config.desktop.tsx` (sync imports). Drift can cause unregistered routes / blank screen.44- Mobile router: `src/spa/router/mobileRouter.config.tsx`45- Router utilities: `src/utils/router.tsx`4647### `.desktop.{ts,tsx}` File Sync Rule4849**CRITICAL**: Some files have a `.desktop.ts(x)` variant that Electron uses instead of the base file. When editing a base file, **always check** if a `.desktop` counterpart exists and update it in sync. Drift causes blank pages or missing features in Electron.5051Known pairs that must stay in sync:5253| Base file (web, dynamic imports) | Desktop file (Electron, sync imports) |54| ----------------------------------------------------- | ------------------------------------------------------------- |55| `src/spa/router/desktopRouter.config.tsx` | `src/spa/router/desktopRouter.config.desktop.tsx` |56| `src/routes/(main)/settings/features/componentMap.ts` | `src/routes/(main)/settings/features/componentMap.desktop.ts` |5758**How to check**: After editing any `.ts` / `.tsx` file, run `Glob` for `<filename>.desktop.{ts,tsx}` in the same directory. If a match exists, update it with the equivalent sync-import change.5960### Router Utilities6162```tsx63import { dynamicElement, redirectElement, ErrorBoundary } from '@/utils/router';6465element: dynamicElement(() => import('./chat'), 'Desktop > Chat');66element: redirectElement('/settings/profile');67errorElement: <ErrorBoundary resetPath="/chat" />;68```6970### Navigation7172**Important**: For SPA pages, use `Link` from `react-router-dom`, NOT `next/link`.7374```tsx75// ❌ Wrong76import Link from 'next/link';77<Link href="/">Home</Link>;7879// ✅ Correct80import { Link } from 'react-router-dom';81<Link to="/">Home</Link>;8283// In components84import { useNavigate } from 'react-router-dom';85const navigate = useNavigate();86navigate('/chat');8788// From stores89const navigate = useGlobalStore.getState().navigate;90navigate?.('/settings');91```9293---94> Converted and distributed by [TomeVault](https://tomevault.io) | [Claim this content](https://tomevault.io/claim/lobehub/lobehub)95<!-- tomevault:2.0:skill_md:2026-04-05 -->