Skip to content

Commit

Permalink
Merge pull request #117 from JohnsonMao/refactor/update-menu-style
Browse files Browse the repository at this point in the history
Refactor/update menu style
  • Loading branch information
JohnsonMao authored Nov 8, 2023
2 parents 8315a7a + f478f90 commit 199024d
Show file tree
Hide file tree
Showing 6 changed files with 61 additions and 32 deletions.
43 changes: 34 additions & 9 deletions src/app/[lang]/Menu.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
'use client';

import { CSSProperties, useLayoutEffect, useRef, useState } from 'react';
import { usePathname } from 'next/navigation';

import Link from '@/components/Link';
Expand All @@ -16,6 +17,8 @@ export type MenuProps = {
};

function Menu({ menu }: MenuProps) {
const [offset, setOffset] = useState({ left: 0, width: 16 });
const menuRef = useRef<HTMLUListElement>(null);
const pathname = usePathname();
const locale = getLocale(pathname) || '';
const localePrefix = new RegExp(`^/${locale}/?([^/]*)/?`);
Expand All @@ -24,11 +27,28 @@ function Menu({ menu }: MenuProps) {
(item) => item.href === `/${rootPathname}`
);

const menuStyle = {
'--active-offset-w': (offset.width - 16) / 40,
'--active-offset-x': `${offset.left + 8}px`,
} as CSSProperties;

useLayoutEffect(() => {
const itemElement = menuRef.current?.children[activeLinkIndex];

if (itemElement instanceof HTMLElement) {
setOffset({
left: itemElement.offsetLeft,
width: itemElement.offsetWidth,
});
}
}, [activeLinkIndex]);

return (
<nav>
<nav className="relative" style={menuStyle}>
<ul
ref={menuRef}
className={cn(
'fluorescent-box flex rounded-full px-2 backdrop-blur-sm',
'neon-box flex rounded-full px-2 backdrop-blur-sm',
'bg-zinc-100/80 dark:bg-zinc-900/80'
)}
>
Expand All @@ -37,20 +57,25 @@ function Menu({ menu }: MenuProps) {
<Link
href={href}
className={cn(
'relative block p-3 text-xl leading-none no-underline',
'text-zinc-700 hover:text-primary-500 dark:text-zinc-300 dark:hover:text-primary-500',
activeLinkIndex === index &&
'fluorescent-text text-primary-500 dark:text-primary-500'
'block p-3 text-xl leading-none no-underline',
'text-zinc-700 dark:text-zinc-300',
activeLinkIndex === index
? 'neon-text text-primary-600 dark:text-primary-400'
: 'hover:text-primary-700 dark:hover:text-primary-300'
)}
>
{text}
{activeLinkIndex === index && (
<span className="absolute inset-x-2 bottom-0 h-px translate-y-1/2 bg-gradient-to-l from-transparent via-primary-500 to-transparent" />
)}
</Link>
</li>
))}
</ul>
<span
className={cn(
'absolute bottom-0 left-0 h-px w-10',
'origin-left translate-x-[var(--active-offset-x)] translate-y-1/3 scale-x-[var(--active-offset-w)] scale-y-50 transition-transform',
'bg-gradient-to-r from-transparent via-primary-600 to-transparent dark:via-primary-400'
)}
/>
</nav>
);
}
Expand Down
6 changes: 3 additions & 3 deletions src/app/[lang]/__tests__/menu.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ describe('Menu component', () => {
];

it('should render correct element', () => {
mockPathname.mockReturnValueOnce('/');
mockPathname.mockReturnValue('/');

render(<Menu menu={menu} />);

Expand All @@ -36,12 +36,12 @@ describe('Menu component', () => {
])(
'should render correct active link based on the pathname "%s"',
(pathname, activeLinkText) => {
mockPathname.mockReturnValueOnce(pathname);
mockPathname.mockReturnValue(pathname);

render(<Menu menu={menu} />);

const links = screen.getAllByRole('link');
const activeClassName = 'text-primary-500';
const activeClassName = 'neon-text';

links.forEach((link) => {
if (link.textContent === activeLinkText) {
Expand Down
2 changes: 1 addition & 1 deletion src/app/[lang]/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ async function I18nLayout({
<Menu menu={menu} />
<ThemeSwitcher
className={cn(
'fluorescent-box rounded-full p-3 backdrop-blur-sm',
'neon-box rounded-full p-3 backdrop-blur-sm',
'bg-zinc-100/80 dark:bg-zinc-900/80'
)}
/>
Expand Down
2 changes: 1 addition & 1 deletion src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ function HtmlLayout({ children }: React.PropsWithChildren) {
<Html>
<body>
<div className="lattice fixed inset-x-0 top-0 -z-50 h-screen">
<Container className="h-screen border-x-2 border-zinc-500/5 bg-zinc-100/70 dark:bg-zinc-900/70" />
<Container className="h-screen bg-zinc-50/70 shadow shadow-zinc-500/50 dark:bg-zinc-950/70" />
</div>
<Providers>{children}</Providers>
</body>
Expand Down
8 changes: 6 additions & 2 deletions src/components/ThemeSwitcher/ThemeSwitcher.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,14 @@ function ThemeSwitcher({ className }: ThemeSwitcher) {
}

return (
<button onClick={handleClick} className={className}>
<button
aria-label="theme switcher"
className={className}
onClick={handleClick}
>
{isDarkTheme ? (
<BsMoonFill size="1.25rem" />
) : (
) : (
<BsSunFill size="1.25rem" />
)}
</button>
Expand Down
32 changes: 16 additions & 16 deletions tailwind.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ const tailwindcssConfig = {
theme: {
extend: {
colors: {
primary: { ...colors.lime, DEFAULT: colors.lime[500] },
primary: { ...colors.violet, DEFAULT: colors.violet[500] },
},
typography: {
DEFAULT: {
Expand Down Expand Up @@ -40,7 +40,7 @@ const tailwindcssConfig = {
plugin(({ addComponents, theme }) => {
addComponents({
'.lattice': {
'--lattice-base-color': theme('colors.stone.100'),
'--lattice-base-color': theme('colors.stone.50'),
'--lattice-line-color': 'rgba(0, 0, 0, 0.04)',
'--lattice-ratio': '10%',
'--lattice-size': '10px 10px',
Expand All @@ -63,33 +63,33 @@ const tailwindcssConfig = {
backgroundSize: 'var(--lattice-size);',
},
'.dark .lattice': {
'--lattice-base-color': theme('colors.stone.900'),
'--lattice-base-color': theme('colors.stone.950'),
'--lattice-line-color': 'rgba(255, 255, 255, 0.04)',
},
});
addComponents({
'.fluorescent-box': {
'--fluorescent-color': '35, 35, 35',
'.neon-box': {
'--neon-color': '35, 35, 35',
background: `
linear-gradient(
to top,
rgba(var(--fluorescent-color), .1) 0,
transparent 50%,
rgba(var(--neon-color), .1) 0,
transparent 30%,
transparent 100%
)`,
boxShadow: `
0 0 1px rgba(var(--fluorescent-color), .8),
0 1px 3px rgba(var(--fluorescent-color), .2)`,
0 0 1px rgba(var(--neon-color), .8),
0 1px 3px rgba(var(--neon-color), .2)`,
},
'.dark .fluorescent-box': {
'--fluorescent-color': '220, 220, 220',
'.dark .neon-box': {
'--neon-color': '220, 220, 220',
},
'.fluorescent-text': {
'--fluorescent-color': theme('colors.primary.300'),
textShadow: '0 0 .25em var(--fluorescent-color)',
'.neon-text': {
'--neon-color': theme('colors.primary.400'),
textShadow: '0 0 .125em var(--neon-color)',
},
'.dark .fluorescent-text': {
'--fluorescent-color': theme('colors.primary.700'),
'.dark .neon-text': {
'--neon-color': theme('colors.primary.600'),
},
});
}),
Expand Down

0 comments on commit 199024d

Please sign in to comment.