Commit b8e5ce43 authored by fisherdaddy's avatar fisherdaddy

chore: fix some layout bugs

parent 57d488f2
......@@ -4,10 +4,13 @@ import events from '../data/anthropic-releases.json';
import SEO from '../components/SEO';
import { useTranslation } from '../js/i18n';
import { useScrollToTop } from '../hooks/useScrollToTop';
import { usePageLoading } from '../hooks/usePageLoading';
import LoadingOverlay from './LoadingOverlay';
const AnthropicTimeline = () => {
const { t } = useTranslation();
useScrollToTop();
const isLoading = usePageLoading();
return (
<>
......@@ -15,7 +18,8 @@ const AnthropicTimeline = () => {
title={t('tools.anthropicTimeline.title')}
description={t('tools.anthropicTimeline.description')}
/>
<div className="container">
{isLoading && <LoadingOverlay />}
<div className="timeline-container">
<h1 className="timeline-title">{t('tools.anthropicTimeline.title')}</h1>
<ul className="timeline">
{events.map((item, index) => (
......@@ -34,4 +38,4 @@ const AnthropicTimeline = () => {
);
};
export default AnthropicTimeline;
\ No newline at end of file
export default AnthropicTimeline;
\ No newline at end of file
......@@ -4,6 +4,8 @@ import styled from 'styled-components';
import { useTranslation } from '../js/i18n';
import SEO from './SEO';
import { useScrollToTop } from '../hooks/useScrollToTop';
import { usePageLoading } from '../hooks/usePageLoading';
import LoadingOverlay from './LoadingOverlay';
// Reuse container style
const Container = styled.div`
......@@ -81,6 +83,20 @@ const PreviewArea = styled.div`
align-items: center;
justify-content: center;
gap: 1rem;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: rgba(255, 255, 255, 0.9);
z-index: 10;
opacity: 1;
transition: opacity 0.3s ease-in-out;
&.hide {
opacity: 0;
pointer-events: none;
}
}
.upload-prompt {
......@@ -160,6 +176,7 @@ const PrivacyNote = styled.div`
function BackgroundRemover() {
useScrollToTop();
const { t } = useTranslation();
const isPageLoading = usePageLoading();
const [selectedImage, setSelectedImage] = useState(null);
const [removedBgImage, setRemovedBgImage] = useState(null);
const [isProcessing, setIsProcessing] = useState(false);
......@@ -202,6 +219,7 @@ function BackgroundRemover() {
title={t('tools.imageBackgroundRemover.title')}
description={t('tools.imageBackgroundRemover.description')}
/>
{(isPageLoading || isProcessing) && <LoadingOverlay />}
<Container>
<ContentWrapper>
<ControlPanel>
......@@ -217,7 +235,6 @@ function BackgroundRemover() {
{t('tools.imageBackgroundRemover.uploadPrompt')}
</ImageUploadArea>
{/* 添加提示语 */}
<PrivacyNote>
{t('tools.imageBackgroundRemover.privacyNote')}
</PrivacyNote>
......@@ -230,11 +247,7 @@ function BackgroundRemover() {
</DownloadButton>
)}
<div className="preview-content">
{isProcessing ? (
<div className="loading-container">
<span>{t('tools.imageBackgroundRemover.processing')}</span>
</div>
) : removedBgImage ? (
{removedBgImage ? (
<div style={{
position: 'relative',
width: '100%',
......
......@@ -4,10 +4,13 @@ import '../styles/Timeline.css';
import events from '../data/openai-releases.json';
import SEO from '../components/SEO';
import { useTranslation } from '../js/i18n';
import { usePageLoading } from '../hooks/usePageLoading';
import LoadingOverlay from './LoadingOverlay';
const Timeline = () => {
useScrollToTop();
const { t } = useTranslation();
const isLoading = usePageLoading();
return (
<>
......@@ -15,7 +18,8 @@ const Timeline = () => {
title={t('tools.openAITimeline.title')}
description={t('tools.openAITimeline.description')}
/>
<div className="container">
{isLoading && <LoadingOverlay />}
<div className="timeline-container">
<h1 className="timeline-title">{t('tools.openAITimeline.title')}</h1>
<ul className="timeline">
{events.map((item, index) => (
......
......@@ -5,9 +5,12 @@ import OpenaiPricing from '../data/openai-pricing.json';
import LLMPricing from '../data/llm-pricing.json';
import VisionPricing from '../data/vision-model-pricing.json';
import SEO from '../components/SEO';
import { usePageLoading } from '../hooks/usePageLoading';
import LoadingOverlay from './LoadingOverlay';
const PricingCharts = () => {
useScrollToTop();
const isLoading = usePageLoading();
const lastUpdateTime = '2024-11-06 21:30';
return (
......@@ -16,6 +19,7 @@ const PricingCharts = () => {
title="AI Model Pricing Comparison"
description="Compare prices of different AI models"
/>
{isLoading && <LoadingOverlay />}
<div className="pricing-charts-container">
<div className="update-time">
Last Updated: {lastUpdateTime}
......
......@@ -13,36 +13,38 @@ const Home = () => {
const { t } = useTranslation();
return (
<>
<div className="min-h-screen w-full">
<SEO
title={t('blog.title')}
description={t('blog.description')}
/>
<main className="container mx-auto px-4 pt-16 pb-8">
<section className="mt-8">
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6 px-4">
{tools.map(tool => (
<Link
to={tool.path}
key={tool.id}
className="flex items-center p-4 bg-white/10 backdrop-blur-md rounded-xl border border-white/10 transition-all hover:translate-y-[-2px] hover:shadow-lg hover:bg-white/15"
>
<img
src={tool.icon}
alt={`${t(`tools.${tool.id}.title`)} icon`}
className="w-12 h-12 object-contain mr-4"
loading="lazy"
/>
<div className="flex-1 min-w-0">
<h3 className="text-lg font-semibold mb-1 text-gray-800">{t(`tools.${tool.id}.title`)}</h3>
<p className="text-sm text-gray-600 line-clamp-2">{t(`tools.${tool.id}.description`)}</p>
</div>
</Link>
))}
<main className="container mx-auto px-4 pt-16 pb-8 min-h-screen w-full">
<section className="mt-8 w-full">
<div className="w-full max-w-[1400px] mx-auto">
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6 px-4">
{tools.map(tool => (
<Link
to={tool.path}
key={tool.id}
className="flex items-center p-4 bg-white/10 backdrop-blur-md rounded-xl border border-white/10 transition-all hover:translate-y-[-2px] hover:shadow-lg hover:bg-white/15"
>
<img
src={tool.icon}
alt={`${t(`tools.${tool.id}.title`)} icon`}
className="w-12 h-12 object-contain mr-4"
loading="lazy"
/>
<div className="flex-1 min-w-0">
<h3 className="text-lg font-semibold mb-1 text-gray-800">{t(`tools.${tool.id}.title`)}</h3>
<p className="text-sm text-gray-600 line-clamp-2">{t(`tools.${tool.id}.description`)}</p>
</div>
</Link>
))}
</div>
</div>
</section>
</main>
</>
</div>
);
};
......
......@@ -20,9 +20,9 @@ const DevTools = () => {
title={t('dev-tools.title')}
description={t('dev-tools.description')}
/>
<main className="container mx-auto px-4 pt-16 pb-8">
<section className="mt-8">
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6 px-4">
<main className="container mx-auto px-4 pt-16 pb-8 min-h-screen">
<section className="mt-8 w-full">
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6 px-4 w-full">
{tools.map(tool => (
<Link
to={tool.path}
......
......@@ -24,9 +24,9 @@ const tools = [
title={t('title')}
description={t('slogan')}
/>
<main className="container mx-auto px-4 pt-16 pb-8">
<section className="mt-8">
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6 px-4">
<main className="container mx-auto px-4 pt-16 pb-8 min-h-screen">
<section className="mt-8 w-full">
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-6 px-4 w-full">
{tools.map(tool => (
<Link
to={tool.path}
......
.container {
.timeline-container {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
line-height: 1.6;
max-width: 1000px;
......@@ -9,7 +9,7 @@
min-height: 100vh;
}
.container::before {
.timeline-container::before {
content: '';
position: absolute;
top: 0;
......@@ -72,7 +72,7 @@
.event-content {
position: relative;
width: 45%;
width: 40%;
padding: 1.5rem;
background: rgba(255, 255, 255, 0.9);
backdrop-filter: blur(10px);
......@@ -89,11 +89,11 @@
}
.event:nth-child(odd) .event-content {
left: 55%;
left: 57%;
}
.event:nth-child(even) .event-content {
left: 0;
left: 3%;
}
.event-date {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment