@thorprovider/storefront 0.3.1
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/CHANGELOG.md +61 -0
- package/README.md +333 -0
- package/assets/templates/app/app/[[...slug]]/page.tsx +17 -0
- package/assets/templates/app/app/[[...slug]]/renderer.tsx +10 -0
- package/assets/templates/app/app/globals.css +101 -0
- package/assets/templates/app/app/layout.tsx +35 -0
- package/assets/templates/app/lib/__STOREFRONT__/catalog.ts +88 -0
- package/assets/templates/app/lib/__STOREFRONT__/handlers.ts +42 -0
- package/assets/templates/app/lib/__STOREFRONT__/mappers.ts +47 -0
- package/assets/templates/app/lib/__STOREFRONT__/registry.tsx +98 -0
- package/assets/templates/app/lib/__STOREFRONT__/runtime.ts +17 -0
- package/assets/templates/app/lib/__STOREFRONT__/spec/index.ts +48 -0
- package/assets/templates/app/lib/__STOREFRONT__/spec/page-root.ts +26 -0
- package/assets/templates/app/lib/__STOREFRONT__/spec/types.ts +14 -0
- package/assets/templates/app/lib/__STOREFRONT__/state.ts +35 -0
- package/assets/templates/app/lib/__STOREFRONT__/views/index.ts +7 -0
- package/assets/templates/app/lib/__STOREFRONT__/views/sections/faq.tsx +29 -0
- package/assets/templates/app/lib/__STOREFRONT__/views/sections/logoCloud.tsx +29 -0
- package/assets/templates/app/lib/__STOREFRONT__/views/sections/pricing.tsx +33 -0
- package/assets/templates/app/lib/__STOREFRONT__/views/sections/statistics.tsx +29 -0
- package/assets/templates/app/lib/__STOREFRONT__/views/sections/testimonials.tsx +28 -0
- package/assets/templates/app/lib/__STOREFRONT__/views/types.ts +46 -0
- package/assets/templates/views/home/index.tsx +142 -0
- package/assets/templates/views/home/registry.tsx +65 -0
- package/bin/storefront.js +531 -0
- package/commands/sf-add-view.md +26 -0
- package/commands/sf-theme.md +20 -0
- package/commands/sf-view.md +25 -0
- package/package.json +48 -0
- package/recipes/archetype.schema.json +39 -0
- package/recipes/archetypes.json +148 -0
- package/recipes/recipe.schema.json +59 -0
- package/recipes/recipes.json +90 -0
- package/recipes/sections.json +46 -0
- package/recipes/validate.mjs +190 -0
- package/scripts/render-templates.mjs +255 -0
- package/scripts/sync-assets.mjs +87 -0
- package/skills/building-storefronts/SKILL.md +178 -0
- package/skills/building-storefronts/references/frontend-integration.md +229 -0
- package/skills/json-render-core/SKILL.md +291 -0
- package/skills/json-render-next/SKILL.md +194 -0
- package/skills/json-render-react/SKILL.md +298 -0
- package/skills/json-render-remotion/SKILL.md +111 -0
- package/skills/json-render-shadcn/SKILL.md +159 -0
- package/skills/json-render-solid/SKILL.md +204 -0
- package/skills/nextjs-shadcn/SKILL.md +367 -0
- package/skills/nextjs-shadcn/references/architecture.md +499 -0
- package/skills/nextjs-shadcn/references/project-setup.md +162 -0
- package/skills/nextjs-shadcn/references/shadcn-platform.md +261 -0
- package/skills/nextjs-shadcn/references/sidebar.md +274 -0
- package/skills/nextjs-shadcn/references/styling.md +555 -0
- package/skills/sf-theme-gen/SKILL.md +61 -0
- package/skills/sf-view-gen/SKILL.md +116 -0
- package/skills/sf-view-gen/assets/recipes/archetypes.json +148 -0
- package/skills/sf-view-gen/assets/recipes/recipes.json +90 -0
- package/skills/sf-view-gen/assets/recipes/sections.json +46 -0
- package/skills/sf-view-gen/assets/templates/views/category/index.tsx +86 -0
- package/skills/sf-view-gen/assets/templates/views/category/registry.tsx +48 -0
- package/skills/sf-view-gen/assets/templates/views/checkout/index.tsx +192 -0
- package/skills/sf-view-gen/assets/templates/views/checkout/registry.tsx +45 -0
- package/skills/sf-view-gen/assets/templates/views/product/index.tsx +122 -0
- package/skills/sf-view-gen/assets/templates/views/product/registry.tsx +49 -0
- package/skills/sf-view-gen/assets/templates/views/sections/faq.client.tsx +20 -0
- package/skills/sf-view-gen/assets/templates/views/sections/faq.tsx +21 -0
- package/skills/sf-view-gen/assets/templates/views/sections/logoCloud.client.tsx +18 -0
- package/skills/sf-view-gen/assets/templates/views/sections/logoCloud.tsx +21 -0
- package/skills/sf-view-gen/assets/templates/views/sections/pricing.client.tsx +20 -0
- package/skills/sf-view-gen/assets/templates/views/sections/pricing.tsx +23 -0
- package/skills/sf-view-gen/assets/templates/views/sections/statistics.client.tsx +18 -0
- package/skills/sf-view-gen/assets/templates/views/sections/statistics.tsx +21 -0
- package/skills/sf-view-gen/assets/templates/views/sections/testimonials.client.tsx +19 -0
- package/skills/sf-view-gen/assets/templates/views/sections/testimonials.tsx +19 -0
- package/skills/sf-view-gen/assets/templates/views/user-panel/index.tsx +168 -0
- package/skills/sf-view-gen/assets/templates/views/user-panel/registry.tsx +49 -0
- package/skills/sf-view-gen/references/views.md +69 -0
- package/skills/sf-view-gen/scripts/validate.mjs +190 -0
- package/skills/shadcn-component-discovery/SKILL.md +273 -0
- package/skills/shadcn-component-discovery/references/registries.md +226 -0
- package/skills/shadcn-theming/SKILL.md +104 -0
- package/skills/shadcn-theming/references/templates/theme-setup.md +109 -0
- package/skills/shadcn-theming/references/theming-guide.md +90 -0
- package/skills/storefront-best-practices/SKILL.md +421 -0
- package/skills/storefront-best-practices/reference/components/breadcrumbs.md +123 -0
- package/skills/storefront-best-practices/reference/components/cart-popup.md +189 -0
- package/skills/storefront-best-practices/reference/components/country-selector.md +298 -0
- package/skills/storefront-best-practices/reference/components/footer.md +112 -0
- package/skills/storefront-best-practices/reference/components/hero.md +241 -0
- package/skills/storefront-best-practices/reference/components/megamenu.md +239 -0
- package/skills/storefront-best-practices/reference/components/navbar.md +397 -0
- package/skills/storefront-best-practices/reference/components/popups.md +221 -0
- package/skills/storefront-best-practices/reference/components/product-card.md +125 -0
- package/skills/storefront-best-practices/reference/components/product-reviews.md +217 -0
- package/skills/storefront-best-practices/reference/components/product-slider.md +174 -0
- package/skills/storefront-best-practices/reference/components/search.md +101 -0
- package/skills/storefront-best-practices/reference/connecting-to-backend.md +391 -0
- package/skills/storefront-best-practices/reference/design.md +388 -0
- package/skills/storefront-best-practices/reference/features/promotions.md +307 -0
- package/skills/storefront-best-practices/reference/features/wishlist.md +230 -0
- package/skills/storefront-best-practices/reference/layouts/account.md +380 -0
- package/skills/storefront-best-practices/reference/layouts/cart.md +316 -0
- package/skills/storefront-best-practices/reference/layouts/checkout.md +486 -0
- package/skills/storefront-best-practices/reference/layouts/home-page.md +264 -0
- package/skills/storefront-best-practices/reference/layouts/order-confirmation.md +231 -0
- package/skills/storefront-best-practices/reference/layouts/product-details.md +527 -0
- package/skills/storefront-best-practices/reference/layouts/product-listing.md +520 -0
- package/skills/storefront-best-practices/reference/layouts/static-pages.md +356 -0
- package/skills/storefront-best-practices/reference/medusa.md +307 -0
- package/skills/storefront-best-practices/reference/mobile-responsiveness.md +183 -0
- package/skills/storefront-best-practices/reference/seo.md +195 -0
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
# Breadcrumbs Component
|
|
2
|
+
|
|
3
|
+
## Contents
|
|
4
|
+
|
|
5
|
+
- [Overview](#overview)
|
|
6
|
+
- [When to Use Breadcrumbs](#when-to-use-breadcrumbs)
|
|
7
|
+
- [Ecommerce Breadcrumb Patterns](#ecommerce-breadcrumb-patterns)
|
|
8
|
+
- [Mobile Breadcrumbs](#mobile-breadcrumbs)
|
|
9
|
+
- [SEO Structured Data](#seo-structured-data)
|
|
10
|
+
- [Checklist](#checklist)
|
|
11
|
+
|
|
12
|
+
## Overview
|
|
13
|
+
|
|
14
|
+
Breadcrumbs show the user's location within the site hierarchy (Home → Category → Subcategory → Product). Critical for ecommerce navigation and SEO.
|
|
15
|
+
|
|
16
|
+
**Assumed knowledge**: AI agents know how to build breadcrumbs with separators and links. This guide focuses on ecommerce-specific patterns.
|
|
17
|
+
|
|
18
|
+
### Key Requirements
|
|
19
|
+
|
|
20
|
+
- Show full path from homepage to current page
|
|
21
|
+
- Each level clickable (except current page)
|
|
22
|
+
- Position below navbar, above page title
|
|
23
|
+
- Include structured data for SEO (JSON-LD)
|
|
24
|
+
- Mobile-optimized (back link pattern)
|
|
25
|
+
|
|
26
|
+
## When to Use Breadcrumbs
|
|
27
|
+
|
|
28
|
+
**Use for:**
|
|
29
|
+
- Product pages (Home → Category → Subcategory → Product)
|
|
30
|
+
- Category pages (Home → Category → Subcategory)
|
|
31
|
+
- Deep site hierarchies (3+ levels)
|
|
32
|
+
- Large catalogs with many categories
|
|
33
|
+
|
|
34
|
+
**Don't use for:**
|
|
35
|
+
- Homepage (no parent pages)
|
|
36
|
+
- Flat site structures (1-2 levels)
|
|
37
|
+
- Checkout flow (linear, not hierarchical)
|
|
38
|
+
- Search results (not hierarchical)
|
|
39
|
+
|
|
40
|
+
## Ecommerce Breadcrumb Patterns
|
|
41
|
+
|
|
42
|
+
### Product Page Breadcrumbs
|
|
43
|
+
|
|
44
|
+
**Standard pattern:**
|
|
45
|
+
- Home / Category / Subcategory / Product Name
|
|
46
|
+
- Example: Home / Electronics / Laptops / Gaming Laptop Pro
|
|
47
|
+
|
|
48
|
+
**Key considerations:**
|
|
49
|
+
- All levels except product name are clickable
|
|
50
|
+
- Product name is current page (non-clickable, darker text)
|
|
51
|
+
- Shows product's location in catalog
|
|
52
|
+
|
|
53
|
+
**Multiple category membership:**
|
|
54
|
+
- If product in multiple categories, choose primary/canonical
|
|
55
|
+
- Match category in URL or navigation path
|
|
56
|
+
- Be consistent across site
|
|
57
|
+
|
|
58
|
+
### Category Page Breadcrumbs
|
|
59
|
+
|
|
60
|
+
**Standard pattern:**
|
|
61
|
+
- Home / Parent Category / Current Category
|
|
62
|
+
- Example: Home / Electronics / Laptops
|
|
63
|
+
|
|
64
|
+
**Current category:**
|
|
65
|
+
- Non-clickable (plain text)
|
|
66
|
+
- Visually distinct from links (darker or bold)
|
|
67
|
+
|
|
68
|
+
### Path Construction
|
|
69
|
+
|
|
70
|
+
**Hierarchy:**
|
|
71
|
+
- Start with "Home" (or home icon)
|
|
72
|
+
- Follow category hierarchy
|
|
73
|
+
- End with current page
|
|
74
|
+
- Maximum 5-6 levels (keep shallow)
|
|
75
|
+
|
|
76
|
+
**URL alignment:**
|
|
77
|
+
- Breadcrumb path should match URL hierarchy
|
|
78
|
+
- Consistent naming between URLs and breadcrumbs
|
|
79
|
+
- Example: `/categories/electronics/laptops` → "Home / Electronics / Laptops"
|
|
80
|
+
|
|
81
|
+
## Mobile Breadcrumbs
|
|
82
|
+
|
|
83
|
+
### Mobile Pattern: Collapse to Back Link
|
|
84
|
+
|
|
85
|
+
**Recommended approach:**
|
|
86
|
+
- Show only previous level as back link
|
|
87
|
+
- Back arrow icon (←) + parent page name
|
|
88
|
+
- Example: "← Gaming Laptops"
|
|
89
|
+
|
|
90
|
+
**Why:**
|
|
91
|
+
- Saves vertical space on mobile
|
|
92
|
+
- Clear affordance (back navigation)
|
|
93
|
+
- Simpler than full breadcrumb trail
|
|
94
|
+
- Mobile users have device back button
|
|
95
|
+
|
|
96
|
+
**Alternative: Truncated path**
|
|
97
|
+
- Show "Home ... Current Page"
|
|
98
|
+
- Hide middle levels
|
|
99
|
+
- Balances space and context
|
|
100
|
+
|
|
101
|
+
## SEO Structured Data
|
|
102
|
+
|
|
103
|
+
**BreadcrumbList schema (CRITICAL)**: Add JSON-LD structured data. Breadcrumbs appear in search results, improves CTR, helps search engines understand site structure.
|
|
104
|
+
|
|
105
|
+
**Implementation**: schema.org BreadcrumbList with items array. Each item has position (1, 2, 3...), name, and URL. See seo.md for schema details.
|
|
106
|
+
|
|
107
|
+
## Checklist
|
|
108
|
+
|
|
109
|
+
**Essential features:**
|
|
110
|
+
|
|
111
|
+
- [ ] Positioned below navbar, above page title
|
|
112
|
+
- [ ] Full path shown (Home → Category → Product)
|
|
113
|
+
- [ ] All levels clickable except current page
|
|
114
|
+
- [ ] Current page visually distinct (non-clickable, darker)
|
|
115
|
+
- [ ] Clear separators (›, /, > or chevron)
|
|
116
|
+
- [ ] Mobile: Back link pattern ("← Category")
|
|
117
|
+
- [ ] Structured data (JSON-LD BreadcrumbList)
|
|
118
|
+
- [ ] Semantic HTML (`<nav aria-label="Breadcrumb">`)
|
|
119
|
+
- [ ] `aria-current="page"` on current item
|
|
120
|
+
- [ ] Keyboard accessible (tab through links)
|
|
121
|
+
- [ ] Truncate long labels (20-30 characters max)
|
|
122
|
+
- [ ] Consistent with navigation labels
|
|
123
|
+
- [ ] Maximum 5-6 levels deep
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
# Cart Popup Component
|
|
2
|
+
|
|
3
|
+
## Contents
|
|
4
|
+
|
|
5
|
+
- [Overview](#overview)
|
|
6
|
+
- [When to Show Cart Popup](#when-to-show-cart-popup)
|
|
7
|
+
- [Layout Patterns](#layout-patterns)
|
|
8
|
+
- [Cart Display](#cart-display)
|
|
9
|
+
- [Actions and CTAs](#actions-and-ctas)
|
|
10
|
+
- [Empty State](#empty-state)
|
|
11
|
+
- [Mobile Considerations](#mobile-considerations)
|
|
12
|
+
- [Checklist](#checklist)
|
|
13
|
+
|
|
14
|
+
## Overview
|
|
15
|
+
|
|
16
|
+
Cart popup (mini cart/cart drawer) shows quick cart overview without navigating away. Opens from cart icon click or after adding items.
|
|
17
|
+
|
|
18
|
+
**⚠️ CRITICAL: Always display variant details (size, color, material, etc.) in cart popup, not just product titles.**
|
|
19
|
+
|
|
20
|
+
**Assumed knowledge**: AI agents know how to build modals, dialogs, and overlays. This focuses on ecommerce-specific patterns.
|
|
21
|
+
|
|
22
|
+
**Cart popup vs full cart page:**
|
|
23
|
+
- Popup: Quick overview, fast checkout path, continue shopping easily
|
|
24
|
+
- Full page: Detailed review, promo codes, complex operations
|
|
25
|
+
- **Recommended**: Both - popup for speed, full cart page for details
|
|
26
|
+
|
|
27
|
+
## When to Show Cart Popup
|
|
28
|
+
|
|
29
|
+
**Trigger options:**
|
|
30
|
+
|
|
31
|
+
1. **On cart icon click** (always) - Click cart icon in navbar opens popup
|
|
32
|
+
2. **After adding to cart** (recommended) - Auto-open popup when item added, confirms action, allows checkout or continue shopping
|
|
33
|
+
3. **Hover cart icon** (desktop only, optional) - Quick peek on hover. Can be accidental, not recommended.
|
|
34
|
+
|
|
35
|
+
**Add-to-cart feedback alternatives:**
|
|
36
|
+
- Show popup (most common) - Immediate confirmation, clear path to checkout
|
|
37
|
+
- Toast only (less intrusive) - Small notification, user clicks cart icon to see details
|
|
38
|
+
- Navigate to cart page (traditional) - Goes directly to full cart page, less common now
|
|
39
|
+
|
|
40
|
+
## Layout Patterns
|
|
41
|
+
|
|
42
|
+
**Two common patterns:**
|
|
43
|
+
|
|
44
|
+
**1. Dropdown (recommended for simplicity):**
|
|
45
|
+
- Drops down from cart icon, positioned below navbar
|
|
46
|
+
- Width: 280-320px, max height with scroll
|
|
47
|
+
- No backdrop overlay (click outside to close)
|
|
48
|
+
- Better for few items, simpler implementation
|
|
49
|
+
|
|
50
|
+
**2. Slide-in drawer (more prominent):**
|
|
51
|
+
- Slides from right, full height, width 320-400px (desktop) or 80-90% (mobile)
|
|
52
|
+
- Semi-transparent backdrop overlay (click to close)
|
|
53
|
+
- Better for multiple items or complex carts
|
|
54
|
+
|
|
55
|
+
**Both patterns have:**
|
|
56
|
+
- Header: Title + item count + close button (optional for dropdown)
|
|
57
|
+
- Scrollable content: List of cart items
|
|
58
|
+
- Sticky footer: Subtotal + action buttons (Checkout, View Cart)
|
|
59
|
+
|
|
60
|
+
## Cart Display
|
|
61
|
+
|
|
62
|
+
**Fetch cart data from backend:**
|
|
63
|
+
- Cart ID from localStorage
|
|
64
|
+
- Line items (products, variants, quantities, prices)
|
|
65
|
+
- Cart totals (subtotal, tax, shipping)
|
|
66
|
+
- See connecting-to-backend.md for backend integration
|
|
67
|
+
|
|
68
|
+
**When to fetch:**
|
|
69
|
+
- On app initialization (update cart icon badge)
|
|
70
|
+
- On popup open (show loading state)
|
|
71
|
+
- After cart updates (add/remove/change quantity)
|
|
72
|
+
|
|
73
|
+
**State management:**
|
|
74
|
+
- Store cart data globally (React Context or TanStack Query)
|
|
75
|
+
- Persist cart ID in localStorage
|
|
76
|
+
- Optimistic UI updates (update immediately, revert on error)
|
|
77
|
+
- **CRITICAL: Clear cart state after order is placed** - See connecting-to-backend.md for cart cleanup pattern
|
|
78
|
+
- Common issue: Cart popup shows old items after checkout because cart state wasn't cleared
|
|
79
|
+
- See connecting-to-backend.md for cart state patterns
|
|
80
|
+
|
|
81
|
+
**Cart item display:**
|
|
82
|
+
|
|
83
|
+
**CRITICAL: Always show variant details (size, color, material, etc.) for each cart item.**
|
|
84
|
+
|
|
85
|
+
Without variant details, users can't confirm they added the correct variant. This is especially critical when products have multiple options.
|
|
86
|
+
|
|
87
|
+
- Product image (60-80px thumbnail)
|
|
88
|
+
- Product title (truncated to 2 lines)
|
|
89
|
+
- **Variant details (REQUIRED)**: Size, color, material, or other variant options
|
|
90
|
+
- Format: "Size: Large, Color: Black" or "Large / Black"
|
|
91
|
+
- Show ALL selected variant options, not just product title
|
|
92
|
+
- Display below title, smaller text (gray)
|
|
93
|
+
- Quantity controls (+/- buttons, debounce 300-500ms)
|
|
94
|
+
- Unit price and total price (line item total = price × quantity)
|
|
95
|
+
- Remove button (X icon, no confirmation needed)
|
|
96
|
+
|
|
97
|
+
**Why variant details are critical:**
|
|
98
|
+
- User confirmation: "Did I add the right size?"
|
|
99
|
+
- Prevents cart abandonment from uncertainty
|
|
100
|
+
- Allows corrections before checkout
|
|
101
|
+
- Essential for products with multiple variants (clothing, shoes, configurable products)
|
|
102
|
+
|
|
103
|
+
## Actions and CTAs
|
|
104
|
+
|
|
105
|
+
**Cart summary display:**
|
|
106
|
+
- Subtotal (sum of all items)
|
|
107
|
+
- Shipping and tax: "Calculated at checkout" or actual amount
|
|
108
|
+
- Total: Bold and prominent
|
|
109
|
+
|
|
110
|
+
**Free shipping indicator (optional):**
|
|
111
|
+
- "Add $25 more for free shipping" with progress bar
|
|
112
|
+
- Encourages larger orders, updates as cart changes
|
|
113
|
+
|
|
114
|
+
**Promo codes:**
|
|
115
|
+
- Usually NOT in cart popup (too cramped)
|
|
116
|
+
- Reserve for full cart page
|
|
117
|
+
- Exception: Simple code input if space permits
|
|
118
|
+
|
|
119
|
+
**Action buttons:**
|
|
120
|
+
1. **Checkout** (primary) - Most prominent, high contrast (brand color), navigates to checkout
|
|
121
|
+
2. **View Cart** (secondary) - Outline or subtle, navigates to full cart page
|
|
122
|
+
|
|
123
|
+
Both buttons full-width, 44-48px height on mobile.
|
|
124
|
+
|
|
125
|
+
## Empty State
|
|
126
|
+
|
|
127
|
+
Show icon/illustration + "Your cart is empty" + "Continue Shopping" button. Centered, friendly, minimal design.
|
|
128
|
+
|
|
129
|
+
## Loading and Error States
|
|
130
|
+
|
|
131
|
+
**On popup open**: Show skeleton/placeholder while fetching (avoid blank screen)
|
|
132
|
+
|
|
133
|
+
**During updates**:
|
|
134
|
+
- Quantity changes: Inline spinner, disable controls, debounce 300-500ms
|
|
135
|
+
- Item removal: Fade out animation, disable remove button during request
|
|
136
|
+
- Add to cart: Loading indicator on button ("Adding...")
|
|
137
|
+
|
|
138
|
+
**Error handling**:
|
|
139
|
+
- Network errors: Show retry option, don't close popup
|
|
140
|
+
- Invalid cart ID: Create new cart automatically
|
|
141
|
+
- Out of stock: Disable quantity increase, show message
|
|
142
|
+
- Revert optimistic updates on failure
|
|
143
|
+
|
|
144
|
+
**Animations**: Smooth transitions (250-350ms), slide-in drawer, backdrop fade-in/out. Highlight newly added items.
|
|
145
|
+
|
|
146
|
+
## Mobile Considerations
|
|
147
|
+
|
|
148
|
+
**Dropdown on mobile:**
|
|
149
|
+
- Full-width (100% minus margins)
|
|
150
|
+
- Max height 60-70% viewport, scrollable
|
|
151
|
+
- Tap outside to close
|
|
152
|
+
|
|
153
|
+
**Drawer on mobile:**
|
|
154
|
+
- 85-95% screen width or full screen
|
|
155
|
+
- Slides from right or bottom
|
|
156
|
+
- Swipe to close gesture supported
|
|
157
|
+
- Backdrop overlay
|
|
158
|
+
|
|
159
|
+
**Mobile adjustments:**
|
|
160
|
+
- Large touch targets (44-48px minimum)
|
|
161
|
+
- Full-width action buttons (48-52px height)
|
|
162
|
+
- Smaller images (60px), truncate titles
|
|
163
|
+
- Sticky footer with actions
|
|
164
|
+
- Large close button (44x44px)
|
|
165
|
+
|
|
166
|
+
## Checklist
|
|
167
|
+
|
|
168
|
+
**Essential features:**
|
|
169
|
+
- [ ] Opens on cart icon click
|
|
170
|
+
- [ ] Dropdown (280-320px) or drawer (320-400px) layout
|
|
171
|
+
- [ ] Close button or click outside to close
|
|
172
|
+
- [ ] Backdrop overlay if drawer
|
|
173
|
+
- [ ] **CRITICAL: Cart items show variant details (size, color, etc.) - not just product title**
|
|
174
|
+
- [ ] Cart items with image, title, variant options, quantity, prices
|
|
175
|
+
- [ ] Quantity controls (+/- buttons, debounced)
|
|
176
|
+
- [ ] Remove item button
|
|
177
|
+
- [ ] Subtotal displayed
|
|
178
|
+
- [ ] Checkout button (primary)
|
|
179
|
+
- [ ] View Cart button (secondary)
|
|
180
|
+
- [ ] Empty state with "Continue Shopping" CTA
|
|
181
|
+
- [ ] Loading states (skeleton/spinner)
|
|
182
|
+
- [ ] Smooth animations (250-350ms)
|
|
183
|
+
- [ ] Mobile: Full-width dropdown or 85-95% drawer
|
|
184
|
+
- [ ] Touch targets 44-48px minimum
|
|
185
|
+
- [ ] `role="dialog"` and `aria-modal="true"`
|
|
186
|
+
- [ ] ARIA labels on cart button ("Shopping cart with 3 items")
|
|
187
|
+
- [ ] Keyboard accessible (focus trap, Escape closes, return focus)
|
|
188
|
+
- [ ] Screen reader announcements (item added/removed)
|
|
189
|
+
- [ ] Real-time cart count badge updates
|
|
@@ -0,0 +1,298 @@
|
|
|
1
|
+
# Country Selector Component
|
|
2
|
+
|
|
3
|
+
## Contents
|
|
4
|
+
|
|
5
|
+
- [Overview](#overview)
|
|
6
|
+
- [When to Implement](#when-to-implement)
|
|
7
|
+
- [UI Patterns](#ui-patterns)
|
|
8
|
+
- [State Management](#state-management)
|
|
9
|
+
- [Backend Integration](#backend-integration)
|
|
10
|
+
- [Detection and Defaults](#detection-and-defaults)
|
|
11
|
+
- [Mobile Considerations](#mobile-considerations)
|
|
12
|
+
- [Checklist](#checklist)
|
|
13
|
+
|
|
14
|
+
## Overview
|
|
15
|
+
|
|
16
|
+
Country selector allows customers to choose their country/region, which determines currency, pricing, available products, shipping options, payment methods, and localized content.
|
|
17
|
+
|
|
18
|
+
### Key Ecommerce Functions
|
|
19
|
+
|
|
20
|
+
- Display prices in correct currency
|
|
21
|
+
- Show country-specific product availability
|
|
22
|
+
- Apply region-specific promotions and discounts
|
|
23
|
+
- Calculate accurate shipping costs and delivery times
|
|
24
|
+
- Enable appropriate payment methods
|
|
25
|
+
- Display localized content and language
|
|
26
|
+
|
|
27
|
+
### Purpose
|
|
28
|
+
|
|
29
|
+
**Why country/region selection matters:**
|
|
30
|
+
- Prices vary by region (currency, taxes, import fees)
|
|
31
|
+
- Product availability differs by market
|
|
32
|
+
- Shipping methods and costs are region-specific
|
|
33
|
+
- Legal requirements vary (privacy, consumer protection)
|
|
34
|
+
- Payment methods differ by country
|
|
35
|
+
- Improves user experience with relevant content
|
|
36
|
+
|
|
37
|
+
## When to Implement
|
|
38
|
+
|
|
39
|
+
**Implement country selector when:**
|
|
40
|
+
- Backend supports multiple countries or regions
|
|
41
|
+
- Selling to multiple countries or regions
|
|
42
|
+
- Prices vary by location (currency, taxes)
|
|
43
|
+
- International shipping with different rates
|
|
44
|
+
- Region-specific product catalogs
|
|
45
|
+
- Multi-currency support needed
|
|
46
|
+
- Legal or regulatory requirements vary by region
|
|
47
|
+
|
|
48
|
+
**Skip if:**
|
|
49
|
+
- Backend doesn't support multiple countries or regions
|
|
50
|
+
- All prices in one currency
|
|
51
|
+
- No regional differences in catalog or pricing
|
|
52
|
+
|
|
53
|
+
## UI Patterns
|
|
54
|
+
|
|
55
|
+
### Placement Options
|
|
56
|
+
|
|
57
|
+
**Footer placement (modern and minimal):**
|
|
58
|
+
- Bottom of page in footer
|
|
59
|
+
- Less prominent but always accessible
|
|
60
|
+
- Icon (flag or globe) + country code/name
|
|
61
|
+
|
|
62
|
+
**Header placement (most common):**
|
|
63
|
+
- Top-right of navigation bar
|
|
64
|
+
- Icon (flag or globe) + country code/name
|
|
65
|
+
- Click opens dropdown or modal selector
|
|
66
|
+
|
|
67
|
+
**Modal/popup on first visit:**
|
|
68
|
+
- Detect location and suggest country
|
|
69
|
+
- Allow user to confirm or change
|
|
70
|
+
- Store preference for future visits
|
|
71
|
+
|
|
72
|
+
### Selector Design Patterns
|
|
73
|
+
|
|
74
|
+
**Pattern 1: Dropdown (Recommended)**
|
|
75
|
+
|
|
76
|
+
Small, compact selector in header. Shows current country flag/name, click to open dropdown with country list.
|
|
77
|
+
|
|
78
|
+
**Pros:** Doesn't interrupt browsing, always accessible, familiar pattern.
|
|
79
|
+
|
|
80
|
+
**Pattern 2: Modal on First Visit**
|
|
81
|
+
|
|
82
|
+
Full-screen or centered modal on first visit. "Select your country to see accurate prices and shipping."
|
|
83
|
+
|
|
84
|
+
**Pros:** Forces initial selection, ensures accurate pricing from start.
|
|
85
|
+
**Cons:** Can be intrusive, delays browsing.
|
|
86
|
+
|
|
87
|
+
**Tradeoff:** Modal ensures selection but adds friction. Dropdown is less intrusive but users may miss it.
|
|
88
|
+
|
|
89
|
+
**Pattern 3: Inline Banner**
|
|
90
|
+
|
|
91
|
+
Sticky banner at top: "Shipping to United States? Change" with link to selector.
|
|
92
|
+
|
|
93
|
+
**Pros:** Non-intrusive reminder, doesn't block content.
|
|
94
|
+
**Cons:** Takes vertical space, easy to ignore.
|
|
95
|
+
|
|
96
|
+
### Country List Display
|
|
97
|
+
|
|
98
|
+
**Search + list:**
|
|
99
|
+
- Search input at top
|
|
100
|
+
- Alphabetical country list below
|
|
101
|
+
- Popular countries at top (US, UK, Canada, etc.)
|
|
102
|
+
- Flag icons for visual recognition
|
|
103
|
+
|
|
104
|
+
**Grouped by region:**
|
|
105
|
+
- North America, Europe, Asia, etc.
|
|
106
|
+
- Collapsible sections
|
|
107
|
+
- Helpful for large lists (100+ countries)
|
|
108
|
+
|
|
109
|
+
**Format:**
|
|
110
|
+
```
|
|
111
|
+
🇺🇸 United States (USD)
|
|
112
|
+
🇬🇧 United Kingdom (GBP)
|
|
113
|
+
🇨🇦 Canada (CAD)
|
|
114
|
+
───────────────────
|
|
115
|
+
🇩🇪 Germany (EUR)
|
|
116
|
+
🇫🇷 France (EUR)
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Show flag, country name, and currency code for clarity.
|
|
120
|
+
|
|
121
|
+
## State Management
|
|
122
|
+
|
|
123
|
+
### Storing Country Selection
|
|
124
|
+
|
|
125
|
+
**Client-side storage (recommended):**
|
|
126
|
+
- localStorage or cookies
|
|
127
|
+
- Persists across sessions
|
|
128
|
+
- Key: `region_id` or `country_code`
|
|
129
|
+
|
|
130
|
+
**Why local storage:**
|
|
131
|
+
- Fast access without API call
|
|
132
|
+
- Available immediately on page load
|
|
133
|
+
- No server round-trip needed
|
|
134
|
+
|
|
135
|
+
### Context Provider Pattern
|
|
136
|
+
|
|
137
|
+
**Recommended: Create context for region/country data.**
|
|
138
|
+
|
|
139
|
+
Provides quick access throughout the app to:
|
|
140
|
+
- Selected country
|
|
141
|
+
- Selected region (if applicable)
|
|
142
|
+
- Currency
|
|
143
|
+
- Available payment methods
|
|
144
|
+
- Shipping options
|
|
145
|
+
|
|
146
|
+
**Benefits:**
|
|
147
|
+
- Centralized country/region logic
|
|
148
|
+
- Easy access from any component
|
|
149
|
+
- Single source of truth
|
|
150
|
+
- Simplified cart and product queries
|
|
151
|
+
|
|
152
|
+
**Example structure:**
|
|
153
|
+
```typescript
|
|
154
|
+
interface RegionContext {
|
|
155
|
+
country: string
|
|
156
|
+
region?: string
|
|
157
|
+
currency: string
|
|
158
|
+
changeCountry: (country: string) => void
|
|
159
|
+
}
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### When to Apply Selection
|
|
163
|
+
|
|
164
|
+
**Apply country/region to:**
|
|
165
|
+
- Product price display (convert currency, apply regional pricing)
|
|
166
|
+
- Cart creation (set region for accurate totals)
|
|
167
|
+
- Product queries (retrieve accurate pricing)
|
|
168
|
+
- Checkout flow (shipping methods, payment options)
|
|
169
|
+
- Content display (language, measurements)
|
|
170
|
+
|
|
171
|
+
## Backend Integration
|
|
172
|
+
|
|
173
|
+
### General Backend Requirements
|
|
174
|
+
|
|
175
|
+
**What backend needs to provide:**
|
|
176
|
+
- List of available countries/regions
|
|
177
|
+
- Mapping of countries to regions (if using regional structure)
|
|
178
|
+
- Pricing per region or country
|
|
179
|
+
- Product availability by region
|
|
180
|
+
- Shipping methods by region
|
|
181
|
+
- Supported payment methods by region
|
|
182
|
+
|
|
183
|
+
**API considerations:**
|
|
184
|
+
- Fetch country/region list on app load
|
|
185
|
+
- Pass selected country/region to product queries
|
|
186
|
+
- Include region in cart creation
|
|
187
|
+
- Validate country selection on backend
|
|
188
|
+
|
|
189
|
+
### Medusa Backend Integration
|
|
190
|
+
|
|
191
|
+
**For Medusa users, regions are critical for accurate pricing.**
|
|
192
|
+
|
|
193
|
+
Medusa uses regions (not individual countries) for pricing. A region can contain multiple countries.
|
|
194
|
+
|
|
195
|
+
**Key concepts:**
|
|
196
|
+
- **Region**: Group of countries with shared pricing (e.g., "Europe" region)
|
|
197
|
+
- **Country**: Individual country within a region
|
|
198
|
+
- **Currency**: Each region has one currency
|
|
199
|
+
|
|
200
|
+
**Mapping country to region:**
|
|
201
|
+
1. Customer selects country (e.g., "Germany")
|
|
202
|
+
2. Find which region contains that country (e.g., "Europe" region)
|
|
203
|
+
3. Store region ID for cart and product operations
|
|
204
|
+
4. Use region for all pricing queries
|
|
205
|
+
|
|
206
|
+
**Required for:**
|
|
207
|
+
- Creating carts: Must pass region ID
|
|
208
|
+
- Retrieving products: Pass region to get accurate prices
|
|
209
|
+
- Product availability: Products may be region-specific
|
|
210
|
+
|
|
211
|
+
**Implementation pattern:**
|
|
212
|
+
Create a context that stores both country and region. When country changes, look up corresponding region and update both.
|
|
213
|
+
|
|
214
|
+
**For detailed Medusa region implementation, see:**
|
|
215
|
+
- Medusa storefront regions documentation: https://docs.medusajs.com/resources/storefront-development/regions/context
|
|
216
|
+
- Medusa JS SDK regions endpoints
|
|
217
|
+
- Consult Medusa MCP server for real-time API details
|
|
218
|
+
|
|
219
|
+
**Other backends:**
|
|
220
|
+
Check the ecommerce backend's documentation for country/region handling patterns.
|
|
221
|
+
|
|
222
|
+
## Detection and Defaults
|
|
223
|
+
|
|
224
|
+
### Auto-Detection
|
|
225
|
+
|
|
226
|
+
**IP-based geolocation (recommended):**
|
|
227
|
+
Detect user's country from IP address. Use as default but allow user to change.
|
|
228
|
+
|
|
229
|
+
**Implementation:**
|
|
230
|
+
- Use geolocation API or service (MaxMind, ipapi.co, CloudFlare)
|
|
231
|
+
- Server-side detection (more accurate)
|
|
232
|
+
- Set as default, show confirmation: "Shipping to United States?"
|
|
233
|
+
|
|
234
|
+
**Benefits:** Reduces friction, most users keep detected country.
|
|
235
|
+
|
|
236
|
+
**Tradeoff:** Not 100% accurate (VPNs, proxies). Always allow manual override.
|
|
237
|
+
|
|
238
|
+
### Fallback Strategy
|
|
239
|
+
|
|
240
|
+
**If detection fails or unavailable:**
|
|
241
|
+
1. Check localStorage for previous selection
|
|
242
|
+
2. Use browser language as hint (`navigator.language`)
|
|
243
|
+
3. Default to primary market (e.g., US for US-based store)
|
|
244
|
+
4. Prompt user to select on first interaction (cart, checkout)
|
|
245
|
+
|
|
246
|
+
**Never block browsing if country unknown.**
|
|
247
|
+
Allow browsing with default pricing, prompt selection before checkout.
|
|
248
|
+
|
|
249
|
+
## Mobile Considerations
|
|
250
|
+
|
|
251
|
+
**Selector placement:**
|
|
252
|
+
Mobile hamburger menu or bottom of page. Top-right in mobile header if space allows.
|
|
253
|
+
|
|
254
|
+
**Modal selector:**
|
|
255
|
+
Full-screen modal on mobile for country selection. Large touch targets (48px), search input at top, easy scrolling.
|
|
256
|
+
|
|
257
|
+
**Sticky reminder:**
|
|
258
|
+
Small banner: "Shipping to US? Change" with tap to open selector.
|
|
259
|
+
|
|
260
|
+
**Detection prompt:**
|
|
261
|
+
Bottom sheet: "We detected you're in Germany. Is this correct?" with Confirm/Change buttons.
|
|
262
|
+
|
|
263
|
+
## Checklist
|
|
264
|
+
|
|
265
|
+
**Essential features:**
|
|
266
|
+
|
|
267
|
+
- [ ] Country selector visible (header, footer, or first-visit modal)
|
|
268
|
+
- [ ] Current country clearly displayed (flag, name, currency)
|
|
269
|
+
- [ ] Dropdown or modal with country list
|
|
270
|
+
- [ ] Search functionality for long country lists
|
|
271
|
+
- [ ] Popular countries at top of list
|
|
272
|
+
- [ ] Flag icons for visual recognition
|
|
273
|
+
- [ ] Show currency code per country
|
|
274
|
+
- [ ] localStorage persistence (save selection)
|
|
275
|
+
- [ ] Context provider for region/country data
|
|
276
|
+
- [ ] Auto-detection based on IP (optional)
|
|
277
|
+
- [ ] Manual override always available
|
|
278
|
+
- [ ] Apply to product prices (currency, regional pricing)
|
|
279
|
+
- [ ] Apply to cart creation (set region)
|
|
280
|
+
- [ ] Apply to checkout (shipping, payment methods)
|
|
281
|
+
- [ ] Fallback if detection fails
|
|
282
|
+
- [ ] Mobile: Full-screen modal or bottom sheet
|
|
283
|
+
- [ ] Mobile: Large touch targets (48px)
|
|
284
|
+
- [ ] Backend integration (fetch regions, map countries)
|
|
285
|
+
- [ ] For Medusa: Region context with country-to-region mapping
|
|
286
|
+
- [ ] For Medusa: Pass region to cart and product queries
|
|
287
|
+
- [ ] ARIA label on selector button
|
|
288
|
+
- [ ] Keyboard accessible (Tab, Enter, arrows)
|
|
289
|
+
- [ ] Screen reader announces country changes
|
|
290
|
+
|
|
291
|
+
**Optional enhancements:**
|
|
292
|
+
|
|
293
|
+
- [ ] Currency conversion display (show original + converted)
|
|
294
|
+
- [ ] Language selector tied to country
|
|
295
|
+
- [ ] Shipping estimate based on country
|
|
296
|
+
- [ ] Tax estimation display
|
|
297
|
+
- [ ] Regional content (images, messaging)
|
|
298
|
+
- [ ] "Not shipping to your country?" alternative
|