feat: header component

feat: dropdown component
feat: avatar component
This commit is contained in:
2023-12-30 13:01:04 +01:00
parent 7416196221
commit 0ccc447e40
31 changed files with 726 additions and 58 deletions

View File

@@ -0,0 +1,18 @@
.root {
width: 100%;
height: var(--header-height);
padding: 12px var(--horizontal-padding);
background: var(--color-dark-700);
border-bottom: 1px solid var(--color-dark-500);
}
.content {
display: flex;
align-items: center;
justify-content: space-between;
width: 100%;
max-width: var(--max-width);
margin: 0 auto;
}

View File

@@ -0,0 +1,34 @@
import type { Meta, StoryObj } from '@storybook/react'
import { Header } from './'
const meta = {
argTypes: {
onLogout: { action: 'logout' },
},
component: Header,
parameters: {
layout: 'fullscreen',
},
tags: ['autodocs'],
title: 'Components/Header',
} satisfies Meta<typeof Header>
export default meta
type Story = StoryObj<typeof meta>
export const LoggedIn: Story = {
// @ts-expect-error onLogout is required but it is provided through argTypes
args: {
avatar: 'https://avatars.githubusercontent.com/u/1196870?v=4',
email: 'johndoe@gmail.com',
isLoggedIn: true,
userName: 'John Doe',
},
}
export const LoggedOut: Story = {
args: {
isLoggedIn: false,
},
}

View File

@@ -0,0 +1,37 @@
import { memo } from 'react'
import { Link } from 'react-router-dom'
import { Logo } from '@/assets'
import { UserDropdown, UserDropdownProps } from '@/components/layout/header/user-dropdown'
import s from './header.module.scss'
import { Button } from '../../ui'
export type HeaderProps =
| (Partial<UserDropdownProps> & {
isLoggedIn: false
})
| (UserDropdownProps & {
isLoggedIn: true
})
export const Header = memo(({ avatar, email, isLoggedIn, onLogout, userName }: HeaderProps) => {
return (
<header className={s.root}>
<div className={s.content}>
<Link to={'/'}>
<Logo />
</Link>
{isLoggedIn && (
<UserDropdown avatar={avatar} email={email} onLogout={onLogout} userName={userName} />
)}
{!isLoggedIn && (
<Button as={Link} to={'/sign-in'}>
Sign In
</Button>
)}
</div>
</header>
)
})

View File

@@ -0,0 +1 @@
export * from './header'

View File

@@ -0,0 +1 @@
export * from './user-dropdown'

View File

@@ -0,0 +1,3 @@
.email {
color: var(--color-dark-100);
}

View File

@@ -0,0 +1,27 @@
import type { Meta, StoryObj } from '@storybook/react'
import { UserDropdown } from './'
const meta = {
argTypes: {
onLogout: { action: 'logout' },
},
component: UserDropdown,
parameters: {
layout: 'centered',
},
tags: ['autodocs'],
title: 'Components/UserDropdown',
} satisfies Meta<typeof UserDropdown>
export default meta
type Story = StoryObj<typeof meta>
export const Default: Story = {
// @ts-expect-error onLogout is required but it is provided through argTypes
args: {
avatar: 'https://avatars.githubusercontent.com/u/1196870?v=4',
email: 'johndoe@gmail.com',
userName: 'John Doe',
},
}

View File

@@ -0,0 +1,59 @@
import { ComponentPropsWithoutRef } from 'react'
import { Link } from 'react-router-dom'
import { Logout, PersonOutline } from '@/assets'
import {
Avatar,
Button,
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuTrigger,
Typography,
} from '@/components'
import s from './user-dropdown.module.scss'
export type UserDropdownProps = {
avatar: string
email: string
onLogout: ComponentPropsWithoutRef<typeof DropdownMenuItem>['onSelect']
userName: string
}
export const UserDropdown = ({ avatar, email, onLogout, userName }: UserDropdownProps) => {
return (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button rounded variant={'icon'}>
<Avatar src={avatar} />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent>
<DropdownMenuLabel>
<Avatar src={avatar} />
<div>
<Typography variant={'subtitle2'}>{userName}</Typography>
<Typography className={s.email} variant={'caption'}>
{email}
</Typography>
</div>
</DropdownMenuLabel>
<DropdownMenuSeparator />
<DropdownMenuItem asChild>
<Link to={'/profile'}>
<PersonOutline />
My profile
</Link>
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem onSelect={onLogout}>
<Logout />
Sign out
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
)
}