Skip to content

Commit

Permalink
animated header
Browse files Browse the repository at this point in the history
  • Loading branch information
jitunayak committed Jun 20, 2024
1 parent fb99857 commit b3feedf
Show file tree
Hide file tree
Showing 5 changed files with 269 additions and 18 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"@tanstack/react-router": "^1.34.9",
"@tanstack/zod-form-adapter": "^0.20.3",
"axios": "^1.7.2",
"framer-motion": "^11.2.11",
"lucide-react": "^0.383.0",
"moment": "^2.30.1",
"react": "^18.3.1",
Expand Down
29 changes: 29 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

218 changes: 218 additions & 0 deletions src/components/HeaderAnimate.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
import { styled } from '@/stitches.config';
import { setLocalStorage } from '@/utils/LocalStorage';
import { useKindeAuth } from '@kinde-oss/kinde-auth-react';
import { useNavigate } from '@tanstack/react-router';
import { motion, useMotionValueEvent, useScroll } from 'framer-motion';
import { Globe, MapPin, Search } from 'lucide-react';
import { useEffect, useRef, useState } from 'react';

import { AirBnbIcon, HumBurgerIcon } from '../assets';
import { useOutsideClick } from '../hooks';
import { Button } from './Button';
import { Row } from './Common';
import { Divider } from './Divider';
import UserMenu from './UserMenu';

const locations = [
'Banglore',
'London',
'Paris',
'New York',
'San Francisco',
'Tokyo',
];

function HeaderAnimate() {
const navigate = useNavigate();
const { getToken, isAuthenticated, isLoading, login, user } = useKindeAuth();
const [showUserMenu, setShowUserMenu] = useState(false);
const menuRef = useRef<HTMLDivElement>(null);
useOutsideClick(menuRef, () => setShowUserMenu(false));

const [selectLocation, setSelectLocation] =
useState<(typeof locations)[number]>('');
const [showLocationOtions, setShowLocationOtions] = useState(false);

// console.log(user && getPermissions().permissions);

useEffect(() => {
if (!isAuthenticated) {
localStorage.removeItem('access_token');
localStorage.removeItem('user');
return;
}
getToken().then((token) => {
if (token) {
setLocalStorage('access_token', token);
setLocalStorage('user', user);
}
});
}, [getToken, isAuthenticated, user]);

const handleSwitchToHosting = () => {
navigate({ to: '/hosting' });
};

const [isHidden, setIsHidden] = useState(false);
const { scrollY } = useScroll();
const lastRef = useRef(0);

useMotionValueEvent(scrollY, 'change', (y) => {
const difference = y - lastRef.current;
if (Math.abs(difference) > 50) {
setIsHidden(difference > 0);
lastRef.current = y;
}
});

return (
<motion.div
style={{
backgroundColor: 'white',
maxWidth: '74rem',
paddingBottom: '1rem',
paddingTop: '1rem',
position: 'fixed',
top: '0',
width: '100%',
zIndex: '10',
}}
variants={{
hidden: { y: '-100%' },
visible: { y: '0%' },
}}
animate={isHidden ? 'hidden' : 'visible'}
onFocusCapture={() => setIsHidden(false)}
transition={{ duration: 0.3 }}
whileHover="visible"
>
<HeaderWrapper>
<span
onClick={() => navigate({ to: '/' })}
style={{ cursor: 'pointer' }}
>
<AirBnbIcon />
</span>
<Button
color="outline"
shadow="1"
style={{ marginLeft: '4rem', position: 'relative' }}
>
<Button
style={{
cursor: 'pointer',
fontWeight: selectLocation ? 'bold' : 'normal',
}}
color="text"
onClick={() => setShowLocationOtions(!showLocationOtions)}
>
{selectLocation || 'Anywhere'}
</Button>
{showLocationOtions && (
<div
style={{
backgroundColor: 'white',
border: '1px solid #eee',
borderRadius: '5px',
left: '0',
position: 'absolute',
top: '3.5rem',
zIndex: '1',
}}
>
{locations.map((location) => (
<Row
style={{
alignItems: 'center',
cursor: 'pointer',
justifyContent: 'flex-start',
paddingLeft: '1rem',
}}
>
<MapPin size={15} strokeWidth={2.6} />
<Button
onClick={() => {
setSelectLocation(location);
setShowLocationOtions(false);
}}
color="text"
key={location}
>
{location}
</Button>
</Row>
))}
</div>
)}
<Divider />
<Button color="text">Any week</Button>
<Divider />
<Button color="textSecondary">Add guest</Button>
<Button color="primary">
Search <Search size={14} strokeWidth={2.6} />
</Button>
</Button>

<GroupWrapper>
<Button
color={'lightText'}
onClick={() => handleSwitchToHosting()}
size={'m'}
style={{ fontWeight: '600' }}
>
Switch to hosting
</Button>
<Globe size={20} />
{isAuthenticated && !isLoading && user && (
<Button
color={'outline'}
gap="s"
onClick={() => setShowUserMenu(!showUserMenu)}
onMouseEnter={() => setShowUserMenu(true)}
round={'l'}
size={'s'}
>
<HumBurgerIcon />
<RoundIcon>{user?.given_name?.charAt(0)}</RoundIcon>
</Button>
)}
{showUserMenu && <UserMenu menuRef={menuRef} />}
{!user && !isLoading && (
<Button onClick={() => login({})}>Login</Button>
)}
</GroupWrapper>
</HeaderWrapper>
</motion.div>
);
}

export default HeaderAnimate;

const HeaderWrapper = styled('div', {
alignItems: 'center',
display: 'flex',
justifyContent: 'space-between',
margin: '0rem 2rem',
});
const RoundIcon = styled('span', {
alignItems: 'center',
backgroundColor: 'black',
borderRadius: '100%',
color: 'white',
cursor: 'pointer',
display: 'flex',
fontSize: '10px',
fontWeight: '500',
height: '16px',
justifyContent: 'center',
padding: '0.5rem',
width: '16px',
});

const GroupWrapper = styled('span', {
alignItems: 'center',
display: 'inline-flex',
gap: '1rem',
justifyContent: 'center',
position: 'relative',
});
30 changes: 15 additions & 15 deletions src/components/StickyHeader.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { styled } from "@stitches/react";
import { styled } from '@stitches/react';

import CategoryActionBar from "./CategoryActionBar";
import Header from "./Header";
import CategoryActionBar from './CategoryActionBar';
import Header from './Header';

function StickyHeader() {
return (
Expand All @@ -14,19 +14,19 @@ function StickyHeader() {
}
export default StickyHeader;

const StickyHeaderWrapper = styled("div", {
backgroundColor: "white",
paddingTop: "1rem",
position: "fixed",
const StickyHeaderWrapper = styled('div', {
backgroundColor: 'white',
paddingTop: '1rem',
position: 'fixed',
top: 0,
width: "100%",
zIndex: "9",
width: '100%',
zIndex: '9',
});

const Line = styled("span", {
backgroundColor: "#eee",
display: "flex",
height: "1px",
margin: "1rem",
width: "100%",
const Line = styled('span', {
backgroundColor: '#eee',
display: 'flex',
height: '1px',
margin: '1rem',
width: '100%',
});
9 changes: 6 additions & 3 deletions src/pages/Room/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Column, Divider, Row } from '@/components';
import Header from '@/components/Header';
import HeaderAnimate from '@/components/HeaderAnimate';
import { styled } from '@/stitches.config';
import { useQuery } from '@tanstack/react-query';
import { useParams } from '@tanstack/react-router';
Expand Down Expand Up @@ -43,8 +43,11 @@ function RoomPage() {

return (
<Container>
<Header />
<Divider orientation={'horizontal'} style={{ marginTop: '1rem' }} />
<HeaderAnimate />
<Divider
orientation={'horizontal'}
style={{ marginBottom: '2rem', marginTop: '3.6rem' }}
/>
<PageContainer>
{/* RoomPage {roomId} */}
<Title>{room.name}</Title>
Expand Down

0 comments on commit b3feedf

Please sign in to comment.