create hamburger menu and responsive header

This commit is contained in:
zahravaziri
2025-06-02 18:36:20 +03:30
parent 919364a4dd
commit a5a287f11f
15 changed files with 501 additions and 241 deletions
+14
View File
@@ -0,0 +1,14 @@
export interface IBaseButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
children: ReactNode;
loading?: boolean;
disabled?: boolean;
className?: string
}
export interface ITextButtonProps extends IBaseButtonProps{
endIcon?: ReactNode;
}
export interface IIconButtonProps extends IBaseButtonProps{
color?: 'primary' | 'secondary'
size?: 'small' | 'medium' | 'large'
}
+63 -25
View File
@@ -1,36 +1,24 @@
'use client';
import React, { ButtonHTMLAttributes, ReactNode } from 'react';
import React from 'react';
import { IIconButtonProps, ITextButtonProps } from './button';
interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
children?: ReactNode;
loading?: boolean;
disabled?: boolean;
endIcon?: ReactNode;
size?: 'small' | 'medium' | 'large';
variant?: 'solid' | 'text';
}
const Button: React.FC<ButtonProps> = ({
const Button: React.FC<ITextButtonProps> = ({
children,
loading = false,
disabled = false,
endIcon,
size = 'medium',
variant = 'solid',
className,
...props
}) => {
return (
<button
className={`group relative bg-[#FA003F] rounded-[0.5625rem] h-12 p-px flex ${className || ''}`}
className={`group relative flex h-12 cursor-pointer rounded-[0.5625rem] bg-[#FA003F] p-px ${className || ''}`}
disabled={disabled || loading}
{...props}
>
{loading ? (
<svg
className="animate-spin -ml-1 mr-3 h-5 w-5 text-primary"
className="text-primary mr-3 -ml-1 h-5 w-5 animate-spin"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
@@ -50,19 +38,69 @@ const Button: React.FC<ButtonProps> = ({
></path>
</svg>
) : null}
<div className={`rounded-lg bg-white text-[#222222] flex items-center justify-center px-3 `}>
<div
className={`flex items-center justify-center rounded-lg bg-white px-3 text-[#222222]`}
>
{children}
</div>
</div>
{endIcon && !loading ? (
<span className=" flex items-center justify-center p-3">
{endIcon}
</span>
<span className="flex items-center justify-center p-3">{endIcon}</span>
) : null}
</button>
);
};
export default Button;
export const IconButton: React.FC<IIconButtonProps> = ({
children,
loading = false,
disabled = false,
size = 'medium',
color = 'primary',
className,
...props
}) => {
const colorClass =
color === 'primary' ? 'bg-primary text-white' : 'bg-gray-300 text-gray-500';
const sizeClass =
size === 'large' ? 'w-12 h-12' : size === 'small' ? 'w-8 h-8' : 'w-10 h-10';
return (
<button
className={`group relative flex cursor-pointer items-center justify-center rounded-[0.5625rem] ${colorClass} ${sizeClass} ${className || ''} `}
disabled={disabled || loading}
{...props}
>
{loading ? (
<svg
className="text-primary mr-3 -ml-1 h-5 w-5 animate-spin"
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
>
<circle
className="opacity-25"
cx="12"
cy="12"
r="10"
stroke="currentColor"
strokeWidth="4"
></circle>
<path
className="opacity-75"
fill="currentColor"
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l2-2.647z"
></path>
</svg>
) : null}
<div className={`flex items-center justify-center text-center`}>
{children}
</div>
</button>
);
};
@@ -0,0 +1,22 @@
export const AchievementIcon = (props: React.SVGProps<SVGSVGElement>) => (
<svg
{...props}
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M10.7499 2.45007C11.4399 1.86007 12.5699 1.86007 13.2699 2.45007L14.8499 3.81007C15.1499 4.07007 15.7099 4.28007 16.1099 4.28007H17.8099C18.8699 4.28007 19.7399 5.15007 19.7399 6.21007V7.91007C19.7399 8.30007 19.9499 8.87007 20.2099 9.17007L21.5699 10.7501C22.1599 11.4401 22.1599 12.5701 21.5699 13.2701L20.2099 14.8501C19.9499 15.1501 19.7399 15.7101 19.7399 16.1101V17.8101C19.7399 18.8701 18.8699 19.7401 17.8099 19.7401H16.1099C15.7199 19.7401 15.1499 19.9501 14.8499 20.2101L13.2699 21.5701C12.5799 22.1601 11.4499 22.1601 10.7499 21.5701L9.16988 20.2101C8.86988 19.9501 8.30988 19.7401 7.90988 19.7401H6.17988C5.11988 19.7401 4.24988 18.8701 4.24988 17.8101V16.1001C4.24988 15.7101 4.03988 15.1501 3.78988 14.8501L2.43988 13.2601C1.85988 12.5701 1.85988 11.4501 2.43988 10.7601L3.78988 9.17007C4.03988 8.87007 4.24988 8.31007 4.24988 7.92007V6.20007C4.24988 5.14007 5.11988 4.27007 6.17988 4.27007H7.90988C8.29988 4.27007 8.86988 4.06007 9.16988 3.80007L10.7499 2.45007Z"
fill="currentColor"
/>
<path
d="M8.37988 12.0001L10.7899 14.4201L15.6199 9.58008"
stroke="white"
stroke-width="1.5"
stroke-linecap="round"
stroke-linejoin="round"
/>
</svg>
);
+15
View File
@@ -0,0 +1,15 @@
export const CloseIcon = (props: React.SVGProps<SVGSVGElement>) => (
<svg
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<path
d="M2.4 24L0 21.6L9.6 12L0 2.4L2.4 0L12 9.6L21.6 0L24 2.4L14.4 12L24 21.6L21.6 24L12 14.4L2.4 24Z"
fill="currentColor"
/>
</svg>
);
+28
View File
@@ -0,0 +1,28 @@
import React from 'react';
import { CloseIcon } from './closeIcon';
import { MenuIcon } from './menuIcon';
import { SettingIcon } from './settingIcon';
import { AchievementIcon } from './achievementIcon';
import { PhoneIcon } from './phoneIcon';
import { InstagramIcon } from './instagramIcon';
export const icons = {
close: CloseIcon,
menu: MenuIcon,
setting: SettingIcon,
achievement: AchievementIcon,
phone: PhoneIcon,
instagram: InstagramIcon,
};
export type IconName = keyof typeof icons;
interface IconProps extends React.SVGProps<SVGSVGElement> {
name: IconName;
}
export const Icon = ({ name, ...props }: IconProps) => {
const Component = icons[name];
if (!Component) return null;
return <Component {...props} />;
};
File diff suppressed because one or more lines are too long
+15
View File
@@ -0,0 +1,15 @@
export const MenuIcon = (props: React.SVGProps<SVGSVGElement>) => (
<svg
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
{...props}
>
<path
d="M0 24H24V20H0V24ZM0 14H24V10H0V14ZM0 0V4H24V0H0Z"
fill="currentColor"
/>
</svg>
);
+38
View File
@@ -0,0 +1,38 @@
export const PhoneIcon = (props: React.SVGProps<SVGSVGElement>) => (
<svg
{...props}
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<g clip-path="url(#clip0_4180_257)">
<path
d="M21.97 18.33C21.97 18.69 21.89 19.06 21.72 19.42C21.55 19.78 21.33 20.12 21.04 20.44C20.55 20.98 20.01 21.37 19.4 21.62C18.8 21.87 18.15 22 17.45 22C16.43 22 15.34 21.76 14.19 21.27C13.04 20.78 11.89 20.12 10.75 19.29C9.6 18.45 8.51 17.52 7.47 16.49C6.44 15.45 5.51 14.36 4.68 13.22C3.86 12.08 3.2 10.94 2.72 9.81C2.24 8.67 2 7.58 2 6.54C2 5.86 2.12 5.21 2.36 4.61C2.6 4 2.98 3.44 3.51 2.94C4.15 2.31 4.85 2 5.59 2C5.87 2 6.15 2.06 6.4 2.18C6.66 2.3 6.89 2.48 7.07 2.74L9.39 6.01C9.57 6.26 9.7 6.49 9.79 6.71C9.88 6.92 9.93 7.13 9.93 7.32C9.93 7.56 9.86 7.8 9.72 8.03C9.59 8.26 9.4 8.5 9.16 8.74L8.4 9.53C8.29 9.64 8.24 9.77 8.24 9.93C8.24 10.01 8.25 10.08 8.27 10.16C8.3 10.24 8.33 10.3 8.35 10.36C8.53 10.69 8.84 11.12 9.28 11.64C9.73 12.16 10.21 12.69 10.73 13.22C11.27 13.75 11.79 14.24 12.32 14.69C12.84 15.13 13.27 15.43 13.61 15.61C13.66 15.63 13.72 15.66 13.79 15.69C13.87 15.72 13.95 15.73 14.04 15.73C14.21 15.73 14.34 15.67 14.45 15.56L15.21 14.81C15.46 14.56 15.7 14.37 15.93 14.25C16.16 14.11 16.39 14.04 16.64 14.04C16.83 14.04 17.03 14.08 17.25 14.17C17.47 14.26 17.7 14.39 17.95 14.56L21.26 16.91C21.52 17.09 21.7 17.3 21.81 17.55C21.91 17.8 21.97 18.05 21.97 18.33Z"
stroke="currentColor"
stroke-width="1.5"
stroke-miterlimit="10"
/>
<path
d="M18.5 9C18.5 8.4 18.03 7.48 17.33 6.73C16.69 6.04 15.84 5.5 15 5.5"
stroke="currentColor"
stroke-width="1.5"
stroke-linecap="round"
stroke-linejoin="round"
/>
<path
d="M22 9C22 5.13 18.87 2 15 2"
stroke="currentColor"
stroke-width="1.5"
stroke-linecap="round"
stroke-linejoin="round"
/>
</g>
<defs>
<clipPath id="clip0_4180_257">
<rect width="24" height="24" fill="white" />
</clipPath>
</defs>
</svg>
);
@@ -0,0 +1,27 @@
export const SettingIcon = (props: React.SVGProps<SVGSVGElement>) => (
<svg
{...props}
width="24"
height="24"
viewBox="0 0 24 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<path
d="M12 15C13.6569 15 15 13.6569 15 12C15 10.3431 13.6569 9 12 9C10.3431 9 9 10.3431 9 12C9 13.6569 10.3431 15 12 15Z"
stroke="currentColor"
stroke-width="1.5"
stroke-miterlimit="10"
stroke-linecap="round"
stroke-linejoin="round"
/>
<path
d="M2 12.8799V11.1199C2 10.0799 2.85 9.21994 3.9 9.21994C5.71 9.21994 6.45 7.93994 5.54 6.36994C5.02 5.46994 5.33 4.29994 6.24 3.77994L7.97 2.78994C8.76 2.31994 9.78 2.59994 10.25 3.38994L10.36 3.57994C11.26 5.14994 12.74 5.14994 13.65 3.57994L13.76 3.38994C14.23 2.59994 15.25 2.31994 16.04 2.78994L17.77 3.77994C18.68 4.29994 18.99 5.46994 18.47 6.36994C17.56 7.93994 18.3 9.21994 20.11 9.21994C21.15 9.21994 22.01 10.0699 22.01 11.1199V12.8799C22.01 13.9199 21.16 14.7799 20.11 14.7799C18.3 14.7799 17.56 16.0599 18.47 17.6299C18.99 18.5399 18.68 19.6999 17.77 20.2199L16.04 21.2099C15.25 21.6799 14.23 21.3999 13.76 20.6099L13.65 20.4199C12.75 18.8499 11.27 18.8499 10.36 20.4199L10.25 20.6099C9.78 21.3999 8.76 21.6799 7.97 21.2099L6.24 20.2199C5.33 19.6999 5.02 18.5299 5.54 17.6299C6.45 16.0599 5.71 14.7799 3.9 14.7799C2.85 14.7799 2 13.9199 2 12.8799Z"
stroke="currentColor"
stroke-width="1.5"
stroke-miterlimit="10"
stroke-linecap="round"
stroke-linejoin="round"
/>
</svg>
);