Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion src/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ import { ExperienceSection } from "@/components/sections/experience";
import Intro from "@/components/sections/hero";
import { ProjectsSection } from "@/components/sections/projects";
import { PublicationsSection } from "@/components/sections/publications";
import { AnimatePresence } from "framer-motion";

import { SkillsSection } from "@/components/sections/skills";
import { UnifiedFilterBar } from "@/components/unified-filter-bar";

Expand Down Expand Up @@ -63,7 +65,7 @@ const Home = () => {
<AboutSection />
</div>
</main>
{showFilter && <UnifiedFilterBar />}
<AnimatePresence>{showFilter && <UnifiedFilterBar />}</AnimatePresence>
</div>
);
};
Expand Down
3 changes: 2 additions & 1 deletion src/components/header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ export const sections = [
const Title = ({ onClick }: { onClick: (e: React.MouseEvent) => void }) => (
<button
onClick={onClick}
className="text-lg font-semibold cursor-pointer hover:text-primary transition-colors"
className="text-lg font-semibold cursor-pointer hover:text-primary transition-colors focus-visible:ring-2 focus-visible:ring-primary focus-visible:outline-none rounded-md px-1"
aria-label="Amr Abed - Scroll to top"
>
Amr Abed
</button>
Expand Down
16 changes: 14 additions & 2 deletions src/components/search.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,25 @@ export const Searchbar = ({
query,
setQuery,
className,
autoFocus = false,
}: {
placeholder: string;
query: string;
setQuery: (query: string) => void;
className?: string;
autoFocus?: boolean;
}) => {
const inputId = useId();
const inputRef = useRef<HTMLInputElement>(null);
const [isFocused, setIsFocused] = useState(false);
const [isMac, setIsMac] = useState(false);

useEffect(() => {
setIsMac(
globalThis.window !== undefined &&
/Mac|iPod|iPhone|iPad/.test(globalThis.navigator.platform),
);

const handleKeyDown = (e: KeyboardEvent) => {
const isSearchShortcut =
(e.key === "k" && (e.metaKey || e.ctrlKey)) || e.key === "/";
Expand Down Expand Up @@ -56,15 +64,19 @@ export const Searchbar = ({
maxLength={100}
onFocus={() => setIsFocused(true)}
onBlur={() => setIsFocused(false)}
autoFocus
autoFocus={autoFocus}
autoCapitalize="none"
autoComplete="off"
autoCorrect="off"
spellCheck="false"
/>
<MagnifyingGlassIcon className="absolute left-3 top-1/2 h-[18px] w-[18px] -translate-y-1/2 text-gray-500 peer-focus:text-zinc-900 dark:peer-focus:text-zinc-100" />
{!isFocused && !query && (
<div className="absolute right-3 top-1/2 -translate-y-1/2 pointer-events-none hidden sm:block">
<div className="absolute right-3 top-1/2 -translate-y-1/2 pointer-events-none hidden sm:flex gap-1 items-center">
<kbd className="px-2 py-1 text-xs font-semibold text-gray-500 bg-gray-100 border border-gray-300 rounded-lg dark:bg-slate-700 dark:text-slate-400 dark:border-slate-600">
{isMac ? "⌘" : "Ctrl"} K
</kbd>
<span className="text-gray-400 text-xs">or</span>
<kbd className="px-2 py-1 text-xs font-semibold text-gray-500 bg-gray-100 border border-gray-300 rounded-lg dark:bg-slate-700 dark:text-slate-400 dark:border-slate-600">
/
</kbd>
Expand Down
12 changes: 10 additions & 2 deletions src/components/unified-filter-bar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import { XMarkIcon } from "@heroicons/react/24/outline";
import { Button } from "@heroui/react";
import { motion } from "framer-motion";

import { useFilter } from "@/contexts/filter";
import { useSearch } from "@/contexts/search";
Expand All @@ -25,14 +26,21 @@ export const UnifiedFilterBar = () => {
};

return (
<div className="fixed bottom-0 left-0 right-0 z-50 w-full bg-background/90 backdrop-blur-md border-t border-divider py-3 px-4 sm:px-6 shadow-[0_-10px_50px_-15px_rgba(0,0,0,0.3)] transition-all duration-500">
<motion.div
initial={{ y: 100, opacity: 0 }}
animate={{ y: 0, opacity: 1 }}
exit={{ y: 100, opacity: 0 }}
transition={{ type: "spring", stiffness: 300, damping: 30 }}
className="fixed bottom-0 left-0 right-0 z-50 w-full bg-background/90 backdrop-blur-md border-t border-divider py-3 px-4 sm:px-6 shadow-[0_-10px_50px_-15px_rgba(0,0,0,0.3)]"
>
<div className="max-w-7xl mx-auto flex items-center justify-center">
<div className="flex-grow max-w-2xl flex items-center">
<Searchbar
placeholder="Search everything..."
query={query}
setQuery={setQuery}
className="rounded-l-2xl rounded-r-none border-r-0"
autoFocus={false}
/>
<Filter className="rounded-l-none rounded-r-2xl border-l-0 bg-white dark:bg-slate-800 h-[38px] min-w-[48px] hover:bg-slate-50 dark:hover:bg-slate-700 transition-colors border-zinc-200 dark:border-zinc-700">
<Selections
Expand Down Expand Up @@ -81,6 +89,6 @@ export const UnifiedFilterBar = () => {
</div>
)}
</div>
</div>
</motion.div>
);
};