igloo-d2c-components 1.0.12 → 1.0.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
@@ -5,17 +5,31 @@ Reusable React component library with **centralized tenant themes** and tenant-a
5
5
  ## 📋 Table of Contents
6
6
 
7
7
  - [Overview](#-overview)
8
+ - [Project Architecture](#-project-architecture)
8
9
  - [Features](#-features)
9
10
  - [Installation](#-installation)
10
11
  - [Quick Start](#-quick-start)
11
12
  - [Centralized Themes](#-centralized-themes)
12
13
  - [Components](#-components)
14
+ - [General Components](#general-components)
15
+ - [Interactive Components](#interactive-components)
16
+ - [Checkout Components](#checkout-components)
17
+ - [Form Components](#form-components)
13
18
  - [Hooks & Utilities](#-hooks--utilities)
19
+ - [Asset Management](#-asset-management)
20
+ - [Integration Guide](#-integration-guide)
21
+ - [Multi-Tenant Architecture](#multi-tenant-architecture)
22
+ - [Checkout Flow Integration](#checkout-flow-integration)
23
+ - [Recommendations Feature](#recommendations-feature)
24
+ - [Header Integration](#header-integration)
25
+ - [Routing Guide](#routing-guide)
14
26
  - [Development](#-development)
15
- - [Publishing](#-publishing)
16
27
  - [Storybook](#-storybook)
28
+ - [Build Pipeline](#-build-pipeline)
29
+ - [Publishing](#-publishing)
17
30
  - [Technical Details](#-technical-details)
18
31
  - [Troubleshooting](#-troubleshooting)
32
+ - [Changelog](#-changelog)
19
33
  - [Contributing](#-contributing)
20
34
 
21
35
  ---
@@ -24,6 +38,15 @@ Reusable React component library with **centralized tenant themes** and tenant-a
24
38
 
25
39
  The D2C Component Library provides reusable, tenant-aware UI components with **centralized theme management**. All tenant themes are defined in one place, ensuring consistency across all applications.
26
40
 
41
+ ### What Are These Projects?
42
+
43
+ We've built a **multi-tenant B2C insurance platform** that enables rapid deployment of white-label insurance applications for different partners.
44
+
45
+ | Project | Purpose |
46
+ | ------------------------- | --------------------------------------------------------------------------- |
47
+ | **d2c-component-library** | Shared component library with centralized themes and reusable UI components |
48
+ | **b2c-web-demo** | Multi-tenant web application consuming the component library |
49
+
27
50
  ### Key Highlights
28
51
 
29
52
  - 🎨 **Centralized Themes** - All tenant themes (Igloo, CIMB, AmmetLife) in one library
@@ -33,6 +56,70 @@ The D2C Component Library provides reusable, tenant-aware UI components with **c
33
56
  - 📖 **Full TypeScript Support** - Complete type definitions
34
57
  - ⚡ **Tree-Shakeable** - Import only what you need
35
58
 
59
+ ### Supported Tenants
60
+
61
+ | Tenant | Port | Description |
62
+ | ------------- | ---- | ----------------------- |
63
+ | **Igloo** | 8000 | Default insurance brand |
64
+ | **AmmetLife** | 8001 | Life insurance partner |
65
+ | **CIMB** | 8002 | Banking partner |
66
+
67
+ ---
68
+
69
+ ## 🏗️ Project Architecture
70
+
71
+ ### The Solution Architecture
72
+
73
+ ```
74
+ ┌─────────────────────────────────────────────────────────────────┐
75
+ │ d2c-component-library │
76
+ │ ┌─────────────────────────────────────────────────────────────┐│
77
+ │ │ Centralized Themes ││
78
+ │ │ ┌───────────────────────┐ ┌───────────────────────┐ ││
79
+ │ │ │ iglooTheme │ │ ammetlifeTheme │ ││
80
+ │ │ └───────────────────────┘ └───────────────────────┘ ││
81
+ │ └─────────────────────────────────────────────────────────────┘│
82
+ │ ┌─────────────────────────────────────────────────────────────┐│
83
+ │ │ Shared Components ││
84
+ │ │ Button │ Card │ Banner │ Header │ CheckoutProgress │ ... ││
85
+ │ └─────────────────────────────────────────────────────────────┘│
86
+ │ ┌─────────────────────────────────────────────────────────────┐│
87
+ │ │ Theme Utilities ││
88
+ │ │ TenantThemeProvider │ useTenantTheme │ getTenantTheme ││
89
+ │ └─────────────────────────────────────────────────────────────┘│
90
+ └─────────────────────────────────────────────────────────────────┘
91
+
92
+
93
+ ┌─────────────────────────────────────────────────────────────────┐
94
+ │ b2c-web-demo │
95
+ │ ┌─────────────────────────────────────────────────────────────┐│
96
+ │ │ Tenant Configurations ││
97
+ │ │ ┌───────────────────────┐ ┌───────────────────────┐ ││
98
+ │ │ │ igloo.ts │ │ ammetlife.ts │ ││
99
+ │ │ │ (uses iglooTheme) │ │ (uses ammetlifeTheme) │ ││
100
+ │ │ └───────────────────────┘ └───────────────────────┘ ││
101
+ │ └─────────────────────────────────────────────────────────────┘│
102
+ │ ┌─────────────────────────────────────────────────────────────┐│
103
+ │ │ Single Codebase, Multiple Tenants ││
104
+ │ │ yarn start-igloo → http://localhost:8000 ││
105
+ │ │ yarn start-ammetlife → http://localhost:8001 ││
106
+ │ └─────────────────────────────────────────────────────────────┘│
107
+ └─────────────────────────────────────────────────────────────────┘
108
+ ```
109
+
110
+ ### Technical Stack
111
+
112
+ ```
113
+ Frontend Framework: React 17 + TypeScript
114
+ Build System: UmiJS (React framework) for b2c-web-demo
115
+ UI Components: MUI v5 + Custom Components
116
+ Styling: Emotion (CSS-in-JS) + Tailwind CSS
117
+ State Management: Recoil + React Context
118
+ Component Library: Rollup (ES2015 output)
119
+ Documentation: Storybook
120
+ Package Manager: Yarn
121
+ ```
122
+
36
123
  ---
37
124
 
38
125
  ## ✨ Features
@@ -47,41 +134,28 @@ The D2C Component Library provides reusable, tenant-aware UI components with **c
47
134
 
48
135
  ### Available Themes
49
136
 
50
- | Tenant | Theme Export | Description |
51
- |--------|-------------|-------------|
52
- | **Igloo** | `iglooTheme` | Default insurance brand |
53
- | **CIMB** | `cimbTheme` | Banking partner theme |
54
- | **AmmetLife** | `ammetlifeTheme` | Life insurance partner |
55
-
56
- ### Components
57
-
58
- #### General Components
59
- - **Button** - Tenant-themed button component
60
- - **Card** - Card with tenant accent border
61
- - **Banner** - Promotional banner with gradients
62
- - **Header** - Application header with navigation
63
- - **NewHeader** - Enhanced header with tenant branding
64
- - **Footer** - Application footer with links
65
-
66
- #### Interactive Components
67
- - **RecommendationsDrawer** - Mobile drawer for user recommendations
68
- - **ProductSelectionDrawer** - Mobile drawer for product selection
69
- - **QuestionSection** - Interactive question component
70
- - **OptionButton** - Customizable option button
71
- - **ToggleGroup** - Toggle button group
72
-
73
- #### Checkout Components
74
- - **CheckoutProgress** - Progress bar with step indicator
75
- - **ProductCard** - Product information card for checkout
76
- - **CheckoutHeader** - Complete checkout header (progress + product + section)
77
- - **CheckoutFormButton** - Fixed/floating form button
78
- - **HealthQuestionGroup** - Health question with Yes/No options
137
+ | Tenant | Theme Export | Description |
138
+ | ------------- | ---------------- | ----------------------- |
139
+ | **Igloo** | `iglooTheme` | Default insurance brand |
140
+ | **CIMB** | `cimbTheme` | Banking partner theme |
141
+ | **AmmetLife** | `ammetlifeTheme` | Life insurance partner |
142
+
143
+ ### Component Categories
144
+
145
+ | Category | Components |
146
+ | --------------- | ----------------------------------------------------------------------------------------- |
147
+ | **General** | Button, Card, Banner, Header, NewHeader, Footer |
148
+ | **Interactive** | RecommendationsDrawer, ProductSelectionDrawer, QuestionSection, OptionButton, ToggleGroup |
149
+ | **Checkout** | CheckoutProgress, ProductCard, CheckoutHeader, CheckoutFormButton, HealthQuestionGroup |
150
+ | **Forms** | PersonalInformationForm, ContactDetailsForm, HealthInformationForm |
79
151
 
80
152
  ### Hooks
81
153
 
82
154
  - `useTenantTheme()` - Access tenant theme and ID
83
155
  - `useTenantId()` - Get current tenant ID
84
156
  - `useIsTenant()` - Check tenant match
157
+ - `useTenantLogo()` - Get tenant logo
158
+ - `useTenantAsset()` - Get tenant-specific asset
85
159
 
86
160
  ### Utilities
87
161
 
@@ -90,6 +164,27 @@ The D2C Component Library provides reusable, tenant-aware UI components with **c
90
164
  - `getThemeColor()` - Extract colors from theme
91
165
  - `createThemeCSSVariables()` - Generate CSS variables
92
166
 
167
+ ### Key Benefits
168
+
169
+ #### For Development Teams
170
+
171
+ | Benefit | Impact |
172
+ | -------------------------- | -------------------------------------------------------- |
173
+ | **Single Source of Truth** | Update themes once, reflected everywhere |
174
+ | **~585 Lines Removed** | From consuming apps (no more duplicated themes) |
175
+ | **Type Safety** | Full TypeScript support with interfaces |
176
+ | **Faster Development** | Reuse tested components instead of building from scratch |
177
+ | **Better DX** | Hot reload, Storybook for component development |
178
+
179
+ #### For Business
180
+
181
+ | Benefit | Impact |
182
+ | ----------------------------- | -------------------------------------------- |
183
+ | **Faster Partner Onboarding** | Days instead of weeks to launch a new tenant |
184
+ | **Consistent UX** | Same quality experience across all brands |
185
+ | **Reduced Costs** | One team maintains one codebase |
186
+ | **Scalability** | Easy to add new tenants and features |
187
+
93
188
  ---
94
189
 
95
190
  ## 📦 Installation
@@ -119,6 +214,7 @@ yarn install
119
214
  ```
120
215
 
121
216
  **Workflow:**
217
+
122
218
  ```bash
123
219
  # Make changes to library
124
220
  cd d2c-component-library
@@ -135,6 +231,7 @@ yarn install # Copies updated build
135
231
  For production deployments and CI/CD.
136
232
 
137
233
  **Install:**
234
+
138
235
  ```bash
139
236
  yarn add igloo-d2c-components
140
237
  # or
@@ -142,6 +239,7 @@ npm install igloo-d2c-components
142
239
  ```
143
240
 
144
241
  **Configure authentication (if using private registry):**
242
+
145
243
  ```bash
146
244
  # For npm
147
245
  export NPM_AUTH_TOKEN="your-npm-token"
@@ -150,6 +248,28 @@ export NPM_AUTH_TOKEN="your-npm-token"
150
248
  export GITLAB_NPM_TOKEN="glpat-your-token"
151
249
  ```
152
250
 
251
+ ### Component Library Management Scripts (in b2c-web-demo)
252
+
253
+ ```bash
254
+ # Check installed version
255
+ yarn lib:check
256
+
257
+ # Get package information
258
+ yarn lib:info
259
+
260
+ # Upgrade to latest version (from registry)
261
+ yarn lib:upgrade
262
+
263
+ # Install local development version
264
+ yarn lib:install-local
265
+
266
+ # Install registry version
267
+ yarn lib:install-registry
268
+
269
+ # Verify registry configuration
270
+ yarn lib:verify-registry
271
+ ```
272
+
153
273
  ---
154
274
 
155
275
  ## 🚀 Quick Start
@@ -227,6 +347,7 @@ function MyPage() {
227
347
  ### Why Centralized Themes?
228
348
 
229
349
  **Before** (❌ Old Way):
350
+
230
351
  ```typescript
231
352
  // In each consuming app - duplicated code
232
353
  const iglooTheme = {
@@ -238,6 +359,7 @@ const iglooTheme = {
238
359
  ```
239
360
 
240
361
  **After** (✅ New Way):
362
+
241
363
  ```typescript
242
364
  // Import from library - single source of truth
243
365
  import { iglooTheme } from 'igloo-d2c-components'
@@ -290,13 +412,18 @@ interface TenantThemeConfig {
290
412
  fontFamily: string
291
413
  }
292
414
  logo: string
415
+ logoDark?: string
416
+ logoAlt?: string
417
+ logoWhite?: string
293
418
  favicon: string
419
+ assetBaseUrl?: string
294
420
  }
295
421
  ```
296
422
 
297
423
  ### Using Themes
298
424
 
299
425
  **In Tenant Configuration:**
426
+
300
427
  ```typescript
301
428
  // config/tenants/igloo.ts
302
429
  import { iglooTheme } from 'igloo-d2c-components'
@@ -308,19 +435,8 @@ const iglooConfig: TenantConfig = {
308
435
  }
309
436
  ```
310
437
 
311
- **Dynamic Loading:**
312
- ```typescript
313
- import { getTenantTheme, isValidTenantId } from 'igloo-d2c-components'
314
-
315
- function loadTheme(tenantId: string) {
316
- if (isValidTenantId(tenantId)) {
317
- return getTenantTheme(tenantId)
318
- }
319
- throw new Error(`Invalid tenant: ${tenantId}`)
320
- }
321
- ```
322
-
323
438
  **In Components:**
439
+
324
440
  ```typescript
325
441
  import { useTenantTheme } from 'igloo-d2c-components'
326
442
 
@@ -338,19 +454,13 @@ function MyComponent() {
338
454
  }
339
455
  ```
340
456
 
341
- ### Theme Benefits
342
-
343
- - ✅ **Single source of truth** - Update in one place
344
- - ✅ **Type-safe** - Full TypeScript support
345
- - ✅ **Consistent** - Same themes across all apps
346
- - ✅ **Maintainable** - Easy to update and extend
347
- - ✅ **Scalable** - Add new tenants easily
348
-
349
457
  ---
350
458
 
351
459
  ## 📚 Components
352
460
 
353
- ### Button
461
+ ### General Components
462
+
463
+ #### Button
354
464
 
355
465
  Tenant-aware button component based on MUI Button.
356
466
 
@@ -369,11 +479,12 @@ import { Button } from 'igloo-d2c-components'
369
479
  ```
370
480
 
371
481
  **Props:**
482
+
372
483
  - `tenantColored?: boolean` - Use tenant primary color
373
484
  - `variant?: 'text' | 'outlined' | 'contained'` - Button variant
374
485
  - All MUI ButtonProps
375
486
 
376
- ### Card
487
+ #### Card
377
488
 
378
489
  Tenant-aware card component based on MUI Card.
379
490
 
@@ -389,14 +500,14 @@ import { Card } from 'igloo-d2c-components'
389
500
  ```
390
501
 
391
502
  **Props:**
503
+
392
504
  - `title?: React.ReactNode` - Card title
393
505
  - `content?: React.ReactNode` - Card content
394
506
  - `actions?: React.ReactNode` - Card actions
395
507
  - `tenantAccent?: boolean` - Add tenant-colored top border
396
- - `headerAction?: React.ReactNode` - Action in header
397
508
  - All MUI CardProps
398
509
 
399
- ### Banner
510
+ #### Banner
400
511
 
401
512
  Promotional banner with tenant theming.
402
513
 
@@ -411,12 +522,402 @@ import { Banner } from 'igloo-d2c-components'
411
522
  />
412
523
  ```
413
524
 
525
+ #### NewHeader
526
+
527
+ Simplified header component with mobile drawer navigation.
528
+
529
+ ```tsx
530
+ import { NewHeader } from 'igloo-d2c-components'
531
+
532
+ <NewHeader
533
+ logo="/path/to/logo.svg"
534
+ navigationLinks={[
535
+ {
536
+ key: 'car',
537
+ label: 'Car Insurance',
538
+ onClick: () => navigate('/car')
539
+ }
540
+ ]}
541
+ additionalMenuSections={[
542
+ {
543
+ title: 'Account',
544
+ items: [
545
+ { key: 'login', label: 'Log in', onClick: handleLogin }
546
+ ]
547
+ }
548
+ ]}
549
+ onLogoClick={() => navigate('/')}
550
+ />
551
+ ```
552
+
414
553
  **Props:**
415
- - `title: string` - Banner title (required)
416
- - `description?: string` - Banner description
417
- - `action?: React.ReactNode` - Action button/element
418
- - `gradient?: boolean` - Use gradient background (default: true)
419
- - All MUI BoxProps
554
+
555
+ ```typescript
556
+ interface NewHeaderProps {
557
+ logo: string // Logo image source
558
+ navigationLinks?: NewHeaderNavigationLink[]
559
+ additionalMenuSections?: {
560
+ title?: string
561
+ items: NewHeaderNavigationLink[]
562
+ }[]
563
+ isMobile?: boolean
564
+ onLogoClick?: () => void
565
+ onMenuOpen?: () => void
566
+ onMenuClose?: () => void
567
+ customDrawerContent?: React.ReactNode
568
+ formatMessage?: (descriptor: { id: string }) => string
569
+ }
570
+ ```
571
+
572
+ ### Interactive Components
573
+
574
+ #### RecommendationsDrawer
575
+
576
+ Mobile drawer for collecting user preferences and showing personalized recommendations.
577
+
578
+ ```tsx
579
+ import {
580
+ RecommendationsDrawer,
581
+ QuestionSection,
582
+ OptionButton,
583
+ ToggleGroup
584
+ } from 'igloo-d2c-components'
585
+
586
+ function MyComponent() {
587
+ const [open, setOpen] = React.useState(false)
588
+ const [selectedOption, setSelectedOption] = React.useState('')
589
+
590
+ const options = [
591
+ { value: 'option1', label: 'Option 1', icon: '🎯' },
592
+ { value: 'option2', label: 'Option 2', icon: '✨' },
593
+ ]
594
+
595
+ return (
596
+ <>
597
+ <Button onClick={() => setOpen(true)}>
598
+ See my recommendations
599
+ </Button>
600
+
601
+ <RecommendationsDrawer
602
+ open={open}
603
+ onClose={() => setOpen(false)}
604
+ title="Personalize Your Plan"
605
+ subtitle="Answer a few questions"
606
+ primaryButtonText="Next"
607
+ onPrimaryAction={handleSubmit}
608
+ >
609
+ <QuestionSection
610
+ question="What's your preference?"
611
+ options={options}
612
+ selectedValue={selectedOption}
613
+ onSelect={setSelectedOption}
614
+ renderOption={(option, isSelected) => (
615
+ <OptionButton
616
+ key={option.value}
617
+ value={option.value}
618
+ label={option.label}
619
+ icon={option.icon}
620
+ selected={isSelected}
621
+ onClick={setSelectedOption}
622
+ />
623
+ )}
624
+ />
625
+ </RecommendationsDrawer>
626
+ </>
627
+ )
628
+ }
629
+ ```
630
+
631
+ **RecommendationsDrawer Props:**
632
+
633
+ ```typescript
634
+ interface RecommendationsDrawerProps {
635
+ open: boolean
636
+ onClose: () => void
637
+ children: React.ReactNode
638
+ headerIcon?: string
639
+ title?: string
640
+ subtitle?: string
641
+ showBackButton?: boolean
642
+ onBack?: () => void
643
+ primaryButtonText?: string
644
+ onPrimaryAction?: () => void
645
+ primaryButtonDisabled?: boolean
646
+ secondaryButtonText?: string
647
+ onSecondaryAction?: () => void
648
+ showFooter?: boolean
649
+ customFooter?: React.ReactNode
650
+ formatMessage?: (descriptor: { id: string }) => string
651
+ }
652
+ ```
653
+
654
+ #### ProductSelectionDrawer
655
+
656
+ Mobile-first bottom drawer for displaying insurance products in a grid.
657
+
658
+ ```tsx
659
+ import { ProductSelectionDrawer, Product } from 'igloo-d2c-components'
660
+
661
+ const products: Product[] = [
662
+ {
663
+ id: 'life-byond',
664
+ name: 'LIFE BYOND',
665
+ type: 'Term Plan',
666
+ logo: '/path/to/logo.png',
667
+ },
668
+ {
669
+ id: 'health-cvr',
670
+ name: 'HEALTH CVR',
671
+ type: 'CI Plan',
672
+ logo: '/path/to/logo.png',
673
+ },
674
+ ]
675
+
676
+ <ProductSelectionDrawer
677
+ open={open}
678
+ onClose={() => setOpen(false)}
679
+ products={products}
680
+ onProductSelect={(productId) => {
681
+ console.log('Selected:', productId)
682
+ setOpen(false)
683
+ }}
684
+ title="Select your product"
685
+ subtitle="Pick the product that suits your protection goals"
686
+ viewPlansButtonText="View plans"
687
+ />
688
+ ```
689
+
690
+ #### ToggleGroup
691
+
692
+ Segmented control for binary/multiple choice toggles.
693
+
694
+ ```tsx
695
+ import { ToggleGroup } from 'igloo-d2c-components'
696
+
697
+ <ToggleGroup
698
+ options={[
699
+ { value: 'domestic', label: 'Domestic', icon: '/icon1.svg' },
700
+ { value: 'international', label: 'International', icon: '/icon2.svg' }
701
+ ]}
702
+ value={travelType}
703
+ onChange={setTravelType}
704
+ />
705
+ ```
706
+
707
+ ### Checkout Components
708
+
709
+ #### CheckoutProgress
710
+
711
+ Progress bar with step indicator for multi-step checkout flows.
712
+
713
+ ```tsx
714
+ import { CheckoutProgress } from 'igloo-d2c-components'
715
+
716
+ <CheckoutProgress
717
+ currentStep={0}
718
+ totalSteps={3}
719
+ onBack={() => handleBack()}
720
+ showBackButton={true}
721
+ />
722
+ ```
723
+
724
+ **Props:**
725
+
726
+ | Prop | Type | Default | Description |
727
+ | ---------------- | ------------ | -------- | ------------------------------------ |
728
+ | `currentStep` | `number` | Required | Current step (0-indexed) |
729
+ | `totalSteps` | `number` | Required | Total number of steps |
730
+ | `onBack` | `() => void` | - | Callback when back button is clicked |
731
+ | `showBackButton` | `boolean` | `true` | Whether to show the back button |
732
+
733
+ #### ProductCard
734
+
735
+ Product information card for checkout flows.
736
+
737
+ ```tsx
738
+ import { ProductCard } from 'igloo-d2c-components'
739
+
740
+ <ProductCard
741
+ productName="LIFE BYOND"
742
+ planName="Plan A"
743
+ price="25"
744
+ currency="RM"
745
+ period="/month"
746
+ logoUrl="path/to/logo.png"
747
+ showIndicator={true}
748
+ />
749
+ ```
750
+
751
+ #### CheckoutHeader
752
+
753
+ Complete header component combining progress, product card, and section information.
754
+
755
+ ```tsx
756
+ import { CheckoutHeader } from 'igloo-d2c-components'
757
+
758
+ <CheckoutHeader
759
+ progress={{
760
+ currentStep: 0,
761
+ totalSteps: 3,
762
+ onBack: () => handleBack(),
763
+ }}
764
+ product={{
765
+ productName: 'LIFE BYOND',
766
+ planName: 'Plan A',
767
+ price: '25',
768
+ currency: 'RM',
769
+ period: '/month',
770
+ }}
771
+ sectionTitle="Personal information"
772
+ sectionDescription="Let's get to know you better..."
773
+ sticky={true}
774
+ />
775
+ ```
776
+
777
+ #### CheckoutFormButton
778
+
779
+ Fixed or floating button for form submission.
780
+
781
+ ```tsx
782
+ import { CheckoutFormButton } from 'igloo-d2c-components'
783
+
784
+ <CheckoutFormButton
785
+ text="Next"
786
+ disabled={!isValid}
787
+ onClick={handleSubmit}
788
+ fixed={true}
789
+ type="button"
790
+ loading={isSubmitting}
791
+ />
792
+ ```
793
+
794
+ **Tenant Theme Support:** The button automatically uses tenant-specific colors:
795
+
796
+ - **AmmetLife**: Blue (#317ABC)
797
+ - **CIMB**: Red (#D71920)
798
+ - **Igloo**: Black (#13131B)
799
+
800
+ #### HealthQuestionGroup
801
+
802
+ Health questions with Yes/No button options.
803
+
804
+ ```tsx
805
+ import { HealthQuestionGroup } from 'igloo-d2c-components'
806
+
807
+ <HealthQuestionGroup
808
+ question="Have you ever had any ongoing or past health conditions?"
809
+ questionNumber={1}
810
+ value={healthConditions}
811
+ onChange={(value) => setHealthConditions(value)}
812
+ error={errors.healthConditions}
813
+ labels={{ yes: 'Yes', no: 'No' }}
814
+ />
815
+ ```
816
+
817
+ ### Form Components
818
+
819
+ The library includes three reusable checkout form components designed to be **form library agnostic**.
820
+
821
+ #### PersonalInformationForm
822
+
823
+ Collects personal details, occupation, and banking information.
824
+
825
+ ```tsx
826
+ import { PersonalInformationForm } from 'igloo-d2c-components'
827
+
828
+ <PersonalInformationForm
829
+ renderField={renderField}
830
+ fields={{
831
+ full_name: {
832
+ name: 'full_name',
833
+ label: 'Full name',
834
+ value: formik.values.full_name,
835
+ error: formik.errors.full_name,
836
+ touched: formik.touched.full_name,
837
+ helperText: 'Full name as per your ID card',
838
+ onChange: formik.handleChange,
839
+ onBlur: formik.handleBlur,
840
+ },
841
+ nric: { /* ... */ },
842
+ date_of_birth: { /* ... */ },
843
+ gender: { /* ... */ },
844
+ // ... other fields
845
+ }}
846
+ consents={{
847
+ bank_account_confirmation: {
848
+ checked: formik.values.bank_account_confirmation,
849
+ onChange: (checked) =>
850
+ formik.setFieldValue('bank_account_confirmation', checked),
851
+ error: formik.errors.bank_account_confirmation,
852
+ },
853
+ marketing_consent: {
854
+ checked: formik.values.marketing_consent,
855
+ onChange: (checked) =>
856
+ formik.setFieldValue('marketing_consent', checked),
857
+ },
858
+ }}
859
+ onSubmit={formik.handleSubmit}
860
+ />
861
+ ```
862
+
863
+ #### ContactDetailsForm
864
+
865
+ Collects contact and address information.
866
+
867
+ ```tsx
868
+ import { ContactDetailsForm } from 'igloo-d2c-components'
869
+
870
+ <ContactDetailsForm
871
+ renderField={renderField}
872
+ fields={{
873
+ phone_number: { /* ... */ },
874
+ email_address: { /* ... */ },
875
+ residential_address: { /* ... */ },
876
+ postal_code: { /* ... */ },
877
+ city: { /* ... */ },
878
+ state: { /* ... */ },
879
+ }}
880
+ mailingAddressSame={{
881
+ checked: formik.values.mailing_same_as_residential,
882
+ onChange: (checked) =>
883
+ formik.setFieldValue('mailing_same_as_residential', checked),
884
+ }}
885
+ onSubmit={formik.handleSubmit}
886
+ />
887
+ ```
888
+
889
+ #### HealthInformationForm
890
+
891
+ Collects health measurements and questions with gender-specific support.
892
+
893
+ ```tsx
894
+ import { HealthInformationForm } from 'igloo-d2c-components'
895
+
896
+ <HealthInformationForm
897
+ renderField={renderField}
898
+ measurementFields={{
899
+ weight: {
900
+ name: 'weight',
901
+ label: 'Weight (kg)',
902
+ type: 'number',
903
+ value: formik.values.weight,
904
+ inputProps: { min: 20, max: 300 },
905
+ onChange: formik.handleChange,
906
+ },
907
+ height: { /* ... */ },
908
+ }}
909
+ healthQuestions={[
910
+ {
911
+ question: 'Have you ever had any ongoing or past health conditions?',
912
+ questionNumber: 1,
913
+ name: 'health_conditions',
914
+ value: formik.values.health_conditions,
915
+ onChange: (value) => formik.setFieldValue('health_conditions', value),
916
+ },
917
+ ]}
918
+ onSubmit={formik.handleSubmit}
919
+ />
920
+ ```
420
921
 
421
922
  ---
422
923
 
@@ -470,6 +971,20 @@ function MyComponent() {
470
971
  }
471
972
  ```
472
973
 
974
+ #### useTenantLogo()
975
+
976
+ Get tenant logo URL.
977
+
978
+ ```tsx
979
+ import { useTenantLogo } from 'igloo-d2c-components'
980
+
981
+ function MyComponent() {
982
+ const logo = useTenantLogo() // Default logo
983
+ const darkLogo = useTenantLogo('dark') // Dark variant
984
+ return <img src={logo} alt="Logo" />
985
+ }
986
+ ```
987
+
473
988
  ### Utility Functions
474
989
 
475
990
  #### getTenantTheme()
@@ -483,8 +998,6 @@ const theme = getTenantTheme('igloo')
483
998
  console.log(theme.palette.primary.main) // '#5656F6'
484
999
  ```
485
1000
 
486
- **Throws:** Error if tenant ID is invalid
487
-
488
1001
  #### isValidTenantId()
489
1002
 
490
1003
  Type guard to check if a string is a valid tenant ID.
@@ -519,15 +1032,348 @@ const color = getThemeColor(theme, 'primary.main', '#000')
519
1032
  // Returns theme.palette.primary.main or '#000' if not found
520
1033
  ```
521
1034
 
522
- #### createThemeCSSVariables()
1035
+ ---
523
1036
 
524
- Create CSS variables from theme.
1037
+ ## 📦 Asset Management
1038
+
1039
+ ### Asset Organization
1040
+
1041
+ ```
1042
+ d2c-component-library/src/assets/
1043
+ ├── icons/ # Common UI icons
1044
+ │ ├── alert.svg
1045
+ │ ├── arrow-down.svg
1046
+ │ ├── close.svg
1047
+ │ ├── facebook.svg
1048
+ │ ├── instagram.svg
1049
+ │ ├── youtube.svg
1050
+ │ └── index.ts # Icon path utilities
1051
+ ├── tenants/ # Tenant-specific assets
1052
+ │ ├── igloo/logo.svg
1053
+ │ ├── cimb/logo.svg
1054
+ │ └── ammetlife/logo.svg
1055
+ └── index.ts # Main asset exports
1056
+ ```
1057
+
1058
+ ### Asset Flow Architecture
1059
+
1060
+ ```
1061
+ ┌─────────────────────────────────────────────────────┐
1062
+ │ ASSET MANAGEMENT ARCHITECTURE │
1063
+ ├─────────────────────────────────────────────────────┤
1064
+ │ │
1065
+ │ d2c-component-library/ │
1066
+ │ └── src/assets/ │
1067
+ │ ├── icons/ → Common UI icons │
1068
+ │ └── tenants/ → Tenant logos │
1069
+ │ ├── igloo/logo.svg │
1070
+ │ ├── cimb/logo.svg │
1071
+ │ └── ammetlife/logo.svg │
1072
+ │ │
1073
+ │ BUILD ⬇️ │
1074
+ │ dist/assets/ → Published with library │
1075
+ │ │
1076
+ │ INSTALL ⬇️ │
1077
+ │ node_modules/igloo-d2c-components/dist/assets/ │
1078
+ │ │
1079
+ │ COPY (yarn copy-assets) ⬇️ │
1080
+ │ public/assets/ → Served by UMI │
1081
+ │ │
1082
+ └─────────────────────────────────────────────────────┘
1083
+ ```
1084
+
1085
+ ### Using Assets
525
1086
 
526
- ```tsx
527
- import { createThemeCSSVariables } from 'igloo-d2c-components'
1087
+ ```typescript
1088
+ // Get Tenant Logo
1089
+ import { useTenantLogo } from 'igloo-d2c-components'
528
1090
 
529
- const vars = createThemeCSSVariables(theme, '--my-app')
530
- // { '--my-app-primary-main': '#5656F6', ... }
1091
+ function MyComponent() {
1092
+ const logo = useTenantLogo() // Default logo
1093
+ const darkLogo = useTenantLogo('dark') // Dark variant
1094
+ return <img src={logo} alt="Logo" />
1095
+ }
1096
+
1097
+ // Get Icon Paths
1098
+ import { ICON_PATHS, getIconPath } from 'igloo-d2c-components'
1099
+ <img src={ICON_PATHS.facebook} alt="Facebook" />
1100
+ <img src={getIconPath('instagram')} alt="Instagram" />
1101
+ ```
1102
+
1103
+ ### Asset Distribution Strategy
1104
+
1105
+ | Asset Type | Location | Reason |
1106
+ | --------------------- | ------------------- | --------------------------- |
1107
+ | **Generic UI Icons** | Library | Reusable across projects |
1108
+ | **Tenant Logos** | Library (via theme) | Centralized management |
1109
+ | **Insurer Logos** | CDN | Shared, updated by partners |
1110
+ | **Marketing Banners** | Application | Frequent changes |
1111
+ | **Documents (PDFs)** | CDN | Large, rarely change |
1112
+
1113
+ ### Logo Rendering in Applications
1114
+
1115
+ **Important**: Assets need to be copied to the `public/` folder for UMI to serve them:
1116
+
1117
+ ```bash
1118
+ # In consuming application
1119
+ yarn copy-assets # Copies library assets to public/assets/
1120
+ ```
1121
+
1122
+ The theme paths reference `/assets/tenants/{tenant}/logo.svg` which maps to:
1123
+
1124
+ - Theme config: `logo: '/assets/tenants/igloo/logo.svg'`
1125
+ - File location: `public/assets/tenants/igloo/logo.svg`
1126
+ - Browser URL: `http://localhost:8001/assets/tenants/igloo/logo.svg`
1127
+
1128
+ ---
1129
+
1130
+ ## 🔌 Integration Guide
1131
+
1132
+ ### Multi-Tenant Architecture
1133
+
1134
+ #### Tenant Configuration Structure
1135
+
1136
+ ```
1137
+ config/tenants/
1138
+ ├── index.ts # Tenant registry and utility functions
1139
+ ├── types.ts # TypeScript interfaces
1140
+ ├── igloo.ts # Igloo tenant configuration
1141
+ ├── ammetlife.ts # AmmetLife tenant configuration
1142
+ └── cimb.ts # CIMB tenant configuration
1143
+ ```
1144
+
1145
+ #### Tenant Configuration Example
1146
+
1147
+ ```typescript
1148
+ // config/tenants/igloo.ts
1149
+ import { iglooTheme } from 'igloo-d2c-components'
1150
+ import { TenantConfig } from './types'
1151
+
1152
+ const iglooConfig: TenantConfig = {
1153
+ id: 'igloo',
1154
+ name: 'igloo',
1155
+ displayName: 'Igloo',
1156
+ domain: 'igloo.co.id',
1157
+
1158
+ theme: iglooTheme, // ← Centralized theme from component library
1159
+
1160
+ features: {
1161
+ showPAMenu: true,
1162
+ enableAIChatbot: true,
1163
+ showWorkshopEntryPoint: false,
1164
+ enableFreeAddons: false,
1165
+ },
1166
+
1167
+ routes: {
1168
+ enabled: ['car', 'motorbike', 'health', 'life', 'travel', 'pet'],
1169
+ disabled: [],
1170
+ },
1171
+
1172
+ branding: {
1173
+ companyName: 'Igloo',
1174
+ supportEmail: 'hello@iglooinsure.com',
1175
+ supportPhone: '+62 21 5022 0888',
1176
+ },
1177
+
1178
+ integrations: {
1179
+ gtmCode: 'GTM-5RHHNVQ',
1180
+ gaCode: 'G-QQV6F41YPJ',
1181
+ },
1182
+ }
1183
+
1184
+ export default iglooConfig
1185
+ ```
1186
+
1187
+ #### AmmetLife Custom Homepage
1188
+
1189
+ AmMetLife uses a custom homepage that displays the life insurance landing page:
1190
+
1191
+ ```typescript
1192
+ // config/tenants/ammetlife.ts
1193
+ customRoutes: [
1194
+ {
1195
+ path: '/',
1196
+ exact: true,
1197
+ component: '@/pages/life-landing-page/index.tsx',
1198
+ },
1199
+ ]
1200
+ ```
1201
+
1202
+ ### Checkout Flow Integration
1203
+
1204
+ #### Complete 3-Step Checkout
1205
+
1206
+ The library provides components for a complete checkout flow:
1207
+
1208
+ 1. **Personal Information** - 11 fields + 2 consent checkboxes
1209
+ 2. **Contact Details** - 6 address fields + mailing checkbox
1210
+ 3. **Health Information** - 2 measurements + health questions (gender-specific)
1211
+
1212
+ #### Session Storage Requirements
1213
+
1214
+ ```typescript
1215
+ // Required before navigating to checkout
1216
+ session.setItem('plan', {
1217
+ name: 'Plan A',
1218
+ premiumInfo: { currency: 'RM', monthlyAmount: '25' }
1219
+ });
1220
+
1221
+ session.setItem('product', {
1222
+ name: 'LIFE BYOND',
1223
+ logoUrl: 'url-to-logo'
1224
+ });
1225
+ ```
1226
+
1227
+ #### Navigation Flow
1228
+
1229
+ ```
1230
+ PDP (/en/ammetlife-pdp)
1231
+ ↓ Click "Buy now"
1232
+ Checkout Step 1/3 (Personal Info) ← Back → PDP
1233
+ ↓ Click "Next"
1234
+ Checkout Step 2/3 (Contact Details) ← Back → Step 1
1235
+ ↓ Click "Next"
1236
+ Checkout Step 3/3 (Health Information) ← Back → Step 2
1237
+ ↓ Click "Submit"
1238
+ Payment (/en/payment-options)
1239
+ ```
1240
+
1241
+ #### Back Button Logic
1242
+
1243
+ ```typescript
1244
+ const handleBack = () => {
1245
+ if (currentStep === 0) {
1246
+ // On first step, redirect to PDP
1247
+ window.location.href = `/${currentLocale}/ammetlife-pdp`;
1248
+ } else {
1249
+ // On other steps, go to previous step
1250
+ setCurrentStep(currentStep - 1);
1251
+ window.scrollTo({ top: 0, behavior: 'smooth' });
1252
+ }
1253
+ };
1254
+ ```
1255
+
1256
+ #### Validation Rules
1257
+
1258
+ **Personal Information:**
1259
+
1260
+ - Full name: minimum 2 characters
1261
+ - NRIC: numbers and dashes only
1262
+ - DOB: 30 days to 80 years old
1263
+ - Bank account: numbers only
1264
+ - Bank confirmation: must be checked
1265
+
1266
+ **Contact Details:**
1267
+
1268
+ - Phone: 9-14 digits
1269
+ - Email: valid format
1270
+ - Address: minimum 10 characters
1271
+ - Postal code: exactly 5 digits
1272
+
1273
+ **Health Information:**
1274
+
1275
+ - Weight: 20-300 kg
1276
+ - Height: 50-250 cm
1277
+ - All questions: must select Yes or No
1278
+
1279
+ ### Recommendations Feature
1280
+
1281
+ #### User Flow
1282
+
1283
+ ```
1284
+ 1. User sees "See my recommendations" button
1285
+ ↓ User clicks
1286
+ 2. Mobile drawer slides up from bottom (95vh height)
1287
+
1288
+ 3. Drawer shows:
1289
+ - Toggle: Domestic/International
1290
+ - 5 Questions with selectable options
1291
+ - Next button
1292
+ ↓ User answers questions
1293
+ 4. User clicks "Next" button
1294
+
1295
+ 5. Data collected, drawer closes, recommendations shown
1296
+ ```
1297
+
1298
+ #### Implementation
1299
+
1300
+ ```typescript
1301
+ import { TravelRecommendations } from '@/components/recommendations';
1302
+ import { RecommendationsButton } from '@/components/recommendations/recommendations-button';
1303
+
1304
+ export default function MyPage() {
1305
+ const [showRecommendations, setShowRecommendations] = React.useState(false);
1306
+
1307
+ return (
1308
+ <div>
1309
+ <RecommendationsButton
1310
+ onClick={() => setShowRecommendations(true)}
1311
+ />
1312
+
1313
+ <TravelRecommendations
1314
+ open={showRecommendations}
1315
+ onClose={() => setShowRecommendations(false)}
1316
+ onSubmit={(data) => {
1317
+ console.log('User selected:', data);
1318
+ }}
1319
+ />
1320
+ </div>
1321
+ );
1322
+ }
1323
+ ```
1324
+
1325
+ #### Data Structure
1326
+
1327
+ ```typescript
1328
+ interface TravelRecommendationsData {
1329
+ travelType: 'domestic' | 'international';
1330
+ selectedPlan: string;
1331
+ monthlyIncome: string;
1332
+ monthlyExpenses: string;
1333
+ currentCoverage: string;
1334
+ employerCoverage: string;
1335
+ }
1336
+ ```
1337
+
1338
+ ### Header Integration
1339
+
1340
+ #### NewHeader Implementation
1341
+
1342
+ The NewHeader component provides a simplified header with mobile drawer navigation.
1343
+
1344
+ **Features:**
1345
+
1346
+ 1. **Product Navigation** - Dynamically loaded from navLinks
1347
+ 2. **User Authentication** - Login/Logout flow
1348
+ 3. **Additional Links** - Partnership, About Us, Blog
1349
+ 4. **Language Selector** - EN/ID with cookie persistence
1350
+ 5. **Analytics** - Google Analytics integration
1351
+
1352
+ **Performance Improvement:**
1353
+
1354
+ | Metric | Before | After |
1355
+ | -------------- | --------- | --------- |
1356
+ | Component size | 860 lines | 200 lines |
1357
+ | Bundle size | ~45KB | ~15KB |
1358
+ | Props count | 30+ | 9 |
1359
+
1360
+ ### Routing Guide
1361
+
1362
+ #### Route Pattern
1363
+
1364
+ ```
1365
+ /:locale/life-checkout
1366
+ ```
1367
+
1368
+ #### Navigation with Locale
1369
+
1370
+ ```typescript
1371
+ // ✅ CORRECT - With locale
1372
+ const { currentLocale } = local.getItem('globalState');
1373
+ window.location.href = `/${currentLocale}/life-checkout`;
1374
+
1375
+ // ❌ WRONG - Without locale
1376
+ window.location.href = '/life-checkout';
531
1377
  ```
532
1378
 
533
1379
  ---
@@ -540,6 +1386,7 @@ const vars = createThemeCSSVariables(theme, '--my-app')
540
1386
  - **Yarn**: `^1.22.0` (recommended) or npm
541
1387
 
542
1388
  Check your version:
1389
+
543
1390
  ```bash
544
1391
  node --version # Should be 16.20.0 - 18.x
545
1392
  yarn --version # Should be 1.22.x
@@ -594,22 +1441,11 @@ dist/
594
1441
  ├── esm/
595
1442
  │ ├── index.js # ES Module bundle (unminified, ES2015)
596
1443
  │ └── index.js.map # Source map
597
- └── types/
598
- └── index.d.ts # TypeScript definitions
1444
+ ├── types/
1445
+ └── index.d.ts # TypeScript definitions
1446
+ └── assets/ # Copied assets
599
1447
  ```
600
1448
 
601
- **Why unminified?**
602
- - ✅ Consuming apps handle minification
603
- - ✅ Better debugging experience
604
- - ✅ Better tree-shaking
605
- - ✅ No impact on final bundle size
606
-
607
- **Why ES2015?**
608
- - ✅ Maximum compatibility with older webpack configs
609
- - ✅ No babel-loader required in consuming apps
610
- - ✅ Optional chaining (`?.`) transpiled to verbose checks
611
- - ✅ Works with webpack 4+
612
-
613
1449
  ### Project Structure
614
1450
 
615
1451
  ```
@@ -618,7 +1454,13 @@ d2c-component-library/
618
1454
  │ ├── components/ # Component implementations
619
1455
  │ │ ├── Button/
620
1456
  │ │ ├── Card/
621
- │ │ └── Banner/
1457
+ │ │ ├── Banner/
1458
+ │ │ ├── NewHeader/
1459
+ │ │ ├── RecommendationsDrawer/
1460
+ │ │ ├── ProductSelectionDrawer/
1461
+ │ │ ├── CheckoutHeader/
1462
+ │ │ ├── PersonalInformationForm/
1463
+ │ │ └── ...
622
1464
  │ ├── context/
623
1465
  │ │ └── TenantThemeContext.tsx
624
1466
  │ ├── themes/
@@ -626,7 +1468,9 @@ d2c-component-library/
626
1468
  │ ├── types/
627
1469
  │ │ └── tenant.ts # TypeScript types
628
1470
  │ ├── utils/
629
- │ │ └── theme.ts # Theme utilities
1471
+ │ │ ├── theme.ts # Theme utilities
1472
+ │ │ └── assets.ts # Asset utilities
1473
+ │ ├── assets/ # UI icons and tenant logos
630
1474
  │ └── index.ts # Main exports
631
1475
  ├── dist/ # Build output (generated)
632
1476
  ├── examples/
@@ -635,8 +1479,129 @@ d2c-component-library/
635
1479
  ├── rollup.config.cjs # Rollup build config
636
1480
  ├── tsconfig.json # TypeScript config
637
1481
  ├── package.json
638
- ├── README.md # This file
639
- └── CHANGELOG.md # Version history
1482
+ └── README.md # This file
1483
+ ```
1484
+
1485
+ ---
1486
+
1487
+ ## 📖 Storybook
1488
+
1489
+ The library includes Storybook for component documentation and testing.
1490
+
1491
+ ### Running Storybook
1492
+
1493
+ ```bash
1494
+ # Start Storybook dev server
1495
+ yarn storybook
1496
+ # Opens at http://localhost:6006
1497
+
1498
+ # Build static Storybook
1499
+ yarn build-storybook
1500
+ # Output in storybook-static/
1501
+ ```
1502
+
1503
+ ### Available Stories
1504
+
1505
+ **NewHeader Stories (12 scenarios):**
1506
+
1507
+ 1. Default - Basic header with Igloo branding
1508
+ 2. Authenticated User - Header with logged-in user menu
1509
+ 3. Mobile View - Responsive mobile layout
1510
+ 4. CIMB Tenant - CIMB branding
1511
+ 5. AmMetLife Tenant - AmMetLife branding
1512
+ 6. Minimal Header - Bare-bones implementation
1513
+ 7. Custom Drawer Content - Advanced customization
1514
+ 8. Many Menu Items - Stress test with scrolling
1515
+ 9. Without Logo - Edge case testing
1516
+ 10. With Internationalization - i18n integration
1517
+ 11. All Tenants Comparison - Side-by-side view
1518
+ 12. Responsive Demo - Interactive responsive testing
1519
+
1520
+ **Other Component Stories:**
1521
+
1522
+ - RecommendationsDrawer - Complete questionnaire flow
1523
+ - ProductSelectionDrawer - Product grid selection
1524
+ - CheckoutHeader - Progress and product display
1525
+ - All checkout components
1526
+
1527
+ ### Keyboard Shortcuts
1528
+
1529
+ | Key | Action |
1530
+ | --- | ------------------- |
1531
+ | `F` | Toggle fullscreen |
1532
+ | `S` | Toggle sidebar |
1533
+ | `A` | Toggle addons panel |
1534
+ | `T` | Toggle toolbar |
1535
+ | `D` | Toggle dark mode |
1536
+ | `/` | Search stories |
1537
+
1538
+ ---
1539
+
1540
+ ## 🔧 Build Pipeline
1541
+
1542
+ ### Problems Solved
1543
+
1544
+ 1. **Module parse error**: Webpack couldn't parse igloo-d2c-components ESM format
1545
+ 2. **Source map error**: Terser plugin couldn't process source maps
1546
+
1547
+ ### Solutions Applied
1548
+
1549
+ #### 1. Library: Disabled Source Maps
1550
+
1551
+ ```javascript
1552
+ // rollup.config.cjs
1553
+ output: [
1554
+ {
1555
+ file: packageJson.main,
1556
+ format: 'cjs',
1557
+ sourcemap: false, // ✅ Disabled
1558
+ exports: 'named',
1559
+ banner: '"use client"',
1560
+ },
1561
+ ]
1562
+ ```
1563
+
1564
+ #### 2. Consumer App: Webpack Configuration
1565
+
1566
+ ```typescript
1567
+ // .umirc.ts
1568
+ chainWebpack: (memo, { type, webpack }) => {
1569
+ // Prefer CommonJS over ESM
1570
+ memo.resolve.mainFields.clear().add('main').add('module').add('browser');
1571
+
1572
+ // Include igloo-d2c-components in babel transpilation
1573
+ memo.module
1574
+ .rule('js')
1575
+ .include.add(/node_modules[\\/]igloo-d2c-components/)
1576
+ .end();
1577
+ }
1578
+ ```
1579
+
1580
+ ### CI/CD Pipeline Options
1581
+
1582
+ **Option A: Publish to npm (Recommended)**
1583
+
1584
+ ```bash
1585
+ cd d2c-component-library
1586
+ npm publish --access public
1587
+ ```
1588
+
1589
+ **Option B: Use Git URL**
1590
+
1591
+ ```json
1592
+ {
1593
+ "igloo-d2c-components": "git+https://gitlab.com/axinan/fe/d2c-component-library.git#main"
1594
+ }
1595
+ ```
1596
+
1597
+ **Option C: Multi-Repo CI/CD**
1598
+
1599
+ ```yaml
1600
+ before_script:
1601
+ - cd ..
1602
+ - git clone https://gitlab.com/axinan/fe/d2c-component-library.git
1603
+ - cd d2c-component-library && yarn install && yarn build
1604
+ - cd ../b2c-web-demo && yarn install
640
1605
  ```
641
1606
 
642
1607
  ---
@@ -646,21 +1611,21 @@ d2c-component-library/
646
1611
  ### Prerequisites
647
1612
 
648
1613
  1. **Ensure clean working directory:**
1614
+
649
1615
  ```bash
650
1616
  git status # Should be clean
651
1617
  ```
652
1618
 
653
1619
  2. **Update version in package.json:**
1620
+
654
1621
  ```json
655
1622
  {
656
1623
  "version": "1.0.7"
657
1624
  }
658
1625
  ```
659
1626
 
660
- 3. **Update CHANGELOG.md:**
661
- Document changes in the new version section
1627
+ 3. **Build the library:**
662
1628
 
663
- 4. **Build the library:**
664
1629
  ```bash
665
1630
  yarn build
666
1631
  ```
@@ -668,15 +1633,13 @@ d2c-component-library/
668
1633
  ### Publishing to NPM
669
1634
 
670
1635
  **Set up NPM token:**
1636
+
671
1637
  ```bash
672
- # Get token from https://www.npmjs.com/settings/YOUR_USERNAME/tokens
673
1638
  export NPM_AUTH_TOKEN="npm_your_actual_token"
674
-
675
- # Or add to ~/.npmrc globally
676
- //registry.npmjs.org/:_authToken=npm_your_token
677
1639
  ```
678
1640
 
679
1641
  **Publish:**
1642
+
680
1643
  ```bash
681
1644
  # Automated script with safety checks
682
1645
  ./publish-to-npm.sh
@@ -686,137 +1649,22 @@ yarn build
686
1649
  npm publish --access public
687
1650
  ```
688
1651
 
689
- ### Publishing to GitLab Package Registry
690
-
691
- **Set up GitLab token:**
692
- ```bash
693
- # Get token from https://gitlab.com/-/profile/personal_access_tokens
694
- # Scopes: api, read_registry, write_registry
695
- export GITLAB_NPM_TOKEN="glpat-your-token"
696
- ```
697
-
698
- **Configure `.npmrc` for GitLab:**
699
- ```ini
700
- @igloo:registry=https://gitlab.com/api/v4/projects/YOUR_PROJECT_ID/packages/npm/
701
- //gitlab.com/api/v4/projects/YOUR_PROJECT_ID/packages/npm/:_authToken=${GITLAB_NPM_TOKEN}
702
- ```
703
-
704
- **Publish:**
705
- ```bash
706
- yarn build
707
- npm publish
708
- ```
709
-
710
- ### CI/CD Publishing
711
-
712
- The library includes a GitLab CI/CD configuration (`.gitlab-ci.yml`) that automatically:
713
-
714
- 1. **Runs on main branch** or tags
715
- 2. **Lints and type-checks** code
716
- 3. **Builds** the library
717
- 4. **Publishes** to registry (if tag)
718
-
719
- **Trigger CI/CD publish:**
720
- ```bash
721
- # Create and push a tag
722
- git tag v1.0.7
723
- git push origin v1.0.7
724
- ```
725
-
726
1652
  ### Version Management
727
1653
 
728
1654
  **Semantic Versioning:**
1655
+
729
1656
  - **Major** (1.0.0 → 2.0.0): Breaking changes
730
1657
  - **Minor** (1.0.0 → 1.1.0): New features, backwards compatible
731
1658
  - **Patch** (1.0.0 → 1.0.1): Bug fixes
732
1659
 
733
1660
  **Update version:**
734
- ```bash
735
- # Manually in package.json
736
- "version": "1.0.7"
737
1661
 
738
- # Or using npm version
1662
+ ```bash
739
1663
  npm version patch # 1.0.6 → 1.0.7
740
1664
  npm version minor # 1.0.6 → 1.1.0
741
1665
  npm version major # 1.0.6 → 2.0.0
742
1666
  ```
743
1667
 
744
- ### Post-Publishing
745
-
746
- After publishing:
747
-
748
- 1. **Tag the release:**
749
- ```bash
750
- git tag v1.0.7
751
- git push origin v1.0.7
752
- ```
753
-
754
- 2. **Update consuming apps:**
755
- ```bash
756
- cd ../b2c-web-demo
757
- yarn upgrade igloo-d2c-components@latest
758
- ```
759
-
760
- 3. **Announce the release** to the team
761
-
762
- ---
763
-
764
- ## 📖 Storybook
765
-
766
- The library includes Storybook for component documentation and testing.
767
-
768
- ### Running Storybook
769
-
770
- ```bash
771
- # Start Storybook dev server
772
- yarn storybook
773
- # Opens at http://localhost:6006
774
-
775
- # Build static Storybook
776
- yarn build-storybook
777
- # Output in storybook-static/
778
- ```
779
-
780
- ### Storybook Features
781
-
782
- - **Component Playground** - Interactive component testing
783
- - **Props Documentation** - Auto-generated from TypeScript
784
- - **Theme Switching** - Test with different tenant themes
785
- - **Responsive Design** - Test different viewports
786
- - **Accessibility** - Built-in a11y addon
787
-
788
- ### Adding Stories
789
-
790
- Create a `.stories.tsx` file next to your component:
791
-
792
- ```tsx
793
- // src/components/MyComponent/MyComponent.stories.tsx
794
- import type { Meta, StoryObj } from '@storybook/react'
795
- import { TenantThemeProvider, iglooTheme } from '../../index'
796
- import { MyComponent } from './MyComponent'
797
-
798
- const meta: Meta<typeof MyComponent> = {
799
- title: 'Components/MyComponent',
800
- component: MyComponent,
801
- decorators: [
802
- (Story) => (
803
- <TenantThemeProvider tenantId="igloo" theme={iglooTheme}>
804
- <Story />
805
- </TenantThemeProvider>
806
- ),
807
- ],
808
- }
809
-
810
- export default meta
811
- type Story = StoryObj<typeof MyComponent>
812
-
813
- export const Default: Story = {
814
- args: {
815
- prop1: 'value1',
816
- },
817
- }
818
- ```
819
-
820
1668
  ---
821
1669
 
822
1670
  ## 🔬 Technical Details
@@ -824,6 +1672,7 @@ export const Default: Story = {
824
1672
  ### Build Configuration
825
1673
 
826
1674
  **Rollup Configuration** (`rollup.config.cjs`):
1675
+
827
1676
  ```javascript
828
1677
  {
829
1678
  input: 'src/index.ts',
@@ -843,19 +1692,6 @@ export const Default: Story = {
843
1692
  banner: '"use client"',
844
1693
  },
845
1694
  ],
846
- plugins: [
847
- peerDepsExternal(),
848
- resolve(),
849
- commonjs(),
850
- typescript({
851
- tsconfig: './tsconfig.json',
852
- compilerOptions: {
853
- declaration: false,
854
- target: 'ES2015', // For compatibility
855
- },
856
- }),
857
- // NO terser() - libraries should not be minified
858
- ],
859
1695
  }
860
1696
  ```
861
1697
 
@@ -881,17 +1717,6 @@ export const Default: Story = {
881
1717
  }
882
1718
  ```
883
1719
 
884
- ### Package Exports
885
-
886
- ```json
887
- {
888
- "main": "dist/cjs/index.js",
889
- "module": "dist/esm/index.js",
890
- "types": "dist/types/index.d.ts",
891
- "files": ["dist", "README.md"]
892
- }
893
- ```
894
-
895
1720
  ---
896
1721
 
897
1722
  ## 🐛 Troubleshooting
@@ -899,129 +1724,107 @@ export const Default: Story = {
899
1724
  ### Webpack Module Parse Error
900
1725
 
901
1726
  **Error:**
1727
+
902
1728
  ```
903
1729
  Module parse failed: Unexpected token
904
1730
  ```
905
1731
 
906
- **Cause:** Webpack can't parse the library output.
907
-
908
1732
  **Solution:**
909
1733
 
910
- 1. **Check library build target:** The library should be built with ES2015 target (✅ already configured)
911
- 2. **Rebuild library:**
912
- ```bash
913
- cd d2c-component-library
914
- yarn clean && yarn build
915
- ```
916
- 3. **Reinstall in consuming app:**
917
- ```bash
918
- cd ../b2c-web-demo
919
- rm -rf node_modules/igloo-d2c-components
920
- yarn install
921
- ```
922
-
923
- **Prevention:** The library is configured to output ES2015 JavaScript which is compatible with webpack 4+. Modern syntax like optional chaining (`?.`) is transpiled to verbose null checks.
1734
+ ```bash
1735
+ cd d2c-component-library
1736
+ yarn clean && yarn build
1737
+ cd ../b2c-web-demo
1738
+ rm -rf node_modules/igloo-d2c-components
1739
+ yarn install
1740
+ ```
924
1741
 
925
1742
  ### Theme Not Found Error
926
1743
 
927
1744
  **Error:**
1745
+
928
1746
  ```
929
1747
  Theme not found for tenant: xxx
930
1748
  ```
931
1749
 
932
1750
  **Solution:** Use valid tenant IDs: `'igloo'`, `'cimb'`, or `'ammetlife'`.
933
1751
 
934
- ```typescript
935
- import { isValidTenantId, getTenantTheme } from 'igloo-d2c-components'
936
-
937
- if (isValidTenantId(tenantId)) {
938
- const theme = getTenantTheme(tenantId)
939
- } else {
940
- console.error('Invalid tenant ID:', tenantId)
941
- }
942
- ```
943
-
944
1752
  ### TypeScript Errors with Imports
945
1753
 
946
1754
  **Error:**
1755
+
947
1756
  ```
948
1757
  Module '"igloo-d2c-components"' has no exported member 'iglooTheme'
949
1758
  ```
950
1759
 
951
1760
  **Solution:**
952
1761
 
953
- 1. **Rebuild the library:**
954
- ```bash
955
- cd d2c-component-library
956
- yarn build
957
- ```
958
-
959
- 2. **Reinstall in consuming app:**
960
- ```bash
961
- cd ../b2c-web-demo
962
- yarn remove igloo-d2c-components
963
- yarn add igloo-d2c-components@file:../d2c-component-library
964
- ```
965
-
966
- 3. **Restart TypeScript server** in your IDE:
967
- - VS Code: Cmd+Shift+P → "TypeScript: Restart TS Server"
1762
+ 1. Rebuild the library: `yarn build`
1763
+ 2. Reinstall in consuming app: `yarn install`
1764
+ 3. Restart TypeScript server in your IDE
968
1765
 
969
1766
  ### Build Failures
970
1767
 
971
1768
  **Error:** Build fails with memory issues
972
1769
 
973
1770
  **Solution:**
1771
+
974
1772
  ```bash
975
1773
  export NODE_OPTIONS="--max-old-space-size=4096"
976
1774
  yarn build
977
1775
  ```
978
1776
 
979
- **Error:** Type errors during build
1777
+ ### Asset Issues
980
1778
 
981
- **Solution:**
982
- ```bash
983
- # Check types first
984
- yarn type-check
1779
+ **Logos not displaying:**
985
1780
 
986
- # Fix any type errors, then build
987
- yarn build
988
- ```
1781
+ 1. Run `yarn copy-assets` in consuming app
1782
+ 2. Verify assets in `public/assets/tenants/`
1783
+ 3. Check theme path: `/assets/tenants/igloo/logo.svg`
989
1784
 
990
- ### Missing Peer Dependencies
1785
+ ### Routing Issues
991
1786
 
992
- **Warning:** `peer dependency "react" not installed`
993
-
994
- **Solution:** Install peer dependencies in consuming app:
995
- ```bash
996
- yarn add react@17 react-dom@17 @mui/material@5 @emotion/react @emotion/styled
997
- ```
1787
+ **Issue: 404 on /life-checkout**
1788
+ Use locale prefix: `/en/life-checkout`, not `/life-checkout`
998
1789
 
999
1790
  ---
1000
1791
 
1001
- ## 🎯 Best Practices
1792
+ ## 📝 Changelog
1793
+
1794
+ ### [Unreleased]
1795
+
1796
+ #### Added
1002
1797
 
1003
- ### For Library Development
1798
+ - **CheckoutProgress** - Progress bar component with step indicator
1799
+ - **ProductCard** - Product information card for checkout flows
1800
+ - **CheckoutHeader** - Complete checkout header combining progress and product card
1801
+ - **CheckoutFormButton** - Fixed/floating button for form submission
1802
+ - **HealthQuestionGroup** - Health question component with Yes/No options
1803
+ - **ProductSelectionDrawer** - Mobile-first bottom drawer for product selection
1804
+ - **PersonalInformationForm** - Personal details form component
1805
+ - **ContactDetailsForm** - Contact and address form component
1806
+ - **HealthInformationForm** - Health measurements and questions form
1807
+ - Comprehensive Storybook documentation
1808
+ - Integration guides for multi-tenant architecture
1004
1809
 
1005
- 1. **Always build before testing** - Run `yarn build` after changes
1006
- 2. **Use ES2015 features** - Avoid ES2020+ syntax
1007
- 3. **Test in consuming apps** - Test changes in b2c-web-demo
1008
- 4. **Update CHANGELOG** - Document all changes
1009
- 5. **Version appropriately** - Follow semantic versioning
1810
+ ### [1.0.1] - 2025-11-11
1010
1811
 
1011
- ### For Library Usage
1812
+ #### Changed
1012
1813
 
1013
- 1. **Wrap with TenantThemeProvider** - Required for theming to work
1014
- 2. **Use pre-built themes** - Import `iglooTheme`, `cimbTheme`, `ammetlifeTheme`
1015
- 3. **Use tenantColored prop** - For tenant-specific styling
1016
- 4. **Maintain type safety** - Use provided TypeScript types
1017
- 5. **Extend via composition** - Don't modify library components
1814
+ - Package name configured for public NPM registry
1815
+ - Updated all documentation
1018
1816
 
1019
- ### For Theme Management
1817
+ ### [1.0.0] - 2025-10-31
1020
1818
 
1021
- 1. **Update themes in library** - Not in consuming apps
1022
- 2. **Test all tenants** - When changing theme structure
1023
- 3. **Document breaking changes** - If theme interface changes
1024
- 4. **Version bump** - Increment version after theme changes
1819
+ #### Added
1820
+
1821
+ - Initial release of D2C Component Library
1822
+ - `TenantThemeProvider` - Context provider for tenant theming
1823
+ - Hooks: `useTenantTheme()`, `useTenantId()`, `useIsTenant()`
1824
+ - Components: `Button`, `Card`, `Banner`
1825
+ - Utility functions for theme management
1826
+ - Full TypeScript support
1827
+ - ESM and CommonJS builds
1025
1828
 
1026
1829
  ---
1027
1830
 
@@ -1031,31 +1834,35 @@ yarn add react@17 react-dom@17 @mui/material@5 @emotion/react @emotion/styled
1031
1834
 
1032
1835
  1. **Fork the repository**
1033
1836
  2. **Create a feature branch:**
1837
+
1034
1838
  ```bash
1035
1839
  git checkout -b feature/my-new-feature
1036
1840
  ```
1841
+
1037
1842
  3. **Make your changes**
1038
1843
  4. **Test thoroughly:**
1844
+
1039
1845
  ```bash
1040
1846
  yarn lint
1041
1847
  yarn type-check
1042
1848
  yarn build
1043
1849
  ```
1850
+
1044
1851
  5. **Test in consuming app:**
1852
+
1045
1853
  ```bash
1046
1854
  cd ../b2c-web-demo
1047
1855
  yarn install
1048
1856
  yarn start-igloo-dev
1049
1857
  ```
1858
+
1050
1859
  6. **Commit your changes:**
1860
+
1051
1861
  ```bash
1052
1862
  git commit -m "feat: add new feature"
1053
1863
  ```
1054
- 7. **Push to branch:**
1055
- ```bash
1056
- git push origin feature/my-new-feature
1057
- ```
1058
- 8. **Create a Pull Request**
1864
+
1865
+ 7. **Push and create a Pull Request**
1059
1866
 
1060
1867
  ### Commit Message Format
1061
1868
 
@@ -1063,13 +1870,10 @@ Follow [Conventional Commits](https://www.conventionalcommits.org/):
1063
1870
 
1064
1871
  ```
1065
1872
  <type>(<scope>): <description>
1066
-
1067
- [optional body]
1068
-
1069
- [optional footer]
1070
1873
  ```
1071
1874
 
1072
1875
  **Types:**
1876
+
1073
1877
  - `feat`: New feature
1074
1878
  - `fix`: Bug fix
1075
1879
  - `docs`: Documentation changes
@@ -1078,22 +1882,15 @@ Follow [Conventional Commits](https://www.conventionalcommits.org/):
1078
1882
  - `test`: Test additions/changes
1079
1883
  - `chore`: Maintenance tasks
1080
1884
 
1081
- **Examples:**
1082
- ```
1083
- feat(themes): add new tenant theme
1084
- fix(Button): correct hover state color
1085
- docs: update installation guide
1086
- chore: bump version to 1.0.7
1087
- ```
1088
-
1089
1885
  ### Adding a New Tenant
1090
1886
 
1091
1887
  1. **Add theme to `src/themes/index.ts`:**
1888
+
1092
1889
  ```typescript
1093
1890
  export const newTenantTheme: TenantThemeConfig = {
1094
1891
  palette: { /* ... */ },
1095
1892
  typography: { /* ... */ },
1096
- logo: '/assets/new-tenant/logo.svg',
1893
+ logo: '/assets/tenants/newtenant/logo.svg',
1097
1894
  favicon: 'https://...',
1098
1895
  }
1099
1896
 
@@ -1106,18 +1903,26 @@ chore: bump version to 1.0.7
1106
1903
  ```
1107
1904
 
1108
1905
  2. **Update TenantId type in `src/types/tenant.ts`:**
1906
+
1109
1907
  ```typescript
1110
1908
  export type TenantId = 'igloo' | 'cimb' | 'ammetlife' | 'newtenant'
1111
1909
  ```
1112
1910
 
1113
- 3. **Build and test:**
1911
+ 3. **Add logo asset to `src/assets/tenants/newtenant/`**
1912
+
1913
+ 4. **Build and test:**
1914
+
1114
1915
  ```bash
1115
1916
  yarn build
1116
- cd ../b2c-web-demo
1117
- yarn install
1118
1917
  ```
1119
1918
 
1120
- 4. **Update documentation and CHANGELOG**
1919
+ ### Adding New Components
1920
+
1921
+ 1. Create component folder in `src/components/`
1922
+ 2. Include: `ComponentName.tsx`, `styled.tsx`, `index.ts`
1923
+ 3. Add Storybook stories
1924
+ 4. Export from `src/index.ts`
1925
+ 5. Update documentation
1121
1926
 
1122
1927
  ---
1123
1928
 
@@ -1135,16 +1940,16 @@ Frontend Engineering Team - Axinan/Igloo
1135
1940
 
1136
1941
  ## 🔗 Links
1137
1942
 
1138
- - **Repository:** https://gitlab.iglooinsure.com/axinan/fe/d2c-component-library
1139
- - **NPM Package:** https://www.npmjs.com/package/igloo-d2c-components
1140
- - **Consuming App:** https://gitlab.iglooinsure.com/axinan/fe/b2c-web-demo
1141
- - **Issue Tracker:** https://gitlab.iglooinsure.com/axinan/fe/d2c-component-library/-/issues
1943
+ - **Repository:** <https://gitlab.iglooinsure.com/axinan/fe/d2c-component-library>
1944
+ - **NPM Package:** <https://www.npmjs.com/package/igloo-d2c-components>
1945
+ - **Consuming App:** <https://gitlab.iglooinsure.com/axinan/fe/b2c-web-demo>
1142
1946
 
1143
1947
  ---
1144
1948
 
1145
1949
  ## 📝 Quick Reference
1146
1950
 
1147
1951
  ### Installation
1952
+
1148
1953
  ```bash
1149
1954
  # Local development
1150
1955
  yarn add igloo-d2c-components@file:../d2c-component-library
@@ -1154,38 +1959,45 @@ yarn add igloo-d2c-components@latest
1154
1959
  ```
1155
1960
 
1156
1961
  ### Import Themes
1962
+
1157
1963
  ```typescript
1158
1964
  import { iglooTheme, cimbTheme, ammetlifeTheme, getTenantTheme } from 'igloo-d2c-components'
1159
1965
  ```
1160
1966
 
1161
1967
  ### Import Components
1968
+
1162
1969
  ```typescript
1163
- import { Button, Card, Banner, TenantThemeProvider } from 'igloo-d2c-components'
1970
+ import { Button, Card, Banner, TenantThemeProvider, NewHeader, CheckoutHeader } from 'igloo-d2c-components'
1164
1971
  ```
1165
1972
 
1166
1973
  ### Import Hooks
1974
+
1167
1975
  ```typescript
1168
- import { useTenantTheme, useTenantId, useIsTenant } from 'igloo-d2c-components'
1976
+ import { useTenantTheme, useTenantId, useIsTenant, useTenantLogo } from 'igloo-d2c-components'
1169
1977
  ```
1170
1978
 
1171
1979
  ### Build & Publish
1980
+
1172
1981
  ```bash
1173
1982
  # Build
1174
1983
  yarn build
1175
1984
 
1176
1985
  # Publish to NPM
1177
1986
  ./publish-to-npm.sh
1987
+ ```
1178
1988
 
1179
- # Publish to GitLab
1180
- npm publish
1989
+ ### Test All Tenants (in b2c-web-demo)
1990
+
1991
+ ```bash
1992
+ yarn start-igloo # Port 8000
1993
+ yarn start-ammetlife # Port 8001
1994
+ yarn start-cimb # Port 8002
1181
1995
  ```
1182
1996
 
1183
1997
  ---
1184
1998
 
1185
- **Version:** 1.0.6
1186
- **Last Updated:** November 12, 2025
1999
+ **Version:** 1.0.11+
2000
+ **Last Updated:** December 2025
1187
2001
  **Node.js:** >=16.20.0 <=18.x
1188
2002
  **Target:** ES2015
1189
2003
  **Output:** Unminified
1190
-
1191
- For version history, see [CHANGELOG.md](./CHANGELOG.md)