hey-pharmacist-ecommerce 1.1.17 → 1.1.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. package/dist/index.d.mts +43 -43
  2. package/dist/index.d.ts +43 -43
  3. package/dist/index.js +4288 -2606
  4. package/dist/index.js.map +1 -1
  5. package/dist/index.mjs +4047 -2365
  6. package/dist/index.mjs.map +1 -1
  7. package/package.json +3 -3
  8. package/src/components/AccountOrdersTab.tsx +1 -1
  9. package/src/components/AccountSettingsTab.tsx +6 -6
  10. package/src/components/FilterChips.tsx +2 -2
  11. package/src/components/Header.tsx +2 -2
  12. package/src/components/Notification.tsx +3 -3
  13. package/src/components/OrderCard.tsx +2 -2
  14. package/src/components/ProductCard.tsx +32 -12
  15. package/src/components/QuickViewModal.tsx +13 -9
  16. package/src/components/ui/Button.tsx +3 -3
  17. package/src/components/ui/Card.tsx +1 -1
  18. package/src/components/ui/Input.tsx +1 -1
  19. package/src/components/ui/Modal.tsx +1 -1
  20. package/src/components/ui/Skeleton.tsx +3 -3
  21. package/src/screens/AddressesScreen.tsx +7 -7
  22. package/src/screens/CartScreen.tsx +8 -8
  23. package/src/screens/ChangePasswordScreen.tsx +1 -1
  24. package/src/screens/CheckoutScreen.tsx +10 -10
  25. package/src/screens/CurrentOrdersScreen.tsx +6 -6
  26. package/src/screens/EditProfileScreen.tsx +1 -1
  27. package/src/screens/LoginScreen.tsx +2 -2
  28. package/src/screens/NewAddressScreen.tsx +3 -3
  29. package/src/screens/OrdersScreen.tsx +2 -2
  30. package/src/screens/ProductDetailScreen.tsx +13 -13
  31. package/src/screens/ProfileScreen.tsx +2 -2
  32. package/src/screens/RegisterScreen.tsx +1 -1
  33. package/src/screens/ShopScreen.tsx +19 -19
  34. package/src/screens/WishlistScreen.tsx +4 -4
  35. package/src/styles/globals.css +114 -7
@@ -26,8 +26,8 @@ export function CurrentOrdersScreen() {
26
26
 
27
27
  return (
28
28
  <div className="min-h-screen bg-slate-50">
29
- <section className="relative overflow-hidden bg-gradient-to-br from-[rgb(var(--header-from))] via-[rgb(var(--header-via))] to-[rgb(var(--header-to))] text-white">
30
- <div className="absolute inset-0 bg-[radial-gradient(circle_at_top_left,_rgba(255,255,255,0.35),_transparent_60%)]" />
29
+ <section className="relative overflow-hidden bg-linear-to-br from-[rgb(var(--header-from))] via-[rgb(var(--header-via))] to-[rgb(var(--header-to))] text-white">
30
+ <div className="absolute inset-0 bg-[radial-gradient(circle_at_top_left,rgba(255,255,255,0.35),transparent_60%)]" />
31
31
  <div className="relative container mx-auto px-4 py-16">
32
32
  <div className="flex flex-col gap-6 md:flex-row md:items-center md:justify-between">
33
33
  <motion.div
@@ -35,7 +35,7 @@ export function CurrentOrdersScreen() {
35
35
  animate={{ opacity: 1, y: 0 }}
36
36
  className="space-y-4"
37
37
  >
38
- <span className="inline-flex items-center gap-2 rounded-full bg-white/15 px-3 py-1 text-sm font-semibold uppercase tracking-[0.35em] text-white/70 backdrop-blur">
38
+ <span className="inline-flex items-center gap-2 rounded-full bg-white/15 px-3 py-1 text-sm font-semibold uppercase tracking-[0.35em] text-white/70 backdrop-blur-sm">
39
39
  <Truck className="h-4 w-4" />
40
40
  Live order tracking
41
41
  </span>
@@ -49,7 +49,7 @@ export function CurrentOrdersScreen() {
49
49
  initial={{ opacity: 0, y: 24 }}
50
50
  animate={{ opacity: 1, y: 0 }}
51
51
  transition={{ delay: 0.1 }}
52
- className="rounded-3xl bg-white/15 p-6 backdrop-blur"
52
+ className="rounded-3xl bg-white/15 p-6 backdrop-blur-sm"
53
53
  >
54
54
  <p className="text-sm font-semibold uppercase tracking-[0.35em] text-white/70">
55
55
  Quick actions
@@ -93,7 +93,7 @@ export function CurrentOrdersScreen() {
93
93
  ))}
94
94
  </div>
95
95
  ) : (
96
- <div className="rounded-3xl border border-slate-100 bg-white p-10 shadow-sm">
96
+ <div className="rounded-3xl border border-slate-100 bg-white p-10 shadow-xs">
97
97
  <EmptyState
98
98
  icon={PackageCheck}
99
99
  title="No active orders"
@@ -135,7 +135,7 @@ export function CurrentOrdersScreen() {
135
135
  </div>
136
136
  </div>
137
137
 
138
- <div className="rounded-3xl border border-primary-100 bg-primary-50/70 p-6 text-sm text-primary-700 shadow-sm">
138
+ <div className="rounded-3xl border border-primary-100 bg-primary-50/70 p-6 text-sm text-primary-700 shadow-xs">
139
139
  <p className="font-semibold uppercase tracking-[0.3em]">Need support?</p>
140
140
  <p className="mt-3 leading-relaxed">
141
141
  Our fulfillment team is online 7 days a week. Message us if you need to adjust
@@ -149,7 +149,7 @@ export function EditProfileScreen() {
149
149
  </Button>
150
150
  <Button
151
151
  type="button"
152
- variant="outline"
152
+ variant="outline-solid"
153
153
  size="lg"
154
154
  className="border-slate-300 text-slate-800 hover:bg-slate-50"
155
155
  onClick={() => router.push(buildPath('/account'))}
@@ -71,7 +71,7 @@ export function LoginScreen() {
71
71
  }
72
72
 
73
73
  return (
74
- <div className="min-h-screen bg-gradient-to-b from-[#F8FAFC] to-[#EBF4FB]">
74
+ <div className="min-h-screen bg-linear-to-b from-[#F8FAFC] to-[#EBF4FB]">
75
75
  <div className="grid min-h-screen overflow-hidden pb-12">
76
76
  <motion.section
77
77
  initial={{ opacity: 0, x: 24 }}
@@ -137,7 +137,7 @@ export function LoginScreen() {
137
137
  <label className="flex items-center gap-2 text-slate-600">
138
138
  <input
139
139
  type="checkbox"
140
- className="h-4 w-4 rounded border-slate-300 text-primary-600 focus:ring-primary-500"
140
+ className="h-4 w-4 rounded-sm border-slate-300 text-primary-600 focus:ring-primary-500"
141
141
  />
142
142
  Remember me
143
143
  </label>
@@ -91,8 +91,8 @@ export default function NewAddressPage() {
91
91
 
92
92
  return (
93
93
  <div className="min-h-screen bg-slate-50">
94
- <div className="relative bg-gradient-to-br from-[rgb(var(--header-from))] via-[rgb(var(--header-via))] to-[rgb(var(--header-to))] text-white">
95
- <div className="absolute inset-0 bg-[radial-gradient(circle_at_top_left,_rgba(255,255,255,0.35),_transparent_60%)]" />
94
+ <div className="relative bg-linear-to-br from-[rgb(var(--header-from))] via-[rgb(var(--header-via))] to-[rgb(var(--header-to))] text-white">
95
+ <div className="absolute inset-0 bg-[radial-gradient(circle_at_top_left,rgba(255,255,255,0.35),transparent_60%)]" />
96
96
  <div className="relative container mx-auto px-4 py-8">
97
97
  <button
98
98
  onClick={() => router.back()}
@@ -175,7 +175,7 @@ export default function NewAddressPage() {
175
175
  <div className="flex justify-end gap-4">
176
176
  <Button
177
177
  type="button"
178
- variant="outline"
178
+ variant="outline-solid"
179
179
  onClick={() => router.back()}
180
180
  >
181
181
  Cancel
@@ -112,7 +112,7 @@ export function OrdersScreen() {
112
112
  {!isLoading && pagination.totalPages > 1 && hasOrders && (
113
113
  <div className="mt-8 flex flex-wrap items-center justify-center gap-4 pt-6 border-t border-gray-200">
114
114
  <Button
115
- variant="outline"
115
+ variant="outline-solid"
116
116
  onClick={() => setPage((current) => Math.max(1, current - 1))}
117
117
  disabled={page === 1}
118
118
  className="rounded-full border-2 border-slate-200 bg-white px-4 py-2 text-sm font-medium text-slate-700 hover:bg-gray-50 transition-colors disabled:opacity-50 disabled:cursor-not-allowed"
@@ -124,7 +124,7 @@ export function OrdersScreen() {
124
124
  Page {page} of {pagination.totalPages}
125
125
  </span>
126
126
  <Button
127
- variant="outline"
127
+ variant="outline-solid"
128
128
  onClick={() =>
129
129
  setPage((current) => Math.min(pagination.totalPages, current + 1))
130
130
  }
@@ -293,7 +293,7 @@ export function ProductDetailScreen({ productId }: ProductDetailScreenProps) {
293
293
  ))}
294
294
  </div>
295
295
  </div>
296
- <div className="space-y-4 rounded-3xl bg-white p-6 shadow-sm">
296
+ <div className="space-y-4 rounded-3xl bg-white p-6 shadow-xs">
297
297
  <div className="h-8 w-32 animate-pulse rounded-full bg-slate-200" />
298
298
  <div className="h-10 w-48 animate-pulse rounded-full bg-slate-200" />
299
299
  <div className="h-6 w-full animate-pulse rounded-full bg-slate-200" />
@@ -310,7 +310,7 @@ export function ProductDetailScreen({ productId }: ProductDetailScreenProps) {
310
310
  return (
311
311
  <div className="min-h-screen bg-slate-50">
312
312
  <div className="container mx-auto px-4 py-16">
313
- <div className="rounded-3xl bg-white p-10 text-center shadow-sm">
313
+ <div className="rounded-3xl bg-white p-10 text-center shadow-xs">
314
314
  <Sparkles className="mx-auto h-10 w-10 text-primary-500" />
315
315
  <h1 className="mt-6 text-2xl font-semibold text-gray-900">Product not found</h1>
316
316
  <p className="mt-2 text-gray-600">
@@ -381,10 +381,10 @@ export function ProductDetailScreen({ productId }: ProductDetailScreenProps) {
381
381
  ) : null}
382
382
 
383
383
  <div className="absolute top-6 left-6 flex flex-col gap-3">
384
- {product.salePrice && (
384
+ {discount > 0 && (
385
385
  <div className="bg-[#E67E50] text-white rounded-full px-4 py-2">
386
386
  <span className="font-['Poppins',sans-serif] font-bold text-[12px] uppercase tracking-wide">
387
- Save {product.discount}%
387
+ Save {discount}%
388
388
  </span>
389
389
  </div>
390
390
  )}
@@ -442,7 +442,7 @@ export function ProductDetailScreen({ productId }: ProductDetailScreenProps) {
442
442
  {product.brand} • {product.parentCategories?.[0].name}
443
443
  </p>
444
444
  <h1 className="text-3xl font-['Poppins',sans-serif] font-semibold text-secondary tracking-[-1.5px] mb-3">
445
- {product.name}
445
+ {selectedVariant?.name || product.name}
446
446
  </h1>
447
447
  {/* Rating */}
448
448
  <div className="flex items-center gap-3">
@@ -465,16 +465,16 @@ export function ProductDetailScreen({ productId }: ProductDetailScreenProps) {
465
465
 
466
466
  <div className="flex items-center gap-3 mb-6 pb-6 border-b-2 border-gray-100">
467
467
  <span className="font-['Poppins',sans-serif] font-bold text-[40px] text-[#E67E50]">
468
- {selectedVariant ? formatPrice(selectedVariant.finalPrice) : formatPrice(product.finalPrice || product.price || 0)}
468
+ ${variantPrice.toFixed(2)}
469
469
  </span>
470
470
  {variantComparePrice && variantComparePrice > variantPrice && (
471
471
  <>
472
472
  <span className="font-['Poppins',sans-serif] text-[24px] text-muted line-through">
473
- ${product.price.toFixed(2)}
473
+ ${variantComparePrice.toFixed(2)}
474
474
  </span>
475
475
  <div className="px-3 py-1 rounded-full bg-[#E67E50]/10">
476
476
  <span className="font-['Poppins',sans-serif] font-semibold text-[13px] text-[#E67E50]">
477
- Save ${formatPrice(variantComparePrice)}
477
+ Save ${formatPrice(variantComparePrice - variantPrice)}
478
478
  </span>
479
479
  </div>
480
480
  </>
@@ -495,8 +495,8 @@ export function ProductDetailScreen({ productId }: ProductDetailScreenProps) {
495
495
  </>
496
496
  ) : selectedVariant.inventoryCount <= 10 ? (
497
497
  <>
498
- <div className="size-3 rounded-full bg-orange-500 animate-pulse" />
499
- <span className="font-['Poppins',sans-serif] text-[13px] text-orange-600 font-medium">
498
+ <div className="size-3 rounded-full bg-primary animate-pulse" />
499
+ <span className="font-['Poppins',sans-serif] text-[13px] text-primary font-medium">
500
500
  Only {selectedVariant.inventoryCount} left in stock - Order soon!
501
501
  </span>
502
502
  </>
@@ -547,7 +547,7 @@ export function ProductDetailScreen({ productId }: ProductDetailScreenProps) {
547
547
  : 'border-gray-200 hover:border-primary/50'
548
548
  }`}
549
549
  >
550
- <div className={`relative h-12 w-12 flex-shrink-0 overflow-hidden rounded-full border-2 ${isSelected ? 'border-primary' : 'border-slate-200'}`}>
550
+ <div className={`relative h-12 w-12 shrink-0 overflow-hidden rounded-full border-2 ${isSelected ? 'border-primary' : 'border-slate-200'}`}>
551
551
  <Image
552
552
  src={variantImage}
553
553
  alt={variant.name || 'Variant image'}
@@ -565,7 +565,7 @@ export function ProductDetailScreen({ productId }: ProductDetailScreenProps) {
565
565
  )}
566
566
  </div>
567
567
  {isSelected && (
568
- <Check className="h-5 w-5 text-secondary flex-shrink-0" />
568
+ <Check className="h-5 w-5 text-secondary shrink-0" />
569
569
  )}
570
570
  </button>
571
571
  );
@@ -648,7 +648,7 @@ export function ProductDetailScreen({ productId }: ProductDetailScreenProps) {
648
648
  </div>
649
649
 
650
650
  {/* Benefits */}
651
- <div className="grid grid-cols-1 sm:grid-cols-2 gap-4 p-6 bg-gradient-to-br from-[#5B9BD5]/5 to-[#2B4B7C]/5 rounded-[24px]">
651
+ <div className="grid grid-cols-1 sm:grid-cols-2 gap-4 p-6 bg-linear-to-br from-[#5B9BD5]/5 to-[#2B4B7C]/5 rounded-[24px]">
652
652
  <div className="flex items-start gap-3">
653
653
  <div className="size-10 rounded-full bg-white flex items-center justify-center shrink-0">
654
654
  <Truck className="size-5 text-primary" />
@@ -89,7 +89,7 @@ export default function AccountPage() {
89
89
  };
90
90
 
91
91
  return (
92
- <div className="min-h-screen bg-gradient-to-b from-[#F8FAFC] to-[#EBF4FB]">
92
+ <div className="min-h-screen bg-linear-to-b from-[#F8FAFC] to-[#EBF4FB]">
93
93
  {/* Header */}
94
94
  <div className="">
95
95
  <div className="container mx-auto px-4 py-4">
@@ -110,7 +110,7 @@ export default function AccountPage() {
110
110
 
111
111
  {/* Tab Content */}
112
112
  <div className="container mx-auto max-w-7xl">
113
- <div className="rounded-2xl shadow-sm">
113
+ <div className="rounded-2xl shadow-xs">
114
114
  {renderTabContent()}
115
115
  </div>
116
116
  </div>
@@ -88,7 +88,7 @@ export function RegisterScreen() {
88
88
  };
89
89
 
90
90
  return (
91
- <div className="min-h-screen bg-gradient-to-b from-[#F8FAFC] to-[#EBF4FB]">
91
+ <div className="min-h-screen bg-linear-to-b from-[#F8FAFC] to-[#EBF4FB]">
92
92
  <div className="grid min-h-screen overflow-hidden pb-12">
93
93
  <motion.section
94
94
  initial={{ opacity: 0, x: 24 }}
@@ -674,7 +674,7 @@ export function ShopScreen({ initialFilters = {}, categoryName }: ShopScreenProp
674
674
  placeholder="Search..."
675
675
  value={searchQuery}
676
676
  onChange={handleInputChange}
677
- className="w-full pl-10 pr-4 py-2.5 rounded-xl border-2 border-gray-200 focus:border-primary focus:outline-none font-['Poppins',sans-serif] text-[13px] text-secondary"
677
+ className="w-full pl-10 pr-4 py-2.5 rounded-xl border-2 border-gray-200 focus:border-primary focus:outline-hidden font-['Poppins',sans-serif] text-[13px] text-secondary"
678
678
  />
679
679
  </div>
680
680
  </div>
@@ -822,7 +822,7 @@ export function ShopScreen({ initialFilters = {}, categoryName }: ShopScreenProp
822
822
  onChange={(event) =>
823
823
  setCustomPrice((current) => ({ ...current, min: event.target.value }))
824
824
  }
825
- className="w-1/2 px-4 py-2.5 rounded-xl border-2 border-gray-200 focus:border-primary focus:outline-none font-['Poppins',sans-serif] text-[13px] text-secondary"
825
+ className="w-1/2 px-4 py-2.5 rounded-xl border-2 border-gray-200 focus:border-primary focus:outline-hidden font-['Poppins',sans-serif] text-[13px] text-secondary"
826
826
  />
827
827
  <Input
828
828
  type="number"
@@ -832,7 +832,7 @@ export function ShopScreen({ initialFilters = {}, categoryName }: ShopScreenProp
832
832
  onChange={(event) =>
833
833
  setCustomPrice((current) => ({ ...current, max: event.target.value }))
834
834
  }
835
- className="w-1/2 px-4 py-2.5 rounded-xl border-2 border-gray-200 focus:border-primary focus:outline-none font-['Poppins',sans-serif] text-[13px] text-secondary"
835
+ className="w-1/2 px-4 py-2.5 rounded-xl border-2 border-gray-200 focus:border-primary focus:outline-hidden font-['Poppins',sans-serif] text-[13px] text-secondary"
836
836
  />
837
837
  </div>
838
838
  <button
@@ -881,8 +881,8 @@ export function ShopScreen({ initialFilters = {}, categoryName }: ShopScreenProp
881
881
  >
882
882
  {/* Orange icon and badge */}
883
883
  <div className="flex items-center justify-center gap-2 mb-4">
884
- <Star className="h-5 w-5 text-orange-500 fill-orange-500" />
885
- <span className="text-sm font-semibold uppercase tracking-wider text-orange-500">
884
+ <Star className="h-5 w-5 text-primary fill-primary" />
885
+ <span className="text-sm font-semibold uppercase tracking-wider text-primary">
886
886
  COMPLETE PHARMACY SHOP
887
887
  </span>
888
888
  </div>
@@ -910,7 +910,7 @@ export function ShopScreen({ initialFilters = {}, categoryName }: ShopScreenProp
910
910
  value={searchQuery}
911
911
  onChange={handleInputChange}
912
912
  onKeyDown={handleKeyDown}
913
- className="flex h-16 w-full rounded-full border-0 bg-white px-5 pl-14 pr-5 text-base text-slate-900 placeholder-slate-400 shadow-lg focus:outline-none focus:ring-2 focus:ring-primary-500/30 disabled:opacity-50"
913
+ className="flex h-16 w-full rounded-full border-0 bg-white px-5 pl-14 pr-5 text-base text-slate-900 placeholder-slate-400 shadow-lg focus:outline-hidden focus:ring-2 focus:ring-primary-500/30 disabled:opacity-50"
914
914
  disabled={isSearching}
915
915
  />
916
916
  </div>
@@ -938,14 +938,14 @@ export function ShopScreen({ initialFilters = {}, categoryName }: ShopScreenProp
938
938
  initial={{ opacity: 0, y: 20 }}
939
939
  animate={{ opacity: 1, y: 0 }}
940
940
  transition={{ delay: index * 0.1 }}
941
- className={`group relative overflow-hidden rounded-[24px] p-6 transition-all duration-300 ${!categoryFilter ? 'bg-gradient-to-br from-primary to-secondary text-white shadow-xl scale-105'
942
- : 'bg-gradient-to-br from-gray-50 to-white hover:shadow-lg border-2 border-gray-100 hover:border-primary'
941
+ className={`group relative overflow-hidden rounded-[24px] p-6 transition-all duration-300 ${!categoryFilter ? 'bg-linear-to-br from-primary to-secondary text-white shadow-xl scale-105'
942
+ : 'bg-linear-to-br from-gray-50 to-white hover:shadow-lg border-2 border-gray-100 hover:border-primary'
943
943
  }`}
944
944
  >
945
945
  <div className="relative">
946
946
  <div className={`size-12 rounded-full mb-3 mx-auto flex items-center justify-center transition-all ${!categoryFilter
947
947
  ? 'bg-white/20'
948
- : 'bg-gradient-to-br from-primary/10 to-secondary/10 group-hover:scale-110'
948
+ : 'bg-linear-to-br from-primary/10 to-secondary/10 group-hover:scale-110'
949
949
  }`}>
950
950
  <Icon className={`size-6 ${!categoryFilter ? 'text-white' : 'text-primary'
951
951
  }`} />
@@ -968,14 +968,14 @@ export function ShopScreen({ initialFilters = {}, categoryName }: ShopScreenProp
968
968
  animate={{ opacity: 1, y: 0 }}
969
969
  transition={{ delay: index * 0.1 }}
970
970
  onClick={() => handleCategoryChange(category.id ?? '')}
971
- className={`group relative overflow-hidden rounded-[24px] p-6 transition-all duration-300 ${isSelected ? 'bg-gradient-to-br from-primary to-secondary text-white shadow-xl scale-105'
972
- : 'bg-gradient-to-br from-gray-50 to-white hover:shadow-lg border-2 border-gray-100 hover:border-primary'
971
+ className={`group relative overflow-hidden rounded-[24px] p-6 transition-all duration-300 ${isSelected ? 'bg-linear-to-br from-primary to-secondary text-white shadow-xl scale-105'
972
+ : 'bg-linear-to-br from-gray-50 to-white hover:shadow-lg border-2 border-gray-100 hover:border-primary'
973
973
  }`}
974
974
  >
975
975
  <div className="relative">
976
976
  <div className={`size-12 rounded-full mb-3 mx-auto flex items-center justify-center transition-all ${isSelected
977
977
  ? 'bg-white/20'
978
- : 'bg-gradient-to-br from-primary/10 to-secondary/10 group-hover:scale-110'
978
+ : 'bg-linear-to-br from-primary/10 to-secondary/10 group-hover:scale-110'
979
979
  }`}>
980
980
  <Icon className={`size-6 ${isSelected ? 'text-white' : 'text-primary'
981
981
  }`} />
@@ -1000,14 +1000,14 @@ export function ShopScreen({ initialFilters = {}, categoryName }: ShopScreenProp
1000
1000
  <div className="relative pb-16 mt-8">
1001
1001
  <div className="container mx-auto px-4">
1002
1002
  <div className="flex flex-col gap-8 lg:flex-row">
1003
- <aside className="hidden w-72 flex-shrink-0 lg:block">
1003
+ <aside className="hidden w-72 shrink-0 lg:block">
1004
1004
  <div className="sticky top-24 rounded-lg bg-white">
1005
1005
  {renderFiltersPanel()}
1006
1006
  </div>
1007
1007
  </aside>
1008
1008
 
1009
1009
  <main className="flex-1 space-y-6">
1010
- <div className="rounded-3xl border border-gray-100 bg-white p-6 shadow-sm">
1010
+ <div className="rounded-3xl border border-gray-100 bg-white p-6 shadow-xs">
1011
1011
  <div className="flex flex-col gap-6 md:flex-row md:items-center md:justify-between">
1012
1012
  <div>
1013
1013
  <h2 className="text-base font-medium text-gray-700">
@@ -1025,7 +1025,7 @@ export function ShopScreen({ initialFilters = {}, categoryName }: ShopScreenProp
1025
1025
  onChange={(event) => {
1026
1026
  setSortOption(event.target.value as SortOption);
1027
1027
  }}
1028
- className="appearance-none rounded-full border border-gray-200 bg-white py-2.5 pl-10 pr-9 text-sm font-medium text-gray-700 shadow-sm transition focus:outline-none focus:ring-1 focus:ring-secondary focus:border-primary"
1028
+ className="appearance-none rounded-full border border-gray-200 bg-white py-2.5 pl-10 pr-9 text-sm font-medium text-gray-700 shadow-xs transition focus:outline-hidden focus:ring-1 focus:ring-secondary focus:border-primary"
1029
1029
  >
1030
1030
  <option value="featured">Featured products</option>
1031
1031
  <option value="price-low-high">Price: low to high</option>
@@ -1034,7 +1034,7 @@ export function ShopScreen({ initialFilters = {}, categoryName }: ShopScreenProp
1034
1034
  </select>
1035
1035
  <ChevronDown className="pointer-events-none absolute right-3 top-1/2 -translate-y-1/2 h-4 w-4 text-gray-400" />
1036
1036
  </div>
1037
- <div className="flex items-center rounded-full border border-gray-200 bg-gray-100 shadow-sm p-1">
1037
+ <div className="flex items-center rounded-full border border-gray-200 bg-gray-100 shadow-xs p-1">
1038
1038
  <button
1039
1039
  type="button"
1040
1040
  onClick={() => setViewMode('grid')}
@@ -1124,7 +1124,7 @@ export function ShopScreen({ initialFilters = {}, categoryName }: ShopScreenProp
1124
1124
  <motion.div
1125
1125
  key={product.id}
1126
1126
  whileHover={{ y: -4 }}
1127
- className="group flex cursor-pointer flex-col gap-6 rounded-2xl border border-gray-100 bg-white p-5 shadow-sm transition hover:shadow-xl md:flex-row md:items-start"
1127
+ className="group flex cursor-pointer flex-col gap-6 rounded-2xl border border-gray-100 bg-white p-5 shadow-xs transition hover:shadow-xl md:flex-row md:items-start"
1128
1128
  onClick={() => router.push(buildPath(`/products/${product._id}`))}
1129
1129
  >
1130
1130
  <div className="relative h-48 w-full overflow-hidden rounded-2xl bg-gray-100 md:h-40 md:w-40">
@@ -1207,7 +1207,7 @@ export function ShopScreen({ initialFilters = {}, categoryName }: ShopScreenProp
1207
1207
  {pagination.totalPages > 1 && (
1208
1208
  <div className="mt-10 flex flex-wrap items-center justify-center gap-3">
1209
1209
  <Button
1210
- variant="outline"
1210
+ variant="outline-solid"
1211
1211
  onClick={() => setPage((current) => Math.max(1, current - 1))}
1212
1212
  disabled={page === 1}
1213
1213
  >
@@ -1217,7 +1217,7 @@ export function ShopScreen({ initialFilters = {}, categoryName }: ShopScreenProp
1217
1217
  Page {page} of {pagination.totalPages}
1218
1218
  </span>
1219
1219
  <Button
1220
- variant="outline"
1220
+ variant="outline-solid"
1221
1221
  onClick={() =>
1222
1222
  setPage((current) => Math.min(pagination.totalPages, current + 1))
1223
1223
  }
@@ -205,7 +205,7 @@ export default function WishlistScreen() {
205
205
  type="checkbox"
206
206
  checked={onlyInStock}
207
207
  onChange={(event) => setOnlyInStock(event.target.checked)}
208
- className="h-4 w-4 rounded border-slate-300 text-secondary focus:ring-secondary"
208
+ className="h-4 w-4 rounded-sm border-slate-300 text-secondary focus:ring-secondary"
209
209
  />
210
210
  Only show in-stock
211
211
  </label>
@@ -215,7 +215,7 @@ export default function WishlistScreen() {
215
215
  <select
216
216
  value={sortOption}
217
217
  onChange={(event) => setSortOption(event.target.value as SortOption)}
218
- className="bg-transparent text-sm font-medium text-slate-700 outline-none"
218
+ className="bg-transparent text-sm font-medium text-slate-700 outline-hidden"
219
219
  >
220
220
  {SORT_OPTIONS.map((option) => (
221
221
  <option key={option.value} value={option.value}>
@@ -338,7 +338,7 @@ export default function WishlistScreen() {
338
338
  animate={{ opacity: 1, y: 0 }}
339
339
  exit={{ opacity: 0, y: -20 }}
340
340
  transition={{ duration: 0.2 }}
341
- className="flex flex-col gap-4 rounded-2xl border border-slate-100 bg-slate-50 p-4 shadow-sm shadow-primary-50 sm:flex-row sm:items-center"
341
+ className="flex flex-col gap-4 rounded-2xl border border-slate-100 bg-slate-50 p-4 shadow-xs shadow-primary-50 sm:flex-row sm:items-center"
342
342
  >
343
343
  <div className="relative h-28 w-full overflow-hidden rounded-2xl bg-white sm:w-40">
344
344
  <Image
@@ -390,7 +390,7 @@ export default function WishlistScreen() {
390
390
  </Button>
391
391
  <Button
392
392
  size="sm"
393
- variant="outline"
393
+ variant="outline-solid"
394
394
  onClick={() => handleRemoveFromWishlist(product.id)}
395
395
  className="text-secondary"
396
396
  >
@@ -1,6 +1,117 @@
1
- @tailwind base;
2
- @tailwind components;
3
- @tailwind utilities;
1
+ @import 'tailwindcss';
2
+
3
+ @theme {
4
+ --color-primary-50: rgb(var(--color-primary-50));
5
+ --color-primary-100: rgb(var(--color-primary-100));
6
+ --color-primary-200: rgb(var(--color-primary-200));
7
+ --color-primary-300: rgb(var(--color-primary-300));
8
+ --color-primary-400: rgb(var(--color-primary-400));
9
+ --color-primary-500: rgb(var(--color-primary-500));
10
+ --color-primary-600: rgb(var(--color-primary-600));
11
+ --color-primary-700: rgb(var(--color-primary-700));
12
+ --color-primary-800: rgb(var(--color-primary-800));
13
+ --color-primary-900: rgb(var(--color-primary-900));
14
+ --color-primary-950: rgb(var(--color-primary-950));
15
+ --color-primary: var(--color-primary, #5b9bd5);
16
+ --color-primary-dark: var(--color-primary-dark, #4a8ac4);
17
+ --color-primary-bg: var(--color-primary-bg, #e6ebf0);
18
+
19
+ --color-secondary-50: rgb(var(--color-secondary-50));
20
+ --color-secondary-100: rgb(var(--color-secondary-100));
21
+ --color-secondary-200: rgb(var(--color-secondary-200));
22
+ --color-secondary-300: rgb(var(--color-secondary-300));
23
+ --color-secondary-400: rgb(var(--color-secondary-400));
24
+ --color-secondary-500: rgb(var(--color-secondary-500));
25
+ --color-secondary-600: rgb(var(--color-secondary-600));
26
+ --color-secondary-700: rgb(var(--color-secondary-700));
27
+ --color-secondary-800: rgb(var(--color-secondary-800));
28
+ --color-secondary-900: rgb(var(--color-secondary-900));
29
+ --color-secondary-950: rgb(var(--color-secondary-950));
30
+ --color-secondary: var(--color-secondary, #2b4b7c);
31
+
32
+ --color-accent-50: rgb(var(--color-accent-50));
33
+ --color-accent-100: rgb(var(--color-accent-100));
34
+ --color-accent-200: rgb(var(--color-accent-200));
35
+ --color-accent-300: rgb(var(--color-accent-300));
36
+ --color-accent-400: rgb(var(--color-accent-400));
37
+ --color-accent-500: rgb(var(--color-accent-500));
38
+ --color-accent-600: rgb(var(--color-accent-600));
39
+ --color-accent-700: rgb(var(--color-accent-700));
40
+ --color-accent-800: rgb(var(--color-accent-800));
41
+ --color-accent-900: rgb(var(--color-accent-900));
42
+ --color-accent-950: rgb(var(--color-accent-950));
43
+ --color-accent: var(--color-accent, #e67e50);
44
+ --color-accent-dark: var(--color-accent-dark, #d66f45);
45
+
46
+ --color-muted: var(--color-text-muted, #676c80);
47
+
48
+ --animate-fade-in: fadeIn 0.3s ease-in-out;
49
+ --animate-slide-up: slideUp 0.3s ease-out;
50
+ --animate-slide-down: slideDown 0.3s ease-out;
51
+ --animate-scale-in: scaleIn 0.2s ease-out;
52
+
53
+ @keyframes fadeIn {
54
+ 0% {
55
+ opacity: 0;
56
+ }
57
+ 100% {
58
+ opacity: 1;
59
+ }
60
+ }
61
+ @keyframes slideUp {
62
+ 0% {
63
+ transform: translateY(10px);
64
+ opacity: 0;
65
+ }
66
+ 100% {
67
+ transform: translateY(0);
68
+ opacity: 1;
69
+ }
70
+ }
71
+ @keyframes slideDown {
72
+ 0% {
73
+ transform: translateY(-10px);
74
+ opacity: 0;
75
+ }
76
+ 100% {
77
+ transform: translateY(0);
78
+ opacity: 1;
79
+ }
80
+ }
81
+ @keyframes scaleIn {
82
+ 0% {
83
+ transform: scale(0.95);
84
+ opacity: 0;
85
+ }
86
+ 100% {
87
+ transform: scale(1);
88
+ opacity: 1;
89
+ }
90
+ }
91
+ }
92
+
93
+ /*
94
+ The default border color has changed to `currentcolor` in Tailwind CSS v4,
95
+ so we've added these compatibility styles to make sure everything still
96
+ looks the same as it did with Tailwind CSS v3.
97
+
98
+ If we ever want to remove these styles, we need to add an explicit border
99
+ color utility to any element that depends on these defaults.
100
+ */
101
+ @layer base {
102
+ *,
103
+ ::after,
104
+ ::before,
105
+ ::backdrop,
106
+ ::file-selector-button {
107
+ border-color: var(--color-gray-200, currentcolor);
108
+ }
109
+ }
110
+
111
+ @utility animate-gradient {
112
+ animation: gradient 3s ease infinite;
113
+ background-size: 200% 200%;
114
+ }
4
115
 
5
116
  @layer base {
6
117
  :root {
@@ -22,10 +133,6 @@
22
133
  }
23
134
 
24
135
  @layer utilities {
25
- .animate-gradient {
26
- animation: gradient 3s ease infinite;
27
- background-size: 200% 200%;
28
- }
29
136
 
30
137
  @keyframes gradient {
31
138
  0% {