Files
openhuman/docs/src/06-components.md
T
Steven EnamakelandGitHub 58969667d9 fix: add ESLint and Prettier configuration (#15)
* ran prettier

* Refactor ESLint configuration to use ES module syntax and enhance TypeScript support

- Converted CommonJS `require` statements to ES module `import` syntax for better compatibility with modern JavaScript.
- Added new paths to ignore in ESLint configuration to exclude additional directories.
- Updated TypeScript file patterns to be more specific, improving linting accuracy.
- Adjusted React hooks rules to allow certain patterns, enhancing flexibility in component design.

These changes improve the maintainability and clarity of the ESLint configuration, aligning it with current best practices.

* Refactor ESLint configuration to use ES module syntax and enhance TypeScript support

- Converted CommonJS `require` statements to ES module `import` syntax for better compatibility with modern JavaScript.
- Added new paths to ignore in ESLint configuration to exclude additional directories.
- Updated TypeScript file patterns to be more specific, improving linting accuracy.
- Introduced new React hooks rules and adjusted existing rules for better adherence to best practices.
- Made minor adjustments to import statements across various files for consistency and clarity.

These changes improve the overall linting setup and ensure better code quality across the project.

* Refactor import statements across multiple files for consistency

- Updated import statements to use TypeScript's `type` syntax for type imports, enhancing clarity and consistency across the codebase.
- Consolidated imports from the same module into single statements, improving readability and maintainability.

These changes streamline the code structure and align with best practices for TypeScript imports.

* Refactor import statements in memory manager for improved clarity

- Updated import statements to consolidate type imports and enhance readability.
- Removed redundant imports, streamlining the code structure in the memory manager file.

These changes align with best practices for TypeScript imports and improve maintainability.

* Add Husky for pre-commit and pre-push hooks

- Introduced Husky to manage Git hooks, enhancing the development workflow.
- Added pre-commit and pre-push scripts to enforce code formatting and linting checks before commits and pushes.
- Updated package.json to include Husky as a dependency and added a prepare script for setup.

These changes improve code quality and ensure adherence to formatting and linting standards during the development process.

* Refactor import statements for improved clarity and consistency

- Updated import statements across multiple files to consolidate type imports and enhance readability.
- Adjusted the order of imports for better organization and alignment with best practices in TypeScript.

These changes streamline the code structure and improve maintainability throughout the project.

* ran formatter

* Refactor import statements and improve code formatting across multiple files

- Consolidated and reordered import statements for better clarity and consistency in `SkillsGrid.tsx`, `SkillProvider.tsx`, and `index.ts`.
- Enhanced readability by adjusting formatting and removing redundant lines.
- These changes align with best practices for TypeScript imports and improve overall maintainability of the codebase.

* Refactor and optimize code in multiple components

- Removed redundant properties from the `STATUS_DISPLAY` object in `SkillsGrid.tsx` to streamline status handling.
- Consolidated import statements in `SettingsModal.tsx` for improved organization.
- Simplified state management and error handling in `BillingPanel.tsx`, enhancing performance and readability.
- Added `REHYDRATE` import to `index.ts` for better state persistence management.

These changes improve code clarity, maintainability, and align with best practices in TypeScript development.

* Consolidate import statements in SettingsModal.tsx for improved organization

* Add Prettier and ESLint checks to typecheck workflow

- Integrated a Prettier formatting check to ensure code style consistency.
- Added an ESLint step to enforce code quality and catch potential issues.
- These enhancements improve the development workflow by automating formatting and linting checks during the typecheck process.

* Add activeSkillDescription state to ConnectionsPanel and ConnectStep

- Introduced activeSkillDescription state in both ConnectionsPanel and ConnectStep components to store and manage skill descriptions.
- Updated the SkillSetupModal to accept skillDescription as a prop, enhancing the modal's functionality and data handling.

These changes improve the user experience by providing more detailed information about skills during the connection setup process.

* Enhance pre-push hook to include TypeScript compile check

- Added a TypeScript compile check to the pre-push script, ensuring that code compiles successfully before pushing.
- Updated error handling to include compile errors alongside formatting and linting issues, providing clearer feedback to developers.

These changes improve the reliability of the codebase by preventing non-compiling code from being pushed.

* Update GitHub workflows for pull request handling and publishing logic

- Modified the package-and-publish workflow to support pull request events, ensuring proper handling of branches.
- Adjusted the SHOULD_PUBLISH environment variable to differentiate between pull requests and main branch events.
- Updated the pr-protection workflow to focus solely on the main branch, removing references to the master branch.

These changes enhance the CI/CD process by refining branch handling and improving clarity in workflow conditions.
2026-02-02 06:24:50 +05:30

514 lines
10 KiB
Markdown

# Components
Reusable React components organized by feature.
## Component Structure
```
components/
├── Route Guards
│ ├── ProtectedRoute.tsx
│ ├── PublicRoute.tsx
│ └── DefaultRedirect.tsx
├── Authentication
│ └── TelegramLoginButton.tsx
├── Connection Status
│ ├── ConnectionIndicator.tsx
│ ├── TelegramConnectionIndicator.tsx
│ ├── TelegramConnectionModal.tsx
│ └── GmailConnectionIndicator.tsx
├── Onboarding
│ ├── ProgressIndicator.tsx
│ └── LottieAnimation.tsx
├── Settings Modal (16 files)
│ ├── SettingsModal.tsx
│ ├── SettingsLayout.tsx
│ ├── SettingsHome.tsx
│ ├── panels/
│ ├── components/
│ └── hooks/
└── Development
└── DesignSystemShowcase.tsx
```
## Route Guard Components
### ProtectedRoute
Requires authentication and optionally onboarding.
```typescript
interface ProtectedRouteProps {
requireOnboarded?: boolean;
}
// Usage in AppRoutes.tsx
<Route element={<ProtectedRoute />}>
<Route path="/onboarding/*" element={<Onboarding />} />
</Route>
<Route element={<ProtectedRoute requireOnboarded />}>
<Route path="/home" element={<Home />} />
</Route>
```
### PublicRoute
Redirects authenticated users away.
```typescript
// Usage in AppRoutes.tsx
<Route element={<PublicRoute />}>
<Route path="/" element={<Welcome />} />
<Route path="/login" element={<Login />} />
</Route>
```
### DefaultRedirect
Fallback that routes based on auth state.
```typescript
// Redirects to:
// - "/" if not authenticated
// - "/onboarding" if authenticated but not onboarded
// - "/home" if authenticated and onboarded
```
## Authentication Components
### TelegramLoginButton
OAuth login button for Telegram.
```typescript
interface TelegramLoginButtonProps {
onClick: () => void;
disabled?: boolean;
}
// Usage
<TelegramLoginButton
onClick={() => openUrl(`${BACKEND_URL}/auth/telegram?platform=desktop`)}
/>
```
## Connection Status Components
### ConnectionIndicator
Generic connection status badge.
```typescript
interface ConnectionIndicatorProps {
status: 'connected' | 'connecting' | 'disconnected' | 'error';
label?: string;
}
<ConnectionIndicator status="connected" label="Socket" />
```
### TelegramConnectionIndicator
Telegram-specific status display.
```typescript
interface TelegramConnectionIndicatorProps {
status: 'connected' | 'connecting' | 'disconnected' | 'error';
}
// Usage with Redux state
const telegramStatus = useAppSelector((state) =>
selectTelegramConnectionStatus(state, userId)
);
<TelegramConnectionIndicator status={telegramStatus} />
```
### TelegramConnectionModal
Modal for setting up Telegram connection.
```typescript
interface TelegramConnectionModalProps {
isOpen: boolean;
onClose: () => void;
}
// Usage in onboarding/settings
const [showModal, setShowModal] = useState(false);
<TelegramConnectionModal
isOpen={showModal}
onClose={() => setShowModal(false)}
/>
```
**Features:**
- QR code login flow
- Phone number login flow
- Connection status display
- Error handling
### GmailConnectionIndicator
Gmail status badge (future integration).
```typescript
<GmailConnectionIndicator status="coming-soon" />
```
## Onboarding Components
### ProgressIndicator
Visual progress through onboarding steps.
```typescript
interface ProgressIndicatorProps {
current: number;
total: number;
}
<ProgressIndicator current={2} total={5} />
```
### LottieAnimation
Lottie animation player for onboarding.
```typescript
interface LottieAnimationProps {
animationData: object;
loop?: boolean;
autoplay?: boolean;
className?: string;
}
import welcomeAnimation from '../assets/animations/welcome.json';
<LottieAnimation
animationData={welcomeAnimation}
loop={true}
autoplay={true}
/>
```
## Settings Modal System
Complete modal system with URL-based routing.
### File Structure
```
components/settings/
├── SettingsModal.tsx # Route-based container
├── SettingsLayout.tsx # Portal + backdrop wrapper
├── SettingsHome.tsx # Main menu with profile
├── panels/
│ ├── ConnectionsPanel.tsx # Connection management
│ ├── MessagingPanel.tsx # (Future)
│ ├── PrivacyPanel.tsx # (Future)
│ ├── ProfilePanel.tsx # (Future)
│ ├── AdvancedPanel.tsx # (Future)
│ └── BillingPanel.tsx # (Future)
├── components/
│ ├── SettingsHeader.tsx # User profile section
│ ├── SettingsMenuItem.tsx # Menu item component
│ ├── SettingsBackButton.tsx # Back navigation
│ └── SettingsPanelLayout.tsx# Panel wrapper
└── hooks/
├── useSettingsNavigation.ts # URL routing
└── useSettingsAnimation.ts # Animation state
```
### SettingsModal
Main container that renders based on URL.
```typescript
export function SettingsModal() {
const location = useLocation();
const isOpen = location.pathname.startsWith('/settings');
if (!isOpen) return null;
return (
<SettingsLayout>
{/* Route to appropriate panel */}
{location.pathname === '/settings' && <SettingsHome />}
{location.pathname === '/settings/connections' && <ConnectionsPanel />}
{/* ... more panels */}
</SettingsLayout>
);
}
```
### SettingsLayout
Portal-based modal wrapper.
```typescript
export function SettingsLayout({ children }) {
const { closeModal } = useSettingsNavigation();
return createPortal(
<div className="fixed inset-0 z-50">
{/* Backdrop */}
<div
className="absolute inset-0 bg-black/50 backdrop-blur-sm"
onClick={closeModal}
/>
{/* Modal */}
<div className="absolute inset-4 flex items-center justify-center">
<div className="bg-white rounded-2xl w-full max-w-[520px] shadow-xl">
{children}
</div>
</div>
</div>,
document.body
);
}
```
### SettingsHome
Main menu with user profile.
```typescript
export function SettingsHome() {
const { navigateTo, closeModal } = useSettingsNavigation();
const user = useAppSelector((state) => state.user.profile);
const menuItems = [
{ id: 'connections', label: 'Connections', icon: LinkIcon },
{ id: 'messaging', label: 'Messaging', icon: MessageIcon },
{ id: 'privacy', label: 'Privacy', icon: ShieldIcon },
// ... more items
];
return (
<div>
<SettingsHeader user={user} onClose={closeModal} />
{menuItems.map((item) => (
<SettingsMenuItem
key={item.id}
{...item}
onClick={() => navigateTo(item.id)}
/>
))}
</div>
);
}
```
### ConnectionsPanel
Connection management interface.
```typescript
export function ConnectionsPanel() {
const { navigateBack } = useSettingsNavigation();
const [telegramModalOpen, setTelegramModalOpen] = useState(false);
const telegramStatus = useAppSelector((state) =>
selectTelegramConnectionStatus(state, userId)
);
// Reuses connectOptions from onboarding
const connections = connectOptions.map((opt) => ({
...opt,
status: opt.id === 'telegram' ? telegramStatus : 'coming-soon'
}));
return (
<SettingsPanelLayout title="Connections" onBack={navigateBack}>
{connections.map((conn) => (
<ConnectionItem
key={conn.id}
{...conn}
onConnect={() => conn.id === 'telegram' && setTelegramModalOpen(true)}
/>
))}
<TelegramConnectionModal
isOpen={telegramModalOpen}
onClose={() => setTelegramModalOpen(false)}
/>
</SettingsPanelLayout>
);
}
```
### Settings Hooks
#### useSettingsNavigation
URL-based navigation for settings modal.
```typescript
interface UseSettingsNavigationReturn {
currentRoute: string;
navigateTo: (panel: string) => void;
navigateBack: () => void;
closeModal: () => void;
}
const { navigateTo, navigateBack, closeModal } = useSettingsNavigation();
// Navigate to panel
navigateTo('connections'); // → /settings/connections
// Go back
navigateBack(); // → /settings
// Close modal
closeModal(); // → previous non-settings route
```
#### useSettingsAnimation
Animation state management.
```typescript
interface UseSettingsAnimationReturn {
isEntering: boolean;
isExiting: boolean;
animationClass: string;
}
const { animationClass } = useSettingsAnimation();
<div className={`modal ${animationClass}`}>
{/* Content */}
</div>
```
### Settings Components
#### SettingsHeader
User profile section at top of settings.
```typescript
interface SettingsHeaderProps {
user: User | null;
onClose: () => void;
}
<SettingsHeader user={user} onClose={handleClose} />
```
#### SettingsMenuItem
Individual menu item with icon and chevron.
```typescript
interface SettingsMenuItemProps {
label: string;
icon: React.ComponentType;
onClick: () => void;
badge?: string;
disabled?: boolean;
}
<SettingsMenuItem
label="Connections"
icon={LinkIcon}
onClick={() => navigateTo('connections')}
badge="2"
/>
```
#### SettingsBackButton
Back navigation button.
```typescript
interface SettingsBackButtonProps {
onClick: () => void;
}
<SettingsBackButton onClick={navigateBack} />
```
#### SettingsPanelLayout
Wrapper for settings panels.
```typescript
interface SettingsPanelLayoutProps {
title: string;
onBack: () => void;
children: React.ReactNode;
}
<SettingsPanelLayout title="Connections" onBack={navigateBack}>
{/* Panel content */}
</SettingsPanelLayout>
```
## Component Patterns
### Reusing Connection Options
The `connectOptions` array is shared between onboarding and settings:
```typescript
// Defined in ConnectStep.tsx, imported elsewhere
export const connectOptions = [
{
id: 'telegram',
label: 'Telegram',
icon: TelegramIcon,
description: 'Connect your Telegram account',
},
{
id: 'gmail',
label: 'Gmail',
icon: GmailIcon,
description: 'Connect your Gmail account',
comingSoon: true,
},
];
```
### Modal via Portal
Settings modal uses `createPortal` to render outside the component tree:
```typescript
return createPortal(
<div className="modal-container">
{/* Modal content */}
</div>,
document.body
);
```
### Controlled vs Uncontrolled
Connection modals are controlled components:
```typescript
// Parent controls open state
const [isOpen, setIsOpen] = useState(false);
<TelegramConnectionModal
isOpen={isOpen}
onClose={() => setIsOpen(false)}
/>
```
---
_Previous: [Pages & Routing](./05-pages-routing.md) | Next: [Providers](./07-providers.md)_