astro-component-kit 0.4.0 → 0.4.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.
Files changed (180) hide show
  1. package/README.md +105 -27
  2. package/package.json +16 -3
  3. package/src/components/index.ts +2 -0
  4. package/src/components/lib/Galaxy3D.astro +249 -137
  5. package/src/components/lib/app/AppSidebar.astro +249 -0
  6. package/src/components/lib/app/AppTopbar.astro +284 -0
  7. package/src/components/lib/app/ArrivalsBoard.astro +176 -0
  8. package/src/components/lib/app/AuthCard.astro +213 -0
  9. package/src/components/lib/app/DataTable.astro +346 -0
  10. package/src/components/lib/app/GuestProfileCard.astro +133 -0
  11. package/src/components/lib/app/HousekeepingBoard.astro +189 -0
  12. package/src/components/lib/app/PageHeader.astro +157 -0
  13. package/src/components/lib/app/PlanUsageCard.astro +112 -0
  14. package/src/components/lib/app/RoomRack.astro +207 -0
  15. package/src/components/lib/app/SettingsSection.astro +96 -0
  16. package/src/components/lib/app/SwitchRow.astro +71 -0
  17. package/src/components/lib/app/TeamMembers.astro +190 -0
  18. package/src/components/lib/app/app-icons.ts +52 -0
  19. package/src/components/lib/app/index.ts +19 -0
  20. package/src/components/lib/charts/AreaChart.astro +4 -4
  21. package/src/components/lib/charts/BarChart.astro +3 -3
  22. package/src/components/lib/charts/ChartFrame.astro +10 -10
  23. package/src/components/lib/charts/DonutChart.astro +2 -2
  24. package/src/components/lib/charts/DumbbellChart.astro +1 -1
  25. package/src/components/lib/charts/ForecastLineChart.astro +1 -1
  26. package/src/components/lib/charts/GaugeChart.astro +1 -1
  27. package/src/components/lib/charts/HeatmapChart.astro +1 -1
  28. package/src/components/lib/charts/HorizontalBarChart.astro +2 -2
  29. package/src/components/lib/charts/KpiStatTile.astro +4 -4
  30. package/src/components/lib/charts/LinearProgressGauge.astro +4 -4
  31. package/src/components/lib/charts/MetricDeltaTable.astro +3 -3
  32. package/src/components/lib/charts/RadarMetricChart.astro +4 -4
  33. package/src/components/lib/charts/RadialBarChart.astro +1 -1
  34. package/src/components/lib/charts/RetentionCohortTable.astro +2 -2
  35. package/src/components/lib/charts/TreemapChart.astro +1 -1
  36. package/src/components/lib/ecommerce/CartDrawer.astro +483 -0
  37. package/src/components/lib/ecommerce/CartPageList.astro +290 -0
  38. package/src/components/lib/ecommerce/CartToast.astro +276 -0
  39. package/src/components/lib/ecommerce/CategoryTiles.astro +143 -0
  40. package/src/components/lib/ecommerce/CheckoutForm.astro +423 -0
  41. package/src/components/lib/ecommerce/CountdownBanner.astro +230 -0
  42. package/src/components/lib/ecommerce/FilterBar.astro +278 -0
  43. package/src/components/lib/ecommerce/FilterSidebar.astro +405 -0
  44. package/src/components/lib/ecommerce/LiveActivityToast.astro +213 -0
  45. package/src/components/lib/ecommerce/OrderSummary.astro +295 -0
  46. package/src/components/lib/ecommerce/ProductBuyBox.astro +247 -0
  47. package/src/components/lib/ecommerce/ProductCardMinimal.astro +229 -0
  48. package/src/components/lib/ecommerce/ProductGallery.astro +145 -0
  49. package/src/components/lib/ecommerce/ProductGrid.astro +118 -0
  50. package/src/components/lib/ecommerce/ProductMedia.astro +113 -0
  51. package/src/components/lib/ecommerce/ProductRating.astro +78 -0
  52. package/src/components/lib/ecommerce/ProductToolbar.astro +93 -0
  53. package/src/components/lib/ecommerce/PromoBar.astro +145 -0
  54. package/src/components/lib/ecommerce/StockIndicator.astro +127 -0
  55. package/src/components/lib/ecommerce/StoreHeader.astro +446 -0
  56. package/src/components/lib/ecommerce/StoreHero.astro +260 -0
  57. package/src/components/lib/ecommerce/StoreProductCard.astro +307 -0
  58. package/src/components/lib/ecommerce/TrustBadges.astro +101 -0
  59. package/src/components/lib/ecommerce/VariantPicker.astro +145 -0
  60. package/src/components/lib/ecommerce/cart-store.ts +151 -0
  61. package/src/components/lib/ecommerce/catalog-filter.ts +62 -0
  62. package/src/components/lib/ecommerce/index.ts +34 -0
  63. package/src/components/lib/ecommerce/product-icons.ts +28 -0
  64. package/src/components/lib/ecommerce/types.ts +70 -0
  65. package/src/components/lib/forms/AnimatedInput.astro +4 -2
  66. package/src/components/lib/forms/CustomRadioGroup.astro +3 -1
  67. package/src/components/lib/index.ts +2 -0
  68. package/src/components/lib/layout/BentoGrid3.astro +6 -4
  69. package/src/components/lib/layout/CenterFixedBox.astro +2 -2
  70. package/src/components/lib/layout/CenteredContainer.astro +4 -2
  71. package/src/components/lib/layout/ClusterHorizontal.astro +2 -2
  72. package/src/components/lib/layout/FeatureHero.astro +4 -2
  73. package/src/components/lib/layout/FooterCenteredMinimal.astro +4 -2
  74. package/src/components/lib/layout/FullBleedSection.astro +2 -2
  75. package/src/components/lib/layout/GalleryGrid4.astro +2 -2
  76. package/src/components/lib/layout/HolyGrailGrid.astro +11 -9
  77. package/src/components/lib/layout/LandingSectionSplit.astro +5 -3
  78. package/src/components/lib/layout/MasonryGrid.astro +2 -2
  79. package/src/components/lib/layout/MinimalFooterGrid.astro +1 -1
  80. package/src/components/lib/layout/ScrollSnapSection.astro +1 -1
  81. package/src/components/lib/layout/SidebarLayoutWrapper.astro +4 -2
  82. package/src/components/lib/layout/SplitScreenLayout.astro +3 -3
  83. package/src/components/lib/layout/StepLayoutVertical.astro +1 -1
  84. package/src/components/lib/layout/StickySidebarWrapper.astro +4 -2
  85. package/src/components/lib/sections/AgencyContactBrief.astro +194 -0
  86. package/src/components/lib/sections/AgencyFooterCta.astro +94 -0
  87. package/src/components/lib/sections/AgencyHeader.astro +161 -0
  88. package/src/components/lib/sections/AgencyHeroKinetic.astro +172 -0
  89. package/src/components/lib/sections/AgencyServicesList.astro +113 -0
  90. package/src/components/lib/sections/AgencyTeamGrid.astro +111 -0
  91. package/src/components/lib/sections/AgencyWorkGrid.astro +147 -0
  92. package/src/components/lib/sections/BlogGridSection.astro +9 -7
  93. package/src/components/lib/sections/ButtonsShowcase.astro +20 -18
  94. package/src/components/lib/sections/CardsShowcase.astro +28 -26
  95. package/src/components/lib/sections/CareersOpenings.astro +10 -8
  96. package/src/components/lib/sections/ChangelogSection.astro +14 -7
  97. package/src/components/lib/sections/ContactGlassForm.astro +10 -8
  98. package/src/components/lib/sections/ContactSplitMap.astro +11 -9
  99. package/src/components/lib/sections/CtaAppDownload.astro +13 -11
  100. package/src/components/lib/sections/CtaGlowBanner.astro +12 -10
  101. package/src/components/lib/sections/CtaNewsletterSection.astro +13 -11
  102. package/src/components/lib/sections/CtaSplitImage.astro +13 -11
  103. package/src/components/lib/sections/DataShowcase.astro +23 -21
  104. package/src/components/lib/sections/FaqAccordionSection.astro +8 -8
  105. package/src/components/lib/sections/FaqTwoColumn.astro +9 -7
  106. package/src/components/lib/sections/FeatureAlternatingRows.astro +10 -8
  107. package/src/components/lib/sections/FeatureBentoGrid.astro +13 -11
  108. package/src/components/lib/sections/FeatureIconGrid.astro +6 -6
  109. package/src/components/lib/sections/FeatureTabsShowcase.astro +13 -11
  110. package/src/components/lib/sections/FeatureTimelineFlow.astro +8 -6
  111. package/src/components/lib/sections/FeedbackShowcase.astro +15 -13
  112. package/src/components/lib/sections/FooterMegaSection.astro +13 -11
  113. package/src/components/lib/sections/FormsShowcase.astro +22 -20
  114. package/src/components/lib/sections/HeroDashboardPreview.astro +11 -9
  115. package/src/components/lib/sections/HeroGlass.astro +22 -20
  116. package/src/components/lib/sections/HeroGradient.astro +15 -13
  117. package/src/components/lib/sections/HeroMinimalCentered.astro +10 -10
  118. package/src/components/lib/sections/HeroShowcaseSplit.astro +18 -16
  119. package/src/components/lib/sections/HeroSplit.astro +13 -11
  120. package/src/components/lib/sections/HeroTerminal.astro +14 -12
  121. package/src/components/lib/sections/HeroWaitlist.astro +10 -8
  122. package/src/components/lib/sections/HowItWorksSteps.astro +12 -10
  123. package/src/components/lib/sections/IntegrationsGrid.astro +7 -7
  124. package/src/components/lib/sections/LayoutShowcase.astro +21 -19
  125. package/src/components/lib/sections/LogoCloudSection.astro +4 -4
  126. package/src/components/lib/sections/LogoWallGrid.astro +6 -4
  127. package/src/components/lib/sections/NavigationShowcase.astro +15 -13
  128. package/src/components/lib/sections/OverlaysShowcase.astro +21 -19
  129. package/src/components/lib/sections/PricingComparisonMatrix.astro +15 -13
  130. package/src/components/lib/sections/PricingSinglePlan.astro +13 -11
  131. package/src/components/lib/sections/PricingTierCards.astro +11 -9
  132. package/src/components/lib/sections/PricingToggleCards.astro +13 -13
  133. package/src/components/lib/sections/ShopCategoryHero.astro +103 -0
  134. package/src/components/lib/sections/ShopCollectionMosaic.astro +131 -0
  135. package/src/components/lib/sections/ShopFooterWordmark.astro +100 -0
  136. package/src/components/lib/sections/ShopHeaderEditorial.astro +396 -0
  137. package/src/components/lib/sections/ShopHeroEditorial.astro +151 -0
  138. package/src/components/lib/sections/ShopLookbook.astro +250 -0
  139. package/src/components/lib/sections/ShopNewsletterEditorial.astro +128 -0
  140. package/src/components/lib/sections/ShopProductRail.astro +150 -0
  141. package/src/components/lib/sections/ShopReviewsEditorial.astro +133 -0
  142. package/src/components/lib/sections/ShopValuesMarquee.astro +91 -0
  143. package/src/components/lib/sections/StatsCounterBand.astro +9 -7
  144. package/src/components/lib/sections/StatsDashboardSection.astro +4 -2
  145. package/src/components/lib/sections/StatsMetricShowcase.astro +9 -7
  146. package/src/components/lib/sections/TeamGridSection.astro +12 -10
  147. package/src/components/lib/sections/TestimonialCarousel.astro +10 -8
  148. package/src/components/lib/sections/TestimonialFeatured.astro +7 -5
  149. package/src/components/lib/sections/TestimonialGridSection.astro +7 -7
  150. package/src/components/lib/sections/TestimonialWallGlass.astro +11 -9
  151. package/src/components/lib/sections/TypographyShowcase.astro +10 -8
  152. package/src/components/lib/sections/index.ts +10 -0
  153. package/src/components/lib/templates/ecommerce/StoreCategoryPage.astro +160 -0
  154. package/src/components/lib/templates/ecommerce/StoreCheckoutPage.astro +98 -0
  155. package/src/components/lib/templates/ecommerce/StoreHomePage.astro +191 -0
  156. package/src/components/lib/templates/ecommerce/StoreLayout.astro +169 -0
  157. package/src/components/lib/templates/ecommerce/StoreProductPage.astro +165 -0
  158. package/src/components/lib/templates/ecommerce/data.ts +187 -0
  159. package/src/components/lib/templates/ecommerce/index.ts +14 -0
  160. package/src/components/lib/templates/ecommerce-editorial/EditorialBagPage.astro +52 -0
  161. package/src/components/lib/templates/ecommerce-editorial/EditorialCheckoutPage.astro +123 -0
  162. package/src/components/lib/templates/ecommerce-editorial/EditorialHomePage.astro +102 -0
  163. package/src/components/lib/templates/ecommerce-editorial/EditorialLayout.astro +216 -0
  164. package/src/components/lib/templates/ecommerce-editorial/EditorialProductPage.astro +205 -0
  165. package/src/components/lib/templates/ecommerce-editorial/EditorialShopPage.astro +112 -0
  166. package/src/components/lib/templates/ecommerce-editorial/data.ts +125 -0
  167. package/src/components/lib/templates/ecommerce-editorial/index.ts +16 -0
  168. package/src/components/lib/templates/saas-hotel/AppLayout.astro +83 -0
  169. package/src/components/lib/templates/saas-hotel/DashboardPage.astro +66 -0
  170. package/src/components/lib/templates/saas-hotel/GuestsPage.astro +65 -0
  171. package/src/components/lib/templates/saas-hotel/LandingPage.astro +213 -0
  172. package/src/components/lib/templates/saas-hotel/ReportsPage.astro +63 -0
  173. package/src/components/lib/templates/saas-hotel/ReservationsPage.astro +49 -0
  174. package/src/components/lib/templates/saas-hotel/RoomsPage.astro +48 -0
  175. package/src/components/lib/templates/saas-hotel/SettingsPage.astro +115 -0
  176. package/src/components/lib/templates/saas-hotel/SignInPage.astro +50 -0
  177. package/src/components/lib/templates/saas-hotel/data.ts +229 -0
  178. package/src/components/lib/templates/saas-hotel/index.ts +19 -0
  179. package/src/components/lib/templates/saas-hotel/lobby-theme.css +90 -0
  180. package/src/styles/global.css +95 -0
@@ -37,6 +37,7 @@ const initials = (n: string) => n.split(' ').map((p) => p[0]).slice(0, 2).join('
37
37
  const hues = ['var(--chart-1, #3987e5)', 'var(--chart-2, #d95926)', 'var(--chart-3, #199e70)', 'var(--chart-5, #d55181)', 'var(--chart-7, #9085e9)'];
38
38
  ---
39
39
 
40
+ <div class="cq-testimonial-carousel-cq">
40
41
  <section class={`tc tc--${variant} tc--${size} ${className}`} aria-labelledby={id} aria-roledescription="carousel" data-tc>
41
42
  <div class="tc__inner">
42
43
  <header class="tc__head">
@@ -73,7 +74,7 @@ const hues = ['var(--chart-1, #3987e5)', 'var(--chart-2, #d95926)', 'var(--chart
73
74
  </ul>
74
75
  </div>
75
76
  </section>
76
-
77
+ </div>
77
78
  <script>
78
79
  document.querySelectorAll<HTMLElement>('[data-tc]').forEach((root) => {
79
80
  const track = root.querySelector<HTMLElement>('.tc__track');
@@ -96,6 +97,7 @@ const hues = ['var(--chart-1, #3987e5)', 'var(--chart-2, #d95926)', 'var(--chart
96
97
  </script>
97
98
 
98
99
  <style>
100
+ .cq-testimonial-carousel-cq { container-type: inline-size; }
99
101
  .tc {
100
102
  --tc-py: 5.5rem;
101
103
  padding: var(--tc-py) var(--sp-6, 1.5rem);
@@ -114,13 +116,13 @@ const hues = ['var(--chart-1, #3987e5)', 'var(--chart-2, #d95926)', 'var(--chart
114
116
  width: 48px;
115
117
  height: 48px;
116
118
  border-radius: 50%;
117
- border: 1px solid rgba(255, 255, 255, 0.14);
118
- background: rgba(255, 255, 255, 0.03);
119
+ border: 1px solid rgb(var(--ink-rgb, 255 255 255) / 0.14);
120
+ background: rgb(var(--ink-rgb, 255 255 255) / 0.03);
119
121
  color: var(--c-text-1, #fff);
120
122
  cursor: pointer;
121
123
  transition: background 0.2s ease, border-color 0.2s ease, opacity 0.2s ease;
122
124
  }
123
- .tc__btn:hover:not(:disabled) { background: rgba(255, 255, 255, 0.08); border-color: rgba(255, 255, 255, 0.3); }
125
+ .tc__btn:hover:not(:disabled) { background: rgb(var(--ink-rgb, 255 255 255) / 0.08); border-color: rgb(var(--ink-rgb, 255 255 255) / 0.3); }
124
126
  .tc__btn:disabled { opacity: 0.35; cursor: not-allowed; }
125
127
  .tc__btn:focus-visible { outline: 2px solid var(--c-primary-light, #d4a017); outline-offset: 2px; }
126
128
  .tc__track {
@@ -148,10 +150,10 @@ const hues = ['var(--chart-1, #3987e5)', 'var(--chart-2, #d95926)', 'var(--chart
148
150
  border-radius: var(--r-lg, 20px);
149
151
  box-sizing: border-box;
150
152
  }
151
- .tc--glass .tc__card { background: linear-gradient(160deg, rgba(255, 255, 255, 0.05), rgba(255, 255, 255, 0.015)); border: 1px solid var(--c-border, rgba(255, 255, 255, 0.07)); }
152
- .tc--solid .tc__card { background: var(--c-bg-2, #111); border: 1px solid rgba(255, 255, 255, 0.05); }
153
+ .tc--glass .tc__card { background: linear-gradient(160deg, rgb(var(--ink-rgb, 255 255 255) / 0.05), rgb(var(--ink-rgb, 255 255 255) / 0.015)); border: 1px solid var(--c-border, rgb(var(--ink-rgb, 255 255 255) / 0.07)); }
154
+ .tc--solid .tc__card { background: var(--c-bg-2, #111); border: 1px solid rgb(var(--ink-rgb, 255 255 255) / 0.05); }
153
155
  .tc--quote .tc__card { border-left: 2px solid var(--c-primary-light, #d4a017); border-radius: 0; padding-left: 1.5rem; }
154
- .tc__stars { display: flex; gap: 2px; color: rgba(255, 255, 255, 0.15); }
156
+ .tc__stars { display: flex; gap: 2px; color: rgb(var(--ink-rgb, 255 255 255) / 0.15); }
155
157
  .tc__stars .is-on { color: var(--c-primary-light, #d4a017); }
156
158
  .tc__quote { margin: 0; flex: 1; }
157
159
  .tc__quote p { margin: 0; font-size: 1.0625rem; line-height: 1.6; color: var(--c-text-1, #fff); }
@@ -159,7 +161,7 @@ const hues = ['var(--chart-1, #3987e5)', 'var(--chart-2, #d95926)', 'var(--chart
159
161
  .tc__author strong { display: block; color: var(--c-text-1, #fff); font-weight: 650; }
160
162
  .tc__role { display: block; color: var(--c-text-2, #a3a3a3); font-size: 0.8125rem; }
161
163
  .tc__avatar { display: grid; place-items: center; width: 40px; height: 40px; border-radius: 50%; color: #fff; font-weight: 700; font-size: 0.8125rem; flex-shrink: 0; }
162
- @media (max-width: 560px) {
164
+ @container (max-width: 560px) {
163
165
  .tc__head { flex-direction: column; align-items: flex-start; }
164
166
  }
165
167
  </style>
@@ -44,6 +44,7 @@ const {
44
44
  const initials = name.split(' ').map((p) => p[0]).slice(0, 2).join('');
45
45
  ---
46
46
 
47
+ <div class="cq-testimonial-featured-cq">
47
48
  <section class={`tf tf--${variant} tf--${size} ${className}`} aria-label={`Customer story: ${company}`}>
48
49
  <div class="tf__inner">
49
50
  <figure class="tf__figure">
@@ -77,8 +78,9 @@ const initials = name.split(' ').map((p) => p[0]).slice(0, 2).join('');
77
78
  </div>
78
79
  </div>
79
80
  </section>
80
-
81
+ </div>
81
82
  <style>
83
+ .cq-testimonial-featured-cq { container-type: inline-size; }
82
84
  .tf {
83
85
  --tf-py: 5.5rem;
84
86
  padding: var(--tf-py) var(--sp-6, 1.5rem);
@@ -90,8 +92,8 @@ const initials = name.split(' ').map((p) => p[0]).slice(0, 2).join('');
90
92
  .tf--card .tf__inner {
91
93
  padding: clamp(2rem, 5vw, 3.5rem);
92
94
  border-radius: var(--r-xl, 28px);
93
- background: radial-gradient(circle at 0% 0%, var(--c-primary-glow, rgba(184, 134, 11, 0.14)), transparent 55%), rgba(255, 255, 255, 0.025);
94
- border: 1px solid var(--c-border, rgba(255, 255, 255, 0.08));
95
+ background: radial-gradient(circle at 0% 0%, var(--c-primary-glow, color-mix(in srgb, var(--c-primary, #b8860b) 14%, transparent)), transparent 55%), rgb(var(--ink-rgb, 255 255 255) / 0.025);
96
+ border: 1px solid var(--c-border, rgb(var(--ink-rgb, 255 255 255) / 0.08));
95
97
  }
96
98
  .tf--centered .tf__inner { grid-template-columns: 1fr; text-align: center; max-width: 860px; }
97
99
  .tf--centered .tf__author, .tf--centered .tf__company { justify-content: center; }
@@ -106,7 +108,7 @@ const initials = name.split(' ').map((p) => p[0]).slice(0, 2).join('');
106
108
  .tf__role { display: block; font-size: 0.875rem; color: var(--c-text-2, #a3a3a3); }
107
109
  .tf__avatar { display: grid; place-items: center; width: 48px; height: 48px; border-radius: 50%; background: linear-gradient(135deg, var(--chart-7, #9085e9), var(--chart-1, #3987e5)); color: #fff; font-weight: 700; }
108
110
  .tf__side { display: grid; gap: 1.5rem; }
109
- .tf__metrics { margin: 0; display: grid; gap: 1px; border-radius: var(--r-lg, 20px); overflow: hidden; background: rgba(255, 255, 255, 0.07); }
111
+ .tf__metrics { margin: 0; display: grid; gap: 1px; border-radius: var(--r-lg, 20px); overflow: hidden; background: rgb(var(--ink-rgb, 255 255 255) / 0.07); }
110
112
  .tf--centered .tf__metrics { grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); }
111
113
  .tf__metric { display: flex; flex-direction: column-reverse; gap: 0.25rem; padding: 1.25rem 1.5rem; background: var(--c-bg-1, #0a0a0a); }
112
114
  .tf__metric dt { font-size: 0.875rem; color: var(--c-text-2, #a3a3a3); }
@@ -116,5 +118,5 @@ const initials = name.split(' ').map((p) => p[0]).slice(0, 2).join('');
116
118
  .tf__link svg { transition: transform 0.2s ease; }
117
119
  .tf__link:hover svg { transform: translateX(3px); }
118
120
  .tf__link:focus-visible { outline: 2px solid var(--c-primary-light, #d4a017); outline-offset: 2px; border-radius: 4px; }
119
- @media (max-width: 820px) { .tf__inner { grid-template-columns: 1fr; } }
121
+ @container (max-width: 820px) { .tf__inner { grid-template-columns: 1fr; } }
120
122
  </style>
@@ -95,7 +95,7 @@ const testimonials = [
95
95
  letter-spacing: 0.12em;
96
96
  color: var(--c-primary-light, #d4a017);
97
97
  padding: 0.35rem 0.8rem;
98
- border: 1px solid rgba(184, 134, 11, 0.3);
98
+ border: 1px solid color-mix(in srgb, var(--c-primary, #b8860b) 30%, transparent);
99
99
  border-radius: var(--r-sm, 8px);
100
100
  margin-bottom: 1rem;
101
101
  text-transform: uppercase;
@@ -126,21 +126,21 @@ const testimonials = [
126
126
  display: flex;
127
127
  flex-direction: column;
128
128
  padding: var(--sp-8, 2rem);
129
- background: rgba(255, 255, 255, 0.02);
129
+ background: rgb(var(--ink-rgb, 255 255 255) / 0.02);
130
130
  backdrop-filter: blur(16px);
131
- border: 1px solid rgba(255, 255, 255, 0.08);
131
+ border: 1px solid rgb(var(--ink-rgb, 255 255 255) / 0.08);
132
132
  border-radius: var(--r-xl, 24px);
133
133
  transition: transform 0.3s ease, border-color 0.3s ease;
134
134
  }
135
135
 
136
136
  .testi-card:hover {
137
137
  transform: translateY(-4px);
138
- border-color: rgba(184, 134, 11, 0.3);
138
+ border-color: color-mix(in srgb, var(--c-primary, #b8860b) 30%, transparent);
139
139
  }
140
140
 
141
141
  .testi-card--highlight {
142
- background: radial-gradient(circle at top left, rgba(184, 134, 11, 0.1), rgba(255, 255, 255, 0.02) 70%);
143
- border-color: rgba(184, 134, 11, 0.4);
142
+ background: radial-gradient(circle at top left, color-mix(in srgb, var(--c-primary, #b8860b) 10%, transparent), rgb(var(--ink-rgb, 255 255 255) / 0.02) 70%);
143
+ border-color: color-mix(in srgb, var(--c-primary, #b8860b) 40%, transparent);
144
144
  }
145
145
 
146
146
  .testi-card__stars {
@@ -171,7 +171,7 @@ const testimonials = [
171
171
  height: 44px;
172
172
  border-radius: 50%;
173
173
  object-fit: cover;
174
- border: 2px solid rgba(184, 134, 11, 0.4);
174
+ border: 2px solid color-mix(in srgb, var(--c-primary, #b8860b) 40%, transparent);
175
175
  }
176
176
 
177
177
  .testi-card__name {
@@ -21,6 +21,7 @@ const {
21
21
  } = Astro.props;
22
22
  ---
23
23
 
24
+ <div class="cq-testimonial-wall-glass-cq">
24
25
  <section class={`testimonials-section ${className}`} aria-labelledby="testimonials-title">
25
26
  <div class="testimonials-bg" aria-hidden="true">
26
27
  <div class="test-glow test-glow--1"></div>
@@ -151,8 +152,9 @@ const {
151
152
  </div>
152
153
  </div>
153
154
  </section>
154
-
155
+ </div>
155
156
  <style>
157
+ .cq-testimonial-wall-glass-cq { container-type: inline-size; }
156
158
  .testimonials-section {
157
159
  position: relative;
158
160
  padding: var(--sp-20, 5rem) var(--sp-6, 1.5rem);
@@ -211,7 +213,7 @@ const {
211
213
  font-weight: 700;
212
214
  letter-spacing: 0.06em;
213
215
  text-transform: uppercase;
214
- background: rgba(184, 134, 11, 0.12);
216
+ background: color-mix(in srgb, var(--c-primary, #b8860b) 12%, transparent);
215
217
  color: #eab308;
216
218
  border: 1px solid rgba(234, 179, 8, 0.25);
217
219
  margin-bottom: var(--sp-4, 1rem);
@@ -241,7 +243,7 @@ const {
241
243
  gap: 2rem;
242
244
  padding: 1.25rem 2rem;
243
245
  background: rgba(15, 23, 42, 0.7);
244
- border: 1px solid rgba(255, 255, 255, 0.08);
246
+ border: 1px solid rgb(var(--ink-rgb, 255 255 255) / 0.08);
245
247
  border-radius: 16px;
246
248
  backdrop-filter: blur(12px);
247
249
  max-width: 750px;
@@ -284,7 +286,7 @@ const {
284
286
  .trust-sep {
285
287
  width: 1px;
286
288
  height: 40px;
287
- background: rgba(255, 255, 255, 0.1);
289
+ background: rgb(var(--ink-rgb, 255 255 255) / 0.1);
288
290
  }
289
291
 
290
292
  /* Wall Grid */
@@ -299,7 +301,7 @@ const {
299
301
  background: rgba(15, 23, 42, 0.55);
300
302
  backdrop-filter: blur(20px);
301
303
  -webkit-backdrop-filter: blur(20px);
302
- border: 1px solid rgba(255, 255, 255, 0.08);
304
+ border: 1px solid rgb(var(--ink-rgb, 255 255 255) / 0.08);
303
305
  border-radius: var(--r-xl, 18px);
304
306
  padding: 1.75rem;
305
307
  display: flex;
@@ -310,7 +312,7 @@ const {
310
312
 
311
313
  .test-card:hover {
312
314
  transform: translateY(-4px);
313
- border-color: rgba(255, 255, 255, 0.2);
315
+ border-color: rgb(var(--ink-rgb, 255 255 255) / 0.2);
314
316
  }
315
317
 
316
318
  .test-card--featured {
@@ -352,7 +354,7 @@ const {
352
354
  align-items: center;
353
355
  gap: 0.85rem;
354
356
  padding-top: 1rem;
355
- border-top: 1px solid rgba(255, 255, 255, 0.06);
357
+ border-top: 1px solid rgb(var(--ink-rgb, 255 255 255) / 0.06);
356
358
  }
357
359
 
358
360
  .author-avatar {
@@ -364,7 +366,7 @@ const {
364
366
  font-weight: 800;
365
367
  font-size: 0.85rem;
366
368
  color: #fff;
367
- border: 2px solid rgba(255, 255, 255, 0.15);
369
+ border: 2px solid rgb(var(--ink-rgb, 255 255 255) / 0.15);
368
370
  }
369
371
 
370
372
  .author-avatar--1 { background: linear-gradient(135deg, #6366f1, #a855f7); }
@@ -390,7 +392,7 @@ const {
390
392
  color: #64748b;
391
393
  }
392
394
 
393
- @media (max-width: 960px) {
395
+ @container (max-width: 960px) {
394
396
  .trust-bar {
395
397
  flex-direction: column;
396
398
  gap: 1rem;
@@ -8,6 +8,7 @@ interface Props {
8
8
  const { title = "Typography", subtitle = "Headings and text patterns." } = Astro.props;
9
9
  ---
10
10
 
11
+ <div class="cq-typography-showcase-cq">
11
12
  <section class="typography-showcase">
12
13
  <div class="container">
13
14
  <div class="showcase-header">
@@ -54,8 +55,9 @@ const { title = "Typography", subtitle = "Headings and text patterns." } = Astro
54
55
  </div>
55
56
  </div>
56
57
  </section>
57
-
58
+ </div>
58
59
  <style>
60
+ .cq-typography-showcase-cq { container-type: inline-size; }
59
61
  .typography-showcase {
60
62
  padding: var(--sp-16) 0;
61
63
  position: relative;
@@ -72,8 +74,8 @@ const { title = "Typography", subtitle = "Headings and text patterns." } = Astro
72
74
  text-transform: uppercase;
73
75
  letter-spacing: 0.1em;
74
76
  color: var(--c-primary-light);
75
- background: rgba(184,134,11,0.1);
76
- border: 1px solid rgba(184,134,11,0.25);
77
+ background: color-mix(in srgb, var(--c-primary, #b8860b) 10%, transparent);
78
+ border: 1px solid color-mix(in srgb, var(--c-primary, #b8860b) 25%, transparent);
77
79
  border-radius: var(--r-full);
78
80
  margin-bottom: var(--sp-4);
79
81
  }
@@ -95,7 +97,7 @@ const { title = "Typography", subtitle = "Headings and text patterns." } = Astro
95
97
  padding: var(--sp-12);
96
98
  background: rgba(10, 10, 10, 0.6);
97
99
  backdrop-filter: blur(20px);
98
- border: 1px solid rgba(255,255,255,0.08);
100
+ border: 1px solid rgb(var(--ink-rgb, 255 255 255) / 0.08);
99
101
  border-radius: var(--r-xl);
100
102
  margin-bottom: var(--sp-6);
101
103
  box-shadow: 0 20px 60px rgba(0,0,0,0.4);
@@ -117,9 +119,9 @@ const { title = "Typography", subtitle = "Headings and text patterns." } = Astro
117
119
  /* Typography Mockups */
118
120
  .typo-mockup {
119
121
  padding: var(--sp-6);
120
- background: rgba(255,255,255,0.02);
122
+ background: rgb(var(--ink-rgb, 255 255 255) / 0.02);
121
123
  border-radius: var(--r-md);
122
- border: 1px solid rgba(255,255,255,0.05);
124
+ border: 1px solid rgb(var(--ink-rgb, 255 255 255) / 0.05);
123
125
  }
124
126
 
125
127
  /* Gradient Heading */
@@ -221,7 +223,7 @@ const { title = "Typography", subtitle = "Headings and text patterns." } = Astro
221
223
  .usage-code {
222
224
  text-align: center;
223
225
  padding: var(--sp-4);
224
- background: rgba(255,255,255,0.02);
226
+ background: rgb(var(--ink-rgb, 255 255 255) / 0.02);
225
227
  border-radius: var(--r-md);
226
228
  }
227
229
  .usage-code code {
@@ -230,7 +232,7 @@ const { title = "Typography", subtitle = "Headings and text patterns." } = Astro
230
232
  color: var(--c-primary-light);
231
233
  }
232
234
 
233
- @media (max-width: 640px) {
235
+ @container (max-width: 640px) {
234
236
  .typo-stack { gap: var(--sp-5); }
235
237
  .typo-mockup { padding: var(--sp-4); }
236
238
  .preview-stage { padding: var(--sp-8) var(--sp-4); }
@@ -55,3 +55,13 @@ export { default as LogoWallGrid } from './LogoWallGrid.astro';
55
55
  export { default as BlogGridSection } from './BlogGridSection.astro';
56
56
  export { default as ChangelogSection } from './ChangelogSection.astro';
57
57
  export { default as FooterMegaSection } from './FooterMegaSection.astro';
58
+ export { default as ShopHeaderEditorial } from './ShopHeaderEditorial.astro';
59
+ export { default as ShopHeroEditorial } from './ShopHeroEditorial.astro';
60
+ export { default as ShopCollectionMosaic } from './ShopCollectionMosaic.astro';
61
+ export { default as ShopProductRail } from './ShopProductRail.astro';
62
+ export { default as ShopLookbook } from './ShopLookbook.astro';
63
+ export { default as ShopValuesMarquee } from './ShopValuesMarquee.astro';
64
+ export { default as ShopReviewsEditorial } from './ShopReviewsEditorial.astro';
65
+ export { default as ShopNewsletterEditorial } from './ShopNewsletterEditorial.astro';
66
+ export { default as ShopFooterWordmark } from './ShopFooterWordmark.astro';
67
+ export { default as ShopCategoryHero } from './ShopCategoryHero.astro';
@@ -0,0 +1,160 @@
1
+ ---
2
+ /**
3
+ * StoreCategoryPage — E-commerce template catalogue: breadcrumb, category chips, toolbar
4
+ * with live count + sort, FilterSidebar and ProductGrid (instant client-side filtering).
5
+ *
6
+ * Usage (src/pages/shop.astro):
7
+ * import { StoreCategoryPage } from 'astro-component-kit/templates/ecommerce';
8
+ * <StoreCategoryPage />
9
+ * Category links use `?category=<id>`; pass `category` to build one static page per category.
10
+ *
11
+ * @param {StoreConfig} store - Catalogue and settings. Default: demo store.
12
+ * @param {StoreRoutes} routes - Page URLs.
13
+ * @param {string} category - Pre-selected category id (optional).
14
+ * @param {boolean} seedCart - Pre-fill the cart with demo items. Default false.
15
+ * @param {string} theme - Initial theme (dark|light|auto). Default 'dark'.
16
+ * @param {boolean} noindex - Add robots noindex. Default false.
17
+ */
18
+ import StoreLayout from './StoreLayout.astro';
19
+ import ProductToolbar from '../../ecommerce/ProductToolbar.astro';
20
+ import FilterSidebar from '../../ecommerce/FilterSidebar.astro';
21
+ import ProductGrid from '../../ecommerce/ProductGrid.astro';
22
+ import TrustBadges from '../../ecommerce/TrustBadges.astro';
23
+ import { demoStore, defaultRoutes, categoryHref, categoryNames, type StoreConfig, type StoreRoutes } from './data';
24
+
25
+ interface Props {
26
+ store?: StoreConfig;
27
+ routes?: StoreRoutes;
28
+ category?: string;
29
+ seedCart?: boolean;
30
+ noindex?: boolean;
31
+ theme?: 'dark' | 'light' | 'auto';
32
+ }
33
+
34
+ const { store = demoStore, routes = defaultRoutes, category, seedCart = false, noindex = false, theme = 'dark' } = Astro.props;
35
+
36
+ const active = store.categories.find((c) => c.id === category);
37
+ const names = categoryNames(store);
38
+ const maxPrice = Math.ceil(Math.max(...store.products.map((p) => p.price)) / 50) * 50;
39
+ const colors = Array.from(new Map(store.products.flatMap((p) => p.colors ?? []).map((c) => [c.name, c])).values());
40
+ const filterCats = store.categories.map((c) => ({ id: c.id, name: c.name, count: store.products.filter((p) => p.category === c.id).length }));
41
+ const title = active ? active.name : 'All products';
42
+ const description = active?.description ?? 'Everything we make, in one place. Filter by category, price, colour and rating.';
43
+ ---
44
+
45
+ <StoreLayout theme={theme} title={title} description={description} store={store} routes={routes} currentHref={routes.shop} seedCart={seedCart} noindex={noindex}>
46
+ <div class="store-container shop">
47
+ <nav class="crumbs" aria-label="Breadcrumb">
48
+ <ol>
49
+ <li><a href={routes.home}>Home</a></li>
50
+ <li><a href={routes.shop} aria-current={active ? undefined : 'page'}>Shop</a></li>
51
+ {active && <li><span aria-current="page">{active.name}</span></li>}
52
+ </ol>
53
+ </nav>
54
+
55
+ <ProductToolbar title={title} description={description} total={store.products.length} target="shop-grid" filtersId="shop-filters" />
56
+
57
+ <ul class="chips" aria-label="Categories">
58
+ <li><a class="chip" href={routes.shop} aria-current={!active ? 'page' : undefined}>All</a></li>
59
+ {store.categories.map((c) => (
60
+ <li><a class="chip" href={categoryHref(routes, c.id)} aria-current={active?.id === c.id ? 'page' : undefined} data-chip={c.id}>{c.name}</a></li>
61
+ ))}
62
+ </ul>
63
+
64
+ <div class="shop__layout">
65
+ <div class="shop__filters">
66
+ <FilterSidebar
67
+ target="shop-grid"
68
+ id="shop-filters"
69
+ categories={filterCats}
70
+ selected={active ? [active.id] : []}
71
+ maxPrice={maxPrice}
72
+ colors={colors}
73
+ currency={store.currency}
74
+ locale={store.locale}
75
+ />
76
+ </div>
77
+ <ProductGrid
78
+ id="shop-grid"
79
+ products={store.products}
80
+ productBase={routes.product}
81
+ categoryNames={names}
82
+ columns={3}
83
+ currency={store.currency}
84
+ locale={store.locale}
85
+ cartKey={store.cartKey}
86
+ openCart={false}
87
+ />
88
+ </div>
89
+
90
+ <div class="shop__trust">
91
+ <TrustBadges variant="divided" size="sm" />
92
+ </div>
93
+ </div>
94
+ </StoreLayout>
95
+
96
+ <script>
97
+ // Category chips filter in place (no reload) and keep FilterSidebar in sync.
98
+ document.querySelectorAll<HTMLAnchorElement>('.chips a').forEach((chip) => {
99
+ chip.addEventListener('click', (e) => {
100
+ const form = document.getElementById('shop-filters') as HTMLFormElement | null;
101
+ if (!form) return;
102
+ e.preventDefault();
103
+ const id = chip.dataset.chip;
104
+ form.querySelectorAll<HTMLInputElement>('input[name="category"]').forEach((i) => { i.checked = id ? i.value === id : false; });
105
+ form.dispatchEvent(new Event('change', { bubbles: true }));
106
+ });
107
+ });
108
+ const syncChips = () => {
109
+ const form = document.getElementById('shop-filters') as HTMLFormElement | null;
110
+ if (!form) return;
111
+ const checked = Array.from(form.querySelectorAll<HTMLInputElement>('input[name="category"]:checked')).map((i) => i.value);
112
+ document.querySelectorAll<HTMLAnchorElement>('.chips a').forEach((chip) => {
113
+ const id = chip.dataset.chip;
114
+ const on = id ? checked.length === 1 && checked[0] === id : checked.length === 0;
115
+ if (on) chip.setAttribute('aria-current', 'page');
116
+ else chip.removeAttribute('aria-current');
117
+ });
118
+ };
119
+ document.getElementById('shop-filters')?.addEventListener('change', syncChips);
120
+ document.getElementById('shop-filters')?.addEventListener('reset', () => window.setTimeout(syncChips, 0));
121
+ syncChips();
122
+ </script>
123
+
124
+ <style>
125
+ .shop { padding-block: var(--sp-6) clamp(3rem, 7vw, 5rem); }
126
+
127
+ .crumbs ol { display: flex; flex-wrap: wrap; gap: var(--sp-2); margin: 0 0 var(--sp-6); padding: 0; list-style: none; font-size: 0.85rem; }
128
+ .crumbs li { display: flex; align-items: center; gap: var(--sp-2); color: var(--c-text-2); }
129
+ .crumbs li + li::before { content: '/'; opacity: 0.5; }
130
+ .crumbs a { color: var(--c-text-2); }
131
+ .crumbs a:hover { color: var(--c-text-1); }
132
+ .crumbs [aria-current='page'] { color: var(--c-text-1); font-weight: 600; }
133
+
134
+ .chips { display: flex; gap: var(--sp-2); margin: 0 0 var(--sp-6); padding: 0 0 4px; list-style: none; overflow-x: auto; scrollbar-width: none; }
135
+ .chip {
136
+ display: inline-flex;
137
+ align-items: center;
138
+ min-height: 40px;
139
+ padding: 0 var(--sp-4);
140
+ border-radius: var(--r-full);
141
+ border: 1px solid rgb(var(--ink-rgb, 255 255 255) / 0.1);
142
+ color: var(--c-text-2);
143
+ font-size: 0.88rem;
144
+ font-weight: 600;
145
+ white-space: nowrap;
146
+ transition: background 0.2s ease, color 0.2s ease, border-color 0.2s ease;
147
+ }
148
+ .chip:hover { color: var(--c-text-1); border-color: rgb(var(--ink-rgb, 255 255 255) / 0.25); }
149
+ .chip[aria-current='page'] { background: var(--c-text-1); color: var(--c-bg); border-color: var(--c-text-1); }
150
+ .chip:focus-visible { outline: 2px solid var(--c-primary-light); outline-offset: 2px; }
151
+
152
+ .shop__layout { display: grid; grid-template-columns: 260px minmax(0, 1fr); gap: var(--sp-8); align-items: start; }
153
+ .shop__filters { position: sticky; top: 88px; }
154
+ .shop__trust { margin-top: clamp(3rem, 6vw, 4.5rem); }
155
+
156
+ @media (max-width: 900px) {
157
+ .shop__layout { grid-template-columns: 1fr; gap: var(--sp-4); }
158
+ .shop__filters { position: static; }
159
+ }
160
+ </style>
@@ -0,0 +1,98 @@
1
+ ---
2
+ /**
3
+ * StoreCheckoutPage — E-commerce template checkout in focus mode: StepBreadcrumbBar,
4
+ * CheckoutForm (contact, delivery, shipping, payment) and a live OrderSummary.
5
+ *
6
+ * Usage (src/pages/checkout.astro):
7
+ * import { StoreCheckoutPage } from 'astro-component-kit/templates/ecommerce';
8
+ * <StoreCheckoutPage />
9
+ *
10
+ * @param {StoreConfig} store - Catalogue and settings. Default: demo store.
11
+ * @param {StoreRoutes} routes - Page URLs.
12
+ * @param {boolean} seedCart - Pre-fill the cart with demo items. Default false.
13
+ * @param {string} theme - Initial theme (dark|light|auto). Default 'dark'.
14
+ * @param {boolean} noindex - Add robots noindex. Default true (checkout pages should not be indexed).
15
+ */
16
+ import StoreLayout from './StoreLayout.astro';
17
+ import StepBreadcrumbBar from '../../navigation/StepBreadcrumbBar.astro';
18
+ import CheckoutForm from '../../ecommerce/CheckoutForm.astro';
19
+ import OrderSummary from '../../ecommerce/OrderSummary.astro';
20
+ import { demoStore, defaultRoutes, type StoreConfig, type StoreRoutes } from './data';
21
+
22
+ interface Props {
23
+ store?: StoreConfig;
24
+ routes?: StoreRoutes;
25
+ seedCart?: boolean;
26
+ noindex?: boolean;
27
+ theme?: 'dark' | 'light' | 'auto';
28
+ }
29
+
30
+ const { store = demoStore, routes = defaultRoutes, seedCart = false, noindex = true, theme = 'dark' } = Astro.props;
31
+ ---
32
+
33
+ <StoreLayout theme={theme} title="Checkout" description={`Secure checkout — ${store.name}`} store={store} routes={routes} seedCart={seedCart} noindex={noindex} minimal>
34
+ <div class="store-container co">
35
+ <div class="co__steps" data-co-steps>
36
+ <StepBreadcrumbBar
37
+ steps={[
38
+ { step: 1, label: 'Cart', status: 'complete', href: routes.shop },
39
+ { step: 2, label: 'Details & payment', status: 'active', href: '#checkout' },
40
+ { step: 3, label: 'Confirmation', status: 'upcoming', href: '#checkout' },
41
+ ]}
42
+ />
43
+ </div>
44
+
45
+ <div class="co__head">
46
+ <h1>Checkout</h1>
47
+ <a href={routes.shop}><span aria-hidden="true">←</span> Continue shopping</a>
48
+ </div>
49
+
50
+ <div class="co__layout">
51
+ <CheckoutForm
52
+ id="checkout"
53
+ shippingRates={store.shippingRates}
54
+ freeShippingThreshold={store.freeShippingThreshold}
55
+ cartKey={store.cartKey}
56
+ currency={store.currency}
57
+ locale={store.locale}
58
+ continueHref={routes.home}
59
+ />
60
+ <OrderSummary
61
+ cartKey={store.cartKey}
62
+ shippingRates={store.shippingRates}
63
+ freeShippingThreshold={store.freeShippingThreshold}
64
+ taxRate={store.taxRate}
65
+ promoCodes={store.promoCodes}
66
+ currency={store.currency}
67
+ locale={store.locale}
68
+ />
69
+ </div>
70
+ </div>
71
+ </StoreLayout>
72
+
73
+ <script>
74
+ // Move the step bar to "Confirmation" once the order is placed.
75
+ document.addEventListener('ack:order-placed', () => {
76
+ const items = Array.from(document.querySelectorAll<HTMLElement>('[data-co-steps] .step-nav__item'));
77
+ items.forEach((item, i) => {
78
+ item.classList.remove('step-nav__item--active', 'step-nav__item--upcoming');
79
+ item.classList.add(i === items.length - 1 ? 'step-nav__item--active' : 'step-nav__item--complete');
80
+ const link = item.querySelector('a');
81
+ if (i === items.length - 1) link?.setAttribute('aria-current', 'step');
82
+ else link?.removeAttribute('aria-current');
83
+ });
84
+ });
85
+ </script>
86
+
87
+ <style>
88
+ .co { padding-block: var(--sp-8) clamp(3rem, 7vw, 5rem); }
89
+ .co__steps { max-width: 720px; margin: 0 auto var(--sp-8); }
90
+ .co__head { display: flex; align-items: baseline; justify-content: space-between; gap: var(--sp-4); margin-bottom: var(--sp-6); }
91
+ .co__head h1 { margin: 0; font-size: clamp(1.8rem, 4vw, 2.6rem); font-weight: 900; letter-spacing: -0.035em; color: var(--c-text-1); }
92
+ .co__head a { display: inline-flex; align-items: center; gap: 0.35rem; min-height: 44px; font-weight: 600; font-size: 0.9rem; }
93
+ .co__layout { display: grid; grid-template-columns: minmax(0, 1.4fr) minmax(320px, 1fr); gap: clamp(1.5rem, 4vw, 3rem); align-items: start; }
94
+ @media (max-width: 960px) {
95
+ .co__layout { grid-template-columns: 1fr; }
96
+ .co__layout > :global(.o-summary) { order: -1; }
97
+ }
98
+ </style>