diff --git a/eslint.config.mjs b/eslint.config.mjs index 9a536467..47a47718 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -14,6 +14,7 @@ const eslintConfig = [ rules: { '@next/next/no-img-element': 'off', '@typescript-eslint/no-explicit-any': 'off', + '@typescript-eslint/no-require-imports': 'off', 'no-unused-expressions': ['warn'], '@typescript-eslint/no-unused-vars': [ 'warn', { diff --git a/next.config.ts b/next.config.ts index 62a91b49..c41d7549 100644 --- a/next.config.ts +++ b/next.config.ts @@ -1,4 +1,3 @@ -/* eslint-disable @typescript-eslint/no-require-imports */ import type { NextConfig } from 'next'; import { RemotePattern } from 'next/dist/shared/lib/image-config'; diff --git a/src/components/LinkWithStatus.tsx b/src/components/LinkWithStatus.tsx index 5655454d..6b00bf2c 100644 --- a/src/components/LinkWithStatus.tsx +++ b/src/components/LinkWithStatus.tsx @@ -17,10 +17,15 @@ const FLICKER_THRESHOLD = 400; // Clear loading status after long duration const MAX_LOADING_DURATION = 15_000; -export type LinkWithStatusProps = ComponentProps & { +export type LinkWithStatusProps = Omit< + ComponentProps, 'children' +> & { loadingElement?: ReactNode loadingClassName?: string contentClassName?: string + children: ReactNode | ((props: { + isLoading: boolean + }) => ReactNode) } export default function LinkWithStatus({ @@ -44,6 +49,8 @@ export default function LinkWithStatus({ const stopLoadingTimeout = useRef(undefined); const maxLoadingTimeout = useRef(undefined); + const isControlled = typeof children === 'function'; + const clearTimeouts = useCallback(() => { [startLoadingTimeout, stopLoadingTimeout, maxLoadingTimeout] .forEach(timeout => { @@ -114,11 +121,13 @@ export default function LinkWithStatus({ contentClassName, loadingElement ? isLoading ? 'opacity-0' : 'opacity-100' - : loadingClassName + : (loadingClassName || isControlled) ? 'opacity-100' : isLoading ? 'opacity-50' : 'opacity-100', )}> - {children} + {typeof children === 'function' + ? children({ isLoading }) + : children} {isLoading && loadingElement && - - + {({ isLoading }) => +
+ {isLoading && +
+ +
} + +
} + ); }; diff --git a/tailwind.config.js b/tailwind.config.js index f86a24d3..a728d01d 100644 --- a/tailwind.config.js +++ b/tailwind.config.js @@ -28,12 +28,18 @@ module.exports = { animation: { 'rotate-pulse': 'rotate-pulse 0.75s linear infinite normal both running', + 'fade-in': + 'fade-in 0.5s linear', 'hover-drift': 'hover-drift 8s linear infinite', 'hover-wobble': 'hover-wobble 6s linear infinite normal both running', }, keyframes: { + 'fade-in': { + '0%': { opacity: '0' }, + '100%': { opacity: '1' }, + }, 'rotate-pulse': { '0%': { transform: 'rotate(0deg) scale(1)' }, '50%': { transform: 'rotate(180deg) scale(0.8)' },