Feat/525 update drawer (#611)

* feat(console-lite): add nav icons

* feat(console-lite): refactor resizing into reusable hook

* feat(console-lite): refactor navigation drawer

* feat(console-lite): add blue colour to theme-lite.js

* feat(console-lite): remove liquidity from nav items

* feat(console-lite): make style changes to navbar and add tab-bar for mobile

* chore(console-lite): change div to aside

* fix(console-lite): drawer left to right mode on mobile

* fix(console-lite): add missing className prop to drawer-wrapper.tsx

* feat(console-lite): add accessibility related changes

* fix(console-lite): fix linting errors

* fix(console-lite): fix failing test and add extra accessibility label

* refactor(console-lite): refactor conditional classNames

* refactor(console-lite): move useResize to react-helpers library

* refactor(console-lite): refactor sun and moon classNames

* fix(console-lite): fix broken e2e tests
This commit is contained in:
Elmar 2022-06-27 16:55:51 +01:00 committed by GitHub
parent b269ad16cf
commit 7cc162c57c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
27 changed files with 380 additions and 186 deletions

View File

@ -5,7 +5,10 @@ describe('market list', () => {
});
it('selects menus', () => {
cy.get('.MuiDrawer-root [aria-current]').should('have.text', 'Markets');
cy.get('[aria-label="Sidebar Navigation Menu"] [aria-current]').should(
'have.text',
'Markets'
);
cy.getByTestId('state-trigger').should('have.text', 'Active');
cy.get('[aria-label="Future"]').click();
cy.get('[data-testid="market-assets-menu"] a.active').should(

View File

@ -40,13 +40,7 @@ function App() {
<VegaWalletProvider>
<AppLoader>
<div className="max-h-full min-h-full dark:bg-black dark:text-white-60 bg-white text-black-60 grid grid-rows-[min-content,1fr]">
<div className="flex items-stretch border-b-[7px] border-vega-yellow">
<DrawerToggle
onToggle={onToggle}
variant={DRAWER_TOGGLE_VARIANTS.OPEN}
className="xs:py-32 xs:px-16"
/>
<div className="flex items-stretch p-16 bg-black text-white-60">
<div className="flex items-center gap-4 ml-auto mr-8">
<VegaWalletConnectButton
setConnectDialog={(open) =>
@ -56,8 +50,17 @@ function App() {
setVegaWallet((x) => ({ ...x, manage: open }))
}
/>
<ThemeSwitcher onToggle={toggleTheme} className="-my-4" />
<ThemeSwitcher
onToggle={toggleTheme}
className="-my-4"
sunClassName="text-white"
/>
</div>
<DrawerToggle
onToggle={onToggle}
variant={DRAWER_TOGGLE_VARIANTS.OPEN}
className="xs:py-32 xs:px-16 xs:text-white xs:hover:text-blue"
/>
</div>
<Main isMenuOpen={menuOpen} onToggle={onToggle} />

View File

@ -1,14 +0,0 @@
import * as React from 'react';
import type { ReactElement } from 'react';
interface Props {
children: ReactElement | ReactElement[];
}
export const DrawerContainer = ({ children }: Props) => (
<div className="w-full md:w-3/4 grow-1">{children}</div>
);
export const DrawerWrapper = ({ children }: Props) => (
<div className="flex dark:bg-black">{children}</div>
);

View File

@ -0,0 +1,21 @@
import * as React from 'react';
import classNames from 'classnames';
import type { ReactElement } from 'react';
interface Props {
children: ReactElement | ReactElement[];
className?: string;
}
export const DrawerContent = ({ children, className = '' }: Props) => {
const classes = classNames(
'w-full sm:w-full grow-1 p-20 overflow-hidden',
className
);
return (
<main aria-label="Page Content" className={classes}>
{children}
</main>
);
};

View File

@ -1,38 +0,0 @@
import * as React from 'react';
import type { ReactElement } from 'react';
import { Button } from '@vegaprotocol/ui-toolkit';
import type { ButtonProps } from '@vegaprotocol/ui-toolkit';
type MenuItem = {
label: string;
component: ReactElement | ReactElement[];
onClick(): void;
active: boolean;
};
interface Props {
/**
* Menu items passed as an array
*/
menuItems: MenuItem[];
}
export const NavigationDrawerMenu = ({ menuItems }: Props) => {
return (
<ul>
{menuItems.map((item, index) => {
const btnProps = {
variant: item.active ? 'accent' : 'primary',
className: 'w-full mb-8',
onClick: item.onClick,
} as ButtonProps;
return (
<li key={index}>
<Button {...btnProps}>{item.label}</Button>
</li>
);
})}
</ul>
);
};

View File

@ -19,12 +19,10 @@ interface Props {
export const DrawerToggle = ({
onToggle,
variant = DRAWER_TOGGLE_VARIANTS.CLOSE,
className,
className = '',
}: Props) => {
const [iconName, setIconName] = useState(IconNames.MENU);
const classes = classNames('md:hidden', {
[className as string]: className,
});
const classes = classNames('md:hidden', className);
useEffect(() => {
if (variant === DRAWER_TOGGLE_VARIANTS.OPEN) {
@ -34,8 +32,17 @@ export const DrawerToggle = ({
}
}, [variant]);
const ariaLabel = `${
variant === DRAWER_TOGGLE_VARIANTS.OPEN ? 'Open' : 'Close'
} Sidebar Navigation Menu`;
return (
<Button variant="inline-link" className={classes} onClick={onToggle}>
<Button
aria-label={ariaLabel}
variant="inline-link"
className={classes}
onClick={onToggle}
>
<Icon name={iconName as IconName} />
</Button>
);

View File

@ -0,0 +1,13 @@
import * as React from 'react';
import classNames from 'classnames';
import type { ReactElement } from 'react';
interface Props {
children: ReactElement | ReactElement[];
className?: string;
}
export const DrawerWrapper = ({ children, className = '' }: Props) => {
const classes = classNames('flex dark:bg-black md:flex-row', className);
return <div className={classes}>{children}</div>;
};

View File

@ -1,66 +1,60 @@
import * as React from 'react';
import { themelite as theme } from '@vegaprotocol/tailwindcss-config';
import classNames from 'classnames';
import type { ReactElement } from 'react';
import { useEffect } from 'react';
import Drawer from '@mui/material/Drawer';
interface Props {
children?: ReactElement | ReactElement[];
isMenuOpen?: boolean;
onToggle(): void;
rtl?: boolean;
outerClasses?: string;
innerClasses?: string;
}
export const NavigationDrawer = ({
isMenuOpen = false,
onToggle,
children,
rtl,
outerClasses = '',
innerClasses = '',
}: Props) => {
const [windowSize, setWindowSize] = React.useState({
width: window.innerWidth,
height: window.innerHeight,
const width = 'w-full md:w-auto md:min-w-[15%] shrink-0';
const position = 'absolute inset-0 h-full z-10 md:static';
const background = 'bg-black/50 dark:bg-white/50';
const flex = 'flex justify-end overflow-hidden';
const joinedClasses = [flex, width, position, background].join(' ');
const outerStyles = classNames(joinedClasses, {
visible: isMenuOpen,
'invisible md:visible': !isMenuOpen,
'flex-row-reverse': !rtl,
[outerClasses]: outerClasses,
});
const mobileScreenWidth = parseInt(theme.screens.md);
const isMobile = windowSize.width <= mobileScreenWidth;
const timeout = React.useRef(0);
const handleResize = () => {
if (timeout.current) {
window.cancelAnimationFrame(timeout.current);
}
const translateClose = rtl ? 'translate-x-full' : '-translate-x-full';
// Setup the new requestAnimationFrame()
timeout.current = window.requestAnimationFrame(function () {
setWindowSize({
width: window.innerWidth,
height: window.innerHeight,
});
});
};
useEffect(() => {
window.addEventListener('resize', handleResize);
return () => {
window.removeEventListener('resize', handleResize);
window.cancelAnimationFrame(timeout.current);
};
}, []);
const drawerRootClasses = {
root: 'w-3/4 md:w-1/4 shrink-0',
paper: 'p-16 w-3/4 md:w-1/4 box-border',
};
const innerStyles = classNames('w-3/4 md:w-full bg-white dark:bg-black', {
'translate-x-0 transition-transform md:transform-none': isMenuOpen,
[`${translateClose} md:transform-none`]: !isMenuOpen,
[innerClasses]: innerClasses,
});
return (
<Drawer
classes={drawerRootClasses}
variant={isMobile ? 'temporary' : 'permanent'}
open={isMobile ? isMenuOpen : true}
onClose={onToggle}
ModalProps={{
keepMounted: true, // Better open performance on mobile.
}}
>
{children}
</Drawer>
<aside aria-label="Sidebar Navigation Menu" className={outerStyles}>
<div
role="presentation"
aria-label="Content Overlay - Click To Close Sidebar Navigation"
className="md:hidden grow h-full"
onClick={onToggle}
/>
<div
role="group"
aria-label="Sidebar Navigation Grouped Content"
className={innerStyles}
>
{children}
</div>
</aside>
);
};

View File

@ -1,4 +1,4 @@
export * from './drawer';
export * from './drawer-menu';
export * from './drawer-toggle';
export * from './drawer-container';
export * from './drawer-content';
export * from './drawer-wrapper';

View File

@ -0,0 +1,51 @@
import type { ReactElement } from 'react';
import { LiquidityIconPath } from './liquidity-icon';
import { MarketIconPath } from './market-icon';
import { TradeIconPath } from './trade-icon';
import { PortfolioIconPath } from './portfolio-icon';
interface IconProps {
name: string;
className: string;
}
interface IconSVGWrapperProps {
className: string;
children: ReactElement | ReactElement[] | null;
}
const getIconPath = (name: string): ReactElement | null => {
switch (name) {
case 'liquidity':
return <LiquidityIconPath />;
case 'market':
return <MarketIconPath />;
case 'trade':
return <TradeIconPath />;
case 'portfolio':
return <PortfolioIconPath />;
default:
return null;
}
};
const IconSVGWrapper = ({ className, children }: IconSVGWrapperProps) => {
return (
<svg
role="presentation"
className={className}
width="24"
height="24"
viewBox="0 0 24 24"
fill="currentColor"
>
{children}
</svg>
);
};
export const Icon = ({ name, className }: IconProps) => {
return (
<IconSVGWrapper className={className}>{getIconPath(name)}</IconSVGWrapper>
);
};

View File

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

View File

@ -0,0 +1,15 @@
export const LiquidityIconPath = () => (
<>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M12.5268 1.46612L12 1.99999L11.4732 1.46612L12 0.946381L12.5268 1.46612ZM12 3.07542C11.8274 3.25709 11.6185 3.48044 11.3826 3.73943C10.6899 4.49987 9.76793 5.56335 8.84782 6.77789C7.92587 7.99485 7.01715 9.34862 6.34179 10.6903C5.66046 12.0439 5.25 13.3205 5.25 14.4C5.25 19.0485 8.47431 22.15 12 22.15C15.5257 22.15 18.75 19.0485 18.75 14.4C18.75 13.3205 18.3395 12.0439 17.6582 10.6903C16.9829 9.34862 16.0741 7.99485 15.1522 6.77789C14.2321 5.56335 13.3101 4.49987 12.6174 3.73943C12.3815 3.48044 12.1726 3.25709 12 3.07542ZM11.4732 1.46612C11.4734 1.46597 11.4732 1.46612 12 1.99999C12.5268 1.46612 12.5266 1.46597 12.5268 1.46612L12.5336 1.47291L12.5512 1.49036C12.5663 1.5055 12.5884 1.52759 12.6169 1.55634C12.6739 1.61384 12.7566 1.698 12.8615 1.80641C13.071 2.02319 13.3692 2.33722 13.7263 2.72931C14.4399 3.51261 15.3929 4.61164 16.3478 5.8721C17.3009 7.13013 18.2671 8.56386 18.998 10.0159C19.723 11.4561 20.25 12.9795 20.25 14.4C20.25 19.7514 16.4743 23.65 12 23.65C7.52569 23.65 3.75 19.7514 3.75 14.4C3.75 12.9795 4.27704 11.4561 5.00196 10.0159C5.73285 8.56386 6.69913 7.13013 7.65218 5.8721C8.60707 4.61164 9.56014 3.51261 10.2737 2.72931C10.6308 2.33722 10.929 2.02319 11.1385 1.80641C11.2434 1.698 11.3261 1.61384 11.3831 1.55634C11.4116 1.52759 11.4337 1.5055 11.4488 1.49036L11.4664 1.47291L11.4712 1.46817L11.4732 1.46612Z"
/>
<rect x="11.5" y="17.4" width="1" height="1" />
<rect x="12.5" y="16.4" width="1" height="1" />
<rect x="10.5" y="16.4" width="1" height="1" />
<rect x="14.5" y="15.4" width="1" height="1" />
<rect x="13.5" y="11.4" width="1" height="4" />
<rect x="9.5" y="11.4" width="1" height="5" />
</>
);

View File

@ -0,0 +1,17 @@
export const MarketIconPath = () => (
<>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M3.5 2H2V20.5V22H3.5H22V20.5H3.5V2Z"
/>
<rect x="5" y="15" width="2" height="2" />
<rect x="7" y="13" width="2" height="2" />
<rect x="9" y="11" width="2" height="2" />
<rect x="11" y="9" width="2" height="2" />
<rect x="13" y="11" width="2" height="2" />
<rect x="15" y="9" width="2" height="2" />
<rect x="17" y="7" width="2" height="2" />
<rect x="19" y="5" width="2" height="2" />
</>
);

View File

@ -0,0 +1,17 @@
export const PortfolioIconPath = () => (
<>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M8.5 3.5H15.5V6H8.5V3.5ZM7 6V3.5C7 2.67157 7.67157 2 8.5 2H15.5C16.3284 2 17 2.67157 17 3.5V6H20.5C21.3284 6 22 6.67157 22 7.5V20.5C22 21.3284 21.3284 22 20.5 22H3.5C2.67157 22 2 21.3284 2 20.5V7.5C2 6.67157 2.67157 6 3.5 6H7ZM15.5 7.5H8.5H3.5L3.5 20.5H20.5V7.5H15.5Z"
/>
<rect x="4" y="8" width="2" height="2" />
<rect x="6" y="10" width="2" height="2" />
<rect x="18" y="8" width="2" height="2" />
<rect x="16" y="10" width="2" height="2" />
<rect x="14" y="12" width="2" height="2" />
<rect x="8" y="12" width="2" height="2" />
<rect x="10" y="14" width="2" height="2" />
<rect x="12" y="14" width="2" height="2" />
</>
);

View File

@ -0,0 +1,14 @@
export const TradeIconPath = () => (
<>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M19.3254 7.28784L14.8547 2.93099L15.7621 1.99999L21.4056 7.49983L21.8833 7.96534L21.4056 8.43085L15.7621 13.9307L14.8547 12.9997L19.3819 8.58784L1.99999 8.58784L1.99999 7.28784L19.3254 7.28784Z"
/>
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="M4.55785 16.6429L9.02855 20.9997L8.12124 21.9307L2.47767 16.4309L2 15.9654L2.47767 15.4999L8.12124 10L9.02855 10.931L4.50141 15.3429L21.8833 15.3429V16.6429L4.55785 16.6429Z"
/>
</>
);

View File

@ -1,62 +1,41 @@
import React from 'react';
import { useRoutes, NavLink } from 'react-router-dom';
import { useRoutes } from 'react-router-dom';
import {
NavigationDrawer,
DrawerWrapper,
DrawerContainer,
DrawerContent,
DrawerToggle,
DRAWER_TOGGLE_VARIANTS,
} from '../drawer';
import { Nav, TabBar } from '../nav';
import { routerConfig } from '../../routes/router-config';
export interface RouteChildProps {
name: string;
}
export const AppRouter = () => {
const routes = useRoutes(routerConfig);
return <main className="p-20 overflow-hidden">{routes}</main>;
};
export const Menu = () => (
<nav>
{routerConfig.map((r) => (
<NavLink
key={r.name}
to={r.path}
className={({ isActive }) =>
`text-h5 block mb-8 px-8 hover:bg-vega-yellow hover:text-black ${
isActive && 'bg-vega-yellow text-black'
}`
}
>
{r.text}
</NavLink>
))}
</nav>
);
export const AppRouter = () => useRoutes(routerConfig);
interface Props {
onToggle(): void;
isMenuOpen: boolean;
}
export const Main = ({ onToggle, isMenuOpen }: Props) => {
return (
<DrawerWrapper>
<NavigationDrawer onToggle={onToggle} isMenuOpen={isMenuOpen}>
<NavigationDrawer rtl onToggle={onToggle} isMenuOpen={isMenuOpen}>
<DrawerToggle
onToggle={onToggle}
variant={DRAWER_TOGGLE_VARIANTS.CLOSE}
className="self-end p-16"
className="p-16"
/>
<Menu />
<Nav className="hidden md:block my-20 h-full" />
</NavigationDrawer>
<DrawerContainer>
<DrawerContent>
<AppRouter />
</DrawerContainer>
<TabBar className="md:hidden" />
</DrawerContent>
</DrawerWrapper>
);
};

View File

@ -0,0 +1,2 @@
export * from './nav';
export * from './tab-bar';

View File

@ -0,0 +1,16 @@
import React from 'react';
import { Icon } from '../icons';
interface NavItemProps {
iconName: string;
label?: string;
}
export const NavItem = ({ iconName, label }: NavItemProps) => {
return (
<div className="flex flex-col md:flex-row items-center justify-start cursor-pointer relative">
<Icon name={iconName} className="mr-8" />
<span>{label}</span>
</div>
);
};

View File

@ -0,0 +1,30 @@
import { routerConfig } from '../../routes';
import { NavLink } from 'react-router-dom';
import { NavItem } from './nav-item';
import React from 'react';
interface NavProps {
className?: string;
tabs?: boolean;
}
export const Nav = ({ className, tabs = false }: NavProps) => {
return (
<nav role={tabs ? 'tablist' : 'menu'} className={className}>
{routerConfig.map((r) => (
<NavLink
role={tabs ? 'tab' : 'menuitem'}
key={r.name}
to={r.path}
className={({ isActive }) =>
`text-h5 block md:mb-40 px-40 md:text-black md:dark:text-white ${
isActive && 'text-white md:text-blue md:dark:text-blue'
}`
}
>
<NavItem iconName={r.icon} label={r.text} />
</NavLink>
))}
</nav>
);
};

View File

@ -0,0 +1,15 @@
import { Nav } from './nav';
import React from 'react';
interface TabBarProps {
className?: string;
}
export const TabBar = ({ className }: TabBarProps) => (
<div role="group" aria-label="Tab Bar Navigation Menu" className={className}>
<div role="presentation" className="py-[42px]" />
<div className="md:hidden fixed bottom-0 left-0 right-0 bg-black py-16">
<Nav tabs className="flex justify-evenly items-center" />
</div>
</div>
);

View File

@ -4,20 +4,12 @@ import { SimpleMarketList } from '../components/simple-market-list';
import { Portfolio } from '../components/portfolio';
export const ROUTES = {
HOME: '/',
MARKETS: 'markets',
TRADING: 'trading',
LIQUIDITY: 'liquidity',
PORTFOLIO: 'portfolio',
};
export const routerConfig = [
{
path: ROUTES.HOME,
name: 'Home',
text: t('Home'),
element: <div>Home</div>,
},
{
path: ROUTES.MARKETS,
children: [
@ -36,6 +28,7 @@ export const routerConfig = [
name: 'Markets',
text: t('Markets'),
element: <SimpleMarketList />,
icon: 'market',
},
{
path: ROUTES.TRADING,
@ -48,17 +41,13 @@ export const routerConfig = [
element: <DealTicketContainer />,
},
],
},
{
path: ROUTES.LIQUIDITY,
name: 'Liquidity',
text: t('Liquidity'),
element: <div>Liquidity</div>,
icon: 'trade',
},
{
path: ROUTES.PORTFOLIO,
name: 'Portfolio',
text: t('Portfolio'),
element: <Portfolio />,
icon: 'portfolio',
},
];

View File

@ -2,3 +2,4 @@ export * from './use-apply-grid-transaction';
export * from './use-data-provider';
export * from './use-theme-switcher';
export * from './use-fetch';
export * from './use-resize';

View File

@ -0,0 +1,34 @@
import { useRef, useEffect, useState } from 'react';
export const useResize = () => {
const [windowSize, setWindowSize] = useState({
width: window.innerWidth,
height: window.innerHeight,
});
const timeout = useRef(0);
const handleResize = () => {
if (timeout.current) {
window.cancelAnimationFrame(timeout.current);
}
// Setup the new requestAnimationFrame()
timeout.current = window.requestAnimationFrame(function () {
setWindowSize({
width: window.innerWidth,
height: window.innerHeight,
});
});
};
useEffect(() => {
window.addEventListener('resize', handleResize);
return () => {
window.removeEventListener('resize', handleResize);
window.cancelAnimationFrame(timeout.current);
};
}, []);
return windowSize;
};

View File

@ -11,6 +11,7 @@ module.exports = {
yellow: '#DFFF0B',
mint: '#00F780',
pink: '#FF077F',
blue: '#2E6DE5',
},
fontSize: {
...theme.fontSize,

View File

@ -0,0 +1,25 @@
export const SunIcon = () => (
<svg viewBox="0 0 45 45" className="w-32 h-32">
<g>
<path
d="M22.5 27.79a5.29 5.29 0 1 0 0-10.58 5.29 5.29 0 0 0 0 10.58Z"
fill="currentColor"
></path>
<path
d="M15.01 22.5H10M35 22.5h-5.01M22.5 29.99V35M22.5 10v5.01M17.21 27.79l-3.55 3.55M31.34 13.66l-3.55 3.55M27.79 27.79l3.55 3.55M13.66 13.66l3.55 3.55"
stroke="currentColor"
strokeWidth="1.3"
strokeMiterlimit="10"
></path>
</g>
</svg>
);
export const MoonIcon = () => (
<svg viewBox="0 0 45 45" className="w-32 h-32">
<path
d="M28.75 11.69A12.39 12.39 0 0 0 22.5 10a12.5 12.5 0 1 0 0 25c2.196 0 4.353-.583 6.25-1.69A12.46 12.46 0 0 0 35 22.5a12.46 12.46 0 0 0-6.25-10.81Zm-6.25 22a11.21 11.21 0 0 1-11.2-11.2 11.21 11.21 0 0 1 11.2-11.2c1.246 0 2.484.209 3.66.62a13.861 13.861 0 0 0-5 10.58 13.861 13.861 0 0 0 5 10.58 11.078 11.078 0 0 1-3.66.63v-.01Z"
fill="currentColor"
></path>
</svg>
);

View File

@ -1 +1,2 @@
export * from './theme-switcher';
export * from './icons';

View File

@ -1,34 +1,31 @@
import classNames from 'classnames';
import { SunIcon, MoonIcon } from './icons';
export const ThemeSwitcher = ({
onToggle,
className,
sunClassName = '',
moonClassName = '',
}: {
onToggle: () => void;
className?: string;
}) => (
<button type="button" onClick={() => onToggle()} className={className}>
<span className="dark:hidden text-black">
<svg viewBox="0 0 45 45" className="w-32 h-32">
<g>
<path
d="M22.5 27.79a5.29 5.29 0 1 0 0-10.58 5.29 5.29 0 0 0 0 10.58Z"
fill="currentColor"
></path>
<path
d="M15.01 22.5H10M35 22.5h-5.01M22.5 29.99V35M22.5 10v5.01M17.21 27.79l-3.55 3.55M31.34 13.66l-3.55 3.55M27.79 27.79l3.55 3.55M13.66 13.66l3.55 3.55"
stroke="currentColor"
strokeWidth="1.3"
strokeMiterlimit="10"
></path>
</g>
</svg>
</span>
<span className="hidden dark:inline text-white">
<svg viewBox="0 0 45 45" className="w-32 h-32">
<path
d="M28.75 11.69A12.39 12.39 0 0 0 22.5 10a12.5 12.5 0 1 0 0 25c2.196 0 4.353-.583 6.25-1.69A12.46 12.46 0 0 0 35 22.5a12.46 12.46 0 0 0-6.25-10.81Zm-6.25 22a11.21 11.21 0 0 1-11.2-11.2 11.21 11.21 0 0 1 11.2-11.2c1.246 0 2.484.209 3.66.62a13.861 13.861 0 0 0-5 10.58 13.861 13.861 0 0 0 5 10.58 11.078 11.078 0 0 1-3.66.63v-.01Z"
fill="currentColor"
></path>
</svg>
</span>
</button>
);
sunClassName?: string;
moonClassName?: string;
}) => {
const sunClasses = classNames('dark:hidden text-black', sunClassName);
const moonClasses = classNames(
'hidden dark:inline text-white',
moonClassName
);
return (
<button type="button" onClick={() => onToggle()} className={className}>
<span className={sunClasses}>
<SunIcon />
</span>
<span className={moonClasses}>
<MoonIcon />
</span>
</button>
);
};