Skip to content

Commit 40ced6e

Browse files
committed
refactor: update component styles and structure for improved consistency and responsiveness
1 parent 51c2949 commit 40ced6e

10 files changed

Lines changed: 107 additions & 162 deletions

File tree

src/components/CollectionSection.jsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,10 +61,10 @@ const CollectionSection = () => {
6161

6262
return (
6363
<section className="shop-by-collection">
64-
<h2 className="collection-heading">
65-
<span className="heading-shop">SHOP</span>{' '}
66-
<span className="heading-by">BY</span>{' '}
67-
<span className="heading-collection">COLLECTION</span>
64+
<h2 className="section-title mb-12">
65+
<span className="text-[#000]">SHOP </span>
66+
<span>BY </span>
67+
<span className="text-[#000]">COLLECTION</span>
6868
</h2>
6969

7070
<div className="collection-grid">

src/components/Products/ProductCard.jsx

Lines changed: 47 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ const HeartIcon = ({ isWishlisted = false, animate = false, className = 'h-6 w-6
99
viewBox="0 0 18 17"
1010
fill="none"
1111
xmlns="http://www.w3.org/2000/svg"
12-
className={`${className} transition-transform duration-200 ease-out ${animate ? 'animate-double-pop' : (isWishlisted ? 'scale-110' : '')} ${isWishlisted ? 'text-white' : 'text-current'}`}
12+
className={`${className} transition-transform duration-200 ease-out ${animate ? 'animate-double-pop' : (isWishlisted ? 'scale-110' : '')} ${isWishlisted ? 'text-white' : 'text-current'}`}
1313
aria-hidden="true"
1414
focusable="false"
1515
>
@@ -96,20 +96,21 @@ const ProductCard = forwardRef(({ product }, ref) => {
9696
}
9797

9898
return (
99-
<div
99+
<div
100100
ref={ref}
101-
className="bg-white rounded-2xl p-4 transition-all duration-300 shadow-[0_8px_30px_rgb(0,0,0,0.15)] hover:shadow-[0_8px_30px_rgb(0,0,0,0.25)] flex flex-col select-none"
101+
className="bg-white rounded-2xl p-3 sm:p-4 transition-all duration-300 shadow-[0_8px_30px_rgb(0,0,0,0.15)] hover:shadow-[0_8px_30px_rgb(0,0,0,0.25)] flex flex-col select-none max-w-full"
102102
>
103103
{/* --- IMAGE CONTAINER --- */}
104-
<div
105-
className="relative aspect-square overflow-hidden rounded-xl mb-4 bg-gray-100 group cursor-pointer"
106-
role="button"
107-
tabIndex={0}
108-
aria-label={`View details for ${product.name}`}
109-
onClick={handleProductClick}
110-
onKeyDown={(e) => (e.key === 'Enter' || e.key === ' ') && handleProductClick()}
111-
>
112-
104+
<div
105+
className="relative w-full overflow-hidden rounded-xl mb-3 bg-gray-100 group cursor-pointer"
106+
style={{ paddingTop: '100%' }}
107+
role="button"
108+
tabIndex={0}
109+
aria-label={`View details for ${product.name}`}
110+
onClick={handleProductClick}
111+
onKeyDown={(e) => (e.key === 'Enter' || e.key === ' ') && handleProductClick()}
112+
>
113+
113114
{/* Badges for NEW and SALE */}
114115
<div className="absolute top-3 left-3 z-10 flex flex-col gap-2">
115116
{product.isNew && (
@@ -123,7 +124,7 @@ const ProductCard = forwardRef(({ product }, ref) => {
123124
</span>
124125
)}
125126
</div>
126-
127+
127128
{/* State 1: Image is loading */}
128129
{!imageLoaded && !imageError && (
129130
<div className="absolute inset-0 bg-gradient-to-br from-gray-100 to-gray-200 animate-pulse flex items-center justify-center">
@@ -146,7 +147,7 @@ const ProductCard = forwardRef(({ product }, ref) => {
146147
<img
147148
src={product.imageUrl || 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMzAwIiBoZWlnaHQ9IjMwMCIgdmlld0JveD0iMCAwIDMwMCAzMDAiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSIzMDAiIGhlaWdodD0iMzAwIiBmaWxsPSIjRjNGNEY2Ii8+CjxwYXRoIGQ9Ik0xMjUgMTI1SDEzNVYxMzVIMTI1VjEyNVpNMTM1IDEyNUgxNDVWMTM1SDEzNVYxMjVaTTE0NSAxMjVIMTU1VjEzNUgxNDVWMTI1Wk0xNTUgMTI1SDE2NVYxMzVIMTU1VjEyNVpNMTY1IDEyNUgxNzVWMTM1SDE2NVYxMjVaIiBmaWxsPSIjOUI5QkEzIi8+CjxwYXRoIGQ9Ik0xMzUgMTQ1SDE0NVYxNTVIMTM1VjE0NVpNMTQ1IDE0NUgxNTVWMTU1SDE0NVYxNDVaTTE1NSAxNDVIMTY1VjE1NUgxNTVWMTQ1WiIgZmlsbD0iIzlCOUJBMyIvPgo8L3N2Zz4K'}
148149
alt={product.name}
149-
className={`w-full h-full object-contain transition-opacity duration-500 ${imageLoaded && !imageError ? 'opacity-100' : 'opacity-0'}`}
150+
className={`absolute inset-0 w-full h-full object-cover transition-opacity duration-500 ${imageLoaded && !imageError ? 'opacity-100' : 'opacity-0'}`}
150151
onLoad={() => setImageLoaded(true)}
151152
onError={() => {
152153
setImageLoaded(true);
@@ -185,7 +186,7 @@ const ProductCard = forwardRef(({ product }, ref) => {
185186
<span className="font-bold text-lg text-gray-800">{formatPrice(product.price)}</span>
186187
</div>
187188
</div>
188-
189+
189190
<div className="mb-2">
190191
<h3 className="font-bold text-2xl text-gray-800 leading-tight line-clamp-2">{product.name}</h3>
191192
</div>
@@ -216,15 +217,15 @@ const ProductCard = forwardRef(({ product }, ref) => {
216217
</option>
217218
))}
218219
</select>
219-
<div className="absolute inset-y-0 right-0 flex items-center pr-3 pointer-events-none">
220-
<svg className="w-4 h-4 text-gray-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
220+
<div className="absolute inset-y-0 right-3 flex items-center pointer-events-none">
221+
<svg className="w-4 h-4 text-gray-400" fill="none" stroke="currentColor" viewBox="0 0 24 24" aria-hidden>
221222
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
222223
</svg>
223224
</div>
224225
</div>
225226
)}
226227
</div>
227-
228+
228229
<div className="flex items-center gap-3 mt-auto">
229230
<button
230231
onClick={(e) => handleActionClick(e, handleWishlistToggle)}
@@ -238,40 +239,40 @@ const ProductCard = forwardRef(({ product }, ref) => {
238239
<HeartIcon isWishlisted={isWishlisted} animate={animateLike} className="h-5 w-5" />
239240
</button>
240241

241-
{/* --- Add to Cart Button --- */}
242-
<button
243-
onClick={(e) => handleActionClick(e, handleAddToCart)}
244-
className={`
242+
{/* --- Add to Cart Button --- */}
243+
<button
244+
onClick={(e) => handleActionClick(e, handleAddToCart)}
245+
className={`
245246
-ml-px flex-grow flex items-center justify-center gap-2
246247
bg-[#023e8a] text-white font-medium
247248
py-3 px-4 rounded-r-xl
248249
hover:bg-[#1054ab] transition-colors duration-150 hover:shadow-lg cursor-pointer
249250
focus:outline-none focus:z-10
250251
`}
251-
aria-live="polite"
252-
>
253-
{cartLoading ? (
254-
<span className="ml-2 flex items-center gap-2 font-semibold">
255-
<svg className="w-5 h-5 animate-spin" viewBox="0 0 24 24" fill="none" stroke="currentColor" aria-hidden="true">
256-
<circle cx="12" cy="12" r="10" strokeWidth="3" stroke="currentColor" opacity="0.25" />
257-
<path d="M22 12a10 10 0 00-10-10" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round" />
258-
</svg>
259-
<span>ADDING...</span>
260-
</span>
261-
) : cartAdded ? (
262-
<span className="ml-2 flex items-center gap-2 font-semibold">
263-
<svg className="w-5 h-5" viewBox="0 0 24 24" fill="none" stroke="currentColor" aria-hidden="true">
264-
<path strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" d="M5 13l4 4L19 7" />
265-
</svg>
266-
<span>ADDED</span>
267-
</span>
268-
) : (
269-
<>
270-
<CartIcon />
271-
<span className="ml-2">ADD TO CART</span>
272-
</>
273-
)}
274-
</button>
252+
aria-live="polite"
253+
>
254+
{cartLoading ? (
255+
<span className="ml-2 flex items-center gap-2 font-semibold">
256+
<svg className="w-5 h-5 animate-spin" viewBox="0 0 24 24" fill="none" stroke="currentColor" aria-hidden="true">
257+
<circle cx="12" cy="12" r="10" strokeWidth="3" stroke="currentColor" opacity="0.25" />
258+
<path d="M22 12a10 10 0 00-10-10" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round" />
259+
</svg>
260+
<span>ADDING...</span>
261+
</span>
262+
) : cartAdded ? (
263+
<span className="ml-2 flex items-center gap-2 font-semibold">
264+
<svg className="w-5 h-5" viewBox="0 0 24 24" fill="none" stroke="currentColor" aria-hidden="true">
265+
<path strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" d="M5 13l4 4L19 7" />
266+
</svg>
267+
<span>ADDED</span>
268+
</span>
269+
) : (
270+
<>
271+
<CartIcon />
272+
<span className="ml-2">ADD TO CART</span>
273+
</>
274+
)}
275+
</button>
275276

276277
</div>
277278
</div>

src/components/Products/ProductGrid.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ export default function ProductGrid({ products, lastProductElementRef }) {
66
}
77

88
return (
9-
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-12">
9+
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-8">
1010
{products.map((product, index) => {
1111
// Attach ref to the last product for infinite scroll
1212
const isLastProduct = index === products.length - 1;

src/components/Products/SortDropdown.jsx

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ const SORT_OPTIONS = [
1010
{ label: 'Rating - High to Low', field: 'rating', order: 'desc' },
1111
];
1212

13-
export default function SortDropdown({ sortBy = 'featured', sortOrder = 'desc', onSortChange = () => {} }) {
13+
export default function SortDropdown({ sortBy = 'featured', sortOrder = 'desc', onSortChange = () => {}, className = '' }) {
1414
const [isOpen, setIsOpen] = useState(false);
1515
const dropdownRef = useRef(null);
1616

@@ -50,24 +50,27 @@ export default function SortDropdown({ sortBy = 'featured', sortOrder = 'desc',
5050
};
5151

5252
return (
53-
<div className="flex items-center gap-4">
54-
<div className="relative">
53+
<div className={`flex items-center gap-2 sm:gap-4 ${className}`}>
54+
<div className="relative flex-shrink-0">
5555
<span className="font-semibold text-lg text-gray-800">Sort by:</span>
5656
<div className="absolute -bottom-1 left-0 w-12 h-0.5 bg-gray-800" />
5757
</div>
5858

59-
<div className="relative" ref={dropdownRef}>
59+
<div className="relative flex-1 sm:flex-initial" ref={dropdownRef}>
6060
<button
6161
onClick={() => setIsOpen(!isOpen)}
62-
className="flex items-center gap-2 bg-transparent text-gray-700 px-6 py-3 rounded-lg font-semibold border-2 border-gray-300 hover:border-blue-500 hover:text-blue-600 hover:bg-blue-50 transition-all duration-300"
62+
className="w-full sm:w-[240px] flex items-center justify-between gap-2 bg-transparent text-gray-700 px-4 py-2 sm:px-6 sm:py-3 rounded-lg font-semibold border-2 border-gray-300 hover:border-blue-500 hover:text-blue-600 hover:bg-blue-50 transition-all duration-300"
6363
aria-haspopup="true"
6464
aria-expanded={isOpen}
6565
>
66-
{currentSort.label}
66+
<span className="truncate text-left">{currentSort.label}</span>
67+
<svg className="w-4 h-4 ml-2 text-gray-600 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
68+
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M19 9l-7 7-7-7" />
69+
</svg>
6770
</button>
6871

6972
{isOpen && (
70-
<div className="absolute right-0 z-50 w-56 mt-2 origin-top-right bg-white border border-gray-200 rounded-lg shadow-xl">
73+
<div className="absolute left-0 z-50 w-full sm:w-64 mt-2 origin-top-left sm:origin-top-right bg-white border border-gray-200 rounded-lg shadow-xl">
7174
<div className="py-2">
7275
{SORT_OPTIONS.map((option, index) => (
7376
<button

src/components/RecentlyViewed.jsx

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ const ChevronRightIcon = (props) => (
1515
</svg>
1616
);
1717

18-
1918
export default function RecentlyViewed() {
2019
const [items] = useState(() => getRecentlyViewed());
2120
const [currentIndex, setCurrentIndex] = useState(0);
@@ -31,7 +30,7 @@ export default function RecentlyViewed() {
3130
const newIndex = Math.max(currentIndex - itemsPerPage, 0);
3231
setCurrentIndex(newIndex);
3332
};
34-
33+
3534
if (!items || items.length === 0) {
3635
return null;
3736
}
@@ -42,43 +41,46 @@ export default function RecentlyViewed() {
4241
const visibleItems = items.slice(currentIndex, currentIndex + itemsPerPage);
4342

4443
return (
45-
<section className="max-w-6xl mx-auto px-4 sm:px-6 lg:px-8 py-12">
44+
<section className="max-w-6xl mx-auto px-3 sm:px-6 lg:px-8 py-8">
4645
{/* Header section with title and navigation arrows */}
47-
<div className="flex items-center justify-between mb-8">
48-
<h2 className="text-5xl lg:text-heading-xxl font-montserrat text-black leading-none uppercase text-center tracking-tight py-10 text-stroke-black">
49-
RECENTLY
50-
<span className="ml-5 text-[#f7faff]">VIEWED</span>
46+
<div className="flex items-center justify-between mb-6 flex-col sm:flex-row gap-4 sm:gap-0">
47+
<h2 className="section-title text-center w-full sm:w-auto mb-0">
48+
<span className="text-[#000]">RECENTLY </span>
49+
<span className="text-[#f7faff]">VIEWED</span>
5150
</h2>
5251

5352
{/* Navigation Buttons */}
5453
<div className="flex items-center gap-3">
5554
<button
5655
onClick={prevSlide}
5756
disabled={!canGoPrev}
58-
className="flex h-15 w-15 items-center justify-center rounded-full border border-gray-300 text-gray-500 hover:bg-gray-100 disabled:cursor-not-allowed disabled:opacity-40 transition-all duration-200"
57+
className="flex h-10 w-10 items-center justify-center rounded-full border border-gray-300 text-gray-500 hover:bg-gray-100 disabled:cursor-not-allowed disabled:opacity-40 transition-all duration-200"
5958
aria-label="Previous"
6059
>
6160
<ChevronLeftIcon className="h-5 w-5" />
6261
</button>
62+
6363
<button
6464
onClick={nextSlide}
6565
disabled={!canGoNext}
66-
className="flex h-15 w-15 items-center justify-center rounded-full border border-gray-300 text-gray-500 hover:bg-gray-100 disabled:cursor-not-allowed disabled:opacity-40 transition-all duration-200"
66+
className="flex h-10 w-10 items-center justify-center rounded-full border border-gray-300 text-gray-500 hover:bg-gray-100 disabled:cursor-not-allowed disabled:opacity-40 transition-all duration-200"
6767
aria-label="Next"
6868
>
6969
<ChevronRightIcon className="h-5 w-5" />
7070
</button>
7171
</div>
7272
</div>
73-
{/* Recently Viewed Products Grid */}
74-
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-12 transition-all duration-500 ease-in-out">
75-
{visibleItems.map((product) => (
76-
<div key={product.id} className="opacity-100">
77-
<ProductCard product={product} />
78-
</div>
79-
))}
73+
74+
{/* Recently Viewed Products: grid on desktop, horizontal scroll on mobile */}
75+
<div className="transition-all duration-500 ease-in-out">
76+
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-8">
77+
{visibleItems.map((product) => (
78+
<div key={product.id} className="opacity-100">
79+
<ProductCard product={product} />
80+
</div>
81+
))}
82+
</div>
8083
</div>
8184
</section>
8285
);
83-
8486
}

src/components/SupplementForGoalsSection.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ export default function SupplementForGoalsSection() {
2424
return (
2525
<section id="goals" ref={goalsRef} className="px-10 py-24 flex flex-col gap-16">
2626
<h2 id="why-choose" className="section-title">
27-
Supplements for <span>every</span> goal
27+
<span className="text-[#000]">Supplements for </span><span className="text-[#f7faff]">every</span> <span className="text-[#000]">goal</span>
2828
</h2>
2929

3030
<div className="space-y-10">

src/components/WhyChoose.jsx

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@ function WhyChoose() {
33
<section aria-labelledby="why-choose" className="bg-black">
44
<h2
55
id="why-choose"
6-
className="bg-white text-4xl lg:text-heading-xxl font-montserrat font-bold leading-none uppercase text-center -tracking-widest py-16"
6+
className="bg-white text-4xl lg:text-heading-xxl uppercase py-16 section-title"
77
>
8-
Why <span className="text-white text-outline">Choose</span>
9-
<span className="capitalize"> Core</span>
10-
<span className="text-red-500 text-outline">X</span> Products
8+
<span className="text-[#000]">Why </span><span>Choose</span>
9+
<span className="capitalize text-[#000]"> Core</span>
10+
<span className="text-red-500">X</span><span className="text-[#000]"> Products</span>
1111
</h2>
1212
<div className="grid grid-cols-1 gap-y-16 lg:grid-cols-3 max-w-5xl mx-auto text-white text-center py-23 leading-normal">
1313
<div className="flex flex-col items-center space-y-2">

src/components/collection.css

Lines changed: 0 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -10,33 +10,6 @@
1010
padding: 85px;
1111
}
1212

13-
/* Heading Styles */
14-
.collection-heading {
15-
text-align: center;
16-
font-size: 64px;
17-
font-weight: 700;
18-
margin-bottom: 60px;
19-
letter-spacing: -2%;
20-
line-height: 64px;
21-
text-transform: uppercase;
22-
}
23-
24-
.heading-shop,
25-
.heading-collection {
26-
color: #000;
27-
font-weight: 900;
28-
font-family: 'Montserrat', sans-serif;
29-
text-shadow: 0px 4px 4px rgba(0, 0, 0, 0.25);
30-
}
31-
32-
.heading-by {
33-
color: transparent;
34-
-webkit-text-stroke: 1px #000;
35-
text-stroke: 1px #000;
36-
font-weight: 700;
37-
padding: 0 8px;
38-
}
39-
4013
/* Collection Grid */
4114
.collection-grid {
4215
display: grid;
@@ -118,10 +91,6 @@
11891

11992
/* Responsive Design */
12093
@media (max-width: 1024px) {
121-
.collection-heading {
122-
font-size: 3rem;
123-
}
124-
12594
.collection-grid {
12695
grid-template-columns: repeat(2, 1fr);
12796
gap: 20px;
@@ -133,16 +102,6 @@
133102
padding: 60px 16px;
134103
}
135104

136-
.collection-heading {
137-
font-size: 2rem;
138-
margin-bottom: 40px;
139-
}
140-
141-
.heading-by {
142-
-webkit-text-stroke: 1.5px #000;
143-
text-stroke: 1.5px #000;
144-
}
145-
146105
.collection-grid {
147106
grid-template-columns: 1fr;
148107
gap: 16px;

0 commit comments

Comments
 (0)