This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

add search bar

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