@meonode/ui 0.2.12 โ†’ 0.2.14

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/README.md CHANGED
@@ -4,18 +4,21 @@
4
4
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
5
  [![Bundle Size](https://img.shields.io/bundlephobia/minzip/@meonode/ui)](https://bundlephobia.com/package/@meonode/ui)
6
6
 
7
- ## **Build React UIs with Type-Safe Fluency Without JSX Syntax**
7
+ **Build React UIs with Type-Safe Fluency Without JSX Syntax**
8
8
 
9
- A revolutionary approach to React component composition featuring function-based syntax, direct CSS-first prop styling, built-in theming system, smart prop handling with raw property pass-through, dynamic children management, and powerful portal capabilities.
9
+ A revolutionary approach to React component composition featuring function-based syntax, direct CSS-first prop styling, built-in theming system, and powerful portal capabilities.
10
10
 
11
- ### โœจ Quick Start Example
11
+ ## Quick Start
12
12
 
13
- ```tsx
14
- import { Component, Root, Center, Column, H1, Button, Text } from '@meonode/ui';
13
+ ```bash
14
+ npm install @meonode/ui react
15
+ ```
16
+
17
+ ```typescript
18
+ import { Component, Root, Center, Column, H1, Button } from '@meonode/ui';
15
19
 
16
20
  const theme = {
17
21
  primary: { default: '#FF6B6B', content: '#4A0000' },
18
- secondary: { default: '#6BCB77', content: '#0A3B0F' },
19
22
  base: { default: '#F8F8F8', content: '#333333' }
20
23
  };
21
24
 
@@ -31,15 +34,13 @@ const App = Component(() =>
31
34
  children: [
32
35
  H1('Welcome to MeoNode', {
33
36
  fontSize: '3rem',
34
- color: 'theme.primary.default',
35
- marginBottom: 16
37
+ color: 'theme.primary.default'
36
38
  }),
37
39
  Button('Get Started', {
38
40
  backgroundColor: 'theme.primary.default',
39
41
  color: 'theme.primary.content',
40
42
  padding: '12px 24px',
41
43
  borderRadius: 8,
42
- fontSize: '1.1rem',
43
44
  cursor: 'pointer',
44
45
  onClick: () => alert('Hello MeoNode!')
45
46
  })
@@ -50,1489 +51,71 @@ const App = Component(() =>
50
51
  );
51
52
  ```
52
53
 
53
- -----
54
-
55
- ## ๐Ÿ“ฆ Installation
56
-
57
- ```bash
58
- # Using npm
59
- npm install @meonode/ui react
60
-
61
- # Using yarn
62
- yarn add @meonode/ui react
63
-
64
- # Using pnpm
65
- pnpm add @meonode/ui react
66
- ```
67
-
68
- -----
69
-
70
- ## โš™๏ธ CSS Engine Architecture
71
-
72
- MeoNode UI is powered by **@emotion/react** under the hood, providing a robust and performant CSS-in-JS solution that enables all the advanced styling capabilities you see in the library.
73
-
74
- ### How It Works
75
-
76
- ```tsx
77
- // Behind the scenes, MeoNode transforms this:
78
- const StyledComponent = Component(() =>
79
- Div({
80
- padding: '20px',
81
- backgroundColor: 'theme.primary.default',
82
- css: {
83
- '&:hover': {
84
- transform: 'scale(1.05)',
85
- boxShadow: '0 8px 16px rgba(0,0,0,0.2)'
86
- },
87
- '@media (max-width: 768px)': {
88
- padding: '12px'
89
- }
90
- }
91
- })
92
- );
93
-
94
- // Into this Emotion-powered component:
95
- import { css } from '@emotion/react';
96
-
97
- const emotionStyles = css`
98
- padding: 20px;
99
- background-color: ${theme.primary.default};
100
-
101
- &:hover {
102
- transform: scale(1.05);
103
- box-shadow: 0 8px 16px rgba(0,0,0,0.2);
104
- }
105
-
106
- @media (max-width: 768px) {
107
- padding: 12px;
108
- }
109
- `;
110
- ```
111
-
112
- ### Key Benefits of Emotion Integration
113
-
114
- - **๐ŸŽฏ Performance**: Automatic CSS optimization and dead code elimination
115
- - **๐Ÿงฉ Dynamic Styling**: Runtime theme value resolution and conditional styles
116
- - **๐Ÿ”„ Server-Side Rendering**: Full SSR support with automatic critical CSS extraction
117
- - **๐Ÿ“ฑ Responsive Design**: Native media query support with optimal performance
118
- - **๐ŸŽจ Advanced Features**: Pseudo-classes, keyframe animations, and complex selectors
119
-
120
- ### Style Processing Pipeline
121
-
122
- 1. **Parse Props**: MeoNode separates CSS properties from DOM attributes
123
- 2. **Resolve Theme**: Theme path strings are resolved to actual values
124
- 3. **Generate Emotion CSS**: Styles are converted to Emotion's CSS format
125
- 4. **Optimize**: Emotion handles deduplication, vendor prefixing, and optimization
126
- 5. **Inject**: Styles are injected into the document head with unique class names
127
-
128
- ### Advanced Emotion Features Exposed
129
-
130
- ```tsx
131
- // Access to Emotion's advanced features through MeoNode:
132
- const AnimatedComponent = Component(() =>
133
- Div({
134
- css: {
135
- // Emotion's css prop supports all CSS features
136
- animation: 'slideIn 0.5s ease-out',
137
-
138
- // Advanced selectors
139
- '& > *:nth-of-type(odd)': {
140
- backgroundColor: '#f0f0f0'
141
- },
142
-
143
- // CSS custom properties
144
- '--primary-color': '#3B82F6',
145
- color: 'var(--primary-color)',
146
-
147
- // Container queries (when supported)
148
- '@container (min-width: 400px)': {
149
- padding: '2rem'
150
- },
151
-
152
- // Emotion's interpolation functions
153
- [`@media (min-width: ${theme.breakpoints.md})`]: {
154
- fontSize: '1.2rem'
155
- }
156
- }
157
- })
158
- );
159
- ```
160
-
161
- ### Performance Optimizations
162
-
163
- ```tsx
164
- // MeoNode leverages Emotion's performance features:
165
-
166
- // 1. Automatic style memoization
167
- const MemoizedStyles = Component(() => {
168
- // These styles are automatically memoized by Emotion
169
- const expensiveStyles = {
170
- background: `linear-gradient(45deg,
171
- ${theme.colors.primary.default},
172
- ${theme.colors.secondary.default}
173
- )`,
174
- css: {
175
- // Complex animations are optimized
176
- '@keyframes complexAnimation': {
177
- '0%': { transform: 'rotate(0deg) scale(1)' },
178
- '50%': { transform: 'rotate(180deg) scale(1.2)' },
179
- '100%': { transform: 'rotate(360deg) scale(1)' }
180
- },
181
- animation: 'complexAnimation 2s infinite'
182
- }
183
- };
184
-
185
- return Div(expensiveStyles);
186
- });
187
-
188
- // 2. Critical CSS extraction for SSR
189
- // MeoNode automatically handles Emotion's SSR setup:
190
- import { CacheProvider } from '@emotion/react';
191
- import createEmotionServer from '@emotion/server/create-instance';
192
- import createCache from '@emotion/cache';
193
-
194
- // This is handled internally by MeoNode for optimal SSR performance
195
- ```
196
-
197
- -----
198
-
199
- ## ๐Ÿ“š Core Concepts
200
-
201
- ### 1\. ๐Ÿ—๏ธ Component Architecture
202
-
203
- MeoNode uses function-based component creation for maximum flexibility:
204
-
205
- ```tsx
206
- import { Node, Component, Div, H1, P } from '@meonode/ui';
207
-
208
- // Method 1: Direct element creation
209
- const SimpleCard = () =>
210
- Div({
211
- padding: '20px',
212
- borderRadius: '12px',
213
- backgroundColor: 'white',
214
- boxShadow: '0 4px 12px rgba(0,0,0,0.1)',
215
- children: [
216
- H1('Card Title', { marginBottom: 8 }),
217
- P('Card content goes here...')
218
- ]
219
- });
220
-
221
- // Method 2: Custom element factory
222
- const Card = Node('article', {
223
- padding: '24px',
224
- borderRadius: '16px',
225
- backgroundColor: 'white',
226
- border: '1px solid #e0e0e0'
227
- });
228
-
229
- // Method 3: Reusable component with props
230
- const UserCard = Component<{ user: { name: string; role: string } }>(({ user }) =>
231
- Card({
232
- children: [
233
- H1(user.name, { fontSize: '1.5rem', marginBottom: 4 }),
234
- P(user.role, { color: '#666', fontSize: '0.9rem' })
235
- ]
236
- })
237
- );
238
- ```
239
-
240
- ### 2\. ๐ŸŽจ Advanced Theming System
241
-
242
- Create comprehensive design systems with nested theme objects:
243
-
244
- ```tsx
245
- // Enhanced theme configuration
246
- const theme = {
247
- colors: {
248
- primary: {
249
- 50: '#E3F2FD',
250
- 500: '#2196F3',
251
- 900: '#0D47A1',
252
- gradient: 'linear-gradient(135deg, #2196F3, #21CBF3)'
253
- },
254
- semantic: {
255
- success: '#4CAF50',
256
- warning: '#FF9800',
257
- error: '#F44336'
258
- },
259
- text: {
260
- primary: '#212121',
261
- secondary: '#757575',
262
- disabled: '#BDBDBD'
263
- }
264
- },
265
- spacing: {
266
- xs: '4px',
267
- sm: '8px',
268
- md: '16px',
269
- lg: '24px',
270
- xl: '32px'
271
- },
272
- typography: {
273
- fontFamily: '"Inter", -apple-system, sans-serif',
274
- sizes: {
275
- xs: '0.75rem',
276
- sm: '0.875rem',
277
- base: '1rem',
278
- lg: '1.125rem',
279
- xl: '1.25rem',
280
- '2xl': '1.5rem'
281
- }
282
- },
283
- borderRadius: {
284
- sm: '4px',
285
- md: '8px',
286
- lg: '12px',
287
- xl: '16px'
288
- }
289
- };
290
-
291
- // Usage with theme paths
292
- const ThemedButton = Component(() =>
293
- Button('Primary Action', {
294
- theme, // Provide theme context
295
- backgroundColor: 'theme.colors.primary.500',
296
- color: 'white',
297
- padding: 'theme.spacing.md theme.spacing.lg',
298
- borderRadius: 'theme.borderRadius.md',
299
- fontFamily: 'theme.typography.fontFamily',
300
- fontSize: 'theme.typography.sizes.base'
301
- })
302
- );
303
- ```
304
-
305
- ### 3\. ๐ŸŽฏ Advanced CSS Properties & Selectors
54
+ ## Key Features
306
55
 
307
- MeoNode provides powerful CSS manipulation through the `css` property for complex styling scenarios:
56
+ - **Function-based components** - No JSX required, pure TypeScript functions
57
+ - **Theme-aware styling** - Direct CSS props with automatic theme resolution
58
+ - **Advanced CSS support** - Pseudo-classes, media queries, animations via `css` prop
59
+ - **Portal system** - Context-aware modals and overlays
60
+ - **TypeScript first** - Full type safety with intelligent autocomplete
61
+ - **Performance optimized** - Powered by @emotion/react
308
62
 
309
- ```tsx
310
- import { Component, Div, Button, H2, P } from '@meonode/ui';
311
-
312
- const InteractiveCard = Component(() =>
313
- Div({
314
- padding: '24px',
315
- borderRadius: '12px',
316
- backgroundColor: 'white',
317
- transition: 'all 0.3s ease',
318
-
319
- // Advanced CSS with pseudo-classes, hover states, and nested selectors
320
- css: {
321
- // Hover effects on the card itself
322
- '&:hover': {
323
- transform: 'translateY(-4px)',
324
- boxShadow: '0 12px 24px rgba(0,0,0,0.15)'
325
- },
326
-
327
- // Style child buttons within this card
328
- '& button': {
329
- borderRadius: '8px',
330
- border: 'none',
331
- transition: 'all 0.2s ease'
332
- },
333
-
334
- // Specific button hover states
335
- '& button:hover': {
336
- backgroundColor: '#2196F3',
337
- color: 'white',
338
- transform: 'scale(1.05)',
339
- boxShadow: '0 4px 12px rgba(33, 150, 243, 0.3)'
340
- },
341
-
342
- // Focus states for accessibility
343
- '& button:focus': {
344
- outline: '2px solid #2196F3',
345
- outlineOffset: '2px'
346
- },
347
-
348
- // Media queries for responsive design
349
- '@media (max-width: 768px)': {
350
- padding: '16px',
351
- margin: '8px'
352
- },
353
-
354
- // Advanced selectors
355
- '& h2 + p': {
356
- marginTop: '8px',
357
- color: '#666'
358
- },
359
-
360
- // Pseudo-elements
361
- '&::before': {
362
- content: '""',
363
- position: 'absolute',
364
- top: 0,
365
- left: 0,
366
- right: 0,
367
- height: '4px',
368
- background: 'linear-gradient(90deg, #FF6B6B, #6BCB77)',
369
- borderRadius: '12px 12px 0 0'
370
- }
371
- },
372
-
373
- children: [
374
- H2('Interactive Component', {
375
- fontSize: '1.5rem',
376
- marginBottom: 12,
377
- color: '#333'
378
- }),
379
- P('This card demonstrates advanced CSS capabilities with hover effects, responsive design, and complex selectors.', {
380
- lineHeight: 1.6,
381
- marginBottom: 16
382
- }),
383
- Button('Try Hovering!', {
384
- padding: '10px 20px',
385
- backgroundColor: '#f5f5f5',
386
- color: '#333',
387
- cursor: 'pointer'
388
- })
389
- ]
390
- })
391
- );
392
- ```
63
+ ## Documentation
393
64
 
394
- ### 4\. ๐Ÿ”ง Smart Prop Handling
65
+ ๐Ÿ“š **[Complete Documentation & Examples](https://meonode-ui.vercel.app)**
395
66
 
396
- Automatic differentiation between CSS properties and DOM attributes:
67
+ ๐ŸŽฎ **[Interactive Playground](https://codesandbox.io/p/github/l7aromeo/react-meonode/main?import=true)**
397
68
 
398
- ```tsx
399
- interface CardProps {
400
- title: string;
401
- urgent?: boolean;
402
- }
69
+ ## Core API
403
70
 
404
- const SmartCard = Component<CardProps>(({ title, urgent, ...restProps }) =>
71
+ ```typescript
72
+ // Create reusable components
73
+ const Card = Component<{ title: string }>(({ title }) =>
405
74
  Div({
406
- // CSS Properties (automatically recognized)
407
75
  padding: '20px',
408
76
  borderRadius: '8px',
409
- backgroundColor: urgent ? '#FFF3E0' : 'white',
410
- borderLeft: urgent ? '4px solid #FF9800' : '4px solid transparent',
411
-
412
- // DOM Attributes (passed through)
413
- 'data-testid': 'smart-card',
414
- 'aria-label': `${title} card`,
415
- role: 'article',
416
- tabIndex: 0,
417
-
418
- // Event Handlers
419
- onClick: (e) => console.log('Card clicked:', title),
420
- onKeyDown: (e) => {
421
- if (e.key === 'Enter') console.log('Card activated:', title);
422
- },
423
-
424
- // Merge any additional props
425
- ...restProps,
426
-
427
- children: [
428
- H2(title, {
429
- color: urgent ? '#E65100' : '#333',
430
- marginBottom: 12
431
- }),
432
- P('Smart prop handling automatically separates CSS from DOM attributes.')
433
- ]
434
- })
435
- );
436
- ```
437
-
438
- ### 5\. ๐ŸŒŸ Dynamic Children & Composition
439
-
440
- Handle complex child patterns with ease:
441
-
442
- ```tsx
443
- const DynamicList = Component<{ items: string[]; header?: string }>(({ items, header }) =>
444
- Div({
445
- children: [
446
- // Conditional header
447
- header && H2(header, { marginBottom: 16 }),
448
-
449
- // Dynamic list items
450
- ...items.map((item, index) =>
451
- Div({
452
- key: index,
453
- padding: '12px',
454
- borderBottom: index < items.length - 1 ? '1px solid #eee' : 'none',
455
- children: P(item)
456
- })
457
- ),
458
-
459
- // Conditional footer
460
- items.length === 0 && P('No items found', {
461
- color: '#999',
462
- fontStyle: 'italic',
463
- textAlign: 'center',
464
- padding: '20px'
465
- })
466
- ]
77
+ backgroundColor: 'white',
78
+ children: H2(title)
467
79
  })
468
80
  );
469
- ```
470
-
471
- ### 6\. ๐Ÿšช Portal System with Context Integration
472
-
473
- Create modals, tooltips, and overlays with full context access:
474
-
475
- ```tsx
476
- import { Portal, Center, Column, Button, Text } from '@meonode/ui';
477
- import { Provider, useSelector } from 'react-redux';
478
- import store from './store';
479
-
480
- // Redux Provider wrapper for portal components
481
- const ReduxProvider = Node(Provider, { store });
482
-
483
- // Modal with Redux integration
484
- const NotificationModal = Portal<{ message: string }>(
485
- ReduxProvider, // Context provider wrapper
486
- ({ portal, message }) => {
487
- const userPreferences = useSelector(state => state.user.preferences);
488
-
489
- useEffect(() => {
490
- // Auto-close after 3 seconds
491
- const timer = setTimeout(portal.unmount, 3000);
492
- return () => clearTimeout(timer);
493
- }, [portal]);
494
-
495
- return Center({
496
- position: 'fixed',
497
- top: 0,
498
- left: 0,
499
- right: 0,
500
- bottom: 0,
501
- backgroundColor: 'rgba(0,0,0,0.5)',
502
- backdropFilter: 'blur(8px)',
503
- zIndex: 1000,
504
-
505
- // Click outside to close
506
- onClick: (e) => {
507
- if (e.currentTarget === e.target) portal.unmount();
508
- },
509
-
510
- children: Column({
511
- backgroundColor: 'white',
512
- borderRadius: '16px',
513
- padding: '32px',
514
- maxWidth: '400px',
515
- margin: '20px',
516
- boxShadow: '0 20px 40px rgba(0,0,0,0.15)',
517
-
518
- css: {
519
- // Entrance animation
520
- animation: 'slideIn 0.3s ease-out',
521
- '@keyframes slideIn': {
522
- from: {
523
- opacity: 0,
524
- transform: 'translateY(-20px) scale(0.95)'
525
- },
526
- to: {
527
- opacity: 1,
528
- transform: 'translateY(0) scale(1)'
529
- }
530
- }
531
- },
532
-
533
- children: [
534
- Text(message, {
535
- fontSize: '1.2rem',
536
- marginBottom: 20,
537
- textAlign: 'center',
538
- color: userPreferences.darkMode ? '#fff' : '#333'
539
- }),
540
- Button('Close', {
541
- backgroundColor: '#2196F3',
542
- color: 'white',
543
- padding: '10px 20px',
544
- borderRadius: '8px',
545
- cursor: 'pointer',
546
- onClick: portal.unmount
547
- })
548
- ]
549
- })
550
- });
551
- }
552
- );
553
-
554
- // Usage
555
- const App = Component(() => {
556
- const showModal = () => NotificationModal({
557
- message: 'Portal with Redux context access!'
558
- });
559
-
560
- return Button('Show Modal', { onClick: showModal });
561
- });
562
- ```
563
-
564
- -----
565
-
566
- ## ๐ŸŽฏ Why Choose @meonode/ui?
567
-
568
- ### **Revolutionary Development Experience**
569
-
570
- - **๐ŸŽฏ Type-Safe by Design** - Complete TypeScript integration with intelligent autocomplete for styles, props, and theme paths
571
- - **๐ŸŽจ Theme-Aware Everything** - Write styles directly in props with automatic theme value resolution and inheritance
572
- - **๐Ÿงฉ Function-Based Composition** - Intuitive component building using structured function calls instead of JSX complexity
573
- - **๐Ÿ’ซ Advanced CSS Control** - Full CSS capabilities including pseudo-classes, media queries, and complex selectors
574
- - **๐ŸŒ Contextual Theming** - Theme values propagate automatically through nested component hierarchies
575
- - **โšก Performance Optimized** - Fast theme resolution and efficient CSS in JS powered by @emotion/react
576
-
577
- ### **Enterprise-Ready Features**
578
-
579
- - **๐Ÿ”„ React Ecosystem Compatible** - Seamless integration with hooks, HOCs, context, and React 18+ concurrent features
580
- - **๐Ÿšช Powerful Portal System** - Advanced portal management with context provider integration for modals and overlays
581
- - **๐Ÿ“ฑ Responsive by Default** - Built-in responsive design patterns with media query support
582
- - **โ™ฟ Accessibility First** - Semantic HTML output with ARIA support and keyboard navigation
583
-
584
- -----
585
-
586
- ## ๐Ÿ“– API Reference
587
81
 
588
- ### Core Functions
589
-
590
- | Function | Signature | Description |
591
- | :--- | :--- | :--- |
592
- | `Node` | `(element: string \| ComponentType, baseProps?: object) => NodeFactory` | Creates a configurable UI node factory that supports flexible properties, dynamic styling, and theme resolution. |
593
- | `Component` | `(render: (props: P) => ComponentNode) => React.Component<P>` | Transforms node trees into reusable React components with built-in type safety, prop handling, and seamless React integration. |
594
- | `Portal` | `(component: (props: P & PortalProps) => ComponentNode) \| (provider: NodeElement, component: (props: P & PortalProps) => ComponentNode)` | Creates React Portal components with optional context provider wrapping. Components receive portal controls for programmatic mounting/unmounting and lifecycle management. |
595
-
596
- ### Pre-built Components
597
-
598
- | Component Category | Components | Description |
599
- | :--- | :--- | :--- |
600
- | **Layout** | `Root`, `Center`, `Column`, `Row`, `Div`, `Section`, `Header`, `Footer`, `Main`, `Nav` | Semantic layout primitives with flexbox and grid support |
601
- | **Typography** | `H1`, `H2`, `H3`, `H4`, `H5`, `H6`, `P`, `Text`, `Span`, `Strong`, `Em` | Typography elements with theme-aware styling |
602
- | **Interactive** | `Button`, `Link`, `Input`, `Select`, `Textarea`, `Checkbox`, `Radio` | Form controls and interactive elements |
603
- | **Media** | `Img`, `Video`, `Audio`, `Canvas`, `Svg` | Media and graphics components |
604
- | **Semantic** | `Article`, `Aside`, `Details`, `Summary`, `Figure`, `Figcaption` | HTML5 semantic elements |
605
-
606
- ### PortalProps Interface
607
-
608
- ```tsx
609
- interface PortalProps {
610
- portal: {
611
- unmount: () => void;
612
- mount: (component: ComponentNode) => void;
613
- isVisible: boolean;
614
- }
615
- }
616
- ```
617
-
618
- -----
619
-
620
- ## ๐ŸŽจ Design Patterns
621
-
622
- ### 1\. Theme-First Design System
623
-
624
- ```tsx
625
- // Complete design system setup
626
- const designSystem = {
627
- colors: {
628
- brand: {
629
- primary: '#6366F1',
630
- secondary: '#8B5CF6',
631
- accent: '#F59E0B'
632
- },
633
- neutral: {
634
- 50: '#F9FAFB',
635
- 100: '#F3F4F6',
636
- 500: '#6B7280',
637
- 900: '#111827'
638
- },
639
- semantic: {
640
- success: '#10B981',
641
- warning: '#F59E0B',
642
- error: '#EF4444',
643
- info: '#3B82F6'
644
- }
645
- },
646
- typography: {
647
- fontFamily: {
648
- sans: '"Inter", system-ui, sans-serif',
649
- mono: '"Fira Code", Consolas, monospace'
650
- },
651
- scale: {
652
- xs: '0.75rem',
653
- sm: '0.875rem',
654
- base: '1rem',
655
- lg: '1.125rem',
656
- xl: '1.25rem',
657
- '2xl': '1.5rem',
658
- '3xl': '1.875rem',
659
- '4xl': '2.25rem'
660
- },
661
- weight: {
662
- normal: 400,
663
- medium: 500,
664
- semibold: 600,
665
- bold: 700
666
- }
667
- },
668
- spacing: {
669
- 0: '0px',
670
- 1: '0.25rem',
671
- 2: '0.5rem',
672
- 3: '0.75rem',
673
- 4: '1rem',
674
- 6: '1.5rem',
675
- 8: '2rem',
676
- 12: '3rem',
677
- 16: '4rem'
678
- },
679
- shadows: {
680
- sm: '0 1px 2px 0 rgba(0, 0, 0, 0.05)',
681
- md: '0 4px 6px -1px rgba(0, 0, 0, 0.1)',
682
- lg: '0 10px 15px -3px rgba(0, 0, 0, 0.1)',
683
- xl: '0 20px 25px -5px rgba(0, 0, 0, 0.1)'
684
- },
685
- borderRadius: {
686
- none: '0',
687
- sm: '0.125rem',
688
- md: '0.375rem',
689
- lg: '0.5rem',
690
- xl: '0.75rem',
691
- full: '9999px'
692
- }
693
- };
694
-
695
- // Usage in components
696
- const ThemedCard = Component<{ variant?: 'default' | 'success' | 'warning' | 'error' }>(
697
- ({ variant = 'default', children }) => {
698
- const variantStyles = {
699
- default: {
700
- border: '1px solid theme.neutral.200',
701
- backgroundColor: 'theme.neutral.50'
702
- },
703
- success: {
704
- border: '1px solid theme.semantic.success',
705
- backgroundColor: '#F0FDF4'
706
- },
707
- warning: {
708
- border: '1px solid theme.semantic.warning',
709
- backgroundColor: '#FFFBEB'
710
- },
711
- error: {
712
- border: '1px solid theme.semantic.error',
713
- backgroundColor: '#FEF2F2'
714
- }
715
- };
716
-
717
- return Div({
718
- theme: designSystem,
719
- padding: 'theme.spacing.6',
720
- borderRadius: 'theme.borderRadius.lg',
721
- boxShadow: 'theme.shadows.md',
722
- ...variantStyles[variant],
723
- children
724
- });
82
+ // Advanced styling with css prop
83
+ const AnimatedBox = Div({
84
+ padding: '20px',
85
+ css: {
86
+ '&:hover': { transform: 'scale(1.05)' },
87
+ '@media (max-width: 768px)': { padding: '12px' }
725
88
  }
726
- );
727
- ```
728
-
729
- ### 2\. Responsive Design Patterns
730
-
731
- ```tsx
732
- const ResponsiveGrid = Component<{ items: Array<{ title: string; content: string }> }>(
733
- ({ items }) =>
734
- Div({
735
- css: {
736
- display: 'grid',
737
- gap: '24px',
738
-
739
- // Responsive grid
740
- '@media (min-width: 640px)': {
741
- gridTemplateColumns: 'repeat(2, 1fr)'
742
- },
743
- '@media (min-width: 1024px)': {
744
- gridTemplateColumns: 'repeat(3, 1fr)'
745
- },
746
- '@media (min-width: 1280px)': {
747
- gridTemplateColumns: 'repeat(4, 1fr)'
748
- },
749
-
750
- // Grid item styling
751
- '& > *': {
752
- transition: 'transform 0.2s ease, box-shadow 0.2s ease'
753
- },
754
-
755
- '& > *:hover': {
756
- transform: 'translateY(-4px)',
757
- boxShadow: '0 12px 24px rgba(0,0,0,0.15)'
758
- }
759
- },
760
-
761
- children: items.map((item, index) =>
762
- ThemedCard({
763
- key: index,
764
- children: [
765
- H2(item.title, {
766
- fontSize: '1.25rem',
767
- fontWeight: 'bold',
768
- marginBottom: 8,
769
- color: 'theme.neutral.900'
770
- }),
771
- P(item.content, {
772
- color: 'theme.neutral.600',
773
- lineHeight: 1.6
774
- })
775
- ]
776
- })
777
- )
778
- })
779
- );
780
- ```
781
-
782
- ### 3\. Form Composition
783
-
784
- ```tsx
785
- const ContactForm = Component(() => {
786
- const [formData, setFormData] = useState({
787
- name: '',
788
- email: '',
789
- message: ''
790
- });
791
-
792
- const handleSubmit = (e: React.FormEvent) => {
793
- e.preventDefault();
794
- console.log('Form submitted:', formData);
795
- };
796
-
797
- return Column({
798
- theme: designSystem,
799
- gap: 'theme.spacing.4',
800
- maxWidth: '500px',
801
-
802
- css: {
803
- '& input, & textarea': {
804
- width: '100%',
805
- padding: 'theme.spacing.3',
806
- borderRadius: 'theme.borderRadius.md',
807
- border: '1px solid theme.neutral.300',
808
- fontSize: 'theme.typography.scale.base',
809
- transition: 'border-color 0.2s ease, box-shadow 0.2s ease'
810
- },
811
-
812
- '& input:focus, & textarea:focus': {
813
- outline: 'none',
814
- borderColor: 'theme.colors.brand.primary',
815
- boxShadow: '0 0 0 3px rgba(99, 102, 241, 0.1)'
816
- },
817
-
818
- '& label': {
819
- fontSize: 'theme.typography.scale.sm',
820
- fontWeight: 'theme.typography.weight.medium',
821
- color: 'theme.neutral.700',
822
- marginBottom: 'theme.spacing.2'
823
- }
824
- },
825
-
826
- children: [
827
- // Form element wrapper
828
- Node('form', {
829
- onSubmit: handleSubmit,
830
- children: [
831
- Column({
832
- gap: 'theme.spacing.2',
833
- children: [
834
- Node('label', { children: 'Name' }),
835
- Node('input', {
836
- type: 'text',
837
- value: formData.name,
838
- onChange: (e) => setFormData(prev => ({ ...prev, name: e.target.value })),
839
- placeholder: 'Enter your name'
840
- })
841
- ]
842
- }),
843
-
844
- Column({
845
- gap: 'theme.spacing.2',
846
- children: [
847
- Node('label', { children: 'Email' }),
848
- Node('input', {
849
- type: 'email',
850
- value: formData.email,
851
- onChange: (e) => setFormData(prev => ({ ...prev, email: e.target.value })),
852
- placeholder: 'Enter your email'
853
- })
854
- ]
855
- }),
856
-
857
- Column({
858
- gap: 'theme.spacing.2',
859
- children: [
860
- Node('label', { children: 'Message' }),
861
- Node('textarea', {
862
- value: formData.message,
863
- onChange: (e) => setFormData(prev => ({ ...prev, message: e.target.value })),
864
- placeholder: 'Enter your message',
865
- rows: 4
866
- })
867
- ]
868
- }),
869
-
870
- Button('Send Message', {
871
- type: 'submit',
872
- backgroundColor: 'theme.colors.brand.primary',
873
- color: 'white',
874
- padding: 'theme.spacing.3 theme.spacing.6',
875
- borderRadius: 'theme.borderRadius.md',
876
- fontWeight: 'theme.typography.weight.semibold',
877
- cursor: 'pointer',
878
- marginTop: 'theme.spacing.4'
879
- })
880
- ]
881
- })
882
- ]
883
- });
884
- });
885
- ```
886
-
887
- -----
888
-
889
- ## ๐Ÿ”ง Advanced Techniques
890
-
891
- ### Custom Hook Integration
892
-
893
- ```tsx
894
- import { useState, useCallback } from 'react';
895
-
896
- const useToggle = (initialValue = false) => {
897
- const [value, setValue] = useState(initialValue);
898
- const toggle = useCallback(() => setValue(v => !v), []);
899
- return [value, toggle] as const;
900
- };
901
-
902
- const ToggleCard = Component(() => {
903
- const [isExpanded, toggleExpanded] = useToggle(false);
904
-
905
- return Div({
906
- theme: designSystem,
907
- borderRadius: 'theme.borderRadius.lg',
908
- backgroundColor: 'white',
909
- boxShadow: 'theme.shadows.md',
910
- overflow: 'hidden',
911
-
912
- css: {
913
- transition: 'all 0.3s ease',
914
- cursor: 'pointer',
915
-
916
- '&:hover': {
917
- boxShadow: 'theme.shadows.lg',
918
- transform: 'translateY(-2px)'
919
- }
920
- },
921
-
922
- onClick: toggleExpanded,
923
-
924
- children: [
925
- Div({
926
- padding: 'theme.spacing.6',
927
- children: [
928
- H2('Expandable Card', {
929
- fontSize: 'theme.typography.scale.xl',
930
- marginBottom: 8
931
- }),
932
- P('Click to expand/collapse', {
933
- color: 'theme.neutral.600'
934
- })
935
- ]
936
- }),
937
-
938
- // Conditional expanded content
939
- isExpanded && Div({
940
- padding: 'theme.spacing.6',
941
- paddingTop: 0,
942
- borderTop: '1px solid theme.neutral.200',
943
-
944
- css: {
945
- animation: 'slideDown 0.3s ease',
946
- '@keyframes slideDown': {
947
- from: {
948
- opacity: 0,
949
- maxHeight: 0,
950
- transform: 'translateY(-10px)'
951
- },
952
- to: {
953
- opacity: 1,
954
- maxHeight: '200px',
955
- transform: 'translateY(0)'
956
- }
957
- }
958
- },
959
-
960
- children: P('This is the expanded content that appears when the card is clicked. It demonstrates conditional rendering with smooth animations.')
961
- })
962
- ]
963
- });
964
89
  });
965
- ```
966
-
967
- ### Error Boundaries Integration
968
-
969
- ```tsx
970
- import { Component, Div, H2, P, Button } from '@meonode/ui';
971
- import { ErrorBoundary } from 'react-error-boundary';
972
90
 
973
- const ErrorFallback = Component<{ error: Error; resetErrorBoundary: () => void }>(
974
- ({ error, resetErrorBoundary }) =>
975
- Div({
976
- theme: designSystem,
977
- padding: 'theme.spacing.8',
978
- backgroundColor: 'theme.semantic.error',
979
- color: 'white',
980
- borderRadius: 'theme.borderRadius.lg',
981
- textAlign: 'center',
982
-
91
+ // Portal for modals/overlays
92
+ const Modal = Portal(({ portal, message }) =>
93
+ Center({
94
+ position: 'fixed',
95
+ top: 0, left: 0, right: 0, bottom: 0,
96
+ backgroundColor: 'rgba(0,0,0,0.5)',
97
+ onClick: portal.unmount,
98
+ children: Div({
99
+ backgroundColor: 'white',
100
+ padding: '24px',
101
+ borderRadius: '12px',
983
102
  children: [
984
- H2('Something went wrong', {
985
- fontSize: 'theme.typography.scale.2xl',
986
- marginBottom: 16
987
- }),
988
- P(error.message, {
989
- marginBottom: 24,
990
- opacity: 0.9
991
- }),
992
- Button('Try Again', {
993
- backgroundColor: 'white',
994
- color: 'theme.semantic.error',
995
- padding: '12px 24px',
996
- borderRadius: 'theme.borderRadius.md',
997
- fontWeight: 'bold',
998
- cursor: 'pointer',
999
- onClick: resetErrorBoundary
1000
- })
103
+ Text(message),
104
+ Button('Close', { onClick: portal.unmount })
1001
105
  ]
1002
106
  })
1003
- );
1004
-
1005
- const SafeApp = Component(() =>
1006
- Node(ErrorBoundary, {
1007
- FallbackComponent: ErrorFallback,
1008
- onError: (error, errorInfo) => {
1009
- console.error('App Error:', error, errorInfo);
1010
- },
1011
- children: YourMainApp()
1012
- })
1013
- );
1014
- ```
1015
-
1016
- -----
1017
-
1018
- ## ๐ŸŒŸ Real-World Example Application
1019
-
1020
- ```tsx
1021
- import { Component, Root, Center, Column, Row, H1, H2, P, Button, Text, Portal } from '@meonode/ui';
1022
- import { useState, useEffect } from 'react';
1023
-
1024
- // Complete theme system
1025
- const appTheme = {
1026
- colors: {
1027
- primary: {
1028
- default: '#FF6B6B',
1029
- content: '#4A0000',
1030
- light: '#FFB3B3',
1031
- dark: '#CC5555'
1032
- },
1033
- secondary: {
1034
- default: '#6BCB77',
1035
- content: '#0A3B0F',
1036
- light: '#B3E6BC',
1037
- dark: '#55A862'
1038
- },
1039
- base: {
1040
- default: '#F8F8F8',
1041
- content: '#333333',
1042
- accent: '#88B04B',
1043
- border: '#E0E0E0'
1044
- }
1045
- },
1046
- spacing: {
1047
- xs: '8px',
1048
- sm: '12px',
1049
- md: '16px',
1050
- lg: '24px',
1051
- xl: '32px',
1052
- '2xl': '48px'
1053
- },
1054
- typography: {
1055
- family: '"Inter", -apple-system, BlinkMacSystemFont, sans-serif',
1056
- sizes: {
1057
- sm: '0.875rem',
1058
- base: '1rem',
1059
- lg: '1.125rem',
1060
- xl: '1.25rem',
1061
- '2xl': '1.5rem',
1062
- '3xl': '2rem',
1063
- '4xl': '2.5rem'
1064
- }
1065
- }
1066
- };
1067
-
1068
- const notifications = [
1069
- { id: 1, type: 'success', message: 'Component created successfully!' },
1070
- { id: 2, type: 'info', message: 'MeoNode UI is theme-aware by default.' },
1071
- { id: 3, type: 'warning', message: 'Remember to handle responsive design.' },
1072
- { id: 4, type: 'error', message: 'This is just a demo error message.' }
1073
- ];
1074
-
1075
- // Enhanced Modal with animations and context
1076
- const NotificationModal = Portal<{ notification: typeof notifications[0] }>(
1077
- ({ portal, notification }) => {
1078
- useEffect(() => {
1079
- const timer = setTimeout(portal.unmount, 4000);
1080
- return () => clearTimeout(timer);
1081
- }, [portal]);
1082
-
1083
- const typeStyles = {
1084
- success: { bg: '#F0FDF4', border: '#22C55E', text: '#15803D' },
1085
- info: { bg: '#EFF6FF', border: '#3B82F6', text: '#1D4ED8' },
1086
- warning: { bg: '#FFFBEB', border: '#F59E0B', text: '#D97706' },
1087
- error: { bg: '#FEF2F2', border: '#EF4444', text: '#DC2626' }
1088
- }[notification.type];
1089
-
1090
- return Center({
1091
- theme: appTheme,
1092
- position: 'fixed',
1093
- top: 0,
1094
- left: 0,
1095
- right: 0,
1096
- bottom: 0,
1097
- backgroundColor: 'rgba(0,0,0,0.4)',
1098
- backdropFilter: 'blur(8px)',
1099
- zIndex: 1000,
1100
-
1101
- onClick: (e) => {
1102
- if (e.currentTarget === e.target) portal.unmount();
1103
- },
1104
-
1105
- children: Column({
1106
- backgroundColor: typeStyles.bg,
1107
- borderRadius: 'theme.spacing.md',
1108
- padding: 'theme.spacing.xl',
1109
- margin: 'theme.spacing.lg',
1110
- maxWidth: '400px',
1111
- border: `2px solid ${typeStyles.border}`,
1112
-
1113
- css: {
1114
- animation: 'modalSlideIn 0.4s cubic-bezier(0.34, 1.56, 0.64, 1)',
1115
-
1116
- '@keyframes modalSlideIn': {
1117
- from: {
1118
- opacity: 0,
1119
- transform: 'scale(0.8) translateY(-40px)'
1120
- },
1121
- to: {
1122
- opacity: 1,
1123
- transform: 'scale(1) translateY(0)'
1124
- }
1125
- }
1126
- },
1127
-
1128
- children: [
1129
- H2(`${notification.type.toUpperCase()} Notification`, {
1130
- color: typeStyles.text,
1131
- fontSize: 'theme.typography.sizes.xl',
1132
- marginBottom: 'theme.spacing.md',
1133
- textAlign: 'center',
1134
- textTransform: 'capitalize'
1135
- }),
1136
-
1137
- P(notification.message, {
1138
- color: typeStyles.text,
1139
- lineHeight: 1.6,
1140
- textAlign: 'center',
1141
- marginBottom: 'theme.spacing.lg'
1142
- }),
1143
-
1144
- Row({
1145
- gap: 'theme.spacing.sm',
1146
- justifyContent: 'center',
1147
- children: [
1148
- Button('Dismiss', {
1149
- backgroundColor: 'transparent',
1150
- color: typeStyles.text,
1151
- border: `1px solid ${typeStyles.border}`,
1152
- padding: 'theme.spacing.sm theme.spacing.md',
1153
- borderRadius: 'theme.spacing.xs',
1154
- cursor: 'pointer',
1155
- onClick: portal.unmount
1156
- }),
1157
-
1158
- Button('OK', {
1159
- backgroundColor: typeStyles.border,
1160
- color: 'white',
1161
- padding: 'theme.spacing.sm theme.spacing.md',
1162
- borderRadius: 'theme.spacing.xs',
1163
- cursor: 'pointer',
1164
- fontWeight: 'bold',
1165
- onClick: portal.unmount
1166
- })
1167
- ]
1168
- })
1169
- ]
1170
- })
1171
- });
1172
- }
1173
- );
1174
-
1175
- // Main application component
1176
- const MeoNodeShowcase = Component(() => {
1177
- const [selectedMessage, setSelectedMessage] = useState('');
1178
- const [currentTheme, setCurrentTheme] = useState<'light' | 'dark'>('light');
1179
-
1180
- const surprises = [
1181
- 'MeoNode makes UI development delightful! ๐ŸŽ‰',
1182
- 'Intuitive design meets pure simplicity.',
1183
- 'Build beautiful interfaces effortlessly with type safety.',
1184
- 'Composable, theme-aware, and a joy to use!'
1185
- ];
1186
-
1187
- const getRandomSurprise = () => {
1188
- const randomMessage = surprises[Math.floor(Math.random() * surprises.length)];
1189
- setSelectedMessage(randomMessage);
1190
- };
1191
-
1192
- const showNotification = (type: 'success' | 'info' | 'warning' | 'error') => {
1193
- const notification = notifications.find(n => n.type === type);
1194
- if (notification) {
1195
- NotificationModal({ notification });
1196
- }
1197
- };
1198
-
1199
- return Root({
1200
- theme: appTheme,
1201
- backgroundColor: currentTheme === 'light' ? 'theme.base.default' : '#1a1a1a',
1202
- color: currentTheme === 'light' ? 'theme.base.content' : '#ffffff',
1203
- minHeight: '100vh',
1204
- fontFamily: 'theme.typography.family',
1205
-
1206
- children: Center({
1207
- padding: 'theme.spacing.2xl',
1208
- children: Column({
1209
- gap: 'theme.spacing.xl',
1210
- maxWidth: '800px',
1211
- textAlign: 'center',
1212
-
1213
- css: {
1214
- // Global button styling
1215
- '& button': {
1216
- transition: 'all 0.3s cubic-bezier(0.4, 0, 0.2, 1)',
1217
- border: 'none',
1218
- outline: 'none'
1219
- },
1220
-
1221
- '& button:hover': {
1222
- transform: 'translateY(-2px)',
1223
- boxShadow: '0 8px 25px rgba(0,0,0,0.15)'
1224
- },
1225
-
1226
- '& button:active': {
1227
- transform: 'translateY(0)',
1228
- transition: 'transform 0.1s ease'
1229
- },
1230
-
1231
- // Responsive adjustments
1232
- '@media (max-width: 768px)': {
1233
- gap: 'theme.spacing.lg',
1234
- padding: 'theme.spacing.lg',
1235
-
1236
- '& h1': {
1237
- fontSize: 'theme.typography.sizes.3xl !important'
1238
- }
1239
- }
1240
- },
1241
-
1242
- children: [
1243
- // Header section
1244
- Column({
1245
- gap: 'theme.spacing.md',
1246
- children: [
1247
- H1('MeoNode UI Showcase', {
1248
- fontSize: 'theme.typography.sizes.4xl',
1249
- background: 'linear-gradient(135deg, theme.colors.primary.default, theme.colors.secondary.default)',
1250
- backgroundClip: 'text',
1251
- WebkitBackgroundClip: 'text',
1252
- WebkitTextFillColor: 'transparent',
1253
- fontWeight: 'bold'
1254
- }),
1255
-
1256
- P('Experience the power of function-based React components with advanced theming and CSS capabilities.', {
1257
- fontSize: 'theme.typography.sizes.lg',
1258
- color: currentTheme === 'light' ? 'theme.base.content' : '#cccccc',
1259
- lineHeight: 1.6,
1260
- maxWidth: '600px',
1261
- margin: '0 auto'
1262
- })
1263
- ]
1264
- }),
1265
-
1266
- // Interactive message display
1267
- Div({
1268
- padding: 'theme.spacing.lg',
1269
- backgroundColor: currentTheme === 'light' ? 'white' : '#2a2a2a',
1270
- borderRadius: 'theme.spacing.md',
1271
- border: currentTheme === 'light' ? '1px solid theme.base.border' : '1px solid #404040',
1272
- minHeight: '80px',
1273
- display: 'flex',
1274
- alignItems: 'center',
1275
- justifyContent: 'center',
1276
-
1277
- css: {
1278
- transition: 'all 0.3s ease',
1279
- '&:hover': {
1280
- backgroundColor: currentTheme === 'light' ? '#fafafa' : '#333333'
1281
- }
1282
- },
1283
-
1284
- children: Text(selectedMessage || 'Click a button below to see MeoNode in action! โœจ', {
1285
- fontSize: 'theme.typography.sizes.lg',
1286
- color: currentTheme === 'light' ? 'theme.base.content' : '#ffffff',
1287
- textAlign: 'center',
1288
- lineHeight: 1.5
1289
- })
1290
- }),
1291
-
1292
- // Action buttons grid
1293
- Row({
1294
- gap: 'theme.spacing.md',
1295
- justifyContent: 'center',
1296
- flexWrap: 'wrap',
1297
- children: [
1298
- Button('๐ŸŽ‰ Random Surprise', {
1299
- backgroundColor: 'theme.colors.primary.default',
1300
- color: 'theme.colors.primary.content',
1301
- padding: 'theme.spacing.md theme.spacing.lg',
1302
- borderRadius: 'theme.spacing.sm',
1303
- fontSize: 'theme.typography.sizes.base',
1304
- fontWeight: 'bold',
1305
- cursor: 'pointer',
1306
- onClick: getRandomSurprise
1307
- }),
1308
-
1309
- Button('๐ŸŒ™ Toggle Theme', {
1310
- backgroundColor: currentTheme === 'light' ? '#333333' : '#ffffff',
1311
- color: currentTheme === 'light' ? '#ffffff' : '#333333',
1312
- padding: 'theme.spacing.md theme.spacing.lg',
1313
- borderRadius: 'theme.spacing.sm',
1314
- fontSize: 'theme.typography.sizes.base',
1315
- fontWeight: 'bold',
1316
- cursor: 'pointer',
1317
- onClick: () => setCurrentTheme(t => t === 'light' ? 'dark' : 'light')
1318
- })
1319
- ]
1320
- }),
1321
-
1322
- // Notification demo buttons
1323
- Column({
1324
- gap: 'theme.spacing.sm',
1325
- children: [
1326
- H2('Portal Notifications Demo', {
1327
- fontSize: 'theme.typography.sizes.xl',
1328
- marginBottom: 'theme.spacing.md',
1329
- color: currentTheme === 'light' ? 'theme.base.content' : '#ffffff'
1330
- }),
1331
-
1332
- Row({
1333
- gap: 'theme.spacing.sm',
1334
- justifyContent: 'center',
1335
- flexWrap: 'wrap',
1336
- children: [
1337
- Button('โœ… Success', {
1338
- backgroundColor: 'theme.colors.semantic.success',
1339
- color: 'white',
1340
- padding: 'theme.spacing.sm theme.spacing.md',
1341
- borderRadius: 'theme.spacing.xs',
1342
- cursor: 'pointer',
1343
- onClick: () => showNotification('success')
1344
- }),
1345
-
1346
- Button('โ„น๏ธ Info', {
1347
- backgroundColor: 'theme.colors.semantic.info',
1348
- color: 'white',
1349
- padding: 'theme.spacing.sm theme.spacing.md',
1350
- borderRadius: 'theme.spacing.xs',
1351
- cursor: 'pointer',
1352
- onClick: () => showNotification('info')
1353
- }),
1354
-
1355
- Button('โš ๏ธ Warning', {
1356
- backgroundColor: 'theme.colors.semantic.warning',
1357
- color: 'white',
1358
- padding: 'theme.spacing.sm theme.spacing.md',
1359
- borderRadius: 'theme.spacing.xs',
1360
- cursor: 'pointer',
1361
- onClick: () => showNotification('warning')
1362
- }),
1363
-
1364
- Button('โŒ Error', {
1365
- backgroundColor: 'theme.colors.semantic.error',
1366
- color: 'white',
1367
- padding: 'theme.spacing.sm theme.spacing.md',
1368
- borderRadius: 'theme.spacing.xs',
1369
- cursor: 'pointer',
1370
- onClick: () => showNotification('error')
1371
- })
1372
- ]
1373
- })
1374
- ]
1375
- })
1376
- ]
1377
- })
1378
- })
1379
- });
1380
- });
1381
-
1382
- export default MeoNodeShowcase;
1383
- ```
1384
-
1385
- -----
1386
-
1387
- ## ๐Ÿ“‹ Best Practices
1388
-
1389
- ### 1\. **Theme Organization**
1390
-
1391
- - Structure themes hierarchically with logical groupings
1392
- - Use semantic naming for colors (primary, secondary, success, etc.)
1393
- - Include both light and dark variants in your theme system
1394
- - Define spacing and typography scales for consistency
1395
-
1396
- ### 2\. **Component Composition**
1397
-
1398
- - Keep components focused and single-purpose
1399
- - Use the `Component` wrapper for reusable elements
1400
- - Leverage prop spreading for flexible component APIs
1401
- - Combine multiple simple components to create complex interfaces
1402
-
1403
- ### 3\. **Performance Optimization**
1404
-
1405
- - Use React.memo for expensive components when needed
1406
- - Leverage the built-in tree-shaking capabilities
1407
- - Minimize theme object recreations in render functions
1408
- - Use CSS-in-JS patterns responsibly for optimal performance
1409
-
1410
- ### 4\. **CSS Architecture**
1411
-
1412
- - Prefer theme values over hardcoded styles
1413
- - Use the `css` property for complex selectors and animations
1414
- - Implement responsive design through media queries
1415
- - Maintain consistent hover and focus states across components
1416
-
1417
- -----
1418
-
1419
- ## ๐Ÿ”— Integration Examples
1420
-
1421
- ### Next.js Integration
1422
-
1423
- ```tsx
1424
- // app/layout.tsx
1425
- import { Component, Root } from '@meonode/ui';
1426
- import { theme } from './theme';
1427
-
1428
- const RootLayout = Component<{ children: React.ReactNode }>(({ children }) =>
1429
- Root({
1430
- theme,
1431
- className: 'min-h-screen',
1432
- children
1433
107
  })
1434
108
  );
1435
109
  ```
1436
110
 
1437
- ### Redux Integration
1438
-
1439
- ```tsx
1440
- import { Provider } from 'react-redux';
1441
- import { Node } from '@meonode/ui';
1442
- import store from './store';
1443
-
1444
- const ReduxProvider = Node(Provider, { store });
1445
-
1446
- const AppWithRedux = Component(() =>
1447
- ReduxProvider({
1448
- children: YourApp()
1449
- })
1450
- );
1451
- ```
1452
-
1453
- -----
1454
-
1455
- ## ๐ŸŒ Community & Resources
1456
-
1457
- ### Example Repository
1458
-
1459
- Explore a complete Next.js application showcasing MeoNode UI best practices...
1460
-
1461
- **[๐Ÿ”— MeoNode + Next.js Example](https://github.com/l7aromeo/react-meonode)**
1462
- **[๐Ÿ”— Open in CodeSandbox](https://codesandbox.io/p/github/l7aromeo/react-meonode/main?import=true)**
1463
-
1464
- This repository demonstrates:
1465
-
1466
- - Server Component integration
1467
- - Redux state management with preloaded state
1468
- - Responsive design patterns
1469
- - Advanced portal usage
1470
- - Theme system implementation
1471
-
1472
- -----
1473
-
1474
- ## ๐Ÿค Contributing
1475
-
1476
- We welcome contributions from the community\! Here's how to get started:
1477
-
1478
- ### Development Setup
1479
-
1480
- ```bash
1481
- # 1. Fork and clone the repository
1482
- git clone https://github.com/your-username/meonode-ui.git
1483
- cd meonode-ui
1484
-
1485
- # 2. Install dependencies
1486
- npm install
1487
- # or
1488
- yarn install
1489
- # or
1490
- pnpm install
1491
-
1492
- # 3. Start development server
1493
- npm run dev
1494
-
1495
- # 4. Run tests
1496
- npm test
1497
-
1498
- # 5. Build the project
1499
- npm run build
1500
- ```
1501
-
1502
- ### Contribution Guidelines
1503
-
1504
- 1. **๐Ÿด Fork** the repository and create your feature branch
1505
- 2. **๐Ÿ”ง Install dependencies** and ensure tests pass
1506
- 3. **โœจ Create your feature** with comprehensive tests
1507
- 4. **๐Ÿ“ Update documentation** for any new features
1508
- 5. **๐Ÿงช Test thoroughly** across different scenarios
1509
- 6. **๐Ÿ“ค Submit a Pull Request** with a clear description
1510
-
1511
- ### Development Standards
1512
-
1513
- - **TypeScript First** - All code must include proper type definitions
1514
- - **Test Coverage** - Maintain \>95% test coverage for new features
1515
- - **Documentation** - Update README and examples for new features
1516
- - **Performance** - Ensure no performance regressions
1517
- - **Accessibility** - Follow WCAG guidelines for new components
1518
-
1519
- For major changes or new features, please open an issue first to discuss your proposal with the maintainers.
1520
-
1521
- -----
1522
-
1523
- ## ๐Ÿ“„ License & Support
1524
-
1525
- **MIT Licensed** | Copyright ยฉ 2024 Ukasyah Rahmatullah Zada
111
+ ## Contributing
1526
112
 
1527
- ### Getting Help
113
+ We welcome contributions! Please see our [contributing guidelines](https://github.com/l7aromeo/meonode-ui/blob/main/CONTRIBUTING.md).
1528
114
 
1529
- - ๐Ÿ“š **Documentation**: Full API reference and examples
1530
- - ๐Ÿ› **Issues**: [GitHub Issues](https://github.com/l7aromeo/meonode-ui/issues)
1531
- - ๐Ÿ’ฌ **Discussions**: [GitHub Discussions](https://github.com/l7aromeo/meonode-ui/discussions)
1532
- - ๐Ÿ“ง **Discord**: [l7aromeo](https://discord.com/users/704803255561224264)
115
+ ## License
1533
116
 
1534
- -----
117
+ MIT ยฉ [Ukasyah Rahmatullah Zada](https://github.com/l7aromeo)
1535
118
 
1536
- *Empowering developers to build exceptional UIs with type-safe, theme-aware, function-based React components.*
119
+ ---
1537
120
 
1538
- **MeoNode UI - Where Function Meets Beauty** โœจ
121
+ **[๐Ÿ“– Full Documentation](https://meonode-ui.vercel.app)** โ€ข **[๐Ÿ› Issues](https://github.com/l7aromeo/meonode-ui/issues)** โ€ข **[๐Ÿ’ฌ Discussions](https://github.com/l7aromeo/meonode-ui/discussions)**