Skip to content

Commit e5cb163

Browse files
committed
fix: fixed buttons structure
1 parent ddfc005 commit e5cb163

File tree

10 files changed

+198
-63
lines changed

10 files changed

+198
-63
lines changed

src/app/chats/page.tsx

Lines changed: 8 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@ import { useEffect, useState, useCallback } from "react";
44
import { onAuthStateChanged } from "firebase/auth";
55
import { auth } from "@/lib/firebaseClient";
66
import Link from "next/link";
7-
import { Plus } from "@/components/Icons";
87
import { Post } from "@/types/post";
98
import PostCard from "@/components/PostCard";
109
import PostFilters from "@/components/PostFilters";
1110
import CreatePostModal from "@/components/CreatePostModal";
11+
import CreateButton from "@/components/CreateButton";
1212
import ContentBox from "@/components/ContentBox";
1313
import { colours } from "@/styles/colours";
1414
import { useTopBar } from "@/contexts/TopBarContext";
@@ -149,17 +149,14 @@ export default function PostsPage() {
149149
</div>
150150

151151
{user && (
152-
<button
152+
<CreateButton
153+
user={user}
153154
onClick={() => setShowCreateModal(true)}
154-
className="flex items-center gap-2 px-3 py-2 sm:px-4 sm:py-2 rounded-lg transition-all duration-200 font-medium text-sm sm:text-base hover:scale-[1.02] hover:shadow-lg"
155-
style={{
156-
backgroundColor: colours.button.primary.background,
157-
color: colours.button.primary.text
158-
}}
159-
>
160-
<Plus />
161-
<span className="hidden sm:inline">New Post</span>
162-
</button>
155+
label="Create"
156+
showLabelOnMobile={true}
157+
className="hover:shadow-lg"
158+
ariaLabel="Create New Post"
159+
/>
163160
)}
164161
</div>
165162
{/* Filters */}

src/components/CreateButton.tsx

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
"use client"
2+
3+
import { useRouter } from "next/navigation"
4+
import { UserProfile } from "@/types/user"
5+
6+
interface CreateButtonProps {
7+
user: UserProfile | null
8+
createPath?: string
9+
onClick?: (e: React.MouseEvent) => void
10+
label?: string
11+
showLabelOnMobile?: boolean
12+
className?: string
13+
ariaLabel?: string
14+
}
15+
16+
export default function CreateButton({
17+
user,
18+
createPath,
19+
onClick,
20+
label = "Create",
21+
showLabelOnMobile = true,
22+
className = "shadow-xl",
23+
ariaLabel
24+
}: CreateButtonProps) {
25+
const router = useRouter()
26+
27+
const handleCreate = (e: React.MouseEvent) => {
28+
e.preventDefault()
29+
30+
if (onClick) {
31+
onClick(e)
32+
return
33+
}
34+
35+
if (!createPath) return
36+
37+
if (user) {
38+
router.push(createPath)
39+
} else {
40+
localStorage.setItem("postAuthRedirect", createPath)
41+
router.push("/auth")
42+
}
43+
}
44+
45+
const baseClassName = "flex items-center gap-1.5 py-1.5 px-3 sm:py-2 sm:px-4 rounded-lg shadow-xl border-2 border-black transition-all duration-200 hover:scale-[1.02]"
46+
const fullClassName = `${baseClassName} ${className}`.trim()
47+
48+
const buttonStyle = {
49+
backgroundColor: '#f1f5f9', // slate-100
50+
boxShadow: "0 1px 2px 0 rgba(0, 0, 0, 0.05)",
51+
}
52+
53+
return (
54+
<button
55+
onClick={handleCreate}
56+
className={fullClassName}
57+
style={buttonStyle}
58+
aria-label={ariaLabel || `Create ${label}`}
59+
>
60+
<svg
61+
xmlns="http://www.w3.org/2000/svg"
62+
fill="none"
63+
viewBox="0 0 24 24"
64+
strokeWidth="2"
65+
stroke="currentColor"
66+
className="w-4 h-4 sm:w-5 sm:h-5"
67+
style={{ color: '#1f2937' }}
68+
>
69+
<path strokeLinecap="round" strokeLinejoin="round" d="M12 4.5v15m7.5-7.5h-15" />
70+
</svg>
71+
{label && (
72+
<span
73+
className={`font-medium text-sm sm:text-base ${showLabelOnMobile ? '' : 'hidden sm:inline'}`}
74+
style={{ color: '#1f2937' }}
75+
>
76+
{label}
77+
</span>
78+
)}
79+
</button>
80+
)
81+
}
Lines changed: 8 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,21 @@
11
"use client"
22

3-
import { useRouter } from "next/navigation"
43
import { UserProfile } from "@/types/user"
5-
import { Plus } from "./Icons"
4+
import CreateButton from "./CreateButton"
65

76
interface CreateReviewButtonProps {
87
user: UserProfile | null
98
productId: string
109
}
1110

1211
export default function CreateReviewButton({ user, productId }: CreateReviewButtonProps) {
13-
const router = useRouter()
14-
15-
const handleWriteReview = (e: React.MouseEvent) => {
16-
e.preventDefault()
17-
if (user) {
18-
router.push(`/review/create/${productId}`)
19-
} else {
20-
localStorage.setItem("postAuthRedirect", `/review/create/${productId}`)
21-
router.push("/auth")
22-
}
23-
}
24-
2512
return (
26-
<button
27-
onClick={handleWriteReview}
28-
className="flex items-center gap-2 px-4 py-2 rounded-xl shadow-xl border-2 border-black transition-all duration-200"
29-
style={{
30-
backgroundColor: '#f1f5f9', // slate-100
31-
boxShadow: "0 2px 4px -1px rgba(0, 0, 0, 0.1), 0 1px 2px -1px rgba(0, 0, 0, 0.06)"
32-
}}
33-
aria-label="Write a Review"
34-
>
35-
<Plus />
36-
</button>
13+
<CreateButton
14+
user={user}
15+
createPath={`/review/create/${productId}`}
16+
label="Create"
17+
ariaLabel="Write a Review"
18+
showLabelOnMobile={true}
19+
/>
3720
)
3821
}

src/components/FilterToggleButton.tsx

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,21 @@ interface FilterToggleButtonProps {
66
isActive: boolean
77
selectedCount: number
88
onClick: () => void
9+
size?: 'compact' | 'normal'
910
}
1011

1112
export default function FilterToggleButton({
1213
isActive,
1314
selectedCount,
14-
onClick
15+
onClick,
16+
size = 'compact'
1517
}: FilterToggleButtonProps) {
1618
const hasSelections = selectedCount > 0
17-
const baseClassName = "flex items-center gap-1 py-1 px-2 sm:py-1.5 sm:px-3 rounded-lg shadow border-2 border-black transition-all duration-200"
19+
const sizeClasses = size === 'normal'
20+
? "gap-2 py-2 px-4"
21+
: "gap-1 py-1 px-2 sm:py-1.5 sm:px-3"
22+
23+
const baseClassName = `flex items-center ${sizeClasses} rounded-lg shadow-xl border-2 border-black transition-all duration-200`
1824
const activeRing = isActive || hasSelections ? "ring-1 ring-zinc-200" : ""
1925
const fullClassName = `${baseClassName} ${activeRing}`.trim()
2026

@@ -23,14 +29,17 @@ export default function FilterToggleButton({
2329
boxShadow: "0 1px 2px 0 rgba(0, 0, 0, 0.05)",
2430
}
2531

32+
const iconSize = size === 'normal' ? 18 : 14
33+
const textSize = size === 'normal' ? "text-base font-medium" : "text-xs sm:text-sm font-medium"
34+
2635
return (
2736
<button
2837
onClick={onClick}
2938
className={fullClassName}
3039
style={buttonStyle}
3140
>
32-
<Filter size={14} className="sm:w-4 sm:h-4" style={{ color: '#1f2937' }} />
33-
<span className="font-medium text-xs sm:text-sm" style={{ color: '#1f2937' }}>
41+
<Filter size={iconSize} className="sm:w-4 sm:h-4" style={{ color: '#1f2937' }} />
42+
<span className={textSize} style={{ color: '#1f2937' }}>
3443
Filter {hasSelections && `(${selectedCount})`}
3544
</span>
3645
</button>

src/components/HighToLowSortButton.tsx

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,41 @@ interface HighToLowSortButtonProps {
77
isActive: boolean
88
onClick: () => void
99
label?: string
10+
size?: 'compact' | 'normal'
1011
}
1112

1213
export default function HighToLowSortButton({
1314
isActive,
1415
onClick,
15-
label = "High"
16+
label = "High",
17+
size = 'normal'
1618
}: HighToLowSortButtonProps) {
19+
const sizeClasses = size === 'normal'
20+
? "gap-2 py-2 pl-2 pr-4"
21+
: "gap-1 py-1 px-2 sm:py-1.5 sm:px-3"
22+
23+
const baseClassName = `flex items-center justify-center ${sizeClasses} rounded-lg shadow-xl border-2 border-black transition-all duration-200`
24+
const activeRing = isActive ? "ring-1 ring-zinc-200" : ""
25+
const fullClassName = `${baseClassName} ${activeRing}`.trim()
26+
27+
const buttonStyle = {
28+
backgroundColor: isActive ? '#e2e8f0' : '#f1f5f9', // slate-200 vs slate-100
29+
boxShadow: "0 1px 2px 0 rgba(0, 0, 0, 0.05)",
30+
}
31+
32+
const iconSize = size === 'normal' ? 18 : 14
33+
const textSize = size === 'normal' ? "text-base font-medium" : "text-xs sm:text-sm font-medium"
34+
1735
return (
18-
<SortButton
19-
isActive={isActive}
36+
<button
2037
onClick={onClick}
21-
icon={<TrendingUp size={18} style={{ color: '#1f2937' }} />}
22-
label={label}
23-
className="pl-2 pr-4"
24-
/>
38+
className={fullClassName}
39+
style={buttonStyle}
40+
>
41+
<TrendingUp size={iconSize} style={{ color: '#1f2937' }} />
42+
<span className={textSize} style={{ color: '#1f2937' }}>
43+
{label}
44+
</span>
45+
</button>
2546
)
2647
}

src/components/LowToHighSortButton.tsx

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,20 +7,41 @@ interface LowToHighSortButtonProps {
77
isActive: boolean
88
onClick: () => void
99
label?: string
10+
size?: 'compact' | 'normal'
1011
}
1112

1213
export default function LowToHighSortButton({
1314
isActive,
1415
onClick,
15-
label = "Low"
16+
label = "Low",
17+
size = 'normal'
1618
}: LowToHighSortButtonProps) {
19+
const sizeClasses = size === 'normal'
20+
? "gap-2 py-2 px-2"
21+
: "gap-1 py-1 px-2 sm:py-1.5 sm:px-3"
22+
23+
const baseClassName = `flex items-center justify-center ${sizeClasses} rounded-lg shadow-xl border-2 border-black transition-all duration-200`
24+
const activeRing = isActive ? "ring-1 ring-zinc-200" : ""
25+
const fullClassName = `${baseClassName} ${activeRing}`.trim()
26+
27+
const buttonStyle = {
28+
backgroundColor: isActive ? '#e2e8f0' : '#f1f5f9', // slate-200 vs slate-100
29+
boxShadow: "0 1px 2px 0 rgba(0, 0, 0, 0.05)",
30+
}
31+
32+
const iconSize = size === 'normal' ? 18 : 14
33+
const textSize = size === 'normal' ? "text-base font-medium" : "text-xs sm:text-sm font-medium"
34+
1735
return (
18-
<SortButton
19-
isActive={isActive}
36+
<button
2037
onClick={onClick}
21-
icon={<TrendingDown size={18} style={{ color: '#1f2937' }} />}
22-
label={label}
23-
className="px-2"
24-
/>
38+
className={fullClassName}
39+
style={buttonStyle}
40+
>
41+
<TrendingDown size={iconSize} style={{ color: '#1f2937' }} />
42+
<span className={textSize} style={{ color: '#1f2937' }}>
43+
{label}
44+
</span>
45+
</button>
2546
)
26-
}
47+
}

src/components/PopularSortButton.tsx

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,19 @@ import { Heart } from "lucide-react"
55
interface PopularSortButtonProps {
66
isActive: boolean
77
onClick: () => void
8+
size?: 'compact' | 'normal'
89
}
910

1011
export default function PopularSortButton({
1112
isActive,
12-
onClick
13+
onClick,
14+
size = 'compact'
1315
}: PopularSortButtonProps) {
14-
const baseClassName = "flex items-center justify-center gap-1 py-1 px-2 sm:py-1.5 sm:px-3 rounded-lg shadow border-2 border-black transition-all duration-200"
16+
const sizeClasses = size === 'normal'
17+
? "gap-2 py-2 px-3"
18+
: "gap-1 py-1 px-2 sm:py-1.5 sm:px-3"
19+
20+
const baseClassName = `flex items-center justify-center ${sizeClasses} rounded-lg shadow-xl border-2 border-black transition-all duration-200`
1521
const activeRing = isActive ? "ring-1 ring-zinc-200" : ""
1622
const fullClassName = `${baseClassName} ${activeRing}`.trim()
1723

@@ -20,14 +26,17 @@ export default function PopularSortButton({
2026
boxShadow: "0 1px 2px 0 rgba(0, 0, 0, 0.05)",
2127
}
2228

29+
const iconSize = size === 'normal' ? 18 : 14
30+
const textSize = size === 'normal' ? "text-base font-medium" : "text-xs sm:text-sm font-medium"
31+
2332
return (
2433
<button
2534
onClick={onClick}
2635
className={fullClassName}
2736
style={buttonStyle}
2837
>
29-
<Heart size={14} className="sm:w-4 sm:h-4" style={{ color: '#1f2937' }} />
30-
<span className="font-medium text-xs sm:text-sm" style={{ color: '#1f2937' }}>
38+
<Heart size={iconSize} className="sm:w-4 sm:h-4" style={{ color: '#1f2937' }} />
39+
<span className={textSize} style={{ color: '#1f2937' }}>
3140
Popular
3241
</span>
3342
</button>

src/components/RecentSortButton.tsx

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,15 +7,21 @@ interface RecentSortButtonProps {
77
onClick: () => void
88
label?: string
99
className?: string
10+
size?: 'compact' | 'normal'
1011
}
1112

1213
export default function RecentSortButton({
1314
isActive,
1415
onClick,
1516
label = "Recent",
16-
className = "pl-4 pr-2"
17+
className = "pl-4 pr-2",
18+
size = 'compact'
1719
}: RecentSortButtonProps) {
18-
const baseClassName = "flex items-center justify-center gap-1 py-1 px-2 sm:py-1.5 sm:px-3 rounded-lg shadow border-2 border-black transition-all duration-200"
20+
const sizeClasses = size === 'normal'
21+
? "gap-2 py-2 px-3"
22+
: "gap-1 py-1 px-2 sm:py-1.5 sm:px-3"
23+
24+
const baseClassName = `flex items-center justify-center ${sizeClasses} rounded-lg shadow border-2 border-black transition-all duration-200`
1925
const activeRing = isActive ? "ring-1 ring-zinc-200" : ""
2026
const fullClassName = `${baseClassName} ${activeRing} ${className}`.trim()
2127

@@ -24,14 +30,17 @@ export default function RecentSortButton({
2430
boxShadow: "0 1px 2px 0 rgba(0, 0, 0, 0.05)",
2531
}
2632

33+
const iconSize = size === 'normal' ? 18 : 14
34+
const textSize = size === 'normal' ? "text-base font-medium" : "text-xs sm:text-sm font-medium"
35+
2736
return (
2837
<button
2938
onClick={onClick}
3039
className={fullClassName}
3140
style={buttonStyle}
3241
>
33-
<Clock size={14} className="sm:w-4 sm:h-4" style={{ color: '#1f2937' }} />
34-
<span className="font-medium text-xs sm:text-sm" style={{ color: '#1f2937' }}>
42+
<Clock size={iconSize} className="sm:w-4 sm:h-4" style={{ color: '#1f2937' }} />
43+
<span className={textSize} style={{ color: '#1f2937' }}>
3544
{label}
3645
</span>
3746
</button>

0 commit comments

Comments
 (0)