···
161
161
}
162
162
163
163
.card {
164
164
-
background: var(--card-background);
164
164
+
background-color: var(--card-background);
165
165
+
border: 1px solid var(--tile-border);
165
166
border-radius: 8px;
166
166
-
box-shadow: 0 2px 10px var(--shadow-color);
167
167
-
padding: 2rem;
167
167
+
padding: 1.5rem;
168
168
margin: 1rem 0;
169
169
width: 100%;
170
170
+
box-shadow: 0 2px 5px var(--shadow-color);
171
171
+
transition: transform 0.2s, box-shadow 0.2s;
172
172
+
background-image: repeating-linear-gradient(0deg, var(--tile-border), var(--tile-border) 1px, transparent 1px, transparent 20px);
173
173
+
}
174
174
+
175
175
+
.card:hover {
176
176
+
transform: translateY(-2px);
177
177
+
box-shadow: 0 4px 8px var(--shadow-color);
170
178
}
171
179
172
180
.form-group {
···
4
4
import { ThemeProvider } from '@/lib/theme-context';
5
5
import ThemeToggle from '@/components/ThemeToggle';
6
6
import ClientOnly from '@/components/ClientOnly';
7
7
+
import ProfileSearch from '@/components/ProfileSearch';
7
8
8
9
// Configure this layout as having dynamic runtime to fix SSR issues with theme
9
10
export const dynamic = 'force-dynamic';
···
47
48
<ThemeProvider>
48
49
<header style={{
49
50
display: 'flex',
50
50
-
justifyContent: 'flex-end',
51
51
+
justifyContent: 'space-between',
52
52
+
alignItems: 'center',
51
53
padding: '0.5rem 1rem',
52
54
backgroundColor: 'var(--card-background)',
53
55
borderBottom: '1px solid var(--tile-border)'
54
56
}}>
57
57
+
<div style={{ display: 'flex', alignItems: 'center', gap: '1rem' }}>
58
58
+
<a href="/" style={{
59
59
+
textDecoration: 'none',
60
60
+
fontWeight: 'bold',
61
61
+
color: 'var(--primary-color)',
62
62
+
fontSize: '1.25rem'
63
63
+
}}>
64
64
+
im.flushing
65
65
+
</a>
66
66
+
</div>
55
67
<ClientOnly>
56
56
-
<ThemeToggle />
68
68
+
<div style={{ display: 'flex', alignItems: 'center', gap: '1rem' }}>
69
69
+
<ProfileSearch />
70
70
+
<ThemeToggle />
71
71
+
</div>
57
72
</ClientOnly>
58
73
</header>
59
74
<main>{children}</main>
···
1
1
+
.searchForm {
2
2
+
display: flex;
3
3
+
align-items: center;
4
4
+
background-color: var(--input-background);
5
5
+
border: 1px solid var(--input-border);
6
6
+
border-radius: 24px;
7
7
+
overflow: hidden;
8
8
+
width: 260px;
9
9
+
transition: all 0.2s ease;
10
10
+
}
11
11
+
12
12
+
.searchForm:focus-within {
13
13
+
border-color: var(--primary-color);
14
14
+
box-shadow: 0 0 0 2px rgba(91, 173, 240, 0.25);
15
15
+
}
16
16
+
17
17
+
.searchInput {
18
18
+
flex: 1;
19
19
+
padding: 0.5rem 0.75rem;
20
20
+
font-size: 0.875rem;
21
21
+
border: none;
22
22
+
outline: none;
23
23
+
background-color: transparent;
24
24
+
color: var(--text-color);
25
25
+
}
26
26
+
27
27
+
.searchInput::placeholder {
28
28
+
color: var(--timestamp-color);
29
29
+
}
30
30
+
31
31
+
.searchButton {
32
32
+
display: flex;
33
33
+
align-items: center;
34
34
+
justify-content: center;
35
35
+
background-color: transparent;
36
36
+
border: none;
37
37
+
padding: 0.5rem;
38
38
+
color: var(--primary-color);
39
39
+
cursor: pointer;
40
40
+
transition: all 0.2s ease;
41
41
+
}
42
42
+
43
43
+
.searchButton:hover {
44
44
+
background-color: rgba(91, 173, 240, 0.1);
45
45
+
}
46
46
+
47
47
+
@media (max-width: 600px) {
48
48
+
.searchForm {
49
49
+
width: 180px;
50
50
+
}
51
51
+
52
52
+
.searchInput {
53
53
+
font-size: 0.8rem;
54
54
+
padding: 0.4rem 0.5rem;
55
55
+
}
56
56
+
}
57
57
+
58
58
+
@media (max-width: 450px) {
59
59
+
.searchForm {
60
60
+
width: 140px;
61
61
+
}
62
62
+
63
63
+
.searchInput::placeholder {
64
64
+
font-size: 0.75rem;
65
65
+
}
66
66
+
}
···
1
1
+
'use client';
2
2
+
3
3
+
import React, { useState } from 'react';
4
4
+
import { useRouter } from 'next/navigation';
5
5
+
import styles from './ProfileSearch.module.css';
6
6
+
7
7
+
export default function ProfileSearch() {
8
8
+
const [query, setQuery] = useState('');
9
9
+
const router = useRouter();
10
10
+
11
11
+
const handleSearch = (e: React.FormEvent) => {
12
12
+
e.preventDefault();
13
13
+
if (query.trim()) {
14
14
+
// Normalize the handle by removing @ if present
15
15
+
const handle = query.trim().startsWith('@')
16
16
+
? query.trim().substring(1)
17
17
+
: query.trim();
18
18
+
19
19
+
router.push(`/profile/${handle}`);
20
20
+
}
21
21
+
};
22
22
+
23
23
+
return (
24
24
+
<form onSubmit={handleSearch} className={styles.searchForm}>
25
25
+
<input
26
26
+
type="text"
27
27
+
value={query}
28
28
+
onChange={(e) => setQuery(e.target.value)}
29
29
+
placeholder="Search user @handle"
30
30
+
className={styles.searchInput}
31
31
+
aria-label="Search for a user profile"
32
32
+
/>
33
33
+
<button type="submit" className={styles.searchButton}>
34
34
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
35
35
+
<circle cx="11" cy="11" r="8"></circle>
36
36
+
<line x1="21" y1="21" x2="16.65" y2="16.65"></line>
37
37
+
</svg>
38
38
+
</button>
39
39
+
</form>
40
40
+
);
41
41
+
}