@app-studio/web 0.9.17 → 0.9.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/AuthGuard/index.d.ts +1 -1
- package/dist/utils/request.d.ts +2 -2
- package/dist/web.cjs.development.js +41 -46
- package/dist/web.cjs.development.js.map +1 -1
- package/dist/web.cjs.production.min.js +1 -1
- package/dist/web.cjs.production.min.js.map +1 -1
- package/dist/web.esm.js +43 -48
- package/dist/web.esm.js.map +1 -1
- package/dist/web.umd.development.js +45 -45
- package/dist/web.umd.development.js.map +1 -1
- package/dist/web.umd.production.min.js +1 -1
- package/dist/web.umd.production.min.js.map +1 -1
- package/docs/README.md +52 -0
- package/docs/adk-components.md +316 -0
- package/docs/adk-quick-start.md +294 -0
- package/docs/api-integration.md +801 -0
- package/docs/api-reference/README.md +103 -0
- package/docs/api-reference/data-display/flow.md +220 -0
- package/docs/api-reference/data-display/tree.md +210 -0
- package/docs/api-reference/form/chat-input.md +210 -0
- package/docs/api-reference/utility/button.md +145 -0
- package/docs/api-reference/utility/title.md +301 -0
- package/docs/app-studio.md +302 -0
- package/docs/component-development/guide.md +546 -0
- package/docs/contributing/documentation.md +153 -0
- package/docs/conventions.md +536 -0
- package/docs/design-system/theming.md +299 -0
- package/docs/documentation-system.md +143 -0
- package/docs/getting-started/component-usage.md +211 -0
- package/docs/getting-started/introduction.md +114 -0
- package/docs/guide.md +550 -0
- package/docs/integration-guide.md +449 -0
- package/docs/tutorials/README.md +51 -0
- package/docs/tutorials/basic/creating-a-simple-form.md +566 -0
- package/package.json +3 -2
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# Introduction to App Studio Web Component Library
|
|
2
|
+
|
|
3
|
+
The App Studio Web Component Library is a comprehensive, accessible, and customizable React component library built with TypeScript. It provides a wide range of UI components designed to help you build beautiful and functional web applications quickly and efficiently.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **40+ UI Components**: From basic elements to complex interactive components
|
|
8
|
+
- **Fully Typed**: Built with TypeScript for better developer experience
|
|
9
|
+
- **Accessible**: Follows WCAG guidelines for accessibility
|
|
10
|
+
- **Customizable**: Easily theme and style components to match your brand
|
|
11
|
+
- **Responsive**: Works across all device sizes
|
|
12
|
+
- **Form Integration**: Seamless integration with Formik for form handling
|
|
13
|
+
- **Modern Design**: Clean, consistent design following best practices
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm install @app-studio/web
|
|
19
|
+
# or
|
|
20
|
+
yarn add @app-studio/web
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Quick Start
|
|
24
|
+
|
|
25
|
+
```jsx
|
|
26
|
+
import React from 'react';
|
|
27
|
+
import { Button, Text } from '@app-studio/web';
|
|
28
|
+
|
|
29
|
+
function App() {
|
|
30
|
+
return (
|
|
31
|
+
<div>
|
|
32
|
+
<Text>Hello, world!</Text>
|
|
33
|
+
<Button onClick={() => alert('Clicked!')}>Click me</Button>
|
|
34
|
+
</div>
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Component Categories
|
|
40
|
+
|
|
41
|
+
The library includes components in the following categories:
|
|
42
|
+
|
|
43
|
+
### Layout Components
|
|
44
|
+
- View
|
|
45
|
+
- Center
|
|
46
|
+
- Horizontal
|
|
47
|
+
- Vertical
|
|
48
|
+
- AspectRatio
|
|
49
|
+
- Separator
|
|
50
|
+
- Resizable
|
|
51
|
+
|
|
52
|
+
### Form Components
|
|
53
|
+
- Checkbox
|
|
54
|
+
- ChatInput
|
|
55
|
+
- Radio
|
|
56
|
+
- Select
|
|
57
|
+
- Switch
|
|
58
|
+
- TextArea
|
|
59
|
+
- TextField
|
|
60
|
+
- OTPInput
|
|
61
|
+
|
|
62
|
+
### Navigation Components
|
|
63
|
+
- Accordion
|
|
64
|
+
- Menubar
|
|
65
|
+
- NavigationMenu
|
|
66
|
+
- Pagination
|
|
67
|
+
- Sidebar
|
|
68
|
+
- Tabs
|
|
69
|
+
|
|
70
|
+
### Feedback Components
|
|
71
|
+
- Alert
|
|
72
|
+
- Modal
|
|
73
|
+
- Toast
|
|
74
|
+
- Tooltip
|
|
75
|
+
|
|
76
|
+
### Data Display Components
|
|
77
|
+
- Avatar
|
|
78
|
+
- Badge
|
|
79
|
+
- Card
|
|
80
|
+
- Table
|
|
81
|
+
- Chart
|
|
82
|
+
- Flow
|
|
83
|
+
- Tree
|
|
84
|
+
|
|
85
|
+
### Utility Components
|
|
86
|
+
- Button
|
|
87
|
+
- Gradient
|
|
88
|
+
- Loader
|
|
89
|
+
- Text
|
|
90
|
+
|
|
91
|
+
### Interactive Components
|
|
92
|
+
- Carousel
|
|
93
|
+
- ContextMenu
|
|
94
|
+
- DropdownMenu
|
|
95
|
+
- HoverCard
|
|
96
|
+
- Slider
|
|
97
|
+
- Toggle
|
|
98
|
+
- ToggleGroup
|
|
99
|
+
|
|
100
|
+
## Design System
|
|
101
|
+
|
|
102
|
+
All components follow a consistent design system with:
|
|
103
|
+
|
|
104
|
+
- **Typography**: Inter/Geist font, specific sizes/weights
|
|
105
|
+
- **Spacing**: 4px grid system
|
|
106
|
+
- **Colors**: Neutral palette with semantic colors
|
|
107
|
+
- **Rounded corners**: Consistent border radius
|
|
108
|
+
- **Transitions**: Subtle animations
|
|
109
|
+
|
|
110
|
+
## Next Steps
|
|
111
|
+
|
|
112
|
+
- [Component Usage Guide](./component-usage.md)
|
|
113
|
+
- [Theming Guide](../design-system/theming.md)
|
|
114
|
+
- [Component Development Guide](../component-development/guide.md)
|
package/docs/guide.md
ADDED
|
@@ -0,0 +1,550 @@
|
|
|
1
|
+
# Component Building Guide for @src/components/
|
|
2
|
+
|
|
3
|
+
This guide provides a comprehensive overview of how to build components for the `@src/components/` directory, following the established patterns and best practices in the codebase.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
1. [Component Architecture](#component-architecture)
|
|
8
|
+
2. [File Structure](#file-structure)
|
|
9
|
+
3. [Component Creation Process](#component-creation-process)
|
|
10
|
+
4. [Styling Approach](#styling-approach)
|
|
11
|
+
5. [State Management](#state-management)
|
|
12
|
+
6. [Accessibility Considerations](#accessibility-considerations)
|
|
13
|
+
7. [Examples and Documentation](#examples-and-documentation)
|
|
14
|
+
8. [Utility Scripts](#utility-scripts)
|
|
15
|
+
9. [Component Integration](#component-integration)
|
|
16
|
+
10. [Best Practices](#best-practices)
|
|
17
|
+
|
|
18
|
+
## Component Architecture
|
|
19
|
+
|
|
20
|
+
Components in this library follow a clear separation of concerns with a structured architecture:
|
|
21
|
+
|
|
22
|
+
- **Main Component File**: Orchestrates state and view, exports the public API
|
|
23
|
+
- **Props**: Defines the component's API and TypeScript interfaces
|
|
24
|
+
- **State**: Manages component-specific state through custom hooks
|
|
25
|
+
- **View**: Handles the presentational aspects of the component
|
|
26
|
+
- **Style**: Contains style constants, mappings, and theme definitions
|
|
27
|
+
- **Types**: Defines TypeScript types and enums for the component
|
|
28
|
+
|
|
29
|
+
This architecture promotes maintainability, reusability, and clear separation between logic and presentation.
|
|
30
|
+
|
|
31
|
+
## File Structure
|
|
32
|
+
|
|
33
|
+
Each component follows a consistent file structure:
|
|
34
|
+
|
|
35
|
+
```
|
|
36
|
+
ComponentName/
|
|
37
|
+
├── ComponentName.tsx # Main component file (exports public API)
|
|
38
|
+
├── ComponentName/ # Inner folder for core files
|
|
39
|
+
│ ├── ComponentName.props.ts # Props interface definitions
|
|
40
|
+
│ ├── ComponentName.state.ts # Custom state hook
|
|
41
|
+
│ ├── ComponentName.view.tsx # Presentational component
|
|
42
|
+
│ ├── ComponentName.style.ts # Style constants and theme mappings
|
|
43
|
+
│ └── ComponentName.type.ts # TypeScript type definitions
|
|
44
|
+
└── examples/ # Usage examples
|
|
45
|
+
├── default.tsx # Default usage example
|
|
46
|
+
├── variant.tsx # Variant-specific example
|
|
47
|
+
├── size.tsx # Size-specific example
|
|
48
|
+
└── index.ts # Exports all examples
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Component Creation Process
|
|
52
|
+
|
|
53
|
+
### 1. Plan Your Component
|
|
54
|
+
|
|
55
|
+
Before writing code, define:
|
|
56
|
+
- The component's purpose and functionality
|
|
57
|
+
- Required props and their types
|
|
58
|
+
- State management needs
|
|
59
|
+
- Visual variants (size, shape, color, etc.)
|
|
60
|
+
- Accessibility requirements
|
|
61
|
+
|
|
62
|
+
### 2. Create Component Structure
|
|
63
|
+
|
|
64
|
+
Use the provided script to scaffold the component structure:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
npm run create-structure -- ComponentName
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
This creates the basic file structure with placeholder content.
|
|
71
|
+
|
|
72
|
+
### 3. Define Types and Props
|
|
73
|
+
|
|
74
|
+
In `ComponentName.type.ts`:
|
|
75
|
+
```typescript
|
|
76
|
+
export type Size = 'xs' | 'sm' | 'md' | 'lg' | 'xl';
|
|
77
|
+
export type Variant = 'default' | 'primary' | 'secondary';
|
|
78
|
+
export type Shape = 'sharp' | 'rounded' | 'pillShaped';
|
|
79
|
+
|
|
80
|
+
export interface ComponentNameStyles {
|
|
81
|
+
container?: ViewProps;
|
|
82
|
+
label?: ViewProps;
|
|
83
|
+
icon?: ViewProps;
|
|
84
|
+
// Add other style override points as needed
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
In `ComponentName.props.ts`:
|
|
89
|
+
```typescript
|
|
90
|
+
import { ViewProps } from 'app-studio';
|
|
91
|
+
import { Size, Variant, Shape, ComponentNameStyles } from './ComponentName.type';
|
|
92
|
+
|
|
93
|
+
export interface ComponentNameProps extends ViewProps {
|
|
94
|
+
/**
|
|
95
|
+
* Size variant of the component
|
|
96
|
+
* @default 'md'
|
|
97
|
+
*/
|
|
98
|
+
size?: Size;
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Visual style variant
|
|
102
|
+
* @default 'default'
|
|
103
|
+
*/
|
|
104
|
+
variant?: Variant;
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Shape of the component
|
|
108
|
+
* @default 'rounded'
|
|
109
|
+
*/
|
|
110
|
+
shape?: Shape;
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Whether the component is disabled
|
|
114
|
+
* @default false
|
|
115
|
+
*/
|
|
116
|
+
isDisabled?: boolean;
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Custom styles for different parts of the component
|
|
120
|
+
*/
|
|
121
|
+
views?: ComponentNameStyles;
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Optional theme mode override ('light' or 'dark')
|
|
125
|
+
* If not provided, the component will use the theme mode from context
|
|
126
|
+
*/
|
|
127
|
+
themeMode?: 'light' | 'dark';
|
|
128
|
+
|
|
129
|
+
// Add other props as needed
|
|
130
|
+
}
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
### 4. Implement State Management
|
|
134
|
+
|
|
135
|
+
In `ComponentName.state.ts`:
|
|
136
|
+
```typescript
|
|
137
|
+
import { useState, useCallback } from 'react';
|
|
138
|
+
|
|
139
|
+
export interface ComponentNameStateProps {
|
|
140
|
+
// Add any props needed for state initialization
|
|
141
|
+
defaultValue?: string;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export const useComponentNameState = (props: ComponentNameStateProps = {}) => {
|
|
145
|
+
const { defaultValue = '' } = props;
|
|
146
|
+
|
|
147
|
+
const [value, setValue] = useState(defaultValue);
|
|
148
|
+
const [isHovered, setIsHovered] = useState(false);
|
|
149
|
+
const [isFocused, setIsFocused] = useState(false);
|
|
150
|
+
|
|
151
|
+
const handleHover = useCallback((isHovering: boolean) => {
|
|
152
|
+
setIsHovered(isHovering);
|
|
153
|
+
}, []);
|
|
154
|
+
|
|
155
|
+
const handleFocus = useCallback((isFocusing: boolean) => {
|
|
156
|
+
setIsFocused(isFocusing);
|
|
157
|
+
}, []);
|
|
158
|
+
|
|
159
|
+
return {
|
|
160
|
+
value,
|
|
161
|
+
setValue,
|
|
162
|
+
isHovered,
|
|
163
|
+
isFocused,
|
|
164
|
+
handleHover,
|
|
165
|
+
handleFocus
|
|
166
|
+
};
|
|
167
|
+
};
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### 5. Create Style Definitions
|
|
171
|
+
|
|
172
|
+
In `ComponentName.style.ts`:
|
|
173
|
+
```typescript
|
|
174
|
+
import { ViewProps } from 'app-studio';
|
|
175
|
+
import { Size, Variant, Shape } from './ComponentName.type';
|
|
176
|
+
|
|
177
|
+
// Size mappings
|
|
178
|
+
export const ComponentNameSizes: Record<Size, ViewProps> = {
|
|
179
|
+
xs: { padding: '4px 8px', fontSize: 12 },
|
|
180
|
+
sm: { padding: '6px 12px', fontSize: 14 },
|
|
181
|
+
md: { padding: '8px 16px', fontSize: 16 },
|
|
182
|
+
lg: { padding: '10px 20px', fontSize: 18 },
|
|
183
|
+
xl: { padding: '12px 24px', fontSize: 20 },
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
// Shape mappings
|
|
187
|
+
export const ComponentNameShapes: Record<Shape, ViewProps> = {
|
|
188
|
+
sharp: { borderRadius: 0 },
|
|
189
|
+
rounded: { borderRadius: 4 },
|
|
190
|
+
pillShaped: { borderRadius: 9999 },
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
// Get variant styles based on theme mode
|
|
194
|
+
export const getComponentNameVariants = (themeMode: 'light' | 'dark') => {
|
|
195
|
+
const isDark = themeMode === 'dark';
|
|
196
|
+
|
|
197
|
+
return {
|
|
198
|
+
default: {
|
|
199
|
+
backgroundColor: isDark ? 'color.gray.800' : 'color.gray.100',
|
|
200
|
+
color: isDark ? 'color.gray.100' : 'color.gray.800',
|
|
201
|
+
borderColor: isDark ? 'color.gray.700' : 'color.gray.300',
|
|
202
|
+
},
|
|
203
|
+
primary: {
|
|
204
|
+
backgroundColor: 'theme.primary',
|
|
205
|
+
color: 'color.white',
|
|
206
|
+
borderColor: 'theme.primary',
|
|
207
|
+
},
|
|
208
|
+
secondary: {
|
|
209
|
+
backgroundColor: 'theme.secondary',
|
|
210
|
+
color: 'color.white',
|
|
211
|
+
borderColor: 'theme.secondary',
|
|
212
|
+
},
|
|
213
|
+
};
|
|
214
|
+
};
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
### 6. Implement the View Component
|
|
218
|
+
|
|
219
|
+
In `ComponentName.view.tsx`:
|
|
220
|
+
```typescript
|
|
221
|
+
import React from 'react';
|
|
222
|
+
import { View, Horizontal, Vertical, useTheme } from 'app-studio';
|
|
223
|
+
import { ComponentNameProps } from './ComponentName.props';
|
|
224
|
+
import {
|
|
225
|
+
ComponentNameSizes,
|
|
226
|
+
ComponentNameShapes,
|
|
227
|
+
getComponentNameVariants
|
|
228
|
+
} from './ComponentName.style';
|
|
229
|
+
|
|
230
|
+
export const ComponentNameView: React.FC<ComponentNameProps> = ({
|
|
231
|
+
size = 'md',
|
|
232
|
+
variant = 'default',
|
|
233
|
+
shape = 'rounded',
|
|
234
|
+
isDisabled = false,
|
|
235
|
+
children,
|
|
236
|
+
views = {},
|
|
237
|
+
themeMode: elementMode,
|
|
238
|
+
...props
|
|
239
|
+
}) => {
|
|
240
|
+
// Access theme context
|
|
241
|
+
const { themeMode } = useTheme();
|
|
242
|
+
const currentThemeMode = elementMode || themeMode;
|
|
243
|
+
|
|
244
|
+
// Get styles based on props
|
|
245
|
+
const sizeStyles = ComponentNameSizes[size];
|
|
246
|
+
const shapeStyles = ComponentNameShapes[shape];
|
|
247
|
+
const variantStyles = getComponentNameVariants(currentThemeMode)[variant];
|
|
248
|
+
|
|
249
|
+
return (
|
|
250
|
+
<View
|
|
251
|
+
// Base styles
|
|
252
|
+
display="flex"
|
|
253
|
+
alignItems="center"
|
|
254
|
+
justifyContent="center"
|
|
255
|
+
opacity={isDisabled ? 0.5 : 1}
|
|
256
|
+
cursor={isDisabled ? 'not-allowed' : 'pointer'}
|
|
257
|
+
transition="all 0.2s ease"
|
|
258
|
+
|
|
259
|
+
// Variant-specific styles
|
|
260
|
+
{...sizeStyles}
|
|
261
|
+
{...shapeStyles}
|
|
262
|
+
{...variantStyles}
|
|
263
|
+
|
|
264
|
+
// Custom style overrides
|
|
265
|
+
{...views?.container}
|
|
266
|
+
|
|
267
|
+
// Pass through remaining props
|
|
268
|
+
{...props}
|
|
269
|
+
>
|
|
270
|
+
{children}
|
|
271
|
+
</View>
|
|
272
|
+
);
|
|
273
|
+
};
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
### 7. Create the Main Component
|
|
277
|
+
|
|
278
|
+
In `ComponentName.tsx`:
|
|
279
|
+
```typescript
|
|
280
|
+
import React from 'react';
|
|
281
|
+
import { ComponentNameProps } from './ComponentName/ComponentName.props';
|
|
282
|
+
import { useComponentNameState } from './ComponentName/ComponentName.state';
|
|
283
|
+
import { ComponentNameView } from './ComponentName/ComponentName.view';
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* ComponentName component description
|
|
287
|
+
*/
|
|
288
|
+
const ComponentNameComponent: React.FC<ComponentNameProps> = (props) => {
|
|
289
|
+
// Initialize component state
|
|
290
|
+
const state = useComponentNameState();
|
|
291
|
+
|
|
292
|
+
// Return the view with state and props
|
|
293
|
+
return <ComponentNameView {...state} {...props} />;
|
|
294
|
+
};
|
|
295
|
+
|
|
296
|
+
export const ComponentName = ComponentNameComponent;
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
### 8. Create Examples
|
|
300
|
+
|
|
301
|
+
In `examples/default.tsx`:
|
|
302
|
+
```typescript
|
|
303
|
+
import React from 'react';
|
|
304
|
+
import { ComponentName } from '../ComponentName';
|
|
305
|
+
|
|
306
|
+
export const DefaultDemo = () => {
|
|
307
|
+
return <ComponentName>Default Example</ComponentName>;
|
|
308
|
+
};
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
In `examples/variant.tsx`:
|
|
312
|
+
```typescript
|
|
313
|
+
import React from 'react';
|
|
314
|
+
import { ComponentName } from '../ComponentName';
|
|
315
|
+
import { Horizontal } from 'app-studio';
|
|
316
|
+
|
|
317
|
+
export const VariantDemo = () => {
|
|
318
|
+
return (
|
|
319
|
+
<Horizontal gap={10}>
|
|
320
|
+
<ComponentName variant="default">Default</ComponentName>
|
|
321
|
+
<ComponentName variant="primary">Primary</ComponentName>
|
|
322
|
+
<ComponentName variant="secondary">Secondary</ComponentName>
|
|
323
|
+
</Horizontal>
|
|
324
|
+
);
|
|
325
|
+
};
|
|
326
|
+
```
|
|
327
|
+
|
|
328
|
+
## Styling Approach
|
|
329
|
+
|
|
330
|
+
Components in this library use a consistent styling approach:
|
|
331
|
+
|
|
332
|
+
### App-Studio Layout Components
|
|
333
|
+
|
|
334
|
+
Use the layout components from `app-studio` for consistent layout:
|
|
335
|
+
- `View`: Base container component
|
|
336
|
+
- `Horizontal`: Horizontal flex container
|
|
337
|
+
- `Vertical`: Vertical flex container
|
|
338
|
+
- `Center`: Centered flex container
|
|
339
|
+
|
|
340
|
+
### Theme Integration
|
|
341
|
+
|
|
342
|
+
Use the theme system via `useTheme` hook:
|
|
343
|
+
```typescript
|
|
344
|
+
const { getColor, themeMode } = useTheme();
|
|
345
|
+
const colorValue = getColor('theme.primary', { themeMode });
|
|
346
|
+
```
|
|
347
|
+
|
|
348
|
+
### Style Customization
|
|
349
|
+
|
|
350
|
+
Allow style customization through the `views` prop:
|
|
351
|
+
```typescript
|
|
352
|
+
<View
|
|
353
|
+
{...defaultStyles}
|
|
354
|
+
{...views?.container}
|
|
355
|
+
{...props}
|
|
356
|
+
>
|
|
357
|
+
<Text {...views?.label}>{label}</Text>
|
|
358
|
+
</View>
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
### Style Constants
|
|
362
|
+
|
|
363
|
+
Define style constants in `.style.ts` files:
|
|
364
|
+
```typescript
|
|
365
|
+
export const ComponentSizes = {
|
|
366
|
+
sm: { height: 30, fontSize: 14 },
|
|
367
|
+
md: { height: 40, fontSize: 16 },
|
|
368
|
+
lg: { height: 50, fontSize: 18 },
|
|
369
|
+
};
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
## State Management
|
|
373
|
+
|
|
374
|
+
### Component-Specific State
|
|
375
|
+
|
|
376
|
+
Use custom hooks for component-specific state:
|
|
377
|
+
```typescript
|
|
378
|
+
export const useComponentState = (initialState = {}) => {
|
|
379
|
+
const [value, setValue] = useState(initialState.value || '');
|
|
380
|
+
const [isOpen, setIsOpen] = useState(initialState.isOpen || false);
|
|
381
|
+
|
|
382
|
+
return { value, setValue, isOpen, setIsOpen };
|
|
383
|
+
};
|
|
384
|
+
```
|
|
385
|
+
|
|
386
|
+
### Global State
|
|
387
|
+
|
|
388
|
+
For components that need global state (like Toast, Modal), use Zustand:
|
|
389
|
+
```typescript
|
|
390
|
+
export const useToastStore = create<ToastState>((set) => ({
|
|
391
|
+
toasts: [],
|
|
392
|
+
addToast: (toast) => set((state) => ({
|
|
393
|
+
toasts: [...state.toasts, toast]
|
|
394
|
+
})),
|
|
395
|
+
removeToast: (id) => set((state) => ({
|
|
396
|
+
toasts: state.toasts.filter(toast => toast.id !== id)
|
|
397
|
+
})),
|
|
398
|
+
}));
|
|
399
|
+
```
|
|
400
|
+
|
|
401
|
+
## Accessibility Considerations
|
|
402
|
+
|
|
403
|
+
Ensure components are accessible:
|
|
404
|
+
|
|
405
|
+
- Use semantic HTML elements
|
|
406
|
+
- Add proper ARIA attributes
|
|
407
|
+
- Support keyboard navigation
|
|
408
|
+
- Ensure sufficient color contrast
|
|
409
|
+
- Provide text alternatives for non-text content
|
|
410
|
+
- Make focus states visible
|
|
411
|
+
|
|
412
|
+
Example:
|
|
413
|
+
```typescript
|
|
414
|
+
<View
|
|
415
|
+
role="button"
|
|
416
|
+
aria-disabled={isDisabled}
|
|
417
|
+
tabIndex={isDisabled ? -1 : 0}
|
|
418
|
+
onKeyDown={(e) => {
|
|
419
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
420
|
+
onClick?.();
|
|
421
|
+
}
|
|
422
|
+
}}
|
|
423
|
+
{...props}
|
|
424
|
+
>
|
|
425
|
+
{children}
|
|
426
|
+
</View>
|
|
427
|
+
```
|
|
428
|
+
|
|
429
|
+
## Examples and Documentation
|
|
430
|
+
|
|
431
|
+
### Component Examples
|
|
432
|
+
|
|
433
|
+
Create examples for each significant prop or feature:
|
|
434
|
+
- `default.tsx`: Basic usage
|
|
435
|
+
- `variant.tsx`: Different variants
|
|
436
|
+
- `size.tsx`: Different sizes
|
|
437
|
+
- `isDisabled.tsx`: Disabled state
|
|
438
|
+
|
|
439
|
+
### Example Index
|
|
440
|
+
|
|
441
|
+
Export all examples from `examples/index.ts`:
|
|
442
|
+
```typescript
|
|
443
|
+
export * from './default';
|
|
444
|
+
export * from './variant';
|
|
445
|
+
export * from './size';
|
|
446
|
+
export * from './isDisabled';
|
|
447
|
+
```
|
|
448
|
+
|
|
449
|
+
## Utility Scripts
|
|
450
|
+
|
|
451
|
+
The codebase provides several utility scripts to help with component development:
|
|
452
|
+
|
|
453
|
+
### Create Component Structure
|
|
454
|
+
|
|
455
|
+
```bash
|
|
456
|
+
npm run create-structure -- ComponentName
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
### Create Examples
|
|
460
|
+
|
|
461
|
+
```bash
|
|
462
|
+
npm run create-example -- ComponentName
|
|
463
|
+
```
|
|
464
|
+
|
|
465
|
+
### Create Index Files
|
|
466
|
+
|
|
467
|
+
```bash
|
|
468
|
+
npm run create-indices
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
### Create Component Pages
|
|
472
|
+
|
|
473
|
+
```bash
|
|
474
|
+
npm run create-pages
|
|
475
|
+
```
|
|
476
|
+
|
|
477
|
+
## Component Integration
|
|
478
|
+
|
|
479
|
+
### Compound Components
|
|
480
|
+
|
|
481
|
+
For complex components, use the compound component pattern:
|
|
482
|
+
|
|
483
|
+
```typescript
|
|
484
|
+
const CardComponent: React.FC<CardProps> = (props) => {
|
|
485
|
+
return <CardView {...props} />;
|
|
486
|
+
};
|
|
487
|
+
|
|
488
|
+
export const Card = CardComponent as CardType;
|
|
489
|
+
|
|
490
|
+
// Assign the sub-components to the main component
|
|
491
|
+
Card.Header = CardHeader;
|
|
492
|
+
Card.Content = CardContent;
|
|
493
|
+
Card.Footer = CardFooter;
|
|
494
|
+
```
|
|
495
|
+
|
|
496
|
+
### Context Integration
|
|
497
|
+
|
|
498
|
+
For components that need to share state between sub-components, use React Context:
|
|
499
|
+
|
|
500
|
+
```typescript
|
|
501
|
+
// Create context
|
|
502
|
+
const ComponentContext = createContext<ComponentContextType | undefined>(undefined);
|
|
503
|
+
|
|
504
|
+
// Provider component
|
|
505
|
+
export const ComponentProvider: React.FC<{ children: React.ReactNode }> = ({ children }) => {
|
|
506
|
+
const state = useComponentState();
|
|
507
|
+
return (
|
|
508
|
+
<ComponentContext.Provider value={state}>
|
|
509
|
+
{children}
|
|
510
|
+
</ComponentContext.Provider>
|
|
511
|
+
);
|
|
512
|
+
};
|
|
513
|
+
|
|
514
|
+
// Hook to use the context
|
|
515
|
+
export const useComponentContext = () => {
|
|
516
|
+
const context = useContext(ComponentContext);
|
|
517
|
+
if (!context) {
|
|
518
|
+
throw new Error('useComponentContext must be used within a ComponentProvider');
|
|
519
|
+
}
|
|
520
|
+
return context;
|
|
521
|
+
};
|
|
522
|
+
```
|
|
523
|
+
|
|
524
|
+
## Best Practices
|
|
525
|
+
|
|
526
|
+
### Do's
|
|
527
|
+
|
|
528
|
+
- ✅ Follow the established file structure
|
|
529
|
+
- ✅ Use TypeScript for type safety
|
|
530
|
+
- ✅ Document props with TSDoc comments
|
|
531
|
+
- ✅ Use app-studio layout components
|
|
532
|
+
- ✅ Separate logic from presentation
|
|
533
|
+
- ✅ Make components accessible
|
|
534
|
+
- ✅ Allow style customization via the `views` prop
|
|
535
|
+
- ✅ Use theme variables for colors
|
|
536
|
+
- ✅ Create comprehensive examples
|
|
537
|
+
|
|
538
|
+
### Don'ts
|
|
539
|
+
|
|
540
|
+
- ❌ Use global CSS (except when absolutely necessary)
|
|
541
|
+
- ❌ Mix state logic with presentation
|
|
542
|
+
- ❌ Hardcode colors or sizes
|
|
543
|
+
- ❌ Ignore accessibility
|
|
544
|
+
- ❌ Create overly complex components
|
|
545
|
+
- ❌ Duplicate functionality that exists in other components
|
|
546
|
+
- ❌ Use direct DOM manipulation
|
|
547
|
+
|
|
548
|
+
---
|
|
549
|
+
|
|
550
|
+
By following this guide, you'll create components that are consistent with the existing codebase, maintainable, accessible, and reusable.
|