Skip to content

Commit

Permalink
chore: UI/UX improvements, accessibility fixes, and responsive updates (
Browse files Browse the repository at this point in the history
#78)

This PR encapsulates multiple changes that improve the user experience,
theme toggle functionality, accessibility, and SEO.

- **Social Media Links**: Fixed an issue where some links were not
displaying correctly even when set.
- **SEO Enhancements**: Added more diverse icons for better
compatibility and fixed issues in the manifest file.
- **Theme Toggle**: Implemented a button to toggle between light and
dark modes with preferences stored in localStorage.
- **Home Page UI**: Addressed UI issues for small screen devices to
improve responsiveness.
- **ARIA Improvements**: Enhanced accessibility by enlarging footer
text, and removing hidden icons.
- **Markdown Support**: Fixed image display issues in posts and ensured
better responsiveness for embedded content.
- **Dependencies**: Bumped up package versions and added a debounce
function for the table of contents (TOC).
  • Loading branch information
ZL-Asica authored Dec 1, 2024
2 parents 2c9c1dd + cd66135 commit c89f627
Show file tree
Hide file tree
Showing 15 changed files with 243 additions and 177 deletions.
12 changes: 6 additions & 6 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@
"prepare": "husky"
},
"dependencies": {
"@zl-asica/react": "^0.3.0",
"@zl-asica/react": "^0.3.10",
"clsx": "^2.1.1",
"es-toolkit": "^1.27.0",
"es-toolkit": "^1.28.0",
"gray-matter": "^4.0.3",
"katex": "^0.16.11",
"next": "15.0.3",
Expand All @@ -46,20 +46,20 @@
"devDependencies": {
"@next/eslint-plugin-next": "^15.0.3",
"@tailwindcss/typography": "^0.5.15",
"@types/node": "^22.9.4",
"@types/node": "^22.10.1",
"@types/react": "npm:types-react@19.0.0-rc.1",
"@types/react-dom": "npm:types-react-dom@19.0.0-rc.1",
"@zl-asica/prettier-config": "^1.0.9",
"autoprefixer": "^10.4.20",
"cssnano": "^7.0.6",
"eslint": "^9.15.0",
"eslint": "^9.16.0",
"eslint-config-zl-asica": "^1.0.19",
"husky": "^9.1.7",
"lint-staged": "^15.2.10",
"postcss": "^8.4.49",
"postcss-flexbugs-fixes": "^5.0.2",
"postcss-preset-env": "^10.1.1",
"prettier": "^3.3.3",
"prettier": "^3.4.1",
"prettier-plugin-tailwindcss": "^0.6.9",
"rss": "^1.2.2",
"tailwindcss": "^3.4.15",
Expand Down Expand Up @@ -95,5 +95,5 @@
"last 1 safari version"
]
},
"packageManager": "pnpm@9.14.2"
"packageManager": "pnpm@9.14.4"
}
265 changes: 134 additions & 131 deletions pnpm-lock.yaml

Large diffs are not rendered by default.

Binary file added public/icons/apple-touch-icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/icons/favicon-96x96.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions public/icons/favicon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
16 changes: 7 additions & 9 deletions src/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,13 @@
--font-jetbrains-mono: 'JetBrains Mono', monospace;
}

@media (prefers-color-scheme: dark) {
:root {
--background: #1a1a1a;
--foreground: #d4d4d4;
--skyblue: #4aa7e0;
--sakuraPink: #d890a2;
--lightGray: #1f2937;
--gray: #d1d5db;
}
.dark:root {
--background: #1a1a1a;
--foreground: #d4d4d4;
--skyblue: #4aa7e0;
--sakuraPink: #d890a2;
--lightGray: #1f2937;
--gray: #d1d5db;
}

html {
Expand Down
16 changes: 16 additions & 0 deletions src/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,22 @@ function RootLayout({
</Script>
</>
)}
<link
rel='icon'
type='image/png'
href='/icons/favicon-96x96.png'
sizes='96x96'
/>
<link
rel='icon'
type='image/svg+xml'
href='/icons/favicon.svg'
/>
<link
rel='apple-touch-icon'
sizes='180x180'
href='/icons/apple-touch-icon.png'
/>

<body
className={`${notoSansSC.variable} ${jetBrainsMono.variable} flex max-h-full min-h-screen flex-col antialiased`}
Expand Down
2 changes: 1 addition & 1 deletion src/app/manifest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ function manifest(): MetadataRoute.Manifest {
short_name: config.title,
description: config.description,
start_url: '/',
display: 'browser',
display: 'standalone',
background_color: '#ffffff',
theme_color: '#f6a8b8',
lang: config.lang,
Expand Down
3 changes: 1 addition & 2 deletions src/app/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ async function Home() {
/>
</Head>
<div className='flex max-h-[800px] animate-fadeInDown flex-col items-center justify-center px-6'>
<div className='relative h-[50vh] w-full bg-cover bg-center'>
<div className='relative h-[30vh] w-full bg-cover bg-center md:h-[50vh]'>
<div className='absolute left-1/2 top-[25%] -translate-x-1/2 transform'>
<Image
src={config.avatar}
Expand All @@ -52,7 +52,6 @@ async function Home() {

<SocialMediaLinks
socialMedia={config.socialMedia}
siteUrl={config.siteUrl}
iconSize={40}
/>
</div>
Expand Down
4 changes: 2 additions & 2 deletions src/components/article/parser/markdownComponents.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -195,9 +195,9 @@ const createMarkdownComponents = (
src={source}
alt={alt}
width={500}
height={780}
height={700}
priority={false}
className='relative mx-auto my-6 w-full max-w-full rounded-md'
className='relative mx-auto my-6 h-auto max-h-[500px] min-h-[200px] w-auto min-w-[200px] max-w-full rounded-sm object-contain shadow-md lg:max-h-[700px] lg:min-h-[300px] lg:min-w-[300px] xl:max-h-[800px] xl:min-h-[400px] xl:min-w-[400px]'
{...(props as Record<string, unknown>)}
/>
),
Expand Down
19 changes: 8 additions & 11 deletions src/components/common/Footer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,30 +17,27 @@ const Footer = ({ config }: FooterProperties) => {
return (
<footer className='mb-1 mt-10 w-full'>
<div className='mx-auto max-w-7xl px-4 py-4 text-center'>
{!isHomePage && (
<SocialMediaLink
socialMedia={config.socialMedia}
siteUrl={config.siteUrl}
/>
)}
{!isHomePage && <SocialMediaLink socialMedia={config.socialMedia} />}
<p className='text-[var(--gray)]'>
{${config.startYear && config.startYear < currentYear ? `${config.startYear} - ` : ''}${currentYear} ${config.title}`}
</p>
<p className='text-sm text-[var(--gray)]'>
<p className='text-base text-[var(--gray)]'>
Theme{' '}
<Link
href='https://suzu.zla.app/'
href='https://github.com/ZL-Asica/SuzuBlog'
target='_blank'
aria-label="Suzu's homepage (new tab)"
aria-label="Suzu's GitHub repo (new tab)"
rel='noopener noreferrer'
className='decoration-dashed underline-offset-2'
>
Suzu
</Link>{' '}
by{' '}
<Link
href='https://www.zla.app/'
href='https://www.zla.pub'
target='_blank'
aria-label="ZL Asica's homepage (new tab)"
aria-label="ZL Asica's blog (new tab)"
rel='noopener noreferrer'
className='decoration-dashed underline-offset-2'
>
ZL Asica
Expand Down
8 changes: 4 additions & 4 deletions src/components/common/Header.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@

import { usePathname } from 'next/navigation';
import { useRef } from 'react';
import { FaAngleUp, FaBars } from 'react-icons/fa6';
import { FaBars } from 'react-icons/fa6';
import Link from 'next/link';
import { useClickOutside, useToggle, useScrollProgress } from '@zl-asica/react';
import { useClickOutside, useToggle, useScrollPosition } from '@zl-asica/react';

import HeaderMenu from './HeaderMenu';

Expand All @@ -16,7 +16,7 @@ const Header = ({ config }: HeaderProperties) => {
const [isOpen, toggleOpen] = useToggle();
const siteTitle = config.title;
const translation = config.translation;
const scrollProgress = useScrollProgress();
const scrollProgress = useScrollPosition(undefined, true);
const menuReference = useRef<HTMLDivElement>(null);
const pathname = usePathname();
const isHomePage = pathname === '/';
Expand Down Expand Up @@ -53,7 +53,7 @@ const Header = ({ config }: HeaderProperties) => {
aria-expanded={isOpen}
aria-controls='mobile-menu'
>
{isOpen ? <FaAngleUp /> : <FaBars />}
{!isOpen && <FaBars />}
</button>

{/* Mobile Menu */}
Expand Down
54 changes: 50 additions & 4 deletions src/components/common/HeaderMenu.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
'use client';

import Link from 'next/link';
import React from 'react';
import React, { useEffect, useState } from 'react';
import {
FaHouse,
FaRegNewspaper,
FaPeopleGroup,
FaInfo,
FaRegSun,
FaMoon,
} from 'react-icons/fa6';

interface MenuItem {
Expand Down Expand Up @@ -41,13 +45,40 @@ const HeaderMenu = ({
{ href: '/about', label: translation.about.title, icon: <FaInfo /> },
];

const [isDarkTheme, setIsDarkTheme] = useState(false);

useEffect(() => {
const userPreferredTheme = localStorage.getItem('suzu-color-theme');
const systemPrefersDark = globalThis.matchMedia(
'(prefers-color-scheme: dark)'
).matches;

// Determine initial theme
const initialTheme = userPreferredTheme
? userPreferredTheme === 'dark'
: systemPrefersDark;
setIsDarkTheme(initialTheme);

// Update the HTML class based on the initial theme
document.documentElement.classList.toggle('dark', initialTheme);
}, []);

const toggleTheme = () => {
const newTheme = !isDarkTheme;
setIsDarkTheme(newTheme);

// Update HTML class and localStorage
document.documentElement.classList.toggle('dark', newTheme);
localStorage.setItem('suzu-color-theme', newTheme ? 'dark' : 'light');
};

return (
<ul className={`gap-4 ${ulClassName}`}>
{menuItems.map((item, index) => (
<React.Fragment key={item.href}>
<React.Fragment key={index}>
{/* Link as Full Width */}
<li
key={item.href}
key={index}
className='group relative flex w-full items-center justify-center rounded-lg hover:bg-[var(--lightGray)]'
>
<Link
Expand All @@ -65,13 +96,28 @@ const HeaderMenu = ({
</li>

{/* Divider */}
{isMobile && index < menuItems.length - 1 && (
{isMobile && (
<li className='w-full'>
<div className='h-[1px] w-full bg-gradient-to-r from-[var(--lightGray)] via-[var(--sakuraPink)] to-[var(--lightGray)]'></div>
</li>
)}
</React.Fragment>
))}
<li className='group mx-auto flex items-center justify-center rounded-lg hover:bg-gray-100 dark:hover:bg-gray-800'>
<button
className='flex h-12 w-12 items-center justify-center rounded-full bg-gray-100 transition-all duration-300 ease-in-out hover:bg-gray-200 dark:bg-gray-800 dark:hover:bg-gray-700'
aria-label="$t('aria.theme')"
onClick={toggleTheme}
>
<span className='flex h-6 w-6 items-center justify-center text-gray-600 transition-transform duration-300 ease-in-out hover:text-[var(--sakuraPink)] group-hover:scale-125 dark:text-gray-300 dark:hover:text-[var(--sakuraPink)]'>
{isDarkTheme ? (
<FaRegSun className='h-full w-full' />
) : (
<FaMoon className='h-full w-full' />
)}
</span>
</button>
</li>
</ul>
);
};
Expand Down
10 changes: 4 additions & 6 deletions src/components/common/SocialMediaLinks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,35 +12,33 @@ import {
FaRss,
} from 'react-icons/fa6';
import { upperFirst } from 'es-toolkit/string';
import { words, replace, isString } from 'es-toolkit/compat';
import { words, replace } from 'es-toolkit/compat';
import Link from 'next/link';

interface socialMediaLinksProperties {
socialMedia: SocialMedia;
siteUrl: string;
iconSize?: number;
className?: string;
}

const SocialMediaLinks = ({
socialMedia,
siteUrl,
iconSize = 32,
className = '',
}: socialMediaLinksProperties) => {
return (
<div
className={`mb-5 flex flex-wrap justify-center space-x-4 ${className}`}
className={`mx-4 mb-5 flex flex-wrap justify-center gap-y-4 space-x-4 ${className}`}
>
{Object.entries(socialMedia)
.filter(([key, username]) => key in socialData && isString(username))
.filter(([key, _]) => key in socialData)
.map(([key, username]) => {
const { urlTemplate, icon: IconComponent } =
socialData[key as SocialMediaKey];

const label = upperFirst(words(key)[0]);
if (key === 'rss' && username !== '' && username !== 'false') {
username = `https://${siteUrl}/feed.xml`;
username = `/feed.xml`;
}
return (
<Link
Expand Down
8 changes: 7 additions & 1 deletion src/hooks/useTOCLogic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,13 @@ function useTOCLogic(onLinkClick?: (slug: string) => void) {
};

// Update activeSlug on scroll
useEventListener('scroll', updateActiveSlug);
useEventListener(
'scroll',
updateActiveSlug,
{ current: globalThis },
{ passive: true },
100
);

// Close TOC when clicking outside
useClickOutside(tocReference, () => {
Expand Down

0 comments on commit c89f627

Please # to comment.