diff --git a/components/Footer.tsx b/components/Footer.tsx index e927b79606..5d8a42fe7b 100644 --- a/components/Footer.tsx +++ b/components/Footer.tsx @@ -1,16 +1,10 @@ -import { FaEnvelopeOpenText } from '@react-icons/all-files/fa/FaEnvelopeOpenText' -import { FaGithub } from '@react-icons/all-files/fa/FaGithub' -import { FaLinkedin } from '@react-icons/all-files/fa/FaLinkedin' -import { FaMastodon } from '@react-icons/all-files/fa/FaMastodon' -import { FaTwitter } from '@react-icons/all-files/fa/FaTwitter' -import { FaYoutube } from '@react-icons/all-files/fa/FaYoutube' -import { FaZhihu } from '@react-icons/all-files/fa/FaZhihu' -import { IoMoonSharp } from '@react-icons/all-files/io5/IoMoonSharp' -import { IoSunnyOutline } from '@react-icons/all-files/io5/IoSunnyOutline' import * as React from 'react' +import cs from 'classnames' +import { IoMoonSharp, IoSunnyOutline } from 'react-icons/io5' import * as config from '@/lib/config' import { useDarkMode } from '@/lib/use-dark-mode' +import { PageSocialButtons } from './PageSocial' import styles from './styles.module.css' @@ -54,88 +48,7 @@ export function FooterImpl() {
- {config.twitter && ( - - - - )} - - {config.mastodon && ( - - - - )} - - {config.zhihu && ( - - - - )} - - {config.github && ( - - - - )} - - {config.linkedin && ( - - - - )} - - {config.newsletter && ( - - - - )} - - {config.youtube && ( - - - - )} +
) diff --git a/components/NotionPageHeader.tsx b/components/NotionPageHeader.tsx index 5fbb087ce3..36a6658c1f 100644 --- a/components/NotionPageHeader.tsx +++ b/components/NotionPageHeader.tsx @@ -1,8 +1,7 @@ import type * as types from 'notion-types' -import { IoMoonSharp } from '@react-icons/all-files/io5/IoMoonSharp' -import { IoSunnyOutline } from '@react-icons/all-files/io5/IoSunnyOutline' import cs from 'classnames' import * as React from 'react' +import { IoMoonSharp, IoSunnyOutline } from 'react-icons/io5' import { Breadcrumbs, Header, Search, useNotionContext } from 'react-notion-x' import { isSearchEnabled, navigationLinks, navigationStyle } from '@/lib/config' diff --git a/components/PageActions.tsx b/components/PageActions.tsx index 755c60880c..e6ec96cf6b 100644 --- a/components/PageActions.tsx +++ b/components/PageActions.tsx @@ -1,5 +1,5 @@ -import { AiOutlineRetweet } from '@react-icons/all-files/ai/AiOutlineRetweet' -import { IoHeartOutline } from '@react-icons/all-files/io5/IoHeartOutline' +import { AiOutlineRetweet } from 'react-icons/ai' +import { IoHeartOutline } from 'react-icons/io5' import styles from './styles.module.css' diff --git a/components/PageSocial.module.css b/components/PageSocial.module.css index c82a8ee9a9..855e45db80 100644 --- a/components/PageSocial.module.css +++ b/components/PageSocial.module.css @@ -6,11 +6,10 @@ color: var(--fg-color); } -.action { +.pageSocial a { position: relative; border-radius: 50%; border: 2px solid var(--fg-color-6); - transition: all 300ms ease-out; width: 3.5em; height: 3.5em; margin: 0 0 1em; @@ -23,111 +22,24 @@ cursor: pointer; } -.action:last-child { - margin-bottom: 0; +.pageSocial a:hover { + border: 2px solid var(--hover-background); } -.actionBg { - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; - - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; +.socialLink { + transition: all 500ms ease-out; } -.actionBg svg { - width: 50%; - height: 50%; - fill: var(--fg-color-6); -} - -.actionBgPane { - transition: all 300ms ease-out; +.socialLink:hover { border-radius: 50%; - width: 0; - height: 0; + color: var(--hover-color); + background: var(--hover-background); } -.action:hover { - transition: all 100ms ease-out; -} - -.action:hover .actionBgPane { - width: 100%; - height: 100%; - transition: all 100ms ease-out; -} - -.action:hover svg { - transition: fill 100ms ease-out; - fill: var(--bg-color); -} - -:global(.dark-mode) .action:hover svg { +:global(.dark-mode) .socialLink:hover svg { fill: var(--fg-color); } -.facebook .actionBgPane { - background: #3b5998; -} -.facebook:hover { - border-color: #3b5998; -} - -.twitter .actionBgPane { - background: #2795e9; -} -.twitter:hover { - border-color: #2795e9; -} - -.linkedin .actionBgPane { - background: #0077b5; -} -.linkedin:hover { - border-color: #0077b5; -} - -.github .actionBgPane { - background: #c9510c; -} -.github:hover { - border-color: #c9510c; -} - -.youtube .actionBgPane { - background: #ff0000; -} -.youtube:hover { - border-color: #ff0000; -} - -.medium .actionBgPane { - background: #00ab6c; -} -.medium:hover { - border-color: #00ab6c; -} - -.newsletter .actionBgPane { - background: #777777; -} -.newsletter:hover { - border-color: #777777; -} - -.email .actionBgPane { - background: #777; -} -.email:hover { - border-color: #777; -} - @media only screen and (max-width: 768px) { .links { position: relative; @@ -135,7 +47,7 @@ flex-wrap: wrap; } - .action:last-child { + .pageSocial a:last-child { margin-right: 1em; } } diff --git a/components/PageSocial.tsx b/components/PageSocial.tsx index 5301c06656..3dfff267e2 100644 --- a/components/PageSocial.tsx +++ b/components/PageSocial.tsx @@ -4,90 +4,143 @@ import cs from 'classnames' import * as config from '@/lib/config' import styles from './PageSocial.module.css' +import { FaGithub, FaInstagram, FaLinkedin, FaMastodon, FaReddit, FaTwitter, FaYoutube } from 'react-icons/fa' +import { FaXTwitter, FaGitlab, FaEnvelopeOpenText } from 'react-icons/fa6' +import { IoIosBug } from 'react-icons/io' interface SocialLink { name: string title: string - icon: React.ReactNode + icon: ({ size }: { size: number }) => React.ReactNode + color: string href?: string + // Currently only used for instagram + background?: string } -const socialLinks: SocialLink[] = [ +export const socialLinks: SocialLink[] = [ config.twitter && { name: 'twitter', href: `https://twitter.com/${config.twitter}`, title: `Twitter @${config.twitter}`, - icon: ( - - - - ) + color: "#ffffff", + background: "#2795e9", + icon: FaTwitter + }, + config.twitterX && { + name: 'twitterX', + href: `https://x.com/${config.twitterX}`, + title: `X.com @${config.twitterX}`, + color: "#222", + icon: FaXTwitter + }, + + config.mastodon && { + name: 'mastodon', + href: config.mastodon, + title: 'Mastodon', + color: "#5a4be1", + icon: FaMastodon }, config.github && { name: 'github', href: `https://github.com/${config.github}`, title: `GitHub @${config.github}`, - icon: ( - - - - ) + // FIXME: Figure out great way to preserve github black and white theme, For now it uses rainbow + color: "#ffffff", + // Fun rainbow background, similarl as their pride logo + // FIXME: Gradients can't be transitioned with css :( + background: "linear-gradient(to bottom, #C6474E 0%, #C6474E 17%, #D67940 17%, #D67940 33%, #F8D45C 33%, #F8D45C 50%, #67A25A 50%, #67A25A 67%, #3A63C7 67%, #3A63C7 84%, #6446B4 84%)", + icon: FaGithub + }, + + config.gitlab && { + name: 'gitlab', + href: `https://gitlab.com/${config.github}`, + title: `GitLab @${config.github}`, + color: "#e24329", + icon: FaGitlab }, config.linkedin && { name: 'linkedin', href: `https://www.linkedin.com/in/${config.linkedin}`, title: `LinkedIn ${config.author}`, - icon: ( - - - - ) + color: "#ffffff", + background: "#0077b5", + icon: FaLinkedin }, config.newsletter && { name: 'newsletter', href: `${config.newsletter}`, title: `Newsletter ${config.author}`, - icon: ( - - - - ) + color: "#777", + icon: FaEnvelopeOpenText }, config.youtube && { name: 'youtube', href: `https://www.youtube.com/${config.youtube}`, - title: `YouTube ${config.youtube}`, - icon: ( - - - - ) + title: `YouTube @${config.youtube}`, + color: "#ff0000", + icon: FaYoutube + }, + + config.instagram && { + name: 'instagram', + href: `https://instagram.com/${config.instagram}`, + title: `Instagram @${config.instagram}`, + color: "#ffffff", + background: "radial-gradient(circle at 30% 107%, #fdf497 0%, #fdf497 5%, #fd5949 45%,#d6249f 60%, #285AEB 90%)", + icon: FaInstagram + }, + + config.reddit && { + name: 'reddit', + href: `https://www.reddit.com/u/${config.reddit}`, + title: `Reddit @${config.reddit}`, + color: "#ffffff", + background: "#FF5700", + icon: FaReddit + }, + + config.bugtracker && { + name: 'bugtracker', + href: `${config.bugtracker}`, + title: 'Bugtracker', + color: "#e24329", + icon: IoIosBug } ].filter(Boolean) export function PageSocial() { return ( -
+ <> +
+ +
+ + ) +} + +export function PageSocialButtons({ iconSize = 32 }: { iconSize: number }) { + return ( + <> {socialLinks.map((action) => ( -
-
-
- -
{action.icon}
+ {action.icon({ size: iconSize })}
))} -
+ ) } diff --git a/components/styles.module.css b/components/styles.module.css index bea8ff1ed9..900c19bde7 100644 --- a/components/styles.module.css +++ b/components/styles.module.css @@ -90,34 +90,6 @@ color: #2795e9; } -.twitter:hover { - color: #2795e9; -} - -.mastodon:hover { - color: #5a4be1; -} - -.zhihu:hover { - color: #0066ff; -} - -.github:hover { - color: #c9510c; -} - -.youtube:hover { - color: #ff0000; -} - -.linkedin:hover { - color: #0077b5; -} - -.newsletter:hover { - color: #777777; -} - .comments { width: 100%; margin-top: 2em; diff --git a/lib/config.ts b/lib/config.ts index 4e74d12c97..41843fd931 100644 --- a/lib/config.ts +++ b/lib/config.ts @@ -55,12 +55,17 @@ export const language: string = getSiteConfig('language', 'en') // social accounts export const twitter: string | null = getSiteConfig('twitter', null) +export const twitterX: string | null = getSiteConfig('twitterX', null) export const mastodon: string | null = getSiteConfig('mastodon', null) export const github: string | null = getSiteConfig('github', null) +export const gitlab: string | null = getSiteConfig('gitlab', null) export const youtube: string | null = getSiteConfig('youtube', null) +export const instagram: string | null = getSiteConfig('instagram', null) +export const reddit: string | null = getSiteConfig('reddit', null) export const linkedin: string | null = getSiteConfig('linkedin', null) export const newsletter: string | null = getSiteConfig('newsletter', null) export const zhihu: string | null = getSiteConfig('zhihu', null) +export const bugtracker: string | null = getSiteConfig('bugtracker', null) export const getMastodonHandle = (): string | null => { if (!mastodon) { diff --git a/lib/site-config.ts b/lib/site-config.ts index cfd538e767..922c11b744 100644 --- a/lib/site-config.ts +++ b/lib/site-config.ts @@ -11,12 +11,17 @@ export interface SiteConfig { language?: string twitter?: string + twitterX?: string github?: string + gitlab?: string linkedin?: string newsletter?: string youtube?: string + instagram?: string + reddit?: string zhihu?: string mastodon?: string + bugtracker?: string defaultPageIcon?: string | null defaultPageCover?: string | null diff --git a/package.json b/package.json index 11c066255e..f59569ad5a 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ "@fisch0920/use-dark-mode": "^2.4.0", "@keyvhq/core": "^1.6.9", "@keyvhq/redis": "^1.6.10", - "@react-icons/all-files": "^4.1.0", + "react-icons": "^5.3.0", "@vercel/og": "^0.6.3", "classnames": "^2.5.1", "date-fns": "^2.30.0", diff --git a/pages/_document.tsx b/pages/_document.tsx index 28cc023758..1b0f437ce3 100644 --- a/pages/_document.tsx +++ b/pages/_document.tsx @@ -1,5 +1,5 @@ -import { IconContext } from '@react-icons/all-files' import Document, { Head, Html, Main, NextScript } from 'next/document' +import { IconContext } from 'react-icons' export default class MyDocument extends Document { render() { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5f3290c0f8..5eea58c91e 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -17,9 +17,6 @@ importers: '@keyvhq/redis': specifier: ^1.6.10 version: 1.6.28 - '@react-icons/all-files': - specifier: ^4.1.0 - version: 4.1.0(react@18.3.1) '@vercel/og': specifier: ^0.6.3 version: 0.6.3 @@ -74,6 +71,9 @@ importers: react-dom: specifier: ^18.2.0 version: 18.3.1(react@18.3.1) + react-icons: + specifier: ^5.3.0 + version: 5.3.0(react@18.3.1) react-notion-x: specifier: ^7.0.1 version: 7.0.1(@babel/runtime@7.26.0)(@types/react@18.3.12)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -388,11 +388,6 @@ packages: '@polka/url@1.0.0-next.28': resolution: {integrity: sha512-8LduaNlMZGwdZ6qWrKlfa+2M4gahzFkprZiAt2TF8uS0qQgBizKXpXURqvTJ4WtmupWxaLqjRb2UCTe72mu+Aw==} - '@react-icons/all-files@4.1.0': - resolution: {integrity: sha512-hxBI2UOuVaI3O/BhQfhtb4kcGn9ft12RWAFVMUeNjqqhLsHvFtzIkFaptBJpFDANTKoDfdVoHTKZDlwKCACbMQ==} - peerDependencies: - react: '*' - '@resvg/resvg-wasm@2.4.0': resolution: {integrity: sha512-C7c51Nn4yTxXFKvgh2txJFNweaVcfUPQxwEUFw4aWsCmfiBDJsTSwviIF8EcwjQ6k8bPyMWCl1vw4BdxE569Cg==} engines: {node: '>= 10'} @@ -1929,6 +1924,11 @@ packages: react: '>=16.8.1' react-dom: '>=16.8.1' + react-icons@5.3.0: + resolution: {integrity: sha512-DnUk8aFbTyQPSkCfF8dbX6kQjXA9DktMeJqfjrg6cK9vwQVMxmcA3BfP4QoiztVmEHtwlTgLFsPuH2NskKT6eg==} + peerDependencies: + react: '*' + react-image@4.1.0: resolution: {integrity: sha512-qwPNlelQe9Zy14K2pGWSwoL+vHsAwmJKS6gkotekDgRpcnRuzXNap00GfibD3eEPYu3WCPlyIUUNzcyHOrLHjw==} peerDependencies: @@ -2758,10 +2758,6 @@ snapshots: '@polka/url@1.0.0-next.28': {} - '@react-icons/all-files@4.1.0(react@18.3.1)': - dependencies: - react: 18.3.1 - '@resvg/resvg-wasm@2.4.0': {} '@rtsao/scc@1.1.0': {} @@ -3386,7 +3382,7 @@ snapshots: debug: 4.3.7 enhanced-resolve: 5.17.1 eslint: 8.57.1 - eslint-module-utils: 2.12.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1) + eslint-module-utils: 2.12.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.3))(eslint-plugin-import@2.31.0)(eslint@8.57.1))(eslint@8.57.1) fast-glob: 3.3.2 get-tsconfig: 4.8.1 is-bun-module: 1.2.1 @@ -3399,7 +3395,7 @@ snapshots: - eslint-import-resolver-webpack - supports-color - eslint-module-utils@2.12.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1): + eslint-module-utils@2.12.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.3))(eslint-plugin-import@2.31.0)(eslint@8.57.1))(eslint@8.57.1): dependencies: debug: 3.2.7 optionalDependencies: @@ -3421,7 +3417,7 @@ snapshots: doctrine: 2.1.0 eslint: 8.57.1 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.12.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.1) + eslint-module-utils: 2.12.0(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.3))(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@7.18.0(eslint@8.57.1)(typescript@5.6.3))(eslint-plugin-import@2.31.0)(eslint@8.57.1))(eslint@8.57.1) hasown: 2.0.2 is-core-module: 2.15.1 is-glob: 4.0.3 @@ -4452,6 +4448,10 @@ snapshots: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) + react-icons@5.3.0(react@18.3.1): + dependencies: + react: 18.3.1 + react-image@4.1.0(@babel/runtime@7.26.0)(react-dom@18.3.1(react@18.3.1))(react@18.3.1): dependencies: '@babel/runtime': 7.26.0 diff --git a/site.config.ts b/site.config.ts index cded79c3bf..dc8f87567b 100644 --- a/site.config.ts +++ b/site.config.ts @@ -18,11 +18,19 @@ export default siteConfig({ // social usernames (optional) twitter: 'transitive_bs', + // twitterX: 'transitive_bs', // If you want to use X.com logo instead + // mastodon: '#' // optional mastodon profile URL, provides link verification + github: 'transitive-bullshit', + // gitlab: 'transitive-bullshit', // optional gitlab account + linkedin: 'fisch2', // mastodon: '#', // optional mastodon profile URL, provides link verification // newsletter: '#', // optional newsletter URL // youtube: '#', // optional youtube channel name or `channel/UCGbXXXXXXXXXXXXXXXXXXXXXX` + // instagram: '#', // optional instagram account + // reddit: '#', // optional reddit account + // bugtracker: '#', // optional bugtracker URL // default notion icon and cover images for site-wide consistency (optional) // page-specific values will override these site-wide defaults