新增首页灵感推荐瀑布流
新增 23 张内置灵感图片素材 实现响应式瀑布流和纵向滚动 支持图片全屏预览与遮罩关闭 补充首页交互测试和技术文档
@@ -0,0 +1,118 @@
|
||||
import { useEffect, useState } from 'react';
|
||||
import { createPortal } from 'react-dom';
|
||||
|
||||
import inspiration01 from './assets/inspiration/inspiration-01.webp';
|
||||
import inspiration02 from './assets/inspiration/inspiration-02.webp';
|
||||
import inspiration03 from './assets/inspiration/inspiration-03.webp';
|
||||
import inspiration04 from './assets/inspiration/inspiration-04.webp';
|
||||
import inspiration05 from './assets/inspiration/inspiration-05.webp';
|
||||
import inspiration06 from './assets/inspiration/inspiration-06.webp';
|
||||
import inspiration07 from './assets/inspiration/inspiration-07.webp';
|
||||
import inspiration08 from './assets/inspiration/inspiration-08.webp';
|
||||
import inspiration09 from './assets/inspiration/inspiration-09.webp';
|
||||
import inspiration10 from './assets/inspiration/inspiration-10.webp';
|
||||
import inspiration11 from './assets/inspiration/inspiration-11.webp';
|
||||
import inspiration12 from './assets/inspiration/inspiration-12.webp';
|
||||
import inspiration13 from './assets/inspiration/inspiration-13.webp';
|
||||
import inspiration14 from './assets/inspiration/inspiration-14.webp';
|
||||
import inspiration15 from './assets/inspiration/inspiration-15.webp';
|
||||
import inspiration16 from './assets/inspiration/inspiration-16.webp';
|
||||
import inspiration17 from './assets/inspiration/inspiration-17.webp';
|
||||
import inspiration18 from './assets/inspiration/inspiration-18.webp';
|
||||
import inspiration19 from './assets/inspiration/inspiration-19.webp';
|
||||
import inspiration20 from './assets/inspiration/inspiration-20.webp';
|
||||
import inspiration21 from './assets/inspiration/inspiration-21.webp';
|
||||
import inspiration22 from './assets/inspiration/inspiration-22.webp';
|
||||
import inspiration23 from './assets/inspiration/inspiration-23.webp';
|
||||
|
||||
const INSPIRATION_IMAGES = [
|
||||
inspiration01,
|
||||
inspiration02,
|
||||
inspiration03,
|
||||
inspiration04,
|
||||
inspiration05,
|
||||
inspiration06,
|
||||
inspiration07,
|
||||
inspiration08,
|
||||
inspiration09,
|
||||
inspiration10,
|
||||
inspiration11,
|
||||
inspiration12,
|
||||
inspiration13,
|
||||
inspiration14,
|
||||
inspiration15,
|
||||
inspiration16,
|
||||
inspiration17,
|
||||
inspiration18,
|
||||
inspiration19,
|
||||
inspiration20,
|
||||
inspiration21,
|
||||
inspiration22,
|
||||
inspiration23,
|
||||
] as const;
|
||||
|
||||
export default function InspirationGallery() {
|
||||
const [selectedImage, setSelectedImage] = useState<string | null>(null);
|
||||
|
||||
useEffect(() => {
|
||||
if (!selectedImage) {
|
||||
return;
|
||||
}
|
||||
const previousOverflow = document.body.style.overflow;
|
||||
document.body.style.overflow = 'hidden';
|
||||
const handleKeyDown = (event: KeyboardEvent) => {
|
||||
if (event.key === 'Escape') {
|
||||
setSelectedImage(null);
|
||||
}
|
||||
};
|
||||
window.addEventListener('keydown', handleKeyDown);
|
||||
return () => {
|
||||
document.body.style.overflow = previousOverflow;
|
||||
window.removeEventListener('keydown', handleKeyDown);
|
||||
};
|
||||
}, [selectedImage]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className="columns-3 gap-3 max-[760px]:columns-2 max-[460px]:columns-1">
|
||||
{INSPIRATION_IMAGES.map((image, index) => (
|
||||
<button
|
||||
className="mb-3 block w-full cursor-zoom-in break-inside-avoid overflow-hidden rounded-lg border-0 bg-transparent p-0 shadow-(--platform-panel-shadow) transition duration-200 hover:-translate-y-0.5 hover:shadow-(--platform-profile-action-shadow) focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-(--platform-warm-text)"
|
||||
type="button"
|
||||
key={image}
|
||||
aria-label={`查看灵感图片 ${index + 1}`}
|
||||
onClick={() => setSelectedImage(image)}
|
||||
>
|
||||
<img
|
||||
className="block h-auto w-full"
|
||||
src={image}
|
||||
alt=""
|
||||
loading="lazy"
|
||||
decoding="async"
|
||||
/>
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
|
||||
{selectedImage
|
||||
? createPortal(
|
||||
<div
|
||||
className="fixed inset-0 z-[1000] grid cursor-zoom-out place-items-center bg-black/80 p-6"
|
||||
role="dialog"
|
||||
aria-modal="true"
|
||||
aria-label="查看灵感图片"
|
||||
onClick={() => setSelectedImage(null)}
|
||||
>
|
||||
<img
|
||||
className="block max-h-[92vh] max-w-[92vw] cursor-default object-contain shadow-2xl"
|
||||
src={selectedImage}
|
||||
alt="放大的灵感图片"
|
||||
onClick={(event) => event.stopPropagation()}
|
||||
/>
|
||||
</div>,
|
||||
document.body,
|
||||
)
|
||||
: null}
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
After Width: | Height: | Size: 36 KiB |
|
After Width: | Height: | Size: 28 KiB |
|
After Width: | Height: | Size: 11 KiB |
|
After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 29 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 29 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 40 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 24 KiB |
|
After Width: | Height: | Size: 35 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 31 KiB |
|
After Width: | Height: | Size: 60 KiB |
|
After Width: | Height: | Size: 33 KiB |
|
After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 8.3 KiB |
|
After Width: | Height: | Size: 36 KiB |
|
After Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 34 KiB |
|
After Width: | Height: | Size: 18 KiB |
|
After Width: | Height: | Size: 40 KiB |
@@ -18,6 +18,7 @@ import {
|
||||
richTextToAttachments,
|
||||
richTextToPrompt,
|
||||
} from './components/RichInputArea/richTextToPrompt';
|
||||
import InspirationGallery from './InspirationGallery';
|
||||
import {
|
||||
type HomeCreationType,
|
||||
type HomeDraft,
|
||||
@@ -171,7 +172,11 @@ export default function HomeView({
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="platform-theme platform-theme--light min-h-screen bg-(image:--platform-body-fill) text-(--platform-text-strong)">
|
||||
<div
|
||||
className={`platform-theme platform-theme--light overflow-x-hidden overflow-y-auto bg-(image:--platform-body-fill) pb-12 text-(--platform-text-strong) ${
|
||||
hasPromo ? 'h-[calc(100vh-32px)]' : 'h-screen'
|
||||
}`}
|
||||
>
|
||||
<section
|
||||
className={`grid content-start justify-items-center gap-3.5 px-6 pb-4.5 pt-20 max-[760px]:gap-4 max-[760px]:px-3.5 max-[760px]:pb-8.5 max-[760px]:pt-21 ${
|
||||
hasPromo ? 'pt-28 max-[760px]:pt-21' : ''
|
||||
@@ -352,7 +357,7 @@ export default function HomeView({
|
||||
/>
|
||||
</span>
|
||||
</header>
|
||||
<div className="min-h-24 overflow-hidden rounded-lg border border-(--platform-surface-border) bg-(image:--platform-subpanel-fill)" />
|
||||
<InspirationGallery />
|
||||
</section>
|
||||
</div>
|
||||
);
|
||||
|
||||